-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpage.tsx
More file actions
123 lines (108 loc) · 3.36 KB
/
Copy pathpage.tsx
File metadata and controls
123 lines (108 loc) · 3.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import Link from "next/link";
import { Button } from "@/components/ui/button";
import { db } from "@/lib/db";
import { requireApproved } from "@/lib/guard";
import { listApprovedMembers, listSessions } from "@/lib/sessions";
import {
buildSessionArchiveHref,
parseSessionArchiveParams,
type SessionArchiveSearchParams,
} from "@/lib/session-filters";
import {
HeroBand,
PageShell,
SubNav,
UtilityCard,
} from "@/components/layout/AppChrome";
import { EmptyState } from "./_components/EmptyState";
import { FilterBar } from "./_components/FilterBar";
import { SessionCard } from "./_components/SessionCard";
export const dynamic = "force-dynamic";
type SearchParams = SessionArchiveSearchParams;
type PageProps = {
searchParams: Promise<SearchParams>;
};
export default async function SessionsArchivePage({ searchParams }: PageProps) {
await requireApproved();
const sp = await searchParams;
const { cursorId, filters, hasActiveFilters } = parseSessionArchiveParams(sp);
const [page, members, totalCount] = await Promise.all([
listSessions({ cursorId, filters }),
listApprovedMembers(),
db.session.count(),
]);
const nextHref =
page.nextCursorId != null
? buildSessionArchiveHref({ ...sp, cursor: String(page.nextCursorId) })
: null;
return (
<>
<SubNav title="아카이브">
<Button asChild size="sm">
<Link href="/sessions/new">새 세션</Link>
</Button>
</SubNav>
<HeroBand
size="compact"
eyebrow="Sessions"
title="러닝 아카이브"
description={
<>
지금까지 {totalCount}번 달렸습니다. 날짜, 장소, 참여 멤버로 세션을
찾아보세요.
</>
}
/>
<PageShell width="content" surface="parchment">
<FilterBar
q={filters.q ?? ""}
memberIds={filters.memberIds ?? []}
month={filters.month ?? ""}
pmin={filters.pmin != null ? String(filters.pmin) : ""}
pmax={filters.pmax != null ? String(filters.pmax) : ""}
members={members}
hasActiveFilters={hasActiveFilters}
/>
{page.items.length === 0 ? (
hasActiveFilters ? (
<EmptyFilterResult />
) : (
<EmptyState />
)
) : (
<>
<ul className="grid gap-6 md:grid-cols-2">
{page.items.map((s) => (
<li key={s.id}>
<SessionCard {...s} />
</li>
))}
</ul>
{nextHref && (
<div className="mt-10 flex justify-center">
<Button asChild variant="outline">
<Link href={nextHref}>더 보기</Link>
</Button>
</div>
)}
</>
)}
</PageShell>
</>
);
}
function EmptyFilterResult() {
return (
<UtilityCard className="flex flex-col items-center gap-4 border-dashed text-center">
<p className="font-display text-[24px] font-light leading-[1.5] tracking-normal text-apple-muted-80">
조건에 맞는 세션이 없어요.
</p>
<Link
href="/sessions"
className="font-text text-sm leading-[1.29] tracking-[-0.224px] text-apple-primary underline-offset-4 hover:underline"
>
필터 초기화
</Link>
</UtilityCard>
);
}