"use client" import { zodResolver } from "@hookform/resolvers/zod" import { useForm } 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 { Textarea } from "@/components/ui/textarea" import { toast } from "@/components/ui/use-toast" import { useSession } from "next-auth/react" import { FormEvent, Fragment, useEffect, useState } from "react" import { Icons } from "./icons" import PostItem from "./post-item" import { Card } from "./ui/card" import { Separator } from "./ui/separator" import { Skeleton } from "./ui/skeleton" const FormSchema = z.object({ gweet: z .string() .min(1, { message: "Come on post something...", }) .max(1000, { message: "Gweets cannot be more that 1000 characters.", }), }) export function PostGweets() { const [isGweetLoading, setIsGweetLoading] = useState<boolean>(false); const [isLoading, setIsLoading] = useState<boolean>(false); const [messages, setMessages] = useState<any[]>([]); const user = useSession(); useEffect(() => { fetchMessages(); }, []); const form = useForm<z.infer<typeof FormSchema>>({ resolver: zodResolver(FormSchema), }) async function onGweet(data: z.infer<typeof FormSchema>) { setIsGweetLoading(true); await fetch('/api/messages', { method: 'POST', body: JSON.stringify(data), next: { tags: ['collection'] } }) toast({ title: "Your gweet is being processed...", description: ( <pre className="mt-2 w-[340px] rounded-md bg-slate-600 p-4"> <code className="text-white">{JSON.stringify(data, null, 2)}</code> </pre> ), }) setIsGweetLoading(false); form.setValue('gweet', ''); await fetchMessages(); } async function fetchMessages() { setIsLoading(true); try { const res = await fetch(`/api/messages`); if (!res.ok) { throw new Error("Failed to fetch messages"); } const data = await res.json(); setMessages(data); } catch (error) { return toast({ variant: "destructive", title: "Uh oh! Something went wrong.", description: "Failed to fetch messages. Please try again.", }); } setIsLoading(false); } async function onSubmit(event: FormEvent<HTMLFormElement>) { event.preventDefault(); await fetchMessages(); } return ( <div> <Form {...form}> <form onSubmit={form.handleSubmit(onGweet)} className="space-y-6"> <FormField control={form.control} name="gweet" render={({ field }) => ( <FormItem> <FormLabel>Gweet</FormLabel> <FormControl> <Textarea placeholder="What's on your mind?" className="resize-none" disabled={isGweetLoading || !user.data?.user} {...field} /> </FormControl> <FormDescription> Your gweets will be public, and everyone can see them. </FormDescription> <FormMessage /> </FormItem> )} /> <Button type="submit" disabled={isGweetLoading || !user.data?.user}>Submit</Button> </form> </Form> <Card className="w-full h-full overflow-hidden p-6 md:p-12 mt-12"> <form onSubmit={onSubmit}> <Button disabled={isLoading} type="submit" className="w-full mb-6"> {isLoading && ( <Icons.spinner className="mr-2 h-4 w-4 animate-spin" /> )} Load More </Button> {messages.length > 0 ? ( messages.map((message: any) => ( <Fragment key={message.id}> <PostItem msg={message} /> <Separator className="mt-3 mb-6" /> </Fragment> )) ) : ( <> {Array.from({ length: 4 }, (_, i) => i + 1).map((i) => ( <> <div className="flex"> <Skeleton className="h-10 w-10 rounded-full" /> <div className="ml-4 flex flex-col flex-grow"> <div> <div className="flex items-center"> <div className="mx-auto w-full space-y-6"> <Skeleton className="h-[30px] w-1/4" /> <Skeleton className="h-[20px] w-2/3" /> <Skeleton className="h-[20px] w-full" /> </div> </div> </div> <div className="flex justify-end space-x-3 mt-3" > <Skeleton key={i} className="h-10 w-20 rounded-full" /> <Skeleton key={i} className="h-10 w-20 rounded-full" /> </div> </div> </div> <Separator className="mt-3 mb-6" /> </> ))} </> )} </form> </Card> </div> ) }