refactor(orders): replace local state machine with minimal cache

Strip store/orders.ts to a thin local cache with setOrders and
updateOrder only. Remove all client-side state transition logic,
actor validation, chat sync, notification generation, and wallet
integration — these are now handled by the backend API.

Fix components/order-actions.tsx and stores that depended on
the removed order store methods (markDisputed, autoTimeout*).
This commit is contained in:
zetaloop
2026-05-01 04:13:55 +08:00
parent 452004b194
commit cf0fea9926
6 changed files with 135 additions and 505 deletions
+26 -14
View File
@@ -6,7 +6,7 @@ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { EmptyState } from "@/components/ui/empty-state"
import { StatusBadge } from "@/components/ui/status-badge"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { listChatSessions, listOrders } from "@/lib/api"
import { getPlayerById, listOrders } from "@/lib/api"
import { statusLabels } from "@/lib/constants"
import {
isActiveOrder,
@@ -111,7 +111,7 @@ function OrderListContent({
const orderRole = getOrderRole(currentRole)
const [tab, setTab] = useState<TabFilter | "pending">("all")
const [orders, setOrders] = useState<Awaited<ReturnType<typeof listOrders>>>([])
const [sessions, setSessions] = useState<Awaited<ReturnType<typeof listChatSessions>>>([])
const [chatTargets, setChatTargets] = useState<Record<string, string>>({})
useEffect(() => {
let cancelled = false
@@ -143,27 +143,41 @@ function OrderListContent({
void (async () => {
try {
const items = await Promise.resolve(listChatSessions())
const entries = await Promise.all(
orders.map(async (order) => {
if (currentRole === "consumer") {
const player = await getPlayerById(String(order.playerId))
return [String(order.id), player?.user.id] as const
}
if (currentRole === "player")
return [String(order.id), String(order.consumerId)] as const
return [String(order.id), undefined] as const
}),
)
if (cancelled) return
setSessions(items)
setChatTargets(
Object.fromEntries(
entries.filter((entry): entry is readonly [string, string] => Boolean(entry[1])),
),
)
} catch {
if (cancelled) return
setSessions([])
setChatTargets({})
}
})()
return () => {
cancelled = true
}
}, [])
}, [currentRole, orders])
const tabs =
currentRole === "consumer" ? consumerTabs : currentRole === "player" ? playerTabs : ownerTabs
const roleFiltered = orders.filter((order) => {
if (currentRole === "consumer") return userId ? order.consumerId === userId : false
if (currentRole === "player") return userId ? order.playerId === userId : false
return ownerShopId ? order.shopId === ownerShopId : false
if (currentRole === "consumer") return userId ? String(order.consumerId) === userId : false
if (currentRole === "player") return true
return ownerShopId ? String(order.shopId) === ownerShopId : false
})
const filtered = roleFiltered.filter((order) => {
@@ -241,13 +255,11 @@ function OrderListContent({
if (order.status !== "in_progress" && order.status !== "pending_close") {
return null
}
const session = sessions.find(
(item) => item.type === "order" && item.orderId === order.id,
)
if (!session) return null
const chatTargetId = chatTargets[String(order.id)]
if (!chatTargetId) return null
return (
<Button variant="outline" size="sm" asChild>
<Link href={`/chat/${session.id}`}>
<Link href={`/chat/${chatTargetId}?orderId=${order.id}`}>
<MessageSquare className="mr-1 h-3.5 w-3.5" />
</Link>