Files
juwan-frontend/store/reviews.ts
T
zetaloop 12284290cc refactor(store): adapt Zustand stores to backend-aligned types
- orders: remove name fields from creation, keep dispatchMode logic
- chat: remove readonly/senderName/senderAvatar references
- reviews: remove fromUserAvatar/toUserId, simplify participant check
- disputes: remove initiatorId/initiatorName from creation
- posts: remove authorRole/quotedPostId, keep linkedOrderId as number
- comments: remove postId from creation
- wallet: use string amounts
2026-04-23 21:15:11 +08:00

84 lines
2.4 KiB
TypeScript

import { allow, deny } from "@/lib/decision"
import type { ApiDecision } from "@/lib/errors"
import { generateId } from "@/lib/id"
import type { Review } from "@/lib/types"
import { useOrderStore } from "@/store/orders"
import { create } from "zustand"
interface SubmitReviewInput {
orderId: string
fromUserId: string
rating: number
content?: string
}
interface ReviewState {
reviews: Review[]
submitReview: (input: SubmitReviewInput) => ApiDecision
getReviewsByOrder: (orderId: string) => Review[]
hasUserReviewed: (orderId: string, userId: string) => boolean
}
export const useReviewStore = create<ReviewState>((set, get) => ({
reviews: [],
getReviewsByOrder: (orderId) => get().reviews.filter((review) => review.orderId === orderId),
hasUserReviewed: (orderId, userId) =>
get().reviews.some((review) => review.orderId === orderId && review.fromUserId === userId),
submitReview: (input) => {
if (!input.fromUserId) {
return deny(401, "请先登录")
}
if (!Number.isFinite(input.rating) || input.rating < 1 || input.rating > 5) {
return deny(400, "评分范围应为 1-5")
}
const order = useOrderStore.getState().orders.find((item) => item.id === input.orderId)
if (!order) {
return deny(404, "订单不存在")
}
if (order.status !== "pending_review") {
return deny(400, "仅待评价订单可提交评价")
}
const isParticipant =
order.consumerId === input.fromUserId || order.playerId === input.fromUserId
if (!isParticipant) {
return deny(403, "仅订单参与方可评价")
}
const exists = get().hasUserReviewed(input.orderId, input.fromUserId)
if (exists) {
return deny(400, "该订单已提交过评价")
}
const createdAt = new Date().toISOString()
const review: Review = {
id: generateId("rev"),
orderId: input.orderId,
fromUserId: input.fromUserId,
fromUserName: "",
rating: input.rating,
content: input.content?.trim() ?? "",
sealed: true,
createdAt,
}
set((state) => ({ reviews: [...state.reviews, review] }))
const orderReviews = get().getReviewsByOrder(input.orderId)
if (orderReviews.length >= 2) {
set((state) => ({
reviews: state.reviews.map((item) =>
item.orderId === input.orderId ? { ...item, sealed: false } : item,
),
}))
useOrderStore.getState().autoTimeoutPendingReview(input.orderId)
}
return allow()
},
}))