Files
erika/app/share/all/page.tsx
T

183 lines
6.5 KiB
TypeScript

import Link from "next/link";
import { desc, sql } from "drizzle-orm";
import { ArrowUpRight, Plus } from "lucide-react";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { db } from "@/db";
import { shareTexts } from "@/db/schema";
export const dynamic = "force-dynamic";
function formatBangkok(date: Date) {
return new Intl.DateTimeFormat("en-GB", {
dateStyle: "medium",
timeStyle: "short",
timeZone: "Asia/Bangkok",
}).format(date);
}
export default async function AllSharesPage() {
const shares = await db
.select({
id: shareTexts.id,
authorName: shareTexts.authorName,
source: shareTexts.source,
description: shareTexts.description,
contentPreview: sql<string>`left(${shareTexts.content}, 160)`,
createdAt: shareTexts.createdAt,
})
.from(shareTexts)
.orderBy(desc(shareTexts.createdAt));
return (
<div className="flex w-full flex-col gap-6">
<header className="flex flex-col gap-4 sm:flex-row sm:items-end sm:justify-between">
<div>
<h1 className="text-3xl font-bold tracking-tight">Share</h1>
<p className="mt-1 text-muted-foreground">
{shares.length.toLocaleString("th-TH")} ลิงก์สาธารณะ
</p>
</div>
<Button asChild>
<Link href="/share">
<Plus data-icon="inline-start" />
สร้างลิงก์ใหม่
</Link>
</Button>
</header>
<Card>
<CardHeader>
<CardTitle>ข้อความที่แชร์ทั้งหมด</CardTitle>
<CardDescription>
เลือกข้อความเพื่อเปิดหน้าสาธารณะ
</CardDescription>
</CardHeader>
<CardContent>
<div className="hidden border md:block">
<Table>
<TableHeader>
<TableRow>
<TableHead>Share</TableHead>
<TableHead>Preview</TableHead>
<TableHead>Author</TableHead>
<TableHead>Source</TableHead>
<TableHead>Created</TableHead>
<TableHead className="text-right">Open</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{shares.length === 0 ? (
<TableRow>
<TableCell
colSpan={6}
className="h-24 text-center text-muted-foreground"
>
ยังไม่มีข้อความที่แชร์
</TableCell>
</TableRow>
) : (
shares.map((share) => (
<TableRow key={share.id}>
<TableCell className="font-mono font-medium">
<Link
href={`/share/${share.id}`}
className="hover:underline"
>
{share.id}
</Link>
</TableCell>
<TableCell>
<p className="max-w-md truncate text-muted-foreground">
{share.description || share.contentPreview}
</p>
</TableCell>
<TableCell>{share.authorName}</TableCell>
<TableCell>
<Badge
variant={
share.source === "bot" ? "secondary" : "outline"
}
>
{share.source === "bot" ? "Bot" : "Web"}
</Badge>
</TableCell>
<TableCell>{formatBangkok(share.createdAt)}</TableCell>
<TableCell className="text-right">
<Button variant="ghost" size="icon-sm" asChild>
<Link
href={`/share/${share.id}`}
aria-label={`Open share ${share.id}`}
>
<ArrowUpRight />
</Link>
</Button>
</TableCell>
</TableRow>
))
)}
</TableBody>
</Table>
</div>
<div className="flex flex-col gap-3 md:hidden">
{shares.length === 0 ? (
<p className="py-8 text-center text-sm text-muted-foreground">
ยังไม่มีข้อความที่แชร์
</p>
) : (
shares.map((share) => (
<Card key={share.id} size="sm">
<CardHeader>
<CardTitle className="font-mono">
<Link href={`/share/${share.id}`}>{share.id}</Link>
</CardTitle>
<CardDescription>
{share.authorName} · {formatBangkok(share.createdAt)}
</CardDescription>
</CardHeader>
<CardContent>
<p className="line-clamp-2 text-sm text-muted-foreground">
{share.description || share.contentPreview}
</p>
<div className="flex items-center justify-between gap-3">
<Badge
variant={
share.source === "bot" ? "secondary" : "outline"
}
>
{share.source === "bot" ? "Bot" : "Web"}
</Badge>
<Button variant="outline" size="sm" asChild>
<Link href={`/share/${share.id}`}>
เปิด
<ArrowUpRight data-icon="inline-end" />
</Link>
</Button>
</div>
</CardContent>
</Card>
))
)}
</div>
</CardContent>
</Card>
</div>
);
}