feat(api, i18n): add agent_node_id to various admin queries and enhance multi-language support
Introduced the agent_node_id field in AdminDrawListQuery, AdminPlayerListQuery, AdminSettlementBatchListQuery, TicketItemsListQuery, and TransferOrderListQuery to improve filtering capabilities. Updated the admin-breadcrumb and admin-sidebar components to include new translations for agent-related terms in English, Nepali, and Chinese, enhancing the overall user experience and multi-language support across the admin interface.
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
"use client";
|
||||
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { useCallback, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useAsyncEffect } from "@/hooks/use-async-effect";
|
||||
import { useTranslationRef } from "@/hooks/use-translation-ref";
|
||||
|
||||
import {
|
||||
getAdminJackpotPoolAdjustments,
|
||||
@@ -40,6 +42,7 @@ import {
|
||||
SelectValue,
|
||||
} from "@/components/ui/select";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { AdminLoadingState, AdminLoadingInline, AdminTableLoadingRow } from "@/components/admin/admin-loading-state";
|
||||
|
||||
type Draft = {
|
||||
contribution_rate: string;
|
||||
@@ -78,6 +81,7 @@ type JackpotPoolsConsoleProps = {
|
||||
|
||||
export function JackpotPoolsConsole({ embedded = false }: JackpotPoolsConsoleProps) {
|
||||
const { t } = useTranslation(["jackpot", "common"]);
|
||||
const tRef = useTranslationRef(["jackpot", "common"]);
|
||||
const profile = useAdminProfile();
|
||||
const canManageJackpot = adminHasAnyPermission(profile?.permissions, [PRD_JACKPOT_MANAGE]);
|
||||
const canManualBurst = adminHasAnyPermission(profile?.permissions, [PRD_JACKPOT_MANUAL_BURST]);
|
||||
@@ -114,17 +118,15 @@ export function JackpotPoolsConsole({ embedded = false }: JackpotPoolsConsolePro
|
||||
setAdjustmentDrafts(adjDrafts);
|
||||
setAdjustmentRows(adjRows);
|
||||
} catch (e) {
|
||||
toast.error(e instanceof LotteryApiBizError ? e.message : t("loadFailed"));
|
||||
toast.error(e instanceof LotteryApiBizError ? e.message : tRef.current("loadFailed"));
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, [t]);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
queueMicrotask(() => {
|
||||
void load();
|
||||
});
|
||||
}, [load]);
|
||||
useAsyncEffect(() => {
|
||||
void load();
|
||||
}, []);
|
||||
|
||||
const updateDraft = (id: number, patch: Partial<Draft>) => {
|
||||
setDrafts((prev) => ({
|
||||
@@ -229,7 +231,7 @@ export function JackpotPoolsConsole({ embedded = false }: JackpotPoolsConsolePro
|
||||
|
||||
const poolList = (
|
||||
<div className={embedded ? "space-y-4" : "space-y-8"}>
|
||||
{loading ? <p className="text-muted-foreground text-sm">{t("states.loading", { ns: "common" })}</p> : null}
|
||||
{loading ? <AdminLoadingState minHeight="6rem" className="py-6" /> : null}
|
||||
{!loading && items.length === 0 ? (
|
||||
<p className="text-muted-foreground text-sm">{t("noPoolData")}</p>
|
||||
) : null}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
"use client";
|
||||
|
||||
import type React from "react";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { useCallback, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useAsyncEffect } from "@/hooks/use-async-effect";
|
||||
import { useTranslationRef } from "@/hooks/use-translation-ref";
|
||||
|
||||
import { getAdminJackpotContributions, getAdminJackpotPayoutLogs } from "@/api/admin-jackpot";
|
||||
import { AdminListPaginationFooter } from "@/components/admin/admin-list-pagination-footer";
|
||||
@@ -13,6 +15,7 @@ import { Button } from "@/components/ui/button";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { AdminLoadingState, AdminLoadingInline, AdminTableLoadingRow } from "@/components/admin/admin-loading-state";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
@@ -74,7 +77,7 @@ function JackpotRecordTableSection({
|
||||
/>
|
||||
</div>
|
||||
{loading && !hasData ? (
|
||||
<p className="px-4 py-6 text-sm text-muted-foreground">{t("states.loading")}</p>
|
||||
<AdminLoadingState minHeight="6rem" className="px-4 py-6" />
|
||||
) : (
|
||||
<div className={TABLE_IN_SHELL_CLASS}>{children}</div>
|
||||
)}
|
||||
@@ -83,8 +86,12 @@ function JackpotRecordTableSection({
|
||||
);
|
||||
}
|
||||
|
||||
type RecordTab = "payout" | "contribution";
|
||||
|
||||
export function JackpotRecordsConsole({ embedded = false }: JackpotRecordsConsoleProps) {
|
||||
const { t } = useTranslation(["jackpot", "common"]);
|
||||
const tRef = useTranslationRef(["jackpot"]);
|
||||
const [recordTab, setRecordTab] = useState<RecordTab>("payout");
|
||||
const payoutExport = useExportLabels("jackpotPayouts");
|
||||
const contributionExport = useExportLabels("jackpotContributions");
|
||||
const formatDt = useAdminDateTimeFormatter();
|
||||
@@ -100,7 +107,7 @@ export function JackpotRecordsConsole({ embedded = false }: JackpotRecordsConsol
|
||||
const [cPer, setCPer] = useState(10);
|
||||
|
||||
const [loadingP, setLoadingP] = useState(true);
|
||||
const [loadingC, setLoadingC] = useState(true);
|
||||
const [loadingC, setLoadingC] = useState(false);
|
||||
const [err, setErr] = useState<string | null>(null);
|
||||
|
||||
const loadPayouts = useCallback(async () => {
|
||||
@@ -113,11 +120,11 @@ export function JackpotRecordsConsole({ embedded = false }: JackpotRecordsConsol
|
||||
});
|
||||
setPayouts(d);
|
||||
} catch (e) {
|
||||
setErr(e instanceof LotteryApiBizError ? e.message : t("payoutLoadFailed"));
|
||||
setErr(e instanceof LotteryApiBizError ? e.message : tRef.current("payoutLoadFailed"));
|
||||
} finally {
|
||||
setLoadingP(false);
|
||||
}
|
||||
}, [pPage, pPer, appliedDrawNo, t]);
|
||||
}, [pPage, pPer, appliedDrawNo]);
|
||||
|
||||
const loadContribs = useCallback(async () => {
|
||||
setLoadingC(true);
|
||||
@@ -129,23 +136,22 @@ export function JackpotRecordsConsole({ embedded = false }: JackpotRecordsConsol
|
||||
});
|
||||
setContribs(d);
|
||||
} catch (e) {
|
||||
setErr(e instanceof LotteryApiBizError ? e.message : t("contributionLoadFailed"));
|
||||
setErr(e instanceof LotteryApiBizError ? e.message : tRef.current("contributionLoadFailed"));
|
||||
} finally {
|
||||
setLoadingC(false);
|
||||
}
|
||||
}, [cPage, cPer, appliedDrawNo, t]);
|
||||
}, [cPage, cPer, appliedDrawNo]);
|
||||
|
||||
useEffect(() => {
|
||||
queueMicrotask(() => {
|
||||
void loadPayouts();
|
||||
});
|
||||
}, [loadPayouts]);
|
||||
useAsyncEffect(() => {
|
||||
void loadPayouts();
|
||||
}, [pPage, pPer, appliedDrawNo]);
|
||||
|
||||
useEffect(() => {
|
||||
queueMicrotask(() => {
|
||||
void loadContribs();
|
||||
});
|
||||
}, [loadContribs]);
|
||||
useAsyncEffect(() => {
|
||||
if (recordTab !== "contribution") {
|
||||
return;
|
||||
}
|
||||
void loadContribs();
|
||||
}, [recordTab, cPage, cPer, appliedDrawNo]);
|
||||
|
||||
const applyDraw = () => {
|
||||
setAppliedDrawNo(drawNo);
|
||||
@@ -328,9 +334,27 @@ export function JackpotRecordsConsole({ embedded = false }: JackpotRecordsConsol
|
||||
{filterBlock}
|
||||
{err ? <p className="text-destructive text-sm">{err}</p> : null}
|
||||
|
||||
<div className="flex flex-wrap gap-2 border-b border-border/70 pb-3">
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
variant={recordTab === "payout" ? "default" : "outline"}
|
||||
onClick={() => setRecordTab("payout")}
|
||||
>
|
||||
{t("payoutRecords")}
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
variant={recordTab === "contribution" ? "default" : "outline"}
|
||||
onClick={() => setRecordTab("contribution")}
|
||||
>
|
||||
{t("contributionRecords")}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="space-y-6">
|
||||
{payoutTable}
|
||||
{contributionTable}
|
||||
{recordTab === "payout" ? payoutTable : contributionTable}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user