import { useLocation } from "wouter"; import { useForm, useFieldArray } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import * as z from "zod"; import { useCreateTool, getListToolsQueryKey, getListCategoriesQueryKey, getListAllFeaturesQueryKey, getListAllTagsQueryKey, getGetTopToolsQueryKey, getGetAnalyticsSummaryQueryKey } from "@workspace/api-client-react"; import { useQueryClient } from "@tanstack/react-query"; import { Layout } from "@/components/layout"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Textarea } from "@/components/ui/textarea"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card"; import { useToast } from "@/hooks/use-toast"; import { Wrench, Plus, X, ArrowLeft, LogIn } from "lucide-react"; import { Link } from "wouter"; import { CategoryCombobox } from "@/components/category-combobox"; import { FeatureInput } from "@/components/feature-input"; import { TagInput } from "@/components/tag-input"; import { useAuth } from "@/hooks/use-auth"; import { GuideHelp } from "@/components/guide-help"; import { useTranslation } from "react-i18next"; type ToolFormValues = z.infer>; function buildToolSchema(t: (key: string) => string) { return z.object({ name: z.string().min(2, t("toolForm.nameMin")), description: z.string().min(10, t("toolForm.descriptionMin")), category: z.string().min(2, t("toolForm.categoryRequired")), websiteUrl: z.string().url(t("toolForm.invalidUrl")).optional().or(z.literal("")), iconUrl: z.string().url(t("toolForm.invalidUrl")).optional().or(z.literal("")), features: z.array(z.object({ value: z.string() })).optional(), tags: z.array(z.object({ value: z.string() })).optional(), }); } export default function ToolNew() { const [location, setLocation] = useLocation(); const { t } = useTranslation(); const { toast } = useToast(); const queryClient = useQueryClient(); const createTool = useCreateTool(); const { isAuthenticated, isLoading: authLoading, login } = useAuth(); const toolSchema = buildToolSchema(t); const form = useForm({ resolver: zodResolver(toolSchema), defaultValues: { name: "", description: "", category: "", websiteUrl: "", iconUrl: "", features: [{ value: "" }], tags: [{ value: "" }], }, }); const { fields: featureFields, append: appendFeature, remove: removeFeature } = useFieldArray({ control: form.control, name: "features", }); const { fields: tagFields, append: appendTag, remove: removeTag } = useFieldArray({ control: form.control, name: "tags", }); const onSubmit = (data: ToolFormValues) => { const payload = { ...data, websiteUrl: data.websiteUrl || undefined, iconUrl: data.iconUrl || undefined, features: data.features?.map((f) => f.value).filter((v) => v.trim() !== ""), tags: data.tags?.map((t) => t.value).filter((v) => v.trim() !== ""), }; createTool.mutate( { data: payload }, { onSuccess: (newTool) => { toast({ title: t("toolForm.toastAdded"), description: t("toolForm.toastAddedSub") }); queryClient.invalidateQueries({ queryKey: getListToolsQueryKey() }); queryClient.invalidateQueries({ queryKey: getListCategoriesQueryKey() }); queryClient.invalidateQueries({ queryKey: getListAllFeaturesQueryKey() }); queryClient.invalidateQueries({ queryKey: getListAllTagsQueryKey() }); queryClient.invalidateQueries({ queryKey: getGetTopToolsQueryKey() }); queryClient.invalidateQueries({ queryKey: getGetAnalyticsSummaryQueryKey() }); setLocation(`/tools/${newTool.id}`); }, onError: () => { toast({ title: t("toolForm.toastAddFailed"), description: t("detail.unexpectedError"), variant: "destructive" }); }, }, ); }; return (

{t("toolForm.addTitle")}

{t("toolForm.addSubtitle")}

{!authLoading && !isAuthenticated && (

{t("toolForm.signInRequired")}

{t("toolForm.signInRequiredSub")}

)}
{t("toolForm.toolDetails")} {t("toolForm.toolDetailsNewSub")}
( {t("toolForm.name")} )} /> ( {t("toolForm.category")} )} />
( {t("toolForm.websiteUrlOptional")} )} /> ( {t("toolForm.iconUrlOptional")}
{field.value ? ( {t("toolForm.iconPreview")} { (e.target as HTMLImageElement).style.display = "none"; }} /> ) : ( {t("toolForm.name").charAt(0)} )}
)} /> ( {t("toolForm.description")}