修复(#97): 区分邀请管理加载失败状态
PR Check / Lint, Check, Test and Build (push) Has been cancelled
Build and Release / Build (push) Has been cancelled

This commit is contained in:
2026-05-27 19:13:27 -07:00
parent aeca20ad1e
commit 100b641552
5 changed files with 92 additions and 9 deletions
@@ -12,6 +12,8 @@
"inviter": "Inviter",
"inviterGiftDays": "Inviter Gift Days",
"inviterId": "Inviter ID",
"loadErrorDescription": "Refresh the table or try again later.",
"loadErrorTitle": "Failed to load invites",
"no": "No",
"orderCount": "Orders",
"searchPlaceholder": "Email or phone",
@@ -12,6 +12,8 @@
"inviter": "邀请人",
"inviterGiftDays": "邀请人赠送天数",
"inviterId": "邀请人 ID",
"loadErrorDescription": "刷新表格或稍后重试。",
"loadErrorTitle": "邀请记录加载失败",
"no": "否",
"orderCount": "订单数",
"searchPlaceholder": "邮箱/手机号关键词",
+23 -2
View File
@@ -127,12 +127,33 @@ describe("InviteManagement", () => {
expect(await screen.findByText("No invite records")).not.toBeNull();
});
it("keeps the table empty when the request fails", async () => {
it("shows a loading state while invites are being fetched", () => {
let resolveRequest:
| ((
value: AxiosResponse<
API.Response & { data?: API.GetAdminInviteListResponse }
>
) => void)
| undefined;
mockedGetAdminInviteList.mockReturnValue(
new Promise((resolve) => {
resolveRequest = resolve;
})
);
render(<InviteManagement />);
expect(screen.getByRole("status", { name: "Loading data" })).not.toBeNull();
expect(resolveRequest).toBeTypeOf("function");
});
it("shows an error state when the request fails", async () => {
mockedGetAdminInviteList.mockRejectedValue(new Error("network failed"));
render(<InviteManagement />);
await waitFor(() => expect(mockedGetAdminInviteList).toHaveBeenCalled());
expect(await screen.findByText("No invite records")).not.toBeNull();
expect(await screen.findByText("Failed to load invites")).not.toBeNull();
expect(screen.queryByText("No invite records")).toBeNull();
});
});
+17
View File
@@ -1,5 +1,10 @@
"use client";
import {
Alert,
AlertDescription,
AlertTitle,
} from "@workspace/ui/components/alert";
import {
Avatar,
AvatarFallback,
@@ -12,6 +17,7 @@ import {
type ProTableActions,
} from "@workspace/ui/composed/pro-table/pro-table";
import { getAdminInviteList } from "@workspace/ui/services/admin/invite";
import { CircleAlert } from "lucide-react";
import { useRef } from "react";
import { useTranslation } from "react-i18next";
import { Display } from "@/components/display";
@@ -158,6 +164,17 @@ export default function InviteManagement() {
},
]}
empty={<Empty description={t("empty", "No invite records")} />}
error={
<Alert className="mx-auto max-w-md" variant="destructive">
<CircleAlert aria-hidden="true" />
<AlertTitle>
{t("loadErrorTitle", "Failed to load invites")}
</AlertTitle>
<AlertDescription>
{t("loadErrorDescription", "Refresh the table or try again later.")}
</AlertDescription>
</Alert>
}
header={{ title: t("title", "Invite Management") }}
params={[
{