diff --git a/src/app/(auth)/community/[id]/edit/page.tsx b/src/app/(auth)/community/[id]/edit/page.tsx index 39e3107..87daaa9 100644 --- a/src/app/(auth)/community/[id]/edit/page.tsx +++ b/src/app/(auth)/community/[id]/edit/page.tsx @@ -1,21 +1,43 @@ "use client"; -import { - useSuspenseQuery, -} from "@tanstack/react-query"; +import { useSuspenseQuery } from "@tanstack/react-query"; import { listCommunitiesQuery } from "@/lib/api"; +import { useFormState, useFormStatus } from "react-dom"; +import { updateCommunity } from "@/app/actions"; +import CommunityForm from "@/components/organisms/forms/community-form"; + +const defaultState: ReturnType = Promise.resolve({ + ok: false, +}); export default function CommunityDetailsPage({ params, }: { params: { id: string }; }) { - console.log("details page", params.id); const { data, isLoading } = useSuspenseQuery(listCommunitiesQuery); const community = data?.data?.find((com) => com.id === parseInt(params.id)); - console.log('details', { community, id: params.id }) + const [state, formAction] = useFormState>( + updateCommunity, + defaultState + ); + + const { pending } = useFormStatus(); + + console.log("details", { community, id: params.id }); + if (isLoading || !community) { + return
Loading...
; + } return ( -

Edit: {community?.name}

+ { + formdata.append("communityId", community.id.toString()); + formAction(formdata); + }} + state={state} + defaultValues={community} + pending={pending} + /> ); } diff --git a/src/app/(auth)/community/new/page.tsx b/src/app/(auth)/community/new/page.tsx index 479f0b1..61137ba 100644 --- a/src/app/(auth)/community/new/page.tsx +++ b/src/app/(auth)/community/new/page.tsx @@ -1,401 +1,35 @@ "use client"; -import { zodResolver } from "@hookform/resolvers/zod"; -import { useForm, useFieldArray } from "react-hook-form"; -import * as z from "zod"; -import { Button } from "@/components/ui/button"; -import { - Form, - FormControl, - FormDescription, - FormField, - FormItem, - FormLabel, - FormMessage, -} from "@/components/ui/form"; -import { Input } from "@/components/ui/input"; -import { Textarea } from "@/components/ui/textarea"; -import { Switch } from "@/components/ui/switch"; -import { X } from "lucide-react"; -import { Layout, LayoutBody } from "@/components/custom/Layout"; import { useFormState, useFormStatus } from "react-dom"; import { createCommunity } from "@/app/actions"; -import { useEffect } from "react"; -import { getQueryClient } from "@/lib/get-query-client"; -import { tags } from "@/lib/tags"; +import CommunityForm from "@/components/organisms/forms/community-form"; -const MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB -const ACCEPTED_IMAGE_TYPES = [ - "image/jpeg", - "image/png", - "image/webp", - "image/gif", -]; - -const addCommunitySchema = z.object({ - name: z.string().min(1, "Name is required"), - subtitle: z.string().min(1, "Subtitle cannot be empty"), - description: z.string().min(1, "Description cannot be empty"), - hidden: z.boolean().default(false), - keywords: z - .array(z.string()) - .min(1, "Community must have at least one keyword"), - imageUrl: z.string().url().optional(), - image: z - .any() - .refine((files) => files?.length == 1, "Image is required.") - .refine( - (files) => files?.[0]?.size <= MAX_FILE_SIZE, - `Max file size is 5MB.` - ) - .refine( - (files) => ACCEPTED_IMAGE_TYPES.includes(files?.[0]?.type), - ".jpg, .jpeg, .png, .webp and .gif files are accepted." - ) - .optional(), - slug: z.string().min(3), - links: z.array(z.string().url()).min(1, "At least one link is required"), -}); - -type FormValues = z.infer; - -const initialState: ReturnType = Promise.resolve({ +const defaultState: ReturnType = Promise.resolve({ ok: false, }); -export default function CommunityForm() { +export default function Page() { const [state, formAction] = useFormState>( createCommunity, - initialState + defaultState ); - const formState = state as unknown as Awaited< - ReturnType - >; - const { pending } = useFormStatus(); - - const form = useForm({ - resolver: zodResolver(addCommunitySchema), - defaultValues: { - name: "", - subtitle: "", - description: "", - hidden: false, - keywords: [], - slug: "", - links: [""], - }, - }); - - const { - fields: keywordFields, - append: appendKeyword, - remove: removeKeyword, - } = useFieldArray({ - control: form.control, - name: "keywords", - }); - - const { - fields: linkFields, - append: appendLink, - remove: removeLink, - } = useFieldArray({ - control: form.control, - name: "links", - }); - - function onSubmit(data: FormValues) { - const formData = new FormData(); - - // Append simple fields - formData.append("name", data.name); - formData.append("subtitle", data.subtitle); - formData.append("description", data.description); - formData.append("hidden", data.hidden.toString()); - formData.append("slug", data.slug); - - // Append array fields - data.keywords.forEach((keyword, index) => { - formData.append(`keywords[${index}]`, keyword); - }); - data.links.forEach((link, index) => { - formData.append(`links[${index}]`, link); - }); - - // Append optional fields - if (data.imageUrl) { - formData.append("imageUrl", data.imageUrl); - } - - // Append file if it exists - if (data.image && data.image[0]) { - formData.append("image", data.image[0]); - } - - // Log the FormData (for demonstration purposes) - Array.from(formData.entries()).forEach(([key, value]) => { - console.log(`${key}: ${value}`); - }); - - formAction(formData); - } - - useEffect(() => { - if (formState?.ok) { - form.reset(); - // todo: show success toast - } - }, [form, formState]); + const { pending } = useFormStatus(); return ( - - -
-
-

- Complete this form to add a new Community -

-
-
-
- - ( - - Name - - - - - - )} - /> - ( - - Slug - - - - - The unique identifier for your community in the URL - - - - )} - /> - ( - - Subtitle - - - - - - )} - /> - ( - - Description - -