import { FileInput, Stack, TextInput, Textarea, Checkbox } from "@mantine/core"; import { useForm, UseFormInput } from "@mantine/form"; import { LinkIcon } from "@phosphor-icons/react"; import SlidePanel, { SlidePanelField } from "@/components/sheet/slide-panel"; import { TournamentInput } from "@/features/tournaments/types"; import { isNotEmpty } from "@mantine/form"; import useCreateTournament from "../hooks/use-create-tournament"; import useUpdateTournament from "../hooks/use-update-tournament"; import toast from "@/lib/sonner"; import { logger } from ".."; import { useQueryClient } from "@tanstack/react-query"; import { tournamentKeys } from "@/features/tournaments/queries"; import { useCallback } from "react"; import { DateTimePicker } from "@/components/date-time-picker"; interface TournamentFormProps { close: () => void; initialValues?: Partial; tournamentId?: string; } const TournamentForm = ({ close, initialValues, tournamentId, }: TournamentFormProps) => { const isEditMode = !!tournamentId; const config: UseFormInput = { initialValues: { name: initialValues?.name || "", location: initialValues?.location || "", desc: initialValues?.desc || "", start_time: initialValues?.start_time || "", enroll_time: initialValues?.enroll_time || "", end_time: initialValues?.end_time || "", logo: undefined, regional: initialValues?.regional || false, }, onSubmitPreventDefault: "always", validate: { name: isNotEmpty("Name is required"), location: isNotEmpty("Location is required"), start_time: isNotEmpty("Start time is required"), enroll_time: isNotEmpty("Enrollment time is required"), }, }; const form = useForm(config); const queryClient = useQueryClient(); const { mutate: createTournament, isPending: createPending } = useCreateTournament(); const { mutate: updateTournament, isPending: updatePending } = useUpdateTournament(tournamentId || ""); const isPending = createPending || updatePending; const handleSubmit = useCallback( async (values: TournamentInput) => { const { logo, ...tournamentData } = values; const mutation = isEditMode ? updateTournament : createTournament; const successMessage = isEditMode ? "Tournament updated successfully!" : "Tournament created successfully!"; const errorMessage = isEditMode ? "Failed to update tournament" : "Failed to create tournament"; mutation(tournamentData, { onSuccess: async (tournament) => { if (logo && tournament) { try { const formData = new FormData(); formData.append("tournamentId", tournament.id); formData.append("logo", logo); const response = await fetch("/api/tournaments/upload-logo", { method: "POST", body: formData, }); if (!response.ok) { const error = await response.json(); throw new Error(error.error || "Failed to upload logo"); } const result = await response.json(); queryClient.invalidateQueries({ queryKey: tournamentKeys.list }); queryClient.invalidateQueries({ queryKey: tournamentKeys.details(result.tournament!.id), }); queryClient.setQueryData( tournamentKeys.details(result.tournament!.id), result.tournament ); toast.success(successMessage); } catch (error: any) { const logoErrorMessage = isEditMode ? `Tournament updated but logo upload failed: ${error.message}` : `Tournament created but logo upload failed: ${error.message}`; toast.error(logoErrorMessage); logger.error("Tournament logo upload error", error); } } else { toast.success(successMessage); } close(); }, onError: (error: any) => { toast.error(`${errorMessage}: ${error.message}`); logger.error( `Tournament ${isEditMode ? "update" : "create"} error`, error ); }, }); }, [isEditMode, createTournament, updateTournament, queryClient] ); return (