feat: wire order and chat state flow

This commit is contained in:
zetaloop
2026-02-22 06:40:40 +08:00
parent 4ce7303258
commit 02269dd9c3
10 changed files with 372 additions and 57 deletions
+102
View File
@@ -0,0 +1,102 @@
import { create } from "zustand"
import { mockChatMessages, mockChatSessions, mockUsers } from "@/lib/mock"
import type { ChatMessage, ChatSession, Order } from "@/lib/types"
interface Sender {
id: string
name: string
avatar: string
}
interface ChatState {
sessions: ChatSession[]
messages: ChatMessage[]
ensureOrderSession: (order: Order) => ChatSession
sendTextMessage: (sessionId: string, sender: Sender, content: string) => void
}
function resolveAvatar(userId: string) {
return mockUsers.find((user) => user.id === userId)?.avatar ?? ""
}
function shouldReadonly(status: Order["status"]) {
return status === "pending_review" || status === "completed" || status === "cancelled"
}
export const useChatStore = create<ChatState>((set, get) => ({
sessions: mockChatSessions,
messages: mockChatMessages,
ensureOrderSession: (order) => {
const existing = get().sessions.find(
(session) => session.type === "order" && session.orderId === order.id,
)
const readonly = shouldReadonly(order.status)
if (existing) {
if (existing.readonly !== readonly) {
set((state) => ({
sessions: state.sessions.map((session) =>
session.id === existing.id ? { ...session, readonly } : session,
),
}))
}
return get().sessions.find((session) => session.id === existing.id) ?? existing
}
const session: ChatSession = {
id: `chat-${order.id}`,
type: "order",
orderId: order.id,
participants: [
{
id: order.consumerId,
name: order.consumerName,
avatar: resolveAvatar(order.consumerId),
},
{
id: order.playerId,
name: order.playerName,
avatar: resolveAvatar(order.playerId),
},
],
unreadCount: 0,
readonly,
}
set((state) => ({
sessions: [session, ...state.sessions],
}))
return session
},
sendTextMessage: (sessionId, sender, content) => {
const text = content.trim()
if (!text) return
const now = new Date().toISOString()
const message: ChatMessage = {
id: `msg-${Date.now()}`,
sessionId,
senderId: sender.id,
senderName: sender.name,
senderAvatar: sender.avatar,
type: "text",
content: text,
createdAt: now,
}
set((state) => ({
messages: [...state.messages, message],
sessions: state.sessions.map((session) =>
session.id === sessionId
? {
...session,
lastMessage: text,
lastMessageAt: now,
}
: session,
),
}))
},
}))