/* ============================================================================= * B01_Dashboard_UI_View_Trash.ts * 휴지통(592) — 지운 프로젝트 표(이름 · 종류 · 회사 · 지운 사람 · 지운 시각 · 남은 날) + [되살리기] · [영구 삭제]. * 시스템 관리자 = 전부 · 영구 삭제까지 · 회사 관리자 = 자기 회사 것 되살리기만(서버가 거름). * 남은 날이 다 되면 서버 정리 루프가 DB 행 · 폴더째 지움. * ========================================================================== */ import { askConfirm } from "@ui/ui_template_modal"; import { showToast } from "@ui/ui_template_toast"; import { createButton } from "@ui/ui_template_elements"; import { fetchTrashProjects, purgeTrashProject, restoreTrashProject, type TrashProject, } from "./B01_Dashboard_Api_Fetch"; import { formatDate, formatTime } from "./B01_Dashboard_UI_Common"; import { badge, dataTable, emptyState, nameCell, pageFrame } from "./B01_Dashboard_UI_PageKit"; import { kindBadge } from "./B01_Dashboard_UI_ProjectList_Parts"; import { el as h, loadPage } from "./B01_Dashboard_UI_View_Parts"; import type { ViewCtx } from "./B01_Dashboard_UI_Views"; const COLUMNS = [ { label: "이름" }, { label: "종류" }, { label: "회사" }, { label: "지운 사람" }, { label: "지운 시각" }, { label: "남은 날" }, { label: "관리", align: "end" as const }, ]; export function mountTrash(host: HTMLElement, ctx: ViewCtx): void { const admin = ctx.role === "SYSTEM_ADMIN"; const run = (): void => loadPage(host, async (stage) => { const rows = await fetchTrashProjects(); const frame = pageFrame( stage, "휴지통", "지운 프로젝트는 7 일 동안 여기 있다가 자료째 영구 삭제됩니다. 그 전에 되살릴 수 있습니다.", ); const act = async ( p: TrashProject, ask: string, call: (id: string) => Promise, done: string, danger = false, ): Promise => { if (!(await askConfirm({ title: p.name, message: ask, danger }))) return; try { await call(p.id); showToast(done, "success"); } catch (error) { showToast(error instanceof Error ? error.message : "처리하지 못했습니다.", "error"); } run(); }; const actions = (p: TrashProject): HTMLElement => { const box = h("div", "b01-sys-tool"); box.style.justifyContent = "flex-end"; box.append( createButton({ label: "되살리기", variant: "ghost", size: 28, onClick: () => void act( p, "프로젝트를 되살려 목록에 다시 보이게 합니다.", restoreTrashProject, "되살렸습니다.", ), }), ); if (admin) box.append( createButton({ label: "영구 삭제", variant: "danger-ghost", size: 28, onClick: () => void act( p, "DB 자료와 프로젝트 폴더를 지금 영구 삭제합니다. 되돌릴 수 없습니다.", purgeTrashProject, "영구 삭제했습니다.", true, ), }), ); return box; }; frame.body.append( rows.length ? dataTable( COLUMNS, rows.map((p) => [ p.name, kindBadge(p.project_kind), p.company_name ?? "-", nameCell(p.deleted_by_name ?? "-", p.deleted_by_email), `${formatDate(p.deleted_at)} ${formatTime(p.deleted_at)}`.trim(), badge(`${p.days_left} 일`, p.days_left <= 1 ? "danger" : "neutral"), actions(p), ]), ) : emptyState({ icon: "trash", text: "휴지통이 비어 있습니다." }), ); }); run(); }