"use client";
import Link from "next/link";
import { useCallback, useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { toast } from "sonner";
import {
getAdminDraw,
postAdminCancelDraw,
postAdminManualCloseDraw,
postAdminReopenDraw,
postAdminRunDrawRng,
} from "@/api/admin-draws";
import { postAdminRunDrawSettlement } from "@/api/admin-settlement";
import { Button, buttonVariants } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Label } from "@/components/ui/label";
import { Separator } from "@/components/ui/separator";
import { useAdminDateTimeFormatter } from "@/hooks/use-admin-datetime-formatter";
import { useConfirmAction } from "@/hooks/use-confirm-action";
import { LotteryApiBizError } from "@/types/api/errors";
import type { AdminDrawShowData } from "@/types/api/admin-draws";
import { adminHasAnyPermission } from "@/lib/admin-permissions";
import { useAdminProfile } from "@/stores/admin-session";
import { cn } from "@/lib/utils";
import {
drawResultSourceLabel,
drawStatusLabel,
hallPreviewDiffersFromDbStatus,
} from "./draw-display";
import { DrawStatusBadge } from "./draw-status-badge";
import {
PRD_DRAW_REOPEN_MANAGE,
PRD_DRAW_RESULT_MANAGE,
PRD_PAYOUT_MANAGE,
PRD_PAYOUT_REVIEW,
} from "./draw-prd";
function Field({ label, children }: { label: string; children: React.ReactNode }) {
return (
);
}
export function DrawDetailConsole({ drawId }: { drawId: string }) {
const { t } = useTranslation(["draws", "common"]);
const idNum = Number(drawId);
const profile = useAdminProfile();
const canManageDraw = adminHasAnyPermission(profile?.permissions, [PRD_DRAW_RESULT_MANAGE]);
const canReopenDraw = adminHasAnyPermission(profile?.permissions, [PRD_DRAW_REOPEN_MANAGE]);
const canRunSettlement = adminHasAnyPermission(profile?.permissions, [
PRD_PAYOUT_MANAGE,
PRD_PAYOUT_REVIEW,
]);
const formatDt = useAdminDateTimeFormatter();
const [data, setData] = useState(null);
const [error, setError] = useState(null);
const [loading, setLoading] = useState(true);
const [acting, setActing] = useState(null);
const { request: requestConfirm, ConfirmDialog } = useConfirmAction();
const load = useCallback(async () => {
if (!Number.isFinite(idNum)) {
setError(t("invalidDrawId"));
setLoading(false);
return;
}
setLoading(true);
setError(null);
try {
setData(await getAdminDraw(idNum));
} catch (e) {
setData(null);
setError(e instanceof LotteryApiBizError ? e.message : t("errors.loadFailed", { ns: "common" }));
} finally {
setLoading(false);
}
}, [idNum, t]);
async function runAction(name: string, action: () => Promise): Promise {
if (!Number.isFinite(idNum)) return;
setActing(name);
try {
await action();
toast.success(t("actionSuccess", { name }));
await load();
} catch (e) {
toast.error(e instanceof LotteryApiBizError ? e.message : t("actionFailed", { name }));
} finally {
setActing(null);
}
}
useEffect(() => {
const timer = window.setTimeout(() => {
void load();
}, 0);
return () => window.clearTimeout(timer);
}, [load]);
if (loading && !data) {
return {t("states.loading", { ns: "common" })}
;
}
if (error || !data) {
return {error ?? t("states.noData", { ns: "common" })}
;
}
return (
{data.draw_no}
{t("drawDetail")}
{hallPreviewDiffersFromDbStatus(data.status, data.hall_preview_status) ? (
{t("hallPreviewStatusLabel")}
) : null}
{data.business_date}
{data.sequence_no}
{formatDt(data.start_time)}
{formatDt(data.close_time)}
{formatDt(data.draw_time)}
{formatDt(data.cooling_end_time)}
{drawResultSourceLabel(data.result_source, t)}
{data.current_result_version}
{data.settle_version}
{data.is_reopened ? t("yes") : t("no")}
{t("batchStats")}
{t("batchTotal")}
{data.result_batch_counts.total}
{t("pendingReview")}
{data.result_batch_counts.pending_review}
{t("published")}
{data.result_batch_counts.published}
{t("viewFinance")}
{(canManageDraw || canReopenDraw || canRunSettlement) ? (
{t("drawActions")}
{canReopenDraw ? (
) : null}
) : null}
);
}