refactor(layout, i18n, admin): 优化布局结构与多语言支持
调整 AdminShell 组件的子组件顺序,提升代码可读性。更新 admin-breadcrumb 组件,简化导航标签翻译逻辑,确保多语言支持的一致性。重构 admin-language-switcher 组件,优化语言切换的用户体验,增强界面交互性。更新多语言配置,新增登录界面的副标题,提升用户体验。
This commit is contained in:
@@ -1,12 +1,13 @@
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import { Rocket } from "lucide-react";
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { toast } from "sonner";
|
||||
|
||||
import { getAdminDrawResultBatches, postAdminCreateManualResultBatch } from "@/api/admin-draws";
|
||||
import { Button, buttonVariants } from "@/components/ui/button";
|
||||
import { AdminRowActionsMenu } from "@/components/admin/admin-row-actions-menu";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import {
|
||||
@@ -18,7 +19,6 @@ import {
|
||||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
import { useConfirmAction } from "@/hooks/use-confirm-action";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { adminHasAnyPermission } from "@/lib/admin-permissions";
|
||||
import { useAdminProfile } from "@/stores/admin-session";
|
||||
import { LotteryApiBizError } from "@/types/api/errors";
|
||||
@@ -204,7 +204,7 @@ export function DrawReviewConsole({ drawId }: { drawId: string }) {
|
||||
<TableHead>{t("batchId")}</TableHead>
|
||||
<TableHead>{t("version", { version: "" }).replace(" v", "").trim()}</TableHead>
|
||||
<TableHead>{t("numberCount")}</TableHead>
|
||||
<TableHead className="text-center">{t("actions")}</TableHead>
|
||||
<TableHead className="w-14 text-center">{t("actions")}</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
@@ -215,12 +215,16 @@ export function DrawReviewConsole({ drawId }: { drawId: string }) {
|
||||
<TableCell>{b.items.length}</TableCell>
|
||||
<TableCell className="text-center">
|
||||
{canManageDraw ? (
|
||||
<Link
|
||||
href={`/admin/draws/${drawId}/publish/${b.id}`}
|
||||
className={cn(buttonVariants({ size: "sm" }))}
|
||||
>
|
||||
{t("reviewAndPublishAction")}
|
||||
</Link>
|
||||
<AdminRowActionsMenu
|
||||
actions={[
|
||||
{
|
||||
key: "publish",
|
||||
label: t("reviewAndPublishAction"),
|
||||
icon: Rocket,
|
||||
href: `/admin/draws/${drawId}/publish/${b.id}`,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
) : (
|
||||
<span className="text-xs text-muted-foreground">{t("noPublishPermission")}</span>
|
||||
)}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import { Ban, Eye, Pencil, Trash2 } from "lucide-react";
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { toast } from "sonner";
|
||||
@@ -14,7 +14,8 @@ import {
|
||||
} from "@/api/admin-draws";
|
||||
import { formatAdminInstant } from "@/lib/admin-datetime";
|
||||
import { getAdminRequestLocale } from "@/lib/admin-locale";
|
||||
import { Button, buttonVariants } from "@/components/ui/button";
|
||||
import { AdminRowActionsMenu } from "@/components/admin/admin-row-actions-menu";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { AdminTableExportButton } from "@/components/admin/admin-table-export-button";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { AdminListPaginationFooter } from "@/components/admin/admin-list-pagination-footer";
|
||||
@@ -404,7 +405,7 @@ export function DrawsIndexConsole() {
|
||||
<TableHead className="text-center">{t("betTotal")}</TableHead>
|
||||
<TableHead className="text-center">{t("payoutTotal")}</TableHead>
|
||||
<TableHead className="text-center">{t("profitLoss")}</TableHead>
|
||||
<TableHead className="text-center">{t("actions")}</TableHead>
|
||||
<TableHead className="w-14 text-center">{t("actions")}</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
@@ -462,60 +463,29 @@ export function DrawsIndexConsole() {
|
||||
: "—"}
|
||||
</TableCell>
|
||||
<TableCell className="text-center">
|
||||
<div className="flex flex-wrap items-center justify-center gap-1.5">
|
||||
<Link
|
||||
href={`/admin/draws/${row.id}`}
|
||||
className={cn(buttonVariants({ variant: "outline", size: "sm" }))}
|
||||
>
|
||||
{t("viewDetails")}
|
||||
</Link>
|
||||
{canManageDraw && canEditDrawRow(row) ? (
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => setEditDraw(row)}
|
||||
>
|
||||
{t("editDraw.action")}
|
||||
</Button>
|
||||
) : null}
|
||||
{canManageDraw && canDeleteDrawRow(row) ? (
|
||||
<Button
|
||||
type="button"
|
||||
variant="destructive"
|
||||
size="sm"
|
||||
onClick={() =>
|
||||
requestConfirm({
|
||||
title: t("deleteDraw.title"),
|
||||
description: t("deleteDraw.description", { drawNo: row.draw_no }),
|
||||
confirmVariant: "destructive",
|
||||
onConfirm: async () => {
|
||||
try {
|
||||
await deleteAdminDraw(row.id);
|
||||
toast.success(t("deleteDraw.success"));
|
||||
await load();
|
||||
} catch (e) {
|
||||
toast.error(
|
||||
e instanceof LotteryApiBizError
|
||||
? e.message
|
||||
: t("deleteDraw.failed"),
|
||||
);
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
>
|
||||
{t("deleteDraw.action")}
|
||||
</Button>
|
||||
) : null}
|
||||
{canManageDraw &&
|
||||
canCancelDrawRow(row) &&
|
||||
!canDeleteDrawRow(row) ? (
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() =>
|
||||
<AdminRowActionsMenu
|
||||
actions={[
|
||||
{
|
||||
key: "view",
|
||||
label: t("viewDetails"),
|
||||
icon: Eye,
|
||||
href: `/admin/draws/${row.id}`,
|
||||
},
|
||||
{
|
||||
key: "edit",
|
||||
label: t("editDraw.action"),
|
||||
icon: Pencil,
|
||||
hidden: !(canManageDraw && canEditDrawRow(row)),
|
||||
onClick: () => setEditDraw(row),
|
||||
},
|
||||
{
|
||||
key: "cancel",
|
||||
label: t("cancelFromList.action"),
|
||||
icon: Ban,
|
||||
hidden: !(
|
||||
canManageDraw && canCancelDrawRow(row) && !canDeleteDrawRow(row)
|
||||
),
|
||||
onClick: () =>
|
||||
requestConfirm({
|
||||
title: t("cancelFromList.title"),
|
||||
description: t("cancelFromList.description", {
|
||||
@@ -534,13 +504,36 @@ export function DrawsIndexConsole() {
|
||||
);
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
>
|
||||
{t("cancelFromList.action")}
|
||||
</Button>
|
||||
) : null}
|
||||
</div>
|
||||
}),
|
||||
},
|
||||
{
|
||||
key: "delete",
|
||||
label: t("deleteDraw.action"),
|
||||
icon: Trash2,
|
||||
destructive: true,
|
||||
hidden: !(canManageDraw && canDeleteDrawRow(row)),
|
||||
onClick: () =>
|
||||
requestConfirm({
|
||||
title: t("deleteDraw.title"),
|
||||
description: t("deleteDraw.description", { drawNo: row.draw_no }),
|
||||
confirmVariant: "destructive",
|
||||
onConfirm: async () => {
|
||||
try {
|
||||
await deleteAdminDraw(row.id);
|
||||
toast.success(t("deleteDraw.success"));
|
||||
await load();
|
||||
} catch (e) {
|
||||
toast.error(
|
||||
e instanceof LotteryApiBizError
|
||||
? e.message
|
||||
: t("deleteDraw.failed"),
|
||||
);
|
||||
}
|
||||
},
|
||||
}),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))
|
||||
|
||||
Reference in New Issue
Block a user