feat: enhance ticket order detail and status display
- Updated ticket status display logic to handle "failed" status and improve "settled_win" condition. - Refactored TicketOrderDetailScreen to utilize search parameters for dynamic navigation and grouping of tickets. - Enhanced TicketOrdersListScreen to group ticket items and improve rendering of order details. - Added new translations for order-related terms in multiple languages to support enhanced user experience.
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { getTicketItemDetail } from "@/api/ticket-items";
|
||||
@@ -17,6 +18,7 @@ import {
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { TwentyThreeResultsGrid } from "@/features/results/twenty-three-results-grid";
|
||||
import { useCurrencyCatalog } from "@/hooks/use-currency-catalog";
|
||||
import { orderGroupPath } from "@/features/orders/group-ticket-items";
|
||||
import { StatusDot, ticketStatusDisplay } from "@/features/orders/ticket-item-status";
|
||||
import { formatLotteryInstant } from "@/lib/player-datetime";
|
||||
import { formatMinorAsCurrency } from "@/lib/money";
|
||||
@@ -67,6 +69,7 @@ type TicketItemDetailWithExtras = TicketItemDetailPayload & {
|
||||
|
||||
/** 界面文档 §4.8 注单详情 */
|
||||
export function TicketOrderDetailScreen({ ticketNo }: { ticketNo: string }) {
|
||||
const searchParams = useSearchParams();
|
||||
const { t } = useTranslation("player");
|
||||
const { activeCurrency } = useActivePlayerCurrency();
|
||||
useCurrencyCatalog();
|
||||
@@ -74,6 +77,27 @@ export function TicketOrderDetailScreen({ ticketNo }: { ticketNo: string }) {
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
const fromGroupKey = useMemo(
|
||||
() => (searchParams.get("fromGroup") ?? "").trim(),
|
||||
[searchParams],
|
||||
);
|
||||
const groupTickets = useMemo(
|
||||
() => (searchParams.get("tickets") ?? "").trim(),
|
||||
[searchParams],
|
||||
);
|
||||
const backNav = useMemo(() => {
|
||||
if (!fromGroupKey) {
|
||||
return { href: "/orders", label: t("orders.title") };
|
||||
}
|
||||
const ticketNos = groupTickets
|
||||
? groupTickets.split(",").map((s) => s.trim()).filter(Boolean)
|
||||
: undefined;
|
||||
return {
|
||||
href: orderGroupPath(fromGroupKey, ticketNos),
|
||||
label: t("orders.groupDetail"),
|
||||
};
|
||||
}, [fromGroupKey, groupTickets, t]);
|
||||
|
||||
const load = useCallback(async () => {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
@@ -98,8 +122,8 @@ export function TicketOrderDetailScreen({ ticketNo }: { ticketNo: string }) {
|
||||
return (
|
||||
<PlayerPanel
|
||||
title={t("orders.betDetail")}
|
||||
backHref="/orders"
|
||||
backLabel={t("orders.title")}
|
||||
backHref={backNav.href}
|
||||
backLabel={backNav.label}
|
||||
>
|
||||
<div className="space-y-3">
|
||||
<Skeleton className="h-12 rounded-xl" />
|
||||
@@ -113,8 +137,8 @@ export function TicketOrderDetailScreen({ ticketNo }: { ticketNo: string }) {
|
||||
return (
|
||||
<PlayerPanel
|
||||
title={t("orders.betDetail")}
|
||||
backHref="/orders"
|
||||
backLabel={t("orders.title")}
|
||||
backHref={backNav.href}
|
||||
backLabel={backNav.label}
|
||||
>
|
||||
<div className="rounded-xl border border-red-200 bg-red-50 px-3 py-3 text-sm text-red-700">
|
||||
<p>{error ?? t("orders.noData")}</p>
|
||||
@@ -174,8 +198,8 @@ export function TicketOrderDetailScreen({ ticketNo }: { ticketNo: string }) {
|
||||
return (
|
||||
<PlayerPanel
|
||||
title={t("orders.betDetail")}
|
||||
backHref="/orders"
|
||||
backLabel={t("orders.title")}
|
||||
backHref={backNav.href}
|
||||
backLabel={backNav.label}
|
||||
>
|
||||
<div className="flex flex-col gap-3">
|
||||
<Card className="ring-0 border border-[#e8eef7] bg-white shadow-[0_8px_28px_rgba(15,23,42,0.05)]">
|
||||
@@ -368,12 +392,12 @@ export function TicketOrderDetailScreen({ ticketNo }: { ticketNo: string }) {
|
||||
</Link>
|
||||
) : null}
|
||||
<Link
|
||||
href="/orders"
|
||||
href={backNav.href}
|
||||
className={cn(
|
||||
"inline-flex h-11 min-w-[140px] flex-1 items-center justify-center rounded-xl border border-[#dce7f7] bg-white px-4 text-sm font-semibold text-[#07459f] transition-colors hover:bg-[#f1f6ff]",
|
||||
)}
|
||||
>
|
||||
{t("orders.backToOrders")}
|
||||
{fromGroupKey ? t("orders.backToGroup") : t("orders.backToOrders")}
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user