"use client" import { Badge } from "@/components/ui/badge" 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 { createPost, listOrders, uploadFile } from "@/lib/api" import { toApiError } from "@/lib/errors" import { notifyInfo, notifySuccess } from "@/lib/toast" import { useRequireAuth } from "@/lib/use-require-auth" import { useAuthStore } from "@/store/auth" import { standardSchemaResolver } from "@hookform/resolvers/standard-schema" import { ArrowLeft, ImagePlus, X } from "lucide-react" import Link from "next/link" import { useRouter } from "next/navigation" import { type ChangeEvent, useEffect, useState } from "react" import { useForm } from "react-hook-form" import { z } from "zod" const postSchema = z.object({ title: z.string().min(2, "标题至少2个字符").max(50, "标题最多50个字符"), content: z.string().min(10, "内容至少10个字符"), }) const tagOptions = ["英雄联盟", "王者荣耀", "CS2", "原神", "上分", "攻略", "好评", "吐槽", "求组队"] type PostType = "normal" | "show_order" export default function NewPostPage() { const router = useRouter() const { isAuthenticated, requireAuth } = useRequireAuth() const currentRole = useAuthStore((state) => state.currentRole) const [orders, setOrders] = useState>>([]) const [postType, setPostType] = useState("normal") const [selectedTags, setSelectedTags] = useState([]) const [imageFiles, setImageFiles] = useState([]) const [selectedOrderId, setSelectedOrderId] = useState(undefined) const canShowOrder = currentRole === "consumer" const effectivePostType = canShowOrder || postType !== "show_order" ? postType : "normal" const { register, handleSubmit, formState: { errors, isSubmitting }, } = useForm>({ resolver: standardSchemaResolver(postSchema), }) const toggleTag = (tag: string) => { setSelectedTags((prev) => prev.includes(tag) ? prev.filter((t) => t !== tag) : prev.length < 5 ? [...prev, tag] : prev, ) } useEffect(() => { if (!isAuthenticated || !canShowOrder) { return } let cancelled = false listOrders({ role: "consumer", status: "completed" }) .then((items) => { if (cancelled) return setOrders(items) }) .catch((error) => { if (cancelled) return notifyInfo(toApiError(error).msg) }) return () => { cancelled = true } }, [canShowOrder, isAuthenticated]) const handleSelectImages = (event: ChangeEvent) => { const files = Array.from(event.target.files ?? []) if (files.length === 0) return setImageFiles((prev) => [...prev, ...files].slice(0, 9)) event.target.value = "" } const availableOrders = isAuthenticated && canShowOrder ? orders : [] const onSubmit = async (data: z.infer) => { if (!isAuthenticated) { requireAuth(() => undefined) return } try { const images = await Promise.all(imageFiles.map((file) => uploadFile(file, "post"))) await createPost({ title: data.title, content: data.content, images, tags: selectedTags, linkedOrderId: effectivePostType === "show_order" ? selectedOrderId : undefined, }) notifySuccess("帖子已发布") router.push("/community") } catch (error) { notifyInfo(toApiError(error).msg) } } return (
返回社区 发布帖子
{effectivePostType === "show_order" && (
)}
{errors.title &&

{errors.title.message}

}