后端:Product Module(CRUD)、Requirement Module(CRUD + 状态机流转)、PrismaService 前端:产品列表页、产品详情页(含需求池 Tab)、Zustand Store、API 封装 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
67 lines
2.4 KiB
TypeScript
67 lines
2.4 KiB
TypeScript
'use client';
|
|
|
|
import { create } from 'zustand';
|
|
import { Requirement, RequirementStatus } from '@ftb/shared';
|
|
import { api } from '@/lib/api';
|
|
|
|
interface RequirementWithCreator extends Requirement {
|
|
creator?: { id: string; name: string };
|
|
}
|
|
|
|
interface RequirementState {
|
|
requirements: RequirementWithCreator[];
|
|
loading: boolean;
|
|
error: string | null;
|
|
statusFilter: RequirementStatus | null;
|
|
fetchRequirements: (productId: string, status?: RequirementStatus) => Promise<void>;
|
|
createRequirement: (productId: string, data: { title: string; description?: string; priority?: number; creatorId: string }) => Promise<void>;
|
|
updateRequirement: (productId: string, id: string, data: { title?: string; description?: string; priority?: number }) => Promise<void>;
|
|
updateStatus: (productId: string, id: string, status: RequirementStatus) => Promise<void>;
|
|
deleteRequirement: (productId: string, id: string) => Promise<void>;
|
|
setStatusFilter: (status: RequirementStatus | null) => void;
|
|
}
|
|
|
|
export const useRequirementStore = create<RequirementState>((set, get) => ({
|
|
requirements: [],
|
|
loading: false,
|
|
error: null,
|
|
statusFilter: null,
|
|
|
|
fetchRequirements: async (productId, status) => {
|
|
set({ loading: true, error: null });
|
|
try {
|
|
const query = status ? `?status=${status}` : '';
|
|
const requirements = await api.get<RequirementWithCreator[]>(
|
|
`/products/${productId}/requirements${query}`,
|
|
);
|
|
set({ requirements, loading: false });
|
|
} catch (e: any) {
|
|
set({ error: e.message, loading: false });
|
|
}
|
|
},
|
|
|
|
createRequirement: async (productId, data) => {
|
|
await api.post(`/products/${productId}/requirements`, data);
|
|
await get().fetchRequirements(productId, get().statusFilter || undefined);
|
|
},
|
|
|
|
updateRequirement: async (productId, id, data) => {
|
|
await api.patch(`/products/${productId}/requirements/${id}`, data);
|
|
await get().fetchRequirements(productId, get().statusFilter || undefined);
|
|
},
|
|
|
|
updateStatus: async (productId, id, status) => {
|
|
await api.patch(`/products/${productId}/requirements/${id}/status`, { status });
|
|
await get().fetchRequirements(productId, get().statusFilter || undefined);
|
|
},
|
|
|
|
deleteRequirement: async (productId, id) => {
|
|
await api.delete(`/products/${productId}/requirements/${id}`);
|
|
set({ requirements: get().requirements.filter((r) => r.id !== id) });
|
|
},
|
|
|
|
setStatusFilter: (status) => {
|
|
set({ statusFilter: status });
|
|
},
|
|
}));
|