-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpage.tsx
More file actions
110 lines (93 loc) · 2.97 KB
/
Copy pathpage.tsx
File metadata and controls
110 lines (93 loc) · 2.97 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
import Link from "next/link";
import { Button } from "@/components/ui/button";
import { requireApproved } from "@/lib/guard";
import { listApprovedMembers, listSessions } from "@/lib/sessions";
import {
buildSessionArchiveHref,
parseSessionArchiveParams,
type SessionArchiveSearchParams,
} from "@/lib/session-filters";
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] = await Promise.all([
listSessions({ cursorId, filters }),
listApprovedMembers(),
]);
const nextHref =
page.nextCursorId != null
? buildSessionArchiveHref({ ...sp, cursor: String(page.nextCursorId) })
: null;
return (
<main className="container mx-auto max-w-2xl p-6">
<nav className="mb-4 text-xs text-muted-foreground">
<Link href="/" className="underline-offset-4 hover:underline">
← 홈
</Link>
</nav>
<header className="mb-6 flex items-center justify-between">
<h1 className="text-2xl font-bold tracking-tight">아카이브</h1>
<Link href="/sessions/new">
<Button size="sm">새 세션</Button>
</Link>
</header>
<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="flex flex-col gap-4">
{page.items.map((s) => (
<li key={s.id}>
<SessionCard {...s} />
</li>
))}
</ul>
{nextHref && (
<div className="mt-6 flex justify-center">
<Link href={nextHref}>
<Button variant="outline">더 보기</Button>
</Link>
</div>
)}
</>
)}
</main>
);
}
function EmptyFilterResult() {
return (
<section className="flex flex-col items-center gap-3 rounded-md border border-dashed p-10 text-center">
<p className="text-sm text-muted-foreground">
조건에 맞는 세션이 없어요.
</p>
<Link
href="/sessions"
className="text-xs underline underline-offset-4"
>
필터 초기화
</Link>
</section>
);
}