diff --git a/app/api/auth/[...nextauth]/route.ts b/app/api/auth/[...nextauth]/route.ts
index 1e590ee..dab5c35 100644
--- a/app/api/auth/[...nextauth]/route.ts
+++ b/app/api/auth/[...nextauth]/route.ts
@@ -1,4 +1,4 @@
-import NextAuth, {AuthOptions as NextAuthOptions} from "next-auth";
+import NextAuth, { AuthOptions as NextAuthOptions } from "next-auth";
import { PrismaAdapter } from "@next-auth/prisma-adapter";
import prisma from "@/lib/prisma";
import GoogleProvider from "next-auth/providers/google";
@@ -13,8 +13,8 @@ export const authOptions: NextAuthOptions = {
}),
GitHubProvider({
clientId: process.env.GITHUB_ID as string,
- clientSecret: process.env.GITHUB_SECRET as string
- })
+ clientSecret: process.env.GITHUB_SECRET as string,
+ }),
],
// callbacks: {
// jwt({ token, account, user }) {
@@ -52,7 +52,7 @@ export const authOptions: NextAuthOptions = {
},
},
session: {
- strategy: 'jwt',
+ strategy: "jwt",
},
};
diff --git a/app/api/quiz/[id]/route.ts b/app/api/quiz/[id]/route.ts
index 100b4f7..5305a19 100644
--- a/app/api/quiz/[id]/route.ts
+++ b/app/api/quiz/[id]/route.ts
@@ -1,18 +1,21 @@
-import {NextRequest, NextResponse} from "next/server";
+import { NextRequest, NextResponse } from "next/server";
import prisma from "@/lib/prisma";
-export async function GET(req: NextRequest, context: { params: { id: string } }) {
- const id = context.params.id;
+export async function GET(
+ req: NextRequest,
+ context: { params: { id: string } },
+) {
+ const id = context.params.id;
- const quiz = await prisma.quiz.findUnique({
- where: {
- id
- },
- include: {
- words: true
- }
- });
- console.log("loaded quiz with id: " + id)
- return NextResponse.json(quiz)
-}
\ No newline at end of file
+ const quiz = await prisma.quiz.findUnique({
+ where: {
+ id,
+ },
+ include: {
+ words: true,
+ },
+ });
+ console.log("loaded quiz with id: " + id);
+ return NextResponse.json(quiz);
+}
diff --git a/app/api/quiz/route.ts b/app/api/quiz/route.ts
index 91d2681..c01d9c5 100644
--- a/app/api/quiz/route.ts
+++ b/app/api/quiz/route.ts
@@ -19,49 +19,49 @@
// // });
// }
-import {NextRequest, NextResponse} from "next/server";
+import { NextRequest, NextResponse } from "next/server";
import prisma from "@/lib/prisma";
-import {getServerSession} from "next-auth/next";
-import {authOptions} from "@/app/api/auth/[...nextauth]/route";
+import { getServerSession } from "next-auth/next";
+import { authOptions } from "@/app/api/auth/[...nextauth]/route";
// export const runtime = "edge";
export async function POST(req: NextRequest) {
- console.time("quiz")
+ console.time("quiz");
- const { name, words } = await req.json();
- const session = await getServerSession(authOptions) as any;
- // console.log(session)
+ const { name, words } = await req.json();
+ const session = (await getServerSession(authOptions)) as any;
+ // console.log(session)
- if (!session) {
- return NextResponse.json("Unauthorized", {
- status: 401
- })
- }
-
- console.log(session.user.id)
- const newQuiz = await prisma.quiz.create({
- data: {
- name,
- words: {
- create: words
- },
- user: {
- connect: {
- id: session.user.id
- }
- }
- }
+ if (!session) {
+ return NextResponse.json("Unauthorized", {
+ status: 401,
});
+ }
+
+ console.log(session.user.id);
+ const newQuiz = await prisma.quiz.create({
+ data: {
+ name,
+ words: {
+ create: words,
+ },
+ user: {
+ connect: {
+ id: session.user.id,
+ },
+ },
+ },
+ });
- console.timeEnd("quiz")
+ console.timeEnd("quiz");
- return NextResponse.json(newQuiz)
- // return NextResponse.json({})
+ return NextResponse.json(newQuiz);
+ // return NextResponse.json({})
}
export async function GET() {
- const quizzes = await prisma.quiz.findMany();
- return NextResponse.json(quizzes)
-}
\ No newline at end of file
+ const quizzes = await prisma.quiz.findMany();
+ return NextResponse.json(quizzes);
+}
diff --git a/app/globals.css b/app/globals.css
index 5b2550a..f83d438 100644
--- a/app/globals.css
+++ b/app/globals.css
@@ -1,7 +1,7 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
-
+
@layer base {
:root {
--background: 0 0% 100%;
@@ -9,63 +9,63 @@
--card: 0 0% 100%;
--card-foreground: 222.2 84% 4.9%;
-
+
--popover: 0 0% 100%;
--popover-foreground: 222.2 84% 4.9%;
-
+
--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;
-
+
--secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%;
-
+
--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;
-
+
--accent: 210 40% 96.1%;
--accent-foreground: 222.2 47.4% 11.2%;
-
+
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 40% 98%;
--border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%;
--ring: 222.2 84% 4.9%;
-
+
--radius: 0.5rem;
}
-
+
.dark {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;
-
+
--card: 222.2 84% 4.9%;
--card-foreground: 210 40% 98%;
-
+
--popover: 222.2 84% 4.9%;
--popover-foreground: 210 40% 98%;
-
+
--primary: 210 40% 98%;
--primary-foreground: 222.2 47.4% 11.2%;
-
+
--secondary: 217.2 32.6% 17.5%;
--secondary-foreground: 210 40% 98%;
-
+
--muted: 217.2 32.6% 17.5%;
--muted-foreground: 215 20.2% 65.1%;
-
+
--accent: 217.2 32.6% 17.5%;
--accent-foreground: 210 40% 98%;
-
+
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 210 40% 98%;
-
+
--border: 217.2 32.6% 17.5%;
--input: 217.2 32.6% 17.5%;
--ring: 212.7 26.8% 83.9%;
}
}
-
+
@layer base {
* {
@apply border-border;
@@ -83,4 +83,4 @@ body {
html body {
overflow: initial !important;
-}
\ No newline at end of file
+}
diff --git a/app/layout.tsx b/app/layout.tsx
index 46d512f..669719a 100644
--- a/app/layout.tsx
+++ b/app/layout.tsx
@@ -1,49 +1,47 @@
import "./globals.css";
-import {Analytics} from "@vercel/analytics/react";
+import { Analytics } from "@vercel/analytics/react";
import Nav from "@/components/layout/nav";
import React from "react";
-import {ThemeProvider} from "@/components/theme-provider";
-import {inter, sfPro} from "@/app/fonts";
-import {cx} from "class-variance-authority";
+import { ThemeProvider } from "@/components/theme-provider";
+import { inter, sfPro } from "@/app/fonts";
+import { cx } from "class-variance-authority";
import { Toaster } from "@/components/ui/toaster";
export const metadata = {
+ title: "NextQuiz",
+ description:
+ "NextQuiz is a quiz app built with Next.js, Prisma, and Tailwind CSS.",
+ twitter: {
+ card: "summary_large_image",
title: "NextQuiz",
description:
- "NextQuiz is a quiz app built with Next.js, Prisma, and Tailwind CSS.",
- twitter: {
- card: "summary_large_image",
- title: "NextQuiz",
- description:
- "NextQuiz is a quiz app built with Next.js, Prisma, and Tailwind CSS.",
- creator: "@davide_marcoli",
- },
- metadataBase: new URL("https://next-quiz.davidemarcoli.dev"),
- themeColor: "#000000",
+ "NextQuiz is a quiz app built with Next.js, Prisma, and Tailwind CSS.",
+ creator: "@davide_marcoli",
+ },
+ metadataBase: new URL("https://next-quiz.davidemarcoli.dev"),
+ themeColor: "#000000",
};
export default async function RootLayout({
- children,
- }: {
- children: React.ReactNode;
+ children,
+}: {
+ children: React.ReactNode;
}) {
- return (
- <>
-
-
-
- {/**/}
- {/* @ts-expect-error Server Component */}
-
- {/**/}
-
- {children}
-
-
-
-
-
-
- >
- );
+ return (
+ <>
+
+
+
+ {/**/}
+ {/* @ts-expect-error Server Component */}
+
+ {/**/}
+ {children}
+
+
+
+
+
+ >
+ );
}
diff --git a/app/opengraph-image.tsx b/app/opengraph-image.tsx
index c80df74..ceec14c 100644
--- a/app/opengraph-image.tsx
+++ b/app/opengraph-image.tsx
@@ -6,9 +6,9 @@ export const alt = "Next Quiz";
export const contentType = "image/png";
export default async function OG() {
- const sfPro = await fetch(
- new URL("./fonts/SF-Pro-Display-Medium.otf", import.meta.url),
- ).then((res) => res.arrayBuffer());
+ // const sfPro = await fetch(
+ // new URL("./fonts/SF-Pro-Display-Medium.otf", import.meta.url),
+ // ).then((res) => res.arrayBuffer());
return new ImageResponse(
(
@@ -42,19 +42,19 @@ export default async function OG() {
letterSpacing: "-0.02em",
}}
>
- Next Quiz
+ Next Quiz
),
{
width: 1200,
height: 630,
- fonts: [
- {
- name: "SF Pro",
- data: sfPro,
- },
- ],
+ // fonts: [
+ // {
+ // name: "SF Pro",
+ // data: sfPro,
+ // },
+ // ],
},
);
}
diff --git a/app/page.tsx b/app/page.tsx
index 47ab3cc..6f8ad5a 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -1,12 +1,10 @@
import ListQuiz from "@/app/quiz/list/page";
export default async function Home() {
-
-
return (
- <>
- {/* @ts-expect-error Server Component */}
-
- >
+ <>
+ {/* @ts-expect-error Server Component */}
+
+ >
);
}
diff --git a/app/quiz/[id]/cards/page.tsx b/app/quiz/[id]/cards/page.tsx
index 533dd4c..c69dad2 100644
--- a/app/quiz/[id]/cards/page.tsx
+++ b/app/quiz/[id]/cards/page.tsx
@@ -1,27 +1,29 @@
"use client";
-import {Quiz, QuizWord} from "@prisma/client";
-import {useEffect, useState} from "react";
-import {Card, CardContent, CardTitle} from "@/components/ui/card";
-import {Button} from "@/components/ui/button";
-import {Shuffle} from "lucide-react";
-import {timeout} from "rxjs";
+import { Quiz, QuizWord } from "@prisma/client";
+import { useEffect, useState } from "react";
+import { Card, CardContent, CardTitle } from "@/components/ui/card";
+import { Button } from "@/components/ui/button";
+import { Shuffle } from "lucide-react";
+import { timeout } from "rxjs";
-async function getQuizWithWords(id: string): Promise {
- // return await prisma.quiz.findFirst({
- // where: {id: id}, include: {
- // words: true
- // }
- // });
+async function getQuizWithWords(
+ id: string,
+): Promise<(Quiz & { words: QuizWord[] }) | null> {
+ // return await prisma.quiz.findFirst({
+ // where: {id: id}, include: {
+ // words: true
+ // }
+ // });
- console.log(`Getting quiz with id ${id}`)
- return await fetch('/api/quiz/' + id, {
- method: 'GET',
- cache: 'no-cache',
- }).then(value => {
- console.log('value', value.ok)
- return value.json()
- });
+ console.log(`Getting quiz with id ${id}`);
+ return await fetch("/api/quiz/" + id, {
+ method: "GET",
+ cache: "no-cache",
+ }).then((value) => {
+ console.log("value", value.ok);
+ return value.json();
+ });
}
// function WordCard({cardData, isFlipped}: { cardData: QuizWord, isFlipped: boolean }) {
@@ -39,77 +41,107 @@ async function getQuizWithWords(id: string): Promise(null);
- const [isLoading, setLoading] = useState(true)
- const [animateFlip, setAnimateFlip] = useState(true);
-
- useEffect(() => {
- console.log('useEffect', params.id)
- getQuizWithWords(params.id).then(value => {
- console.log('value 2', value);
- setFullQuiz(value);
- setLoading(false);
- }).catch(reason => {
- console.log('reason', reason);
- });
- }, []);
+ const [currentCard, setCurrentCard] = useState(0);
+ const [isFlipped, setIsFlipped] = useState(false);
+ const [fullQuiz, setFullQuiz] = useState<
+ (Quiz & { words: QuizWord[] }) | null
+ >(null);
+ const [isLoading, setLoading] = useState(true);
+ const [animateFlip, setAnimateFlip] = useState(true);
- console.log(isLoading)
- if (isLoading) return Loading...
- if (!fullQuiz) return Quiz Words not found
+ useEffect(() => {
+ console.log("useEffect", params.id);
+ getQuizWithWords(params.id)
+ .then((value) => {
+ console.log("value 2", value);
+ setFullQuiz(value);
+ setLoading(false);
+ })
+ .catch((reason) => {
+ console.log("reason", reason);
+ });
+ }, []);
- function changeCard(indexChange: number) {
- setAnimateFlip(false); // Disable flip animation
- setIsFlipped(false);
+ console.log(isLoading);
+ if (isLoading) return Loading...
;
+ if (!fullQuiz) return Quiz Words not found
;
- console.log('changeCard', indexChange);
- if (currentCard + indexChange < 0) {
- setCurrentCard(fullQuiz!.words.length - 1);
- } else if (currentCard + indexChange >= fullQuiz!.words.length) {
- setCurrentCard(0);
- } else {
- setCurrentCard(currentCard + indexChange);
- }
+ function changeCard(indexChange: number) {
+ setAnimateFlip(false); // Disable flip animation
+ setIsFlipped(false);
+ console.log("changeCard", indexChange);
+ if (currentCard + indexChange < 0) {
+ setCurrentCard(fullQuiz!.words.length - 1);
+ } else if (currentCard + indexChange >= fullQuiz!.words.length) {
+ setCurrentCard(0);
+ } else {
+ setCurrentCard(currentCard + indexChange);
}
+ }
- return (
- <>
- {fullQuiz.name}
- {
- setIsFlipped(!isFlipped)
- setAnimateFlip(true); // Enable flip animation
- }}>
- {/**/}
-
- {/**/}
- {fullQuiz.words[currentCard].term}
- {fullQuiz.words[currentCard].definition}
- {/**/}
-
-
-
-
-
- >
- );
+ return (
+ <>
+ {fullQuiz.name}
+ {
+ setIsFlipped(!isFlipped);
+ setAnimateFlip(true); // Enable flip animation
+ }}
+ >
+ {/**/}
+
+ {/**/}
+
+ {fullQuiz.words[currentCard].term}
+
+
+ {fullQuiz.words[currentCard].definition}
+
+ {/**/}
+
+
+
+
+
+ >
+ );
}
diff --git a/app/quiz/[id]/page.tsx b/app/quiz/[id]/page.tsx
index 0d612a1..bd9d0c5 100644
--- a/app/quiz/[id]/page.tsx
+++ b/app/quiz/[id]/page.tsx
@@ -1,95 +1,102 @@
-import {Quiz, QuizWord} from "@prisma/client";
+import { Quiz, QuizWord } from "@prisma/client";
import prisma from "@/lib/prisma";
-import {Suspense} from "react";
-import {Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle} from "@/components/ui/card";
-import {Button} from "@/components/ui/button";
+import { Suspense } from "react";
+import {
+ Card,
+ CardContent,
+ CardDescription,
+ CardFooter,
+ CardHeader,
+ CardTitle,
+} from "@/components/ui/card";
+import { Button } from "@/components/ui/button";
import Link from "next/link";
async function getQuiz(id: string): Promise {
- console.log(`Getting small quiz with id ${id}`)
- return await prisma.quiz.findFirst({where: {id: id}});
+ console.log(`Getting small quiz with id ${id}`);
+ return await prisma.quiz.findFirst({ where: { id: id } });
}
-async function getQuizWithWords(id: string): Promise {
- // return await prisma.quiz.findFirst({
- // where: {id: id}, include: {
- // words: true
- // }
- // });
+async function getQuizWithWords(
+ id: string,
+): Promise<(Quiz & { words: QuizWord[] }) | null> {
+ // return await prisma.quiz.findFirst({
+ // where: {id: id}, include: {
+ // words: true
+ // }
+ // });
- console.log(`Getting quiz with id ${id}`)
+ console.log(`Getting quiz with id ${id}`);
- console.time('quiz');
- const quiz = await prisma.quiz.findFirst({
- where: {id: id},
- include: {
- words: true
- }
- });
- console.timeEnd('quiz');
- console.log(`This quiz has ${quiz?.words.length} words`);
- return quiz;
+ console.time("quiz");
+ const quiz = await prisma.quiz.findFirst({
+ where: { id: id },
+ include: {
+ words: true,
+ },
+ });
+ console.timeEnd("quiz");
+ console.log(`This quiz has ${quiz?.words.length} words`);
+ return quiz;
}
-export default async function Page({params}: { params: { id: string } }) {
- console.log(params)
- const quiz = await getQuiz(params.id);
+export default async function Page({ params }: { params: { id: string } }) {
+ console.log(params);
+ const quiz = await getQuiz(params.id);
- if (!quiz) {
- return Quiz not found
- }
+ if (!quiz) {
+ return Quiz not found
;
+ }
- return (
- <>
- {quiz.name}
- Loading Words...}>
- {/* @ts-expect-error Server Component */}
-
-
- >
- )
+ return (
+ <>
+ {quiz.name}
+ Loading Words...}>
+ {/* @ts-expect-error Server Component */}
+
+
+ >
+ );
}
-async function ShowQuiz({params}: { params: { id: string } }) {
+async function ShowQuiz({ params }: { params: { id: string } }) {
+ const fullQuiz = await getQuizWithWords(params.id);
+ if (!fullQuiz) {
+ return Quiz Words not found
;
+ }
- const fullQuiz = await getQuizWithWords(params.id);
-
- if (!fullQuiz) {
- return Quiz Words not found
- }
-
- return (
- <>
-
-
-
-
- {fullQuiz.words.map((word) => {
- return (
- //
- //
{word.term}
- //
{word.definition}
- //
-
-
- {word.id}
- {/*Card Description*/}
-
-
- {word.term}
- {word.definition}
-
- {/**/}
- {/* Card Footer
*/}
- {/**/}
-
- );
- })}
-
- >
- );
+ return (
+ <>
+
+
+
+
+ {fullQuiz.words.map((word) => {
+ return (
+ //
+ //
{word.term}
+ //
{word.definition}
+ //
+
+
+ {word.id}
+ {/*Card Description*/}
+
+
+ {word.term}
+ {word.definition}
+
+ {/**/}
+ {/* Card Footer
*/}
+ {/**/}
+
+ );
+ })}
+
+ >
+ );
}
diff --git a/app/quiz/create/page.tsx b/app/quiz/create/page.tsx
index f89b8e2..f494839 100644
--- a/app/quiz/create/page.tsx
+++ b/app/quiz/create/page.tsx
@@ -1,211 +1,226 @@
-"use client"
+"use client";
-import {useState} from "react";
+import { useState } from "react";
-import * as z from "zod"
-import {useForm} from "react-hook-form";
-import {zodResolver} from "@hookform/resolvers/zod";
+import * as z from "zod";
+import { useForm } from "react-hook-form";
+import { zodResolver } from "@hookform/resolvers/zod";
import {
- Form,
- FormControl,
- FormDescription,
- FormField,
- FormItem,
- FormLabel,
- FormMessage,
-} from "@/components/ui/form"
-import { Input } from "@/components/ui/input"
+ Form,
+ FormControl,
+ FormDescription,
+ FormField,
+ FormItem,
+ FormLabel,
+ FormMessage,
+} from "@/components/ui/form";
+import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
-import {Textarea} from "@/components/ui/textarea";
+import { Textarea } from "@/components/ui/textarea";
import { RadioGroupItem } from "@/components/ui/radio-group";
import { Label } from "@/components/ui/label";
import { RadioGroup } from "@radix-ui/react-radio-group";
import { useToast } from "@/components/ui/use-toast";
const formSchema = z.object({
- quizName: z.string(),
- csvWords: z.string(),
- separator: z.string(),
-})
+ quizName: z.string(),
+ csvWords: z.string(),
+ separator: z.string(),
+});
export default function CreateQuiz() {
-
- const { toast } = useToast()
-
- // 1. Define your form.
- const form = useForm>({
- resolver: zodResolver(formSchema),
- defaultValues: {
- quizName: "",
- csvWords: "",
- separator: "\t",
- },
+ const { toast } = useToast();
+
+ // 1. Define your form.
+ const form = useForm>({
+ resolver: zodResolver(formSchema),
+ defaultValues: {
+ quizName: "",
+ csvWords: "",
+ separator: "\t",
+ },
+ });
+
+ // const [formData, setFormData] = useState({
+ // quizName: "",
+ // csvWords: "",
+ // separator: "\t",
+ // });
+ //
+ // function handleInput(event: any) {
+ // const {name, value} = event.target;
+ // setFormData((prev) => ({...prev, [name]: value}));
+ // }
+ //
+ // function handleSeparator(newSeparator: string) {
+ // setFormData((prev) => ({...prev, separator: newSeparator}));
+ // }
+
+ function onSubmit(values: z.infer) {
+ console.log(values);
+
+ // parse seperator
+ values.separator =
+ values.separator === "tab"
+ ? "\t"
+ : values.separator === "comma"
+ ? ","
+ : ";";
+
+ // formData.csvWords is a csv string which is split by a tab
+ // each line is a word and its definition
+ const lines = values.csvWords.split("\n");
+ console.log(lines);
+ const words = lines.map((line: string) => {
+ const [term, definition] = line.split(values.separator);
+ return {
+ term,
+ definition,
+ };
+ });
+
+ console.table(words);
+
+ fetch("/api/quiz", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({
+ name: values.quizName,
+ words,
+ }),
})
-
- // const [formData, setFormData] = useState({
- // quizName: "",
- // csvWords: "",
- // separator: "\t",
- // });
- //
- // function handleInput(event: any) {
- // const {name, value} = event.target;
- // setFormData((prev) => ({...prev, [name]: value}));
- // }
- //
- // function handleSeparator(newSeparator: string) {
- // setFormData((prev) => ({...prev, separator: newSeparator}));
- // }
-
- function onSubmit(values: z.infer) {
- console.log(values)
-
- // parse seperator
- values.separator = values.separator === "tab" ? "\t" : values.separator === "comma" ? "," : ";"
-
- // formData.csvWords is a csv string which is split by a tab
- // each line is a word and its definition
- const lines = values.csvWords.split("\n");
- console.log(lines);
- const words = lines.map((line: string) => {
- const [term, definition] = line.split(values.separator);
- return {
- term,
- definition,
- };
- });
-
- console.table(words);
-
- fetch("/api/quiz", {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- },
- body: JSON.stringify({
- name: values.quizName,
- words
- })
- }).then(r => r.json()).then(r => {
- console.log(r)
- toast({
- title: "Quiz created",
- description: "Your quiz has been created",
- })
+ .then((r) => r.json())
+ .then((r) => {
+ console.log(r);
+ toast({
+ title: "Quiz created",
+ description: "Your quiz has been created",
});
- }
-
- return (
- <>
-
-
-
-
- Get started by creating a quiz
-
-
- {/* */}
-
- {/* */}
- {/* Separator:*/}
- {/* */}
- {/* */}
- {/* */}
- {/*
*/}
-
- {/*
-
- >
- );
-}
\ No newline at end of file
+ });
+ }
+
+ return (
+ <>
+
+
+
+ Get started by creating a quiz
+
+ {/* */}
+
+ {/* */}
+ {/* Separator:*/}
+ {/* */}
+ {/* */}
+ {/* */}
+ {/*
*/}
+
+ {/*
+
+ >
+ );
+}
diff --git a/app/quiz/list/page.tsx b/app/quiz/list/page.tsx
index a07d795..77bbf60 100644
--- a/app/quiz/list/page.tsx
+++ b/app/quiz/list/page.tsx
@@ -1,52 +1,60 @@
-import {Quiz} from "@prisma/client";
+import { Quiz } from "@prisma/client";
import Balancer from "react-wrap-balancer";
import ReactMarkdown from "react-markdown";
import Link from "next/link";
import prisma from "@/lib/prisma";
-import {Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle} from "@/components/ui/card";
+import {
+ Card,
+ CardContent,
+ CardDescription,
+ CardFooter,
+ CardHeader,
+ CardTitle,
+} from "@/components/ui/card";
async function getQuizzes(): Promise {
- return await prisma.quiz.findMany();
+ return await prisma.quiz.findMany();
}
export default async function ListQuiz() {
+ const quizzes = await getQuizzes();
- const quizzes = await getQuizzes();
-
- return (
-
- {quizzes.map(value => {
- return <>
- {/*
>}*/}
- {/* large={true}*/}
- {/*/>*/}
-
- {/**/}
- {/*
*/}
- {/* {value.name}*/}
- {/*
*/}
- {/**/}
-
-
- {value.name}
- {/*Card Description*/}
-
- {/**/}
- {/* Card Content
*/}
- {/**/}
- {/**/}
- {/* Card Footer
*/}
- {/**/}
-
-
- >
- })}
-
- );
-}
\ No newline at end of file
+ return (
+
+ {quizzes.map((value) => {
+ return (
+ <>
+ {/*
>}*/}
+ {/* large={true}*/}
+ {/*/>*/}
+
+ {/**/}
+ {/*
*/}
+ {/* {value.name}*/}
+ {/*
*/}
+ {/**/}
+
+
+ {value.name}
+ {/*Card Description*/}
+
+ {/**/}
+ {/* Card Content
*/}
+ {/**/}
+ {/**/}
+ {/* Card Footer
*/}
+ {/**/}
+
+
+ >
+ );
+ })}
+
+ );
+}
diff --git a/components.json b/components.json
index 48c34e4..fd5076f 100644
--- a/components.json
+++ b/components.json
@@ -13,4 +13,4 @@
"components": "@/components",
"utils": "@/lib/utils"
}
-}
\ No newline at end of file
+}
diff --git a/components/layout/Header.tsx b/components/layout/Header.tsx
index 02f2bea..93126d6 100644
--- a/components/layout/Header.tsx
+++ b/components/layout/Header.tsx
@@ -56,106 +56,103 @@
"use client";
import Link from "next/link";
-import {useTheme} from "next-themes";
-import {Button} from "@/components/ui/button";
-import {Sheet, SheetContent, SheetTrigger} from "@/components/ui/sheet";
-import {Menu} from "lucide-react";
-import {Session} from "next-auth";
+import { useTheme } from "next-themes";
+import { Button } from "@/components/ui/button";
+import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet";
+import { Menu } from "lucide-react";
+import { Session } from "next-auth";
import UserDropdown from "./user-dropdown";
-import {useSignInModal} from "./sign-in-modal";
-import {ModeToggle} from "@/components/mode-toggle";
+import { useSignInModal } from "./sign-in-modal";
+import { ModeToggle } from "@/components/mode-toggle";
-const Header = ({session}: { session: Session | null }) => {
- const {SignInModal, setShowSignInModal} = useSignInModal();
- const {theme, setTheme} = useTheme();
- const routes = [
- {
- href: "/",
- label: "Products",
- },
- {
- href: "/",
- label: "Categories",
- },
- {
- href: "/",
- label: "On Sale",
- },
- ];
+const Header = ({ session }: { session: Session | null }) => {
+ const { SignInModal, setShowSignInModal } = useSignInModal();
+ const { theme, setTheme } = useTheme();
+ const routes = [
+ {
+ href: "/",
+ label: "Products",
+ },
+ {
+ href: "/",
+ label: "Categories",
+ },
+ {
+ href: "/",
+ label: "On Sale",
+ },
+ ];
- return (
-
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
STORE NAME
+
+
+
+
+ {/*
*/}
+ {/*
*/}
+
-
-
-
-
-
-
-
-
-
-
-
-
STORE NAME
-
-
-
-
- {/*
*/}
- {/*
*/}
-
-
{
- session ? (
-
- ) : (
-
- )}
-
-
-
+ {" "}
+ {session ?
:
}
-
- );
+
+
+
+
+ );
};
-export default Header;
\ No newline at end of file
+export default Header;
diff --git a/components/layout/Header2.tsx b/components/layout/Header2.tsx
index c5d8fff..2775ba5 100644
--- a/components/layout/Header2.tsx
+++ b/components/layout/Header2.tsx
@@ -56,90 +56,83 @@
"use client";
import Link from "next/link";
-import {Button} from "@/components/ui/button";
-import {Sheet, SheetContent, SheetTrigger} from "@/components/ui/sheet";
-import {Menu} from "lucide-react";
-import {Session} from "next-auth";
+import { Button } from "@/components/ui/button";
+import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet";
+import { Menu } from "lucide-react";
+import { Session } from "next-auth";
import UserDropdown from "./user-dropdown";
-import {useSignInModal} from "./sign-in-modal";
-import {ModeToggle} from "@/components/mode-toggle";
+import { useSignInModal } from "./sign-in-modal";
+import { ModeToggle } from "@/components/mode-toggle";
import Image from "next/image";
import useScroll from "@/lib/hooks/use-scroll";
-const Header = ({session}: { session: Session | null }) => {
- const scrolled = useScroll(50);
- const {SignInModal, setShowSignInModal} = useSignInModal();
- const routes = [
- {
- href: "quiz/create",
- label: "Create Quiz",
- },
- {
- href: "quiz/list",
- label: "Quiz List",
- },
- ];
+const Header = ({ session }: { session: Session | null }) => {
+ const scrolled = useScroll(50);
+ const { SignInModal, setShowSignInModal } = useSignInModal();
+ const routes = [
+ {
+ href: "quiz/create",
+ label: "Create Quiz",
+ },
+ {
+ href: "quiz/list",
+ label: "Quiz List",
+ },
+ ];
- return (
-
- );
+ return (
+
+ );
};
-export default Header;
\ No newline at end of file
+export default Header;
diff --git a/components/layout/navbar.tsx b/components/layout/navbar.tsx
index 958ceb8..9f97d66 100644
--- a/components/layout/navbar.tsx
+++ b/components/layout/navbar.tsx
@@ -3,73 +3,65 @@
import Image from "next/image";
import Link from "next/link";
import useScroll from "@/lib/hooks/use-scroll";
-import {useSignInModal} from "./sign-in-modal";
+import { useSignInModal } from "./sign-in-modal";
import UserDropdown from "./user-dropdown";
-import {Session} from "next-auth";
-import {ModeToggle} from "@/components/mode-toggle";
-import {Button} from "@/components/ui/button";
-import {Sheet, SheetContent, SheetTrigger} from "../ui/sheet";
-import {Menu} from "lucide-react";
+import { Session } from "next-auth";
+import { ModeToggle } from "@/components/mode-toggle";
+import { Button } from "@/components/ui/button";
+import { Sheet, SheetContent, SheetTrigger } from "../ui/sheet";
+import { Menu } from "lucide-react";
-export default function NavBar({session}: { session: Session | null }) {
- const {SignInModal, setShowSignInModal} = useSignInModal();
- const scrolled = useScroll(50);
+export default function NavBar({ session }: { session: Session | null }) {
+ const { SignInModal, setShowSignInModal } = useSignInModal();
+ const scrolled = useScroll(50);
- return (
-
- );
+ return (
+
+ );
}
diff --git a/components/layout/sign-in-modal.tsx b/components/layout/sign-in-modal.tsx
index f993500..9c756c2 100644
--- a/components/layout/sign-in-modal.tsx
+++ b/components/layout/sign-in-modal.tsx
@@ -17,7 +17,7 @@ import {
DialogHeader,
DialogTitle,
DialogTrigger,
-} from "@/components/ui/dialog"
+} from "@/components/ui/dialog";
import { Button } from "../ui/button";
const SignInModal = () => {
@@ -93,47 +93,52 @@ const SignInModal = () => {
//
//
-
);
};
@@ -141,9 +146,7 @@ export function useSignInModal() {
const [showSignInModal, setShowSignInModal] = useState(false);
const SignInModalCallback = useCallback(() => {
- return (
-
- );
+ return ;
}, [showSignInModal, setShowSignInModal]);
return useMemo(
diff --git a/components/layout/user-dropdown.tsx b/components/layout/user-dropdown.tsx
index be5e7b9..dadb2f9 100644
--- a/components/layout/user-dropdown.tsx
+++ b/components/layout/user-dropdown.tsx
@@ -2,25 +2,26 @@
import { useState } from "react";
import { signOut } from "next-auth/react";
-import {LayoutDashboard, LogOut, Moon, Sun} from "lucide-react";
+import { LayoutDashboard, LogOut, Moon, Sun } from "lucide-react";
import Popover from "@/components/shared/popover";
import Image from "next/image";
import { Session } from "next-auth";
import {
DropdownMenu,
- DropdownMenuContent, DropdownMenuItem,
+ DropdownMenuContent,
+ DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
- DropdownMenuTrigger
+ DropdownMenuTrigger,
} from "../ui/dropdown-menu";
-import {Button} from "@/components/ui/button";
+import { Button } from "@/components/ui/button";
import * as React from "react";
export default function UserDropdown({ session }: { session: Session }) {
// console.log("session", session)
const { email, image } = session?.user || {};
const [openPopover, setOpenPopover] = useState(false);
-
+
return (
{/*
*/}
{/*
Toggle theme*/}
{/**/}
-
setOpenPopover(!openPopover)}
- className="flex h-8 w-8 items-center justify-center overflow-hidden rounded-full border transition-all duration-75 focus:outline-none active:scale-95 sm:h-9 sm:w-9"
- >
-
-
+
setOpenPopover(!openPopover)}
+ className="flex h-8 w-8 items-center justify-center overflow-hidden rounded-full border transition-all duration-75 focus:outline-none active:scale-95 sm:h-9 sm:w-9"
+ >
+
+
My Account
signOut()}>
{/* signOut()}>*/}
-
- Logout
+
+ Logout
{/**/}
diff --git a/components/mode-toggle.tsx b/components/mode-toggle.tsx
index 25837ad..9264016 100644
--- a/components/mode-toggle.tsx
+++ b/components/mode-toggle.tsx
@@ -1,40 +1,40 @@
-"use client"
+"use client";
-import * as React from "react"
-import { Moon, Sun } from "lucide-react"
-import { useTheme } from "next-themes"
+import * as React from "react";
+import { Moon, Sun } from "lucide-react";
+import { useTheme } from "next-themes";
-import { Button } from "@/components/ui/button"
+import { Button } from "@/components/ui/button";
import {
- DropdownMenu,
- DropdownMenuContent,
- DropdownMenuItem,
- DropdownMenuTrigger,
-} from "@/components/ui/dropdown-menu"
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuTrigger,
+} from "@/components/ui/dropdown-menu";
export function ModeToggle() {
- const { setTheme } = useTheme()
+ const { setTheme } = useTheme();
- return (
-
-
-
-
-
- Toggle theme
-
-
-
- setTheme("light")}>
- Light
-
- setTheme("dark")}>
- Dark
-
- setTheme("system")}>
- System
-
-
-
- )
+ return (
+
+
+
+
+
+ Toggle theme
+
+
+
+ setTheme("light")}>
+ Light
+
+ setTheme("dark")}>
+ Dark
+
+ setTheme("system")}>
+ System
+
+
+
+ );
}
diff --git a/components/shared/popover.tsx b/components/shared/popover.tsx
index 61a3e9b..ed195e8 100644
--- a/components/shared/popover.tsx
+++ b/components/shared/popover.tsx
@@ -37,7 +37,7 @@ export default function Popover({
{content}
diff --git a/components/shared/tooltip.tsx b/components/shared/tooltip.tsx
index 1e976ca..f2bdde5 100644
--- a/components/shared/tooltip.tsx
+++ b/components/shared/tooltip.tsx
@@ -49,7 +49,7 @@ export default function Tooltip({
{typeof content === "string" ? (
diff --git a/components/theme-provider.tsx b/components/theme-provider.tsx
index e90aa8c..b0ff266 100644
--- a/components/theme-provider.tsx
+++ b/components/theme-provider.tsx
@@ -1,9 +1,9 @@
-"use client"
+"use client";
-import * as React from "react"
-import { ThemeProvider as NextThemesProvider } from "next-themes"
-import { type ThemeProviderProps } from "next-themes/dist/types"
+import * as React from "react";
+import { ThemeProvider as NextThemesProvider } from "next-themes";
+import { type ThemeProviderProps } from "next-themes/dist/types";
export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
- return {children}
+ return {children};
}
diff --git a/components/ui/button.tsx b/components/ui/button.tsx
index ac8e0c9..29123a7 100644
--- a/components/ui/button.tsx
+++ b/components/ui/button.tsx
@@ -1,8 +1,8 @@
-import * as React from "react"
-import { Slot } from "@radix-ui/react-slot"
-import { cva, type VariantProps } from "class-variance-authority"
+import * as React from "react";
+import { Slot } from "@radix-ui/react-slot";
+import { cva, type VariantProps } from "class-variance-authority";
-import { cn } from "@/lib/utils"
+import { cn } from "@/lib/utils";
const buttonVariants = cva(
"inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
@@ -30,27 +30,27 @@ const buttonVariants = cva(
variant: "default",
size: "default",
},
- }
-)
+ },
+);
export interface ButtonProps
extends React.ButtonHTMLAttributes,
VariantProps {
- asChild?: boolean
+ asChild?: boolean;
}
const Button = React.forwardRef(
({ className, variant, size, asChild = false, ...props }, ref) => {
- const Comp = asChild ? Slot : "button"
+ const Comp = asChild ? Slot : "button";
return (
- )
- }
-)
-Button.displayName = "Button"
+ );
+ },
+);
+Button.displayName = "Button";
-export { Button, buttonVariants }
+export { Button, buttonVariants };
diff --git a/components/ui/card.tsx b/components/ui/card.tsx
index afa13ec..dc3b01d 100644
--- a/components/ui/card.tsx
+++ b/components/ui/card.tsx
@@ -1,6 +1,6 @@
-import * as React from "react"
+import * as React from "react";
-import { cn } from "@/lib/utils"
+import { cn } from "@/lib/utils";
const Card = React.forwardRef<
HTMLDivElement,
@@ -10,12 +10,12 @@ const Card = React.forwardRef<
ref={ref}
className={cn(
"rounded-lg border bg-card text-card-foreground shadow-sm",
- className
+ className,
)}
{...props}
/>
-))
-Card.displayName = "Card"
+));
+Card.displayName = "Card";
const CardHeader = React.forwardRef<
HTMLDivElement,
@@ -26,8 +26,8 @@ const CardHeader = React.forwardRef<
className={cn("flex flex-col space-y-1.5 p-6", className)}
{...props}
/>
-))
-CardHeader.displayName = "CardHeader"
+));
+CardHeader.displayName = "CardHeader";
const CardTitle = React.forwardRef<
HTMLParagraphElement,
@@ -37,12 +37,12 @@ const CardTitle = React.forwardRef<
ref={ref}
className={cn(
"text-2xl font-semibold leading-none tracking-tight",
- className
+ className,
)}
{...props}
/>
-))
-CardTitle.displayName = "CardTitle"
+));
+CardTitle.displayName = "CardTitle";
const CardDescription = React.forwardRef<
HTMLParagraphElement,
@@ -53,16 +53,16 @@ const CardDescription = React.forwardRef<
className={cn("text-sm text-muted-foreground", className)}
{...props}
/>
-))
-CardDescription.displayName = "CardDescription"
+));
+CardDescription.displayName = "CardDescription";
const CardContent = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes
>(({ className, ...props }, ref) => (
-))
-CardContent.displayName = "CardContent"
+));
+CardContent.displayName = "CardContent";
const CardFooter = React.forwardRef<
HTMLDivElement,
@@ -73,7 +73,14 @@ const CardFooter = React.forwardRef<
className={cn("flex items-center p-6 pt-0", className)}
{...props}
/>
-))
-CardFooter.displayName = "CardFooter"
+));
+CardFooter.displayName = "CardFooter";
-export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
+export {
+ Card,
+ CardHeader,
+ CardFooter,
+ CardTitle,
+ CardDescription,
+ CardContent,
+};
diff --git a/components/ui/dialog.tsx b/components/ui/dialog.tsx
index 2f33766..aca1068 100644
--- a/components/ui/dialog.tsx
+++ b/components/ui/dialog.tsx
@@ -1,22 +1,22 @@
-"use client"
+"use client";
-import * as React from "react"
-import * as DialogPrimitive from "@radix-ui/react-dialog"
-import { X } from "lucide-react"
+import * as React from "react";
+import * as DialogPrimitive from "@radix-ui/react-dialog";
+import { X } from "lucide-react";
-import { cn } from "@/lib/utils"
+import { cn } from "@/lib/utils";
-const Dialog = DialogPrimitive.Root
+const Dialog = DialogPrimitive.Root;
-const DialogTrigger = DialogPrimitive.Trigger
+const DialogTrigger = DialogPrimitive.Trigger;
const DialogPortal = ({
className,
...props
}: DialogPrimitive.DialogPortalProps) => (
-)
-DialogPortal.displayName = DialogPrimitive.Portal.displayName
+);
+DialogPortal.displayName = DialogPrimitive.Portal.displayName;
const DialogOverlay = React.forwardRef<
React.ElementRef,
@@ -26,12 +26,12 @@ const DialogOverlay = React.forwardRef<
ref={ref}
className={cn(
"fixed inset-0 z-50 bg-background/80 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
- className
+ className,
)}
{...props}
/>
-))
-DialogOverlay.displayName = DialogPrimitive.Overlay.displayName
+));
+DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
const DialogContent = React.forwardRef<
React.ElementRef,
@@ -43,7 +43,7 @@ const DialogContent = React.forwardRef<
ref={ref}
className={cn(
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg md:w-full",
- className
+ className,
)}
{...props}
>
@@ -54,8 +54,8 @@ const DialogContent = React.forwardRef<
-))
-DialogContent.displayName = DialogPrimitive.Content.displayName
+));
+DialogContent.displayName = DialogPrimitive.Content.displayName;
const DialogHeader = ({
className,
@@ -64,12 +64,12 @@ const DialogHeader = ({
-)
-DialogHeader.displayName = "DialogHeader"
+);
+DialogHeader.displayName = "DialogHeader";
const DialogFooter = ({
className,
@@ -78,12 +78,12 @@ const DialogFooter = ({
-)
-DialogFooter.displayName = "DialogFooter"
+);
+DialogFooter.displayName = "DialogFooter";
const DialogTitle = React.forwardRef<
React.ElementRef,
@@ -93,12 +93,12 @@ const DialogTitle = React.forwardRef<
ref={ref}
className={cn(
"text-lg font-semibold leading-none tracking-tight",
- className
+ className,
)}
{...props}
/>
-))
-DialogTitle.displayName = DialogPrimitive.Title.displayName
+));
+DialogTitle.displayName = DialogPrimitive.Title.displayName;
const DialogDescription = React.forwardRef<
React.ElementRef,
@@ -109,8 +109,8 @@ const DialogDescription = React.forwardRef<
className={cn("text-sm text-muted-foreground", className)}
{...props}
/>
-))
-DialogDescription.displayName = DialogPrimitive.Description.displayName
+));
+DialogDescription.displayName = DialogPrimitive.Description.displayName;
export {
Dialog,
@@ -120,4 +120,4 @@ export {
DialogFooter,
DialogTitle,
DialogDescription,
-}
+};
diff --git a/components/ui/dropdown-menu.tsx b/components/ui/dropdown-menu.tsx
index f69a0d6..3a0c7fe 100644
--- a/components/ui/dropdown-menu.tsx
+++ b/components/ui/dropdown-menu.tsx
@@ -1,27 +1,27 @@
-"use client"
+"use client";
-import * as React from "react"
-import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
-import { Check, ChevronRight, Circle } from "lucide-react"
+import * as React from "react";
+import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
+import { Check, ChevronRight, Circle } from "lucide-react";
-import { cn } from "@/lib/utils"
+import { cn } from "@/lib/utils";
-const DropdownMenu = DropdownMenuPrimitive.Root
+const DropdownMenu = DropdownMenuPrimitive.Root;
-const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger
+const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
-const DropdownMenuGroup = DropdownMenuPrimitive.Group
+const DropdownMenuGroup = DropdownMenuPrimitive.Group;
-const DropdownMenuPortal = DropdownMenuPrimitive.Portal
+const DropdownMenuPortal = DropdownMenuPrimitive.Portal;
-const DropdownMenuSub = DropdownMenuPrimitive.Sub
+const DropdownMenuSub = DropdownMenuPrimitive.Sub;
-const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup
+const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
const DropdownMenuSubTrigger = React.forwardRef<
React.ElementRef,
React.ComponentPropsWithoutRef & {
- inset?: boolean
+ inset?: boolean;
}
>(({ className, inset, children, ...props }, ref) => (
{children}
-))
+));
DropdownMenuSubTrigger.displayName =
- DropdownMenuPrimitive.SubTrigger.displayName
+ DropdownMenuPrimitive.SubTrigger.displayName;
const DropdownMenuSubContent = React.forwardRef<
React.ElementRef,
@@ -48,13 +48,13 @@ const DropdownMenuSubContent = React.forwardRef<
ref={ref}
className={cn(
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
- className
+ className,
)}
{...props}
/>
-))
+));
DropdownMenuSubContent.displayName =
- DropdownMenuPrimitive.SubContent.displayName
+ DropdownMenuPrimitive.SubContent.displayName;
const DropdownMenuContent = React.forwardRef<
React.ElementRef,
@@ -66,18 +66,18 @@ const DropdownMenuContent = React.forwardRef<
sideOffset={sideOffset}
className={cn(
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
- className
+ className,
)}
{...props}
/>
-))
-DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName
+));
+DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
const DropdownMenuItem = React.forwardRef<
React.ElementRef,
React.ComponentPropsWithoutRef & {
- inset?: boolean
+ inset?: boolean;
}
>(({ className, inset, ...props }, ref) => (
-))
-DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName
+));
+DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
const DropdownMenuCheckboxItem = React.forwardRef<
React.ElementRef,
@@ -100,7 +100,7 @@ const DropdownMenuCheckboxItem = React.forwardRef<
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
- className
+ className,
)}
checked={checked}
{...props}
@@ -112,9 +112,9 @@ const DropdownMenuCheckboxItem = React.forwardRef<
{children}
-))
+));
DropdownMenuCheckboxItem.displayName =
- DropdownMenuPrimitive.CheckboxItem.displayName
+ DropdownMenuPrimitive.CheckboxItem.displayName;
const DropdownMenuRadioItem = React.forwardRef<
React.ElementRef,
@@ -124,7 +124,7 @@ const DropdownMenuRadioItem = React.forwardRef<
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
- className
+ className,
)}
{...props}
>
@@ -135,13 +135,13 @@ const DropdownMenuRadioItem = React.forwardRef<
{children}
-))
-DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName
+));
+DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
const DropdownMenuLabel = React.forwardRef<
React.ElementRef,
React.ComponentPropsWithoutRef & {
- inset?: boolean
+ inset?: boolean;
}
>(({ className, inset, ...props }, ref) => (
-))
-DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName
+));
+DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
const DropdownMenuSeparator = React.forwardRef<
React.ElementRef,
@@ -165,8 +165,8 @@ const DropdownMenuSeparator = React.forwardRef<
className={cn("-mx-1 my-1 h-px bg-muted", className)}
{...props}
/>
-))
-DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName
+));
+DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
const DropdownMenuShortcut = ({
className,
@@ -177,9 +177,9 @@ const DropdownMenuShortcut = ({
className={cn("ml-auto text-xs tracking-widest opacity-60", className)}
{...props}
/>
- )
-}
-DropdownMenuShortcut.displayName = "DropdownMenuShortcut"
+ );
+};
+DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
export {
DropdownMenu,
@@ -197,4 +197,4 @@ export {
DropdownMenuSubContent,
DropdownMenuSubTrigger,
DropdownMenuRadioGroup,
-}
+};
diff --git a/components/ui/form.tsx b/components/ui/form.tsx
index 4603f8b..497718a 100644
--- a/components/ui/form.tsx
+++ b/components/ui/form.tsx
@@ -1,6 +1,6 @@
-import * as React from "react"
-import * as LabelPrimitive from "@radix-ui/react-label"
-import { Slot } from "@radix-ui/react-slot"
+import * as React from "react";
+import * as LabelPrimitive from "@radix-ui/react-label";
+import { Slot } from "@radix-ui/react-slot";
import {
Controller,
ControllerProps,
@@ -8,27 +8,27 @@ import {
FieldValues,
FormProvider,
useFormContext,
-} from "react-hook-form"
+} from "react-hook-form";
-import { cn } from "@/lib/utils"
-import { Label } from "@/components/ui/label"
+import { cn } from "@/lib/utils";
+import { Label } from "@/components/ui/label";
-const Form = FormProvider
+const Form = FormProvider;
type FormFieldContextValue<
TFieldValues extends FieldValues = FieldValues,
- TName extends FieldPath = FieldPath
+ TName extends FieldPath = FieldPath,
> = {
- name: TName
-}
+ name: TName;
+};
const FormFieldContext = React.createContext(
- {} as FormFieldContextValue
-)
+ {} as FormFieldContextValue,
+);
const FormField = <
TFieldValues extends FieldValues = FieldValues,
- TName extends FieldPath = FieldPath
+ TName extends FieldPath = FieldPath,
>({
...props
}: ControllerProps) => {
@@ -36,21 +36,21 @@ const FormField = <
- )
-}
+ );
+};
const useFormField = () => {
- const fieldContext = React.useContext(FormFieldContext)
- const itemContext = React.useContext(FormItemContext)
- const { getFieldState, formState } = useFormContext()
+ const fieldContext = React.useContext(FormFieldContext);
+ const itemContext = React.useContext(FormItemContext);
+ const { getFieldState, formState } = useFormContext();
- const fieldState = getFieldState(fieldContext.name, formState)
+ const fieldState = getFieldState(fieldContext.name, formState);
if (!fieldContext) {
- throw new Error("useFormField should be used within ")
+ throw new Error("useFormField should be used within ");
}
- const { id } = itemContext
+ const { id } = itemContext;
return {
id,
@@ -59,36 +59,36 @@ const useFormField = () => {
formDescriptionId: `${id}-form-item-description`,
formMessageId: `${id}-form-item-message`,
...fieldState,
- }
-}
+ };
+};
type FormItemContextValue = {
- id: string
-}
+ id: string;
+};
const FormItemContext = React.createContext(
- {} as FormItemContextValue
-)
+ {} as FormItemContextValue,
+);
const FormItem = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes
>(({ className, ...props }, ref) => {
- const id = React.useId()
+ const id = React.useId();
return (
- )
-})
-FormItem.displayName = "FormItem"
+ );
+});
+FormItem.displayName = "FormItem";
const FormLabel = React.forwardRef<
React.ElementRef,
React.ComponentPropsWithoutRef
>(({ className, ...props }, ref) => {
- const { error, formItemId } = useFormField()
+ const { error, formItemId } = useFormField();
return (
- )
-})
-FormLabel.displayName = "FormLabel"
+ );
+});
+FormLabel.displayName = "FormLabel";
const FormControl = React.forwardRef<
React.ElementRef,
React.ComponentPropsWithoutRef
>(({ ...props }, ref) => {
- const { error, formItemId, formDescriptionId, formMessageId } = useFormField()
+ const { error, formItemId, formDescriptionId, formMessageId } =
+ useFormField();
return (
- )
-})
-FormControl.displayName = "FormControl"
+ );
+});
+FormControl.displayName = "FormControl";
const FormDescription = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes
>(({ className, ...props }, ref) => {
- const { formDescriptionId } = useFormField()
+ const { formDescriptionId } = useFormField();
return (
- )
-})
-FormDescription.displayName = "FormDescription"
+ );
+});
+FormDescription.displayName = "FormDescription";
const FormMessage = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes
>(({ className, children, ...props }, ref) => {
- const { error, formMessageId } = useFormField()
- const body = error ? String(error?.message) : children
+ const { error, formMessageId } = useFormField();
+ const body = error ? String(error?.message) : children;
if (!body) {
- return null
+ return null;
}
return (
@@ -160,9 +161,9 @@ const FormMessage = React.forwardRef<
>
{body}
- )
-})
-FormMessage.displayName = "FormMessage"
+ );
+});
+FormMessage.displayName = "FormMessage";
export {
useFormField,
@@ -173,4 +174,4 @@ export {
FormDescription,
FormMessage,
FormField,
-}
+};
diff --git a/components/ui/input.tsx b/components/ui/input.tsx
index 677d05f..9d631e7 100644
--- a/components/ui/input.tsx
+++ b/components/ui/input.tsx
@@ -1,6 +1,6 @@
-import * as React from "react"
+import * as React from "react";
-import { cn } from "@/lib/utils"
+import { cn } from "@/lib/utils";
export interface InputProps
extends React.InputHTMLAttributes {}
@@ -12,14 +12,14 @@ const Input = React.forwardRef(
type={type}
className={cn(
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
- className
+ className,
)}
ref={ref}
{...props}
/>
- )
- }
-)
-Input.displayName = "Input"
+ );
+ },
+);
+Input.displayName = "Input";
-export { Input }
+export { Input };
diff --git a/components/ui/label.tsx b/components/ui/label.tsx
index 5341821..84f8b0c 100644
--- a/components/ui/label.tsx
+++ b/components/ui/label.tsx
@@ -1,14 +1,14 @@
-"use client"
+"use client";
-import * as React from "react"
-import * as LabelPrimitive from "@radix-ui/react-label"
-import { cva, type VariantProps } from "class-variance-authority"
+import * as React from "react";
+import * as LabelPrimitive from "@radix-ui/react-label";
+import { cva, type VariantProps } from "class-variance-authority";
-import { cn } from "@/lib/utils"
+import { cn } from "@/lib/utils";
const labelVariants = cva(
- "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
-)
+ "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
+);
const Label = React.forwardRef<
React.ElementRef,
@@ -20,7 +20,7 @@ const Label = React.forwardRef<
className={cn(labelVariants(), className)}
{...props}
/>
-))
-Label.displayName = LabelPrimitive.Root.displayName
+));
+Label.displayName = LabelPrimitive.Root.displayName;
-export { Label }
+export { Label };
diff --git a/components/ui/radio-group.tsx b/components/ui/radio-group.tsx
index 7a5450a..50ba0d5 100644
--- a/components/ui/radio-group.tsx
+++ b/components/ui/radio-group.tsx
@@ -1,10 +1,10 @@
-"use client"
+"use client";
-import * as React from "react"
-import * as RadioGroupPrimitive from "@radix-ui/react-radio-group"
-import { Circle } from "lucide-react"
+import * as React from "react";
+import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";
+import { Circle } from "lucide-react";
-import { cn } from "@/lib/utils"
+import { cn } from "@/lib/utils";
const RadioGroup = React.forwardRef<
React.ElementRef,
@@ -16,9 +16,9 @@ const RadioGroup = React.forwardRef<
{...props}
ref={ref}
/>
- )
-})
-RadioGroup.displayName = RadioGroupPrimitive.Root.displayName
+ );
+});
+RadioGroup.displayName = RadioGroupPrimitive.Root.displayName;
const RadioGroupItem = React.forwardRef<
React.ElementRef,
@@ -29,7 +29,7 @@ const RadioGroupItem = React.forwardRef<
ref={ref}
className={cn(
"aspect-square h-4 w-4 rounded-full border border-primary text-primary ring-offset-background focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
- className
+ className,
)}
{...props}
>
@@ -37,8 +37,8 @@ const RadioGroupItem = React.forwardRef<
- )
-})
-RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName
+ );
+});
+RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName;
-export { RadioGroup, RadioGroupItem }
+export { RadioGroup, RadioGroupItem };
diff --git a/components/ui/sheet.tsx b/components/ui/sheet.tsx
index 98cdd40..b3fdc11 100644
--- a/components/ui/sheet.tsx
+++ b/components/ui/sheet.tsx
@@ -1,25 +1,25 @@
-"use client"
+"use client";
-import * as React from "react"
-import * as SheetPrimitive from "@radix-ui/react-dialog"
-import { cva, type VariantProps } from "class-variance-authority"
-import { X } from "lucide-react"
+import * as React from "react";
+import * as SheetPrimitive from "@radix-ui/react-dialog";
+import { cva, type VariantProps } from "class-variance-authority";
+import { X } from "lucide-react";
-import { cn } from "@/lib/utils"
+import { cn } from "@/lib/utils";
-const Sheet = SheetPrimitive.Root
+const Sheet = SheetPrimitive.Root;
-const SheetTrigger = SheetPrimitive.Trigger
+const SheetTrigger = SheetPrimitive.Trigger;
-const SheetClose = SheetPrimitive.Close
+const SheetClose = SheetPrimitive.Close;
const SheetPortal = ({
className,
...props
}: SheetPrimitive.DialogPortalProps) => (
-)
-SheetPortal.displayName = SheetPrimitive.Portal.displayName
+);
+SheetPortal.displayName = SheetPrimitive.Portal.displayName;
const SheetOverlay = React.forwardRef<
React.ElementRef,
@@ -28,13 +28,13 @@ const SheetOverlay = React.forwardRef<
-))
-SheetOverlay.displayName = SheetPrimitive.Overlay.displayName
+));
+SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;
const sheetVariants = cva(
"fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500",
@@ -52,8 +52,8 @@ const sheetVariants = cva(
defaultVariants: {
side: "right",
},
- }
-)
+ },
+);
interface SheetContentProps
extends React.ComponentPropsWithoutRef,
@@ -77,8 +77,8 @@ const SheetContent = React.forwardRef<
-))
-SheetContent.displayName = SheetPrimitive.Content.displayName
+));
+SheetContent.displayName = SheetPrimitive.Content.displayName;
const SheetHeader = ({
className,
@@ -87,12 +87,12 @@ const SheetHeader = ({
-)
-SheetHeader.displayName = "SheetHeader"
+);
+SheetHeader.displayName = "SheetHeader";
const SheetFooter = ({
className,
@@ -101,12 +101,12 @@ const SheetFooter = ({
-)
-SheetFooter.displayName = "SheetFooter"
+);
+SheetFooter.displayName = "SheetFooter";
const SheetTitle = React.forwardRef<
React.ElementRef,
@@ -117,8 +117,8 @@ const SheetTitle = React.forwardRef<
className={cn("text-lg font-semibold text-foreground", className)}
{...props}
/>
-))
-SheetTitle.displayName = SheetPrimitive.Title.displayName
+));
+SheetTitle.displayName = SheetPrimitive.Title.displayName;
const SheetDescription = React.forwardRef<
React.ElementRef,
@@ -129,8 +129,8 @@ const SheetDescription = React.forwardRef<
className={cn("text-sm text-muted-foreground", className)}
{...props}
/>
-))
-SheetDescription.displayName = SheetPrimitive.Description.displayName
+));
+SheetDescription.displayName = SheetPrimitive.Description.displayName;
export {
Sheet,
@@ -141,4 +141,4 @@ export {
SheetFooter,
SheetTitle,
SheetDescription,
-}
+};
diff --git a/components/ui/textarea.tsx b/components/ui/textarea.tsx
index 9f9a6dc..9f00573 100644
--- a/components/ui/textarea.tsx
+++ b/components/ui/textarea.tsx
@@ -1,6 +1,6 @@
-import * as React from "react"
+import * as React from "react";
-import { cn } from "@/lib/utils"
+import { cn } from "@/lib/utils";
export interface TextareaProps
extends React.TextareaHTMLAttributes {}
@@ -11,14 +11,14 @@ const Textarea = React.forwardRef(
- )
- }
-)
-Textarea.displayName = "Textarea"
+ );
+ },
+);
+Textarea.displayName = "Textarea";
-export { Textarea }
+export { Textarea };
diff --git a/components/ui/toast.tsx b/components/ui/toast.tsx
index a822477..2bc23c1 100644
--- a/components/ui/toast.tsx
+++ b/components/ui/toast.tsx
@@ -1,11 +1,11 @@
-import * as React from "react"
-import * as ToastPrimitives from "@radix-ui/react-toast"
-import { cva, type VariantProps } from "class-variance-authority"
-import { X } from "lucide-react"
+import * as React from "react";
+import * as ToastPrimitives from "@radix-ui/react-toast";
+import { cva, type VariantProps } from "class-variance-authority";
+import { X } from "lucide-react";
-import { cn } from "@/lib/utils"
+import { cn } from "@/lib/utils";
-const ToastProvider = ToastPrimitives.Provider
+const ToastProvider = ToastPrimitives.Provider;
const ToastViewport = React.forwardRef<
React.ElementRef,
@@ -15,12 +15,12 @@ const ToastViewport = React.forwardRef<
ref={ref}
className={cn(
"fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]",
- className
+ className,
)}
{...props}
/>
-))
-ToastViewport.displayName = ToastPrimitives.Viewport.displayName
+));
+ToastViewport.displayName = ToastPrimitives.Viewport.displayName;
const toastVariants = cva(
"group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full",
@@ -35,8 +35,8 @@ const toastVariants = cva(
defaultVariants: {
variant: "default",
},
- }
-)
+ },
+);
const Toast = React.forwardRef<
React.ElementRef,
@@ -49,9 +49,9 @@ const Toast = React.forwardRef<
className={cn(toastVariants({ variant }), className)}
{...props}
/>
- )
-})
-Toast.displayName = ToastPrimitives.Root.displayName
+ );
+});
+Toast.displayName = ToastPrimitives.Root.displayName;
const ToastAction = React.forwardRef<
React.ElementRef,
@@ -61,12 +61,12 @@ const ToastAction = React.forwardRef<
ref={ref}
className={cn(
"inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium ring-offset-background transition-colors hover:bg-secondary focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 group-[.destructive]:border-muted/40 group-[.destructive]:hover:border-destructive/30 group-[.destructive]:hover:bg-destructive group-[.destructive]:hover:text-destructive-foreground group-[.destructive]:focus:ring-destructive",
- className
+ className,
)}
{...props}
/>
-))
-ToastAction.displayName = ToastPrimitives.Action.displayName
+));
+ToastAction.displayName = ToastPrimitives.Action.displayName;
const ToastClose = React.forwardRef<
React.ElementRef,
@@ -76,15 +76,15 @@ const ToastClose = React.forwardRef<
ref={ref}
className={cn(
"absolute right-2 top-2 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600",
- className
+ className,
)}
toast-close=""
{...props}
>
-))
-ToastClose.displayName = ToastPrimitives.Close.displayName
+));
+ToastClose.displayName = ToastPrimitives.Close.displayName;
const ToastTitle = React.forwardRef<
React.ElementRef,
@@ -95,8 +95,8 @@ const ToastTitle = React.forwardRef<
className={cn("text-sm font-semibold", className)}
{...props}
/>
-))
-ToastTitle.displayName = ToastPrimitives.Title.displayName
+));
+ToastTitle.displayName = ToastPrimitives.Title.displayName;
const ToastDescription = React.forwardRef<
React.ElementRef,
@@ -107,12 +107,12 @@ const ToastDescription = React.forwardRef<
className={cn("text-sm opacity-90", className)}
{...props}
/>
-))
-ToastDescription.displayName = ToastPrimitives.Description.displayName
+));
+ToastDescription.displayName = ToastPrimitives.Description.displayName;
-type ToastProps = React.ComponentPropsWithoutRef
+type ToastProps = React.ComponentPropsWithoutRef;
-type ToastActionElement = React.ReactElement
+type ToastActionElement = React.ReactElement;
export {
type ToastProps,
@@ -124,4 +124,4 @@ export {
ToastDescription,
ToastClose,
ToastAction,
-}
+};
diff --git a/components/ui/toaster.tsx b/components/ui/toaster.tsx
index e223385..7d82ed5 100644
--- a/components/ui/toaster.tsx
+++ b/components/ui/toaster.tsx
@@ -1,4 +1,4 @@
-"use client"
+"use client";
import {
Toast,
@@ -7,11 +7,11 @@ import {
ToastProvider,
ToastTitle,
ToastViewport,
-} from "@/components/ui/toast"
-import { useToast } from "@/components/ui/use-toast"
+} from "@/components/ui/toast";
+import { useToast } from "@/components/ui/use-toast";
export function Toaster() {
- const { toasts } = useToast()
+ const { toasts } = useToast();
return (
@@ -27,9 +27,9 @@ export function Toaster() {
{action}
- )
+ );
})}
- )
+ );
}
diff --git a/components/ui/use-toast.ts b/components/ui/use-toast.ts
index efcac11..1a249a7 100644
--- a/components/ui/use-toast.ts
+++ b/components/ui/use-toast.ts
@@ -1,76 +1,73 @@
// Inspired by react-hot-toast library
-import * as React from "react"
+import * as React from "react";
-import type {
- ToastActionElement,
- ToastProps,
-} from "@/components/ui/toast"
+import type { ToastActionElement, ToastProps } from "@/components/ui/toast";
-const TOAST_LIMIT = 3
-const TOAST_REMOVE_DELAY = 500000
+const TOAST_LIMIT = 3;
+const TOAST_REMOVE_DELAY = 500000;
type ToasterToast = ToastProps & {
- id: string
- title?: React.ReactNode
- description?: React.ReactNode
- action?: ToastActionElement
-}
+ id: string;
+ title?: React.ReactNode;
+ description?: React.ReactNode;
+ action?: ToastActionElement;
+};
const actionTypes = {
ADD_TOAST: "ADD_TOAST",
UPDATE_TOAST: "UPDATE_TOAST",
DISMISS_TOAST: "DISMISS_TOAST",
REMOVE_TOAST: "REMOVE_TOAST",
-} as const
+} as const;
-let count = 0
+let count = 0;
function genId() {
- count = (count + 1) % Number.MAX_VALUE
- return count.toString()
+ count = (count + 1) % Number.MAX_VALUE;
+ return count.toString();
}
-type ActionType = typeof actionTypes
+type ActionType = typeof actionTypes;
type Action =
| {
- type: ActionType["ADD_TOAST"]
- toast: ToasterToast
+ type: ActionType["ADD_TOAST"];
+ toast: ToasterToast;
}
| {
- type: ActionType["UPDATE_TOAST"]
- toast: Partial
+ type: ActionType["UPDATE_TOAST"];
+ toast: Partial;
}
| {
- type: ActionType["DISMISS_TOAST"]
- toastId?: ToasterToast["id"]
+ type: ActionType["DISMISS_TOAST"];
+ toastId?: ToasterToast["id"];
}
| {
- type: ActionType["REMOVE_TOAST"]
- toastId?: ToasterToast["id"]
- }
+ type: ActionType["REMOVE_TOAST"];
+ toastId?: ToasterToast["id"];
+ };
interface State {
- toasts: ToasterToast[]
+ toasts: ToasterToast[];
}
-const toastTimeouts = new Map>()
+const toastTimeouts = new Map>();
const addToRemoveQueue = (toastId: string) => {
if (toastTimeouts.has(toastId)) {
- return
+ return;
}
const timeout = setTimeout(() => {
- toastTimeouts.delete(toastId)
+ toastTimeouts.delete(toastId);
dispatch({
type: "REMOVE_TOAST",
toastId: toastId,
- })
- }, TOAST_REMOVE_DELAY)
+ });
+ }, TOAST_REMOVE_DELAY);
- toastTimeouts.set(toastId, timeout)
-}
+ toastTimeouts.set(toastId, timeout);
+};
export const reducer = (state: State, action: Action): State => {
switch (action.type) {
@@ -78,27 +75,27 @@ export const reducer = (state: State, action: Action): State => {
return {
...state,
toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),
- }
+ };
case "UPDATE_TOAST":
return {
...state,
toasts: state.toasts.map((t) =>
- t.id === action.toast.id ? { ...t, ...action.toast } : t
+ t.id === action.toast.id ? { ...t, ...action.toast } : t,
),
- }
+ };
case "DISMISS_TOAST": {
- const { toastId } = action
+ const { toastId } = action;
// ! Side effects ! - This could be extracted into a dismissToast() action,
// but I'll keep it here for simplicity
if (toastId) {
- addToRemoveQueue(toastId)
+ addToRemoveQueue(toastId);
} else {
state.toasts.forEach((toast) => {
- addToRemoveQueue(toast.id)
- })
+ addToRemoveQueue(toast.id);
+ });
}
return {
@@ -109,46 +106,46 @@ export const reducer = (state: State, action: Action): State => {
...t,
open: false,
}
- : t
+ : t,
),
- }
+ };
}
case "REMOVE_TOAST":
if (action.toastId === undefined) {
return {
...state,
toasts: [],
- }
+ };
}
return {
...state,
toasts: state.toasts.filter((t) => t.id !== action.toastId),
- }
+ };
}
-}
+};
-const listeners: Array<(state: State) => void> = []
+const listeners: Array<(state: State) => void> = [];
-let memoryState: State = { toasts: [] }
+let memoryState: State = { toasts: [] };
function dispatch(action: Action) {
- memoryState = reducer(memoryState, action)
+ memoryState = reducer(memoryState, action);
listeners.forEach((listener) => {
- listener(memoryState)
- })
+ listener(memoryState);
+ });
}
-type Toast = Omit
+type Toast = Omit;
function toast({ ...props }: Toast) {
- const id = genId()
+ const id = genId();
const update = (props: ToasterToast) =>
dispatch({
type: "UPDATE_TOAST",
toast: { ...props, id },
- })
- const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id })
+ });
+ const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id });
dispatch({
type: "ADD_TOAST",
@@ -157,36 +154,36 @@ function toast({ ...props }: Toast) {
id,
open: true,
onOpenChange: (open) => {
- if (!open) dismiss()
+ if (!open) dismiss();
},
},
- })
+ });
return {
id: id,
dismiss,
update,
- }
+ };
}
function useToast() {
- const [state, setState] = React.useState(memoryState)
+ const [state, setState] = React.useState(memoryState);
React.useEffect(() => {
- listeners.push(setState)
+ listeners.push(setState);
return () => {
- const index = listeners.indexOf(setState)
+ const index = listeners.indexOf(setState);
if (index > -1) {
- listeners.splice(index, 1)
+ listeners.splice(index, 1);
}
- }
- }, [state])
+ };
+ }, [state]);
return {
...state,
toast,
dismiss: (toastId?: string) => dispatch({ type: "DISMISS_TOAST", toastId }),
- }
+ };
}
-export { useToast, toast }
+export { useToast, toast };
diff --git a/lib/utils.ts b/lib/utils.ts
index ec79801..365058c 100644
--- a/lib/utils.ts
+++ b/lib/utils.ts
@@ -1,6 +1,6 @@
-import { type ClassValue, clsx } from "clsx"
-import { twMerge } from "tailwind-merge"
-
+import { type ClassValue, clsx } from "clsx";
+import { twMerge } from "tailwind-merge";
+
export function cn(...inputs: ClassValue[]) {
- return twMerge(clsx(inputs))
+ return twMerge(clsx(inputs));
}
diff --git a/next.config.js b/next.config.js
index 9281af7..13ebb82 100644
--- a/next.config.js
+++ b/next.config.js
@@ -3,7 +3,11 @@ const nextConfig = {
reactStrictMode: true,
swcMinify: true,
images: {
- domains: ["lh3.googleusercontent.com", "avatars.githubusercontent.com", "vercel.com"],
+ domains: [
+ "lh3.googleusercontent.com",
+ "avatars.githubusercontent.com",
+ "vercel.com",
+ ],
},
async redirects() {
return [
diff --git a/tailwind.config.js b/tailwind.config.js
index 0377ea1..c05b2ff 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -2,11 +2,11 @@
module.exports = {
darkMode: ["class"],
content: [
- './pages/**/*.{ts,tsx}',
- './components/**/*.{ts,tsx}',
- './app/**/*.{ts,tsx}',
- './src/**/*.{ts,tsx}',
- ],
+ "./pages/**/*.{ts,tsx}",
+ "./components/**/*.{ts,tsx}",
+ "./app/**/*.{ts,tsx}",
+ "./src/**/*.{ts,tsx}",
+ ],
theme: {
container: {
center: true,
@@ -73,4 +73,4 @@ module.exports = {
},
},
plugins: [require("tailwindcss-animate")],
-}
\ No newline at end of file
+};
diff --git a/tsconfig.json b/tsconfig.json
index c5c9aec..b055598 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -6,7 +6,7 @@
"skipLibCheck": true,
"baseUrl": ".",
"paths": {
- "@/*": ["./*"],
+ "@/*": ["./*"]
},
"strict": true,
"forceConsistentCasingInFileNames": true,
diff --git a/types/next-auth.d.ts b/types/next-auth.d.ts
index 31c13b4..0a94ab4 100644
--- a/types/next-auth.d.ts
+++ b/types/next-auth.d.ts
@@ -7,18 +7,18 @@
// } & DefaultSession['user'];
// }
// }
-import type { DefaultUser } from 'next-auth';
+import type { DefaultUser } from "next-auth";
-declare module 'next-auth' {
- interface Session {
- user?: DefaultUser & {
- id: string;
- };
- }
+declare module "next-auth" {
+ interface Session {
+ user?: DefaultUser & {
+ id: string;
+ };
+ }
}
-declare module 'next-auth/jwt/types' {
- interface JWT {
- uid: string;
- }
-}
\ No newline at end of file
+declare module "next-auth/jwt/types" {
+ interface JWT {
+ uid: string;
+ }
+}