"use client" import { Button } from "@/components/ui/button" import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select" import { Textarea } from "@/components/ui/textarea" import { createPlayerService, getGameById, getServiceById, listGames, listPlayers, updatePlayerService, } from "@/lib/api" import { toApiError } from "@/lib/errors" import { GameIcon } from "@/lib/game-icons" import { useMyShop } from "@/lib/hooks/use-my-shop" import { notifyInfo, notifySuccess } from "@/lib/toast" import type { Game, PlayerService } from "@/lib/types" import { useAuthStore } from "@/store/auth" import { standardSchemaResolver } from "@hookform/resolvers/standard-schema" import { ArrowLeft } from "lucide-react" import Link from "next/link" import { useRouter, useSearchParams } from "next/navigation" import { useEffect, useState } from "react" import { useForm, useWatch } from "react-hook-form" import { z } from "zod" const serviceSchema = z.object({ gameId: z.string().min(1, "请选择游戏"), title: z.string().min(2, "标题至少2个字符"), description: z.string().min(10, "描述至少10个字符"), price: z.string().min(1, "请输入价格"), unit: z.string().min(1, "请输入单位"), rankRange: z.string().optional(), availability: z.string().min(1, "请输入可用时间"), }) export default function NewServicePage() { const router = useRouter() const searchParams = useSearchParams() const serviceId = searchParams.get("serviceId") const userId = useAuthStore((state) => state.user?.id) const currentRole = useAuthStore((state) => state.currentRole) const { shop: ownerShop, loading: shopLoading, error: shopError, } = useMyShop(currentRole === "owner") const [players, setPlayers] = useState>>([]) const [editingService, setEditingService] = useState(undefined) const [loadingService, setLoadingService] = useState(Boolean(serviceId)) const scopedPlayerIds = currentRole === "player" ? userId ? players.filter((player) => player.user.id === userId).map((player) => player.id) : [] : currentRole === "owner" ? ownerShop ? players.filter((player) => player.shopId === ownerShop.id).map((player) => player.id) : [] : [] const scopedPlayerIdSet = new Set(scopedPlayerIds) const targetPlayerId = editingService?.playerId ?? scopedPlayerIds[0] const { register, handleSubmit, setValue, control, formState: { errors, isSubmitting }, } = useForm>({ resolver: standardSchemaResolver(serviceSchema), defaultValues: { gameId: "", title: "", description: "", price: "", unit: "", rankRange: "", availability: "", }, }) useEffect(() => { let cancelled = false listPlayers() .then((items) => { if (!cancelled) setPlayers(items) }) .catch((error) => { if (!cancelled) notifyInfo(toApiError(error).msg) }) return () => { cancelled = true } }, []) useEffect(() => { if (!serviceId) return let cancelled = false getServiceById(serviceId) .then((service) => { if (!cancelled) setEditingService(service) }) .catch((error) => { if (!cancelled) notifyInfo(toApiError(error).msg) }) .finally(() => { if (!cancelled) setLoadingService(false) }) return () => { cancelled = true } }, [serviceId]) useEffect(() => { if (!editingService) return setValue("gameId", editingService.gameId) setValue("title", editingService.title) setValue("description", editingService.description) setValue("price", editingService.price.toString()) setValue("unit", editingService.unit) setValue("rankRange", editingService.rankRange ?? "") setValue("availability", editingService.availability.join("、")) }, [editingService, setValue]) const selectedGameId = useWatch({ control, name: "gameId" }) const selectedUnit = useWatch({ control, name: "unit" }) const [games, setGames] = useState([]) useEffect(() => { let cancelled = false listGames() .then((items) => { if (cancelled) return setGames(items) }) .catch(() => { if (cancelled) return setGames([]) }) return () => { cancelled = true } }, []) if (loadingService || (currentRole === "owner" && shopLoading)) { return
加载中...
} if (currentRole === "owner" && shopError) { return
{shopError}
} if (serviceId && (!editingService || !scopedPlayerIdSet.has(editingService.playerId))) { return
服务不存在或当前身份不可编辑
} if (!targetPlayerId) { return
当前身份下没有可管理的服务范围
} const onSubmit = async (data: z.infer) => { const game = await getGameById(data.gameId) if (!game) return const payload: Omit = { playerId: targetPlayerId, gameId: game.id, gameName: game.name, title: data.title, description: data.description, price: Number(data.price), unit: data.unit as PlayerService["unit"], rankRange: data.rankRange?.trim() ? data.rankRange.trim() : undefined, availability: data.availability .split("、") .map((item) => item.trim()) .filter(Boolean), } if (editingService) { await updatePlayerService(editingService.id, payload) notifySuccess("服务已保存") } else { await createPlayerService(payload) notifySuccess("服务已发布") } router.push("/dashboard/services") } return (
返回服务列表 发布服务
{errors.title &&

{errors.title.message}

}