feat: move top donate to dedicated card
Build and Push Image / build-backend (push) Successful in 5m23s
Build and Push Image / build-frontend (push) Failing after 6m22s
Build and Push Image / push (push) Has been skipped

This commit is contained in:
2026-07-12 22:46:19 +07:00 Unverified
parent 78211e6443
commit 3e935077fe
+103 -54
View File
@@ -13,7 +13,7 @@ import {
import Link from "next/link";
import { useRouter } from "next/navigation";
import posthog from "posthog-js";
import { useEffect } from "react";
import { useEffect, useState } from "react";
import { useEllipsisVisible } from "react-hook-text-overflow";
import { DataTable } from "@/components/tantable";
import { SimpleTooltip } from "@/components/tooltip";
@@ -27,6 +27,7 @@ import type { donations } from "@/lib/db/schema";
import { sse } from "@/lib/db/sse-endpoints";
import { ActionButton } from "../../../../components/action-button";
import { getImage, reloadWidget, resendPopup, testPopup } from "./api";
import { formatDistanceToNow } from "date-fns";
const columns: ColumnDef<typeof donations.$inferSelect>[] = [
{ accessorKey: "name", header: "ชื่อ", meta: { className: "w-50 truncate" } },
@@ -103,63 +104,110 @@ const columns: ColumnDef<typeof donations.$inferSelect>[] = [
);
},
cell(row) {
return (
<div className="flex gap-1">
<SimpleTooltip text="แสดง Popup อีกครั้ง">
<ActionButton
variant="outline"
size="icon-sm"
action={() => {
posthog.capture("donation_admin_resend", {
id: row.row.original.id,
});
return resendPopup(row.row.original.id);
}}
>
<MessageCircleWarning />
</ActionButton>
</SimpleTooltip>
{row.row.original.uid ? (
<SimpleTooltip text="ก็อบ UID">
<ActionButton
size="icon-sm"
action={() =>
navigator.clipboard.writeText(row.row.original.uid!)
}
>
<Copy />
</ActionButton>
</SimpleTooltip>
) : (
<div className="size-8" />
)}
{row.row.original.image && (
<SimpleTooltip text="เปิดภาพ">
<ActionButton
size="icon-sm"
variant="outline"
action={async () => {
await getImage(row.row.original.id).then((blob) => {
const url = URL.createObjectURL(blob);
const tab = window.open("about:blank", "_blank");
if (tab) {
tab.location.href = url;
}
});
}}
>
<ImageIcon />
</ActionButton>
</SimpleTooltip>
)}
</div>
);
return <ActionRow row={row.row.original} filler />;
},
meta: { className: "w-27 p-0" },
},
];
function ActionRow({
row,
filler,
}: {
row: typeof donations.$inferSelect;
filler?: boolean;
}) {
return (
<div className="flex gap-1">
<SimpleTooltip text="แสดง Popup อีกครั้ง">
<ActionButton
variant="outline"
size="icon-sm"
action={() => {
posthog.capture("donation_admin_resend", {
id: row.id,
});
return resendPopup(row.id);
}}
>
<MessageCircleWarning />
</ActionButton>
</SimpleTooltip>
{row.uid ? (
<SimpleTooltip text="ก็อบ UID">
<ActionButton
size="icon-sm"
action={() => navigator.clipboard.writeText(row.uid!)}
>
<Copy />
</ActionButton>
</SimpleTooltip>
) : filler ? (
<div className="size-8" />
) : undefined}
{row.image && (
<SimpleTooltip text="เปิดภาพ">
<ActionButton
size="icon-sm"
variant="outline"
action={async () => {
await getImage(row.id).then((blob) => {
const url = URL.createObjectURL(blob);
const tab = window.open("about:blank", "_blank");
if (tab) {
tab.location.href = url;
}
});
}}
>
<ImageIcon />
</ActionButton>
</SimpleTooltip>
)}
</div>
);
}
function TopRow({ row }: { row?: typeof donations.$inferSelect }) {
const [time, setTime] = useState("");
useEffect(() => {
if (!row) return setTime("");
function update() {
setTime(`${formatDistanceToNow(row!.created)} ago`);
}
const interval = setInterval(update, 1000);
update();
return () => clearTimeout(interval);
}, [row]);
return (
<div className="flex w-full gap-2 p-1">
{row ? (
<div className="flex flex-10 flex-col rounded-lg border bg-card/50 py-1 pr-1 pl-2">
<div className="flex justify-between text-xl">
<div className="flex gap-2">
<span className="font-semibold">{row.name}</span>
<span className="opacity-70">{row.amount}฿</span>
</div>
<span className="pr-1 opacity-70">{time}</span>
</div>
<div className="min-h-20">{row.message}</div>
<div className="flex justify-end">
<ActionRow row={row} />
</div>
</div>
) : (
<div className="flex-10 items-center justify-center rounded-lg border bg-card/50 px-2 py-1">
<span>No donation yet</span>
</div>
)}
{/* <div className="flex-1 rounded-lg border bg-card/50 px-2 py-1">Hi</div>
<div className="flex-1 rounded-lg border bg-card/50 px-2 py-1">Hi</div> */}
</div>
);
}
export function DonateAdminPage({
data,
}: {
@@ -171,10 +219,11 @@ export function DonateAdminPage({
<BitcoinIcon size={32} />
โดเนททั้งหมด
</span>
<TopRow row={data[0]} />
<DataTable
columns={columns}
emptyDescription="No donation came in yet."
data={data}
data={data.slice(1)}
className="max-h-[calc(100vh-93px)] w-full overflow-y-auto bg-black/25 backdrop-blur-sm"
></DataTable>
<DonateWatcher />