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
+45 -24
View File
@@ -5,9 +5,10 @@ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { EmptyState } from "@/components/ui/empty-state"
import { Separator } from "@/components/ui/separator"
import { StatusBadge } from "@/components/ui/status-badge"
import { getOrderById, listChatSessions, listReviewsByOrder } from "@/lib/api"
import { getOrderById, getPlayerById, getUserById, listReviewsByOrder } from "@/lib/api"
import { statusLabels } from "@/lib/constants"
import type { OrderStatus } from "@/lib/types"
import type { OrderStatus, Player, User } from "@/lib/types"
import { useAuthStore } from "@/store/auth"
import { ArrowLeft, CheckCircle, Clock, Star } from "lucide-react"
import Link from "next/link"
import { use, useEffect, useState } from "react"
@@ -46,32 +47,15 @@ const statusVariants: Record<OrderStatus, OrderStatusBadgeVariant> = {
export default function OrderDetailPage({ params }: { params: Promise<{ id: string }> }) {
const { id } = use(params)
const [sessions, setSessions] = useState<Awaited<ReturnType<typeof listChatSessions>>>([])
const currentUserId = useAuthStore((state) => state.user?.id)
const [reviews, setReviews] = useState<Awaited<ReturnType<typeof listReviewsByOrder>>>([])
const [chatTarget, setChatTarget] = useState<User | null>(null)
const [player, setPlayer] = useState<Player | null>(null)
const [order, setOrder] = useState<Awaited<ReturnType<typeof getOrderById>> | undefined>(
undefined,
)
const [loading, setLoading] = useState(true)
useEffect(() => {
let cancelled = false
void (async () => {
try {
const sessions = await Promise.resolve(listChatSessions())
if (cancelled) return
setSessions(sessions)
} catch {
if (cancelled) return
setSessions([])
}
})()
return () => {
cancelled = true
}
}, [])
useEffect(() => {
let cancelled = false
@@ -94,6 +78,42 @@ export default function OrderDetailPage({ params }: { params: Promise<{ id: stri
}
}, [id])
useEffect(() => {
let cancelled = false
void (async () => {
if (!order || !currentUserId) {
setPlayer(null)
setChatTarget(null)
return
}
try {
setPlayer(null)
setChatTarget(null)
const player = await getPlayerById(String(order.playerId))
if (!cancelled) setPlayer(player ?? null)
if (String(order.consumerId) === currentUserId) {
if (!cancelled) setChatTarget(player?.user ?? null)
return
}
if (player?.user.id === currentUserId) {
const consumer = await getUserById(String(order.consumerId))
if (!cancelled) setChatTarget(consumer ?? null)
}
} catch {
if (!cancelled) setPlayer(null)
if (!cancelled) setChatTarget(null)
}
})()
return () => {
cancelled = true
}
}, [currentUserId, order])
useEffect(() => {
let cancelled = false
@@ -129,7 +149,6 @@ export default function OrderDetailPage({ params }: { params: Promise<{ id: stri
)
}
const chatSession = sessions.find((session) => session.type === "order" && session.orderId === id)
const statusSteps =
order.status === "disputed"
? disputedStatusSteps
@@ -137,6 +156,7 @@ export default function OrderDetailPage({ params }: { params: Promise<{ id: stri
? cancelledStatusSteps
: normalStatusSteps
const currentStepIndex = statusSteps.indexOf(order.status)
const isPlayerParticipant = player?.user.id === currentUserId
return (
<div className="container mx-auto py-8 px-4 max-w-2xl">
@@ -291,7 +311,8 @@ export default function OrderDetailPage({ params }: { params: Promise<{ id: stri
order={order}
onOrderChange={(next) => setOrder(next)}
initialStatus={order.status}
chatSessionId={chatSession?.id}
chatTargetId={chatTarget?.id}
isPlayerParticipant={isPlayerParticipant}
serviceId={order.service.id}
/>
</div>