Skip to content
Snippets Groups Projects
post-gweets.tsx 5.19 KiB
Newer Older
Yusuf Akgül's avatar
Yusuf Akgül committed
"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>
  )
}