Merge branch 'main' of https://github.com/NerfedJabolo/new-svrjs
This commit is contained in:
commit
b919dcab78
29 changed files with 1580 additions and 100 deletions
7
.env.example
Normal file
7
.env.example
Normal file
|
@ -0,0 +1,7 @@
|
|||
MONGO_URI=
|
||||
|
||||
UPLOADTHING_SECRET=
|
||||
UPLOADTHING_APP_ID=
|
||||
|
||||
ADMIN_USERNAME=
|
||||
ADMIN_PASSWORD=
|
9
actions/login.action.ts
Normal file
9
actions/login.action.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
"use server";
|
||||
|
||||
export function CheckLoggedIn(username: string, password: string) {
|
||||
if (
|
||||
username === process.env.ADMIN_USERNAME &&
|
||||
password === process.env.ADMIN_PASSWORD
|
||||
) {
|
||||
}
|
||||
}
|
23
app/(auth)/_components/Card.tsx
Normal file
23
app/(auth)/_components/Card.tsx
Normal file
|
@ -0,0 +1,23 @@
|
|||
import { ArrowUpRight } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import { FC } from "react";
|
||||
|
||||
interface CardProps {
|
||||
title: string;
|
||||
url: string;
|
||||
}
|
||||
|
||||
const Card: FC<CardProps> = ({ title, url }) => {
|
||||
return (
|
||||
<div className=" bg-zinc-900 border rounded-lg hover:bg-zinc-800 transition-all">
|
||||
<Link href={url} className="group">
|
||||
<div className="flex-center rounded-lg p-6">
|
||||
<h2 className="text-2xl font-bold mb-2">{title}</h2>
|
||||
<ArrowUpRight className="w-5 h-5 mb-2 ml-2 opacity-0 group-hover:opacity-100 transition-all duration-300" />
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Card;
|
56
app/(auth)/_components/Mobilenav.tsx
Normal file
56
app/(auth)/_components/Mobilenav.tsx
Normal file
|
@ -0,0 +1,56 @@
|
|||
"use client";
|
||||
import React from "react";
|
||||
import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet";
|
||||
import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
import { AdminLinks } from "@/constants";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { Menu } from "lucide-react";
|
||||
|
||||
const MobileNav = () => {
|
||||
const pathname = usePathname();
|
||||
return (
|
||||
<header className="header">
|
||||
<Link href="/" className="flex items-center gap-2 md:py-2">
|
||||
<Image src="/logo.svg" alt="" width={180} height={28} />
|
||||
</Link>
|
||||
|
||||
<nav className="flex gap-2">
|
||||
<Sheet>
|
||||
<SheetTrigger>
|
||||
<Menu className="w-5 h-5" />
|
||||
</SheetTrigger>
|
||||
<SheetContent className="sheet-content sm:w-64">
|
||||
<>
|
||||
<Image src="/logo.svg" alt="" width={152} height={23} />
|
||||
<ul className="header-nav_elements">
|
||||
{AdminLinks.slice(0, 6).map((link) => {
|
||||
const isActive = link.url === pathname;
|
||||
|
||||
return (
|
||||
<li
|
||||
key={link.url}
|
||||
className={`${
|
||||
isActive && "gradient-text"
|
||||
} p-18 flex whitespace-nowrap text-dark-700`}
|
||||
>
|
||||
<Link
|
||||
className="sidebar-link cursor-pointer"
|
||||
href={link.url}
|
||||
>
|
||||
<link.icon />
|
||||
{link.name}
|
||||
</Link>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</>
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
</nav>
|
||||
</header>
|
||||
);
|
||||
};
|
||||
|
||||
export default MobileNav;
|
65
app/(auth)/_components/Sidebar.tsx
Normal file
65
app/(auth)/_components/Sidebar.tsx
Normal file
|
@ -0,0 +1,65 @@
|
|||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { AdminLinks } from "@/constants";
|
||||
|
||||
const Sidebar = () => {
|
||||
const pathname = usePathname();
|
||||
return (
|
||||
<>
|
||||
<aside className="sidebar">
|
||||
<div className="flex size-full flex-col gap-4">
|
||||
<Link href="/" className="sidebar-logo">
|
||||
<Image src="/logo.svg" alt="" width={180} height={28} />
|
||||
</Link>
|
||||
|
||||
<nav className="sidebar-nav">
|
||||
<ul className="sidebar-nav_elements">
|
||||
{AdminLinks.slice(0, 4).map((link) => {
|
||||
const isActive = link.url === pathname;
|
||||
|
||||
return (
|
||||
<li
|
||||
key={link.url}
|
||||
className={`sidebar-nav_element group ${
|
||||
isActive ? "bg-white/5" : "text-gray-700"
|
||||
}`}
|
||||
>
|
||||
<Link className="sidebar-link" href={link.url}>
|
||||
<link.icon />
|
||||
{link.name}
|
||||
</Link>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
|
||||
<ul className="sidebar-nav_elements">
|
||||
{AdminLinks.slice(4).map((link) => {
|
||||
const isActive = link.url === pathname;
|
||||
|
||||
return (
|
||||
<li
|
||||
key={link.url}
|
||||
className={`sidebar-nav_element group ${
|
||||
isActive ? "bg-purple-gradient" : "text-gray-700"
|
||||
}`}
|
||||
>
|
||||
<Link className="sidebar-link" href={link.url}>
|
||||
<link.icon />
|
||||
{link.name}
|
||||
</Link>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</aside>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Sidebar;
|
125
app/(auth)/admin/downloads/page.tsx
Normal file
125
app/(auth)/admin/downloads/page.tsx
Normal file
|
@ -0,0 +1,125 @@
|
|||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { useForm, SubmitHandler } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { z } from "zod";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@/components/ui/form";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { UploadButton, UploadDropzone } from "@/lib/uploadthing";
|
||||
import { downloadSchema } from "@/lib/validations/validation";
|
||||
|
||||
const AdminPage = () => {
|
||||
const form = useForm<z.infer<typeof downloadSchema>>({
|
||||
resolver: zodResolver(downloadSchema),
|
||||
});
|
||||
|
||||
const onSubmit: SubmitHandler<z.infer<typeof downloadSchema>> = async (
|
||||
data
|
||||
) => {
|
||||
const response = await fetch("/api/upload", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
form.reset();
|
||||
console.log("Upload successful");
|
||||
alert("Uploaded");
|
||||
} else {
|
||||
console.error("Upload failed");
|
||||
alert("Upload Failed");
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<section id="admin-page" className="wrapper container">
|
||||
<h1 className="text-3xl font-bold py-6">Admin Upload Section</h1>
|
||||
<Form {...form}>
|
||||
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="fileName"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>File Name</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="version"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Version</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="downloadLink"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Download Link</FormLabel>
|
||||
<UploadButton
|
||||
endpoint="imageUploader"
|
||||
onClientUploadComplete={(res) => {
|
||||
field.onChange(res[0].url);
|
||||
}}
|
||||
onUploadError={(error: Error) => {
|
||||
alert(`ERROR! ${error.message}`);
|
||||
}}
|
||||
/>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="fileSize"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>File Size</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<Button
|
||||
type="submit"
|
||||
className="w-full text-lg rounded-full"
|
||||
size={"lg"}
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
</form>
|
||||
</Form>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default AdminPage;
|
21
app/(auth)/admin/page.tsx
Normal file
21
app/(auth)/admin/page.tsx
Normal file
|
@ -0,0 +1,21 @@
|
|||
import React from "react";
|
||||
import Card from "../_components/Card";
|
||||
|
||||
const AdminPage = () => {
|
||||
return (
|
||||
<>
|
||||
<section id="adminpage" className="wrapper container">
|
||||
<h1 className="h2-bold py-6">Admin Page</h1>
|
||||
|
||||
<div className="grid lg:grid-cols-2 grid-cols-1 gap-4 ">
|
||||
<Card title="Downloads" url="/admin/downloads" />
|
||||
<Card title="Mods" url="/admin" />
|
||||
<Card title="Logs" url="/admin" />
|
||||
<Card title="Docs" url="/admin" />
|
||||
</div>
|
||||
</section>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default AdminPage;
|
16
app/(auth)/layout.tsx
Normal file
16
app/(auth)/layout.tsx
Normal file
|
@ -0,0 +1,16 @@
|
|||
import MobileNav from "./_components/Mobilenav";
|
||||
import Sidebar from "./_components/Sidebar";
|
||||
|
||||
export default function PageLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<main className="flex flex-col min-h-screen root">
|
||||
<Sidebar />
|
||||
<MobileNav />
|
||||
<div className="flex-grow flex-1 root-container">{children}</div>
|
||||
</main>
|
||||
);
|
||||
}
|
|
@ -1,10 +1,12 @@
|
|||
import { Button } from '@/components/ui/button';
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCaption,
|
||||
TableCell,
|
||||
TableFooter,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
|
@ -12,38 +14,45 @@ import {
|
|||
import { Download } from 'lucide-react';
|
||||
import Link from 'next/link';
|
||||
|
||||
const downloads = [
|
||||
{
|
||||
date: '2024-06-01',
|
||||
fileName: 'SVRJS_v1.0.0.zip',
|
||||
version: '1.0.0',
|
||||
fileSize: '15MB',
|
||||
downloadLink: '/downloads/SVRJS_v1.0.0.zip',
|
||||
},
|
||||
{
|
||||
date: '2024-06-10',
|
||||
fileName: 'SVRJS_v1.1.0.zip',
|
||||
version: '1.1.0',
|
||||
fileSize: '18MB',
|
||||
downloadLink: '/downloads/SVRJS_v1.1.0.zip',
|
||||
},
|
||||
{
|
||||
date: '2024-06-15',
|
||||
fileName: 'SVRJS_v1.2.0.zip',
|
||||
version: '1.2.0',
|
||||
fileSize: '20MB',
|
||||
downloadLink: '/downloads/SVRJS_v1.2.0.zip',
|
||||
},
|
||||
{
|
||||
date: '2024-06-20',
|
||||
fileName: 'SVRJS_v1.3.0.zip',
|
||||
version: '1.3.0',
|
||||
fileSize: '22MB',
|
||||
downloadLink: '/downloads/SVRJS_v1.3.0.zip',
|
||||
},
|
||||
];
|
||||
interface Download {
|
||||
_id: string;
|
||||
date: string;
|
||||
fileName: string;
|
||||
version: string;
|
||||
fileSize: string;
|
||||
downloadLink: string;
|
||||
}
|
||||
|
||||
const DownloadPage: React.FC = () => {
|
||||
const [downloads, setDownloads] = useState<Download[]>([]);
|
||||
const [error, setError] = useState("");
|
||||
|
||||
const fetchDownloads = async () => {
|
||||
try {
|
||||
const response = await fetch("/api/downloads", {
|
||||
method: "GET",
|
||||
});
|
||||
if (response.ok) {
|
||||
const data: Download[] = await response.json();
|
||||
setDownloads(data);
|
||||
} else {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
} catch (error: any) {
|
||||
setError(error);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchDownloads();
|
||||
|
||||
const interval = setInterval(() => {
|
||||
fetchDownloads();
|
||||
}, 10000);
|
||||
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
const DownloadPage = () => {
|
||||
return (
|
||||
<section
|
||||
id="download"
|
||||
|
@ -55,6 +64,7 @@ const DownloadPage = () => {
|
|||
<p className="text-lg text-muted-foreground text-start mb-4">
|
||||
Get all the latest version of SVRJS download and compiled Files here!
|
||||
</p>
|
||||
{error && <p className="text-red-500">{error}</p>}
|
||||
<Table>
|
||||
<TableCaption>A list of all available downloads.</TableCaption>
|
||||
<TableHeader>
|
||||
|
@ -62,23 +72,23 @@ const DownloadPage = () => {
|
|||
<TableHead className="w-[150px]">Date</TableHead>
|
||||
<TableHead>File Name</TableHead>
|
||||
<TableHead>Version</TableHead>
|
||||
<TableHead>Download Link</TableHead>
|
||||
<TableHead className="text-right">File Size</TableHead>
|
||||
<TableHead>File Size</TableHead>
|
||||
<TableHead className="text-right">Download Link</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{downloads
|
||||
.slice()
|
||||
.slice(0, 10)
|
||||
.reverse()
|
||||
.map((download) => (
|
||||
<TableRow key={download.fileName}>
|
||||
<TableRow key={download._id}>
|
||||
<TableCell className="font-medium">{download.date}</TableCell>
|
||||
<TableCell>{download.fileName}</TableCell>
|
||||
<TableCell>{download.version}</TableCell>
|
||||
<TableCell className="text-left">{download.fileSize}</TableCell>
|
||||
<TableCell className="flex items-center justify-end">
|
||||
<Link href={download.downloadLink}>
|
||||
<Button variant={'ghost'} className="">
|
||||
<Button variant={"ghost"} className="">
|
||||
<Download className="w-4 h-4 mr-2" />
|
||||
Download
|
||||
</Button>
|
||||
|
|
16
app/(root)/layout.tsx
Normal file
16
app/(root)/layout.tsx
Normal file
|
@ -0,0 +1,16 @@
|
|||
import Footer from "@/components/shared/Footer";
|
||||
import Navbar from "@/components/shared/Navbar";
|
||||
|
||||
export default function PageLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<main className="flex flex-col min-h-screen">
|
||||
<Navbar />
|
||||
<div className="flex-grow flex-1">{children}</div>
|
||||
<Footer />
|
||||
</main>
|
||||
);
|
||||
}
|
17
app/api/downloads/route.ts
Normal file
17
app/api/downloads/route.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
import { NextRequest, NextResponse } from "next/server";
|
||||
import clientPromise from "@/lib/db";
|
||||
|
||||
// Handler for GET requests
|
||||
export async function GET(req: NextRequest) {
|
||||
try {
|
||||
const client = await clientPromise;
|
||||
const db = client.db("downloadsDatabase");
|
||||
const downloads = await db.collection("downloads").find().toArray();
|
||||
return NextResponse.json(downloads, { status: 200 });
|
||||
} catch (error) {
|
||||
return NextResponse.json(
|
||||
{ error: "Failed to fetch downloads" },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,31 +1,31 @@
|
|||
// import { NextResponse } from 'next/server';
|
||||
// import { setCookie } from 'nookies';
|
||||
// require('dotenv').config();
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { serialize } from "cookie";
|
||||
|
||||
// // nvm, clerk is overkill for one u
|
||||
export async function POST(request: NextRequest) {
|
||||
const { username, password } = await request.json();
|
||||
|
||||
// export async function POST(request: NextApiRequest) {
|
||||
// const { username, password } = await request.json();
|
||||
// console.log(username, password);
|
||||
// console.log(process.env.PASSWORD);
|
||||
const adminUsername = process.env.ADMIN_USERNAME;
|
||||
const adminPassword = process.env.ADMIN_PASSWORD;
|
||||
|
||||
// if (username === process.env.USERNAME && password === process.env.PASSWORD) {
|
||||
// const response = NextResponse.json(
|
||||
// { message: 'Login successful' },
|
||||
// { status: 200 }
|
||||
// );
|
||||
if (username === adminUsername && password === adminPassword) {
|
||||
const cookie = serialize("auth", "authenticated", {
|
||||
httpOnly: true,
|
||||
path: "/",
|
||||
maxAge: 60 * 60 * 24, // 1 day
|
||||
});
|
||||
|
||||
// setCookie({ res: response }, 'token', 'your-auth-token', {
|
||||
// httpOnly: true,
|
||||
// secure: process.env.NODE_ENV !== 'development',
|
||||
// maxAge: 30 * 24 * 60 * 60,
|
||||
// path: '/',
|
||||
// });
|
||||
return new NextResponse(JSON.stringify({ message: "Login successful" }), {
|
||||
headers: {
|
||||
"Set-Cookie": cookie,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// return response;
|
||||
// } else {
|
||||
// return NextResponse.json({ message: 'Login failed' }, { status: 401 });
|
||||
// }
|
||||
// }
|
||||
|
||||
// im gonna create server actions
|
||||
return new NextResponse(JSON.stringify({ message: "Invalid credentials" }), {
|
||||
status: 401,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
20
app/api/upload/route.ts
Normal file
20
app/api/upload/route.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
import { NextResponse } from "next/server";
|
||||
import clientPromise from "@/lib/db";
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const body = await request.json();
|
||||
const { fileName, version, downloadLink, fileSize } = body;
|
||||
|
||||
const client = await clientPromise;
|
||||
const db = client.db("downloadsDatabase");
|
||||
|
||||
const result = await db.collection("downloads").insertOne({
|
||||
date: new Date().toISOString().split("T")[0],
|
||||
fileName,
|
||||
version,
|
||||
downloadLink,
|
||||
fileSize,
|
||||
});
|
||||
|
||||
return NextResponse.json({ success: true, id: result.insertedId });
|
||||
}
|
22
app/api/uploadthing/core.ts
Normal file
22
app/api/uploadthing/core.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
import { createUploadthing, type FileRouter } from "uploadthing/next";
|
||||
import { UploadThingError } from "uploadthing/server";
|
||||
|
||||
const f = createUploadthing();
|
||||
|
||||
// const auth = (req: Request) => ({ id: "fakeId" });
|
||||
|
||||
export const ourFileRouter = {
|
||||
imageUploader: f({ "application/zip": { maxFileSize: "8MB" } })
|
||||
// .middleware(async ({ req }) => {
|
||||
// const user = await auth(req);
|
||||
// if (!user) throw new UploadThingError("Unauthorized");
|
||||
// return { userId: user.id };
|
||||
// })
|
||||
.onUploadComplete(async ({ metadata, file }) => {
|
||||
// console.log("Upload complete for userId:", metadata.userId);
|
||||
console.log("file url", file.url);
|
||||
// return { uploadedBy: metadata.userId };
|
||||
}),
|
||||
} satisfies FileRouter;
|
||||
|
||||
export type OurFileRouter = typeof ourFileRouter;
|
6
app/api/uploadthing/route.ts
Normal file
6
app/api/uploadthing/route.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
import { createRouteHandler } from "uploadthing/next";
|
||||
import { ourFileRouter } from "./core";
|
||||
|
||||
export const { GET, POST } = createRouteHandler({
|
||||
router: ourFileRouter,
|
||||
});
|
BIN
app/favicon.ico
BIN
app/favicon.ico
Binary file not shown.
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 15 KiB |
|
@ -99,6 +99,54 @@ body {
|
|||
.flex-end {
|
||||
@apply flex justify-between items-end;
|
||||
}
|
||||
.root {
|
||||
@apply flex max-h-screen w-full flex-col lg:flex-row;
|
||||
}
|
||||
.root-container {
|
||||
@apply mt-16 flex-1 overflow-auto py-8 lg:mt-0 lg:max-h-screen lg:py-10;
|
||||
}
|
||||
|
||||
/* .gradient-text {
|
||||
@apply bg-purple-gradient bg-cover bg-clip-text text-transparent;
|
||||
} */
|
||||
.sheet-content button {
|
||||
@apply focus:ring-0 focus-visible:ring-transparent focus:ring-offset-0 focus-visible:ring-offset-0 focus-visible:outline-none focus-visible:border-none !important;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
@apply hidden h-screen w-72 p-5 shadow-md shadow-purple-200/50 lg:flex;
|
||||
}
|
||||
.header {
|
||||
@apply flex-between fixed h-16 w-full border-b p-5 lg:hidden;
|
||||
}
|
||||
|
||||
.header-nav_elements {
|
||||
@apply mt-8 flex w-full flex-col items-start gap-5;
|
||||
}
|
||||
|
||||
/* Search Component */
|
||||
.search {
|
||||
@apply flex w-full rounded-[16px] border-2 border-purple-200/20 bg-white px-4 shadow-sm shadow-purple-200/15 md:max-w-96;
|
||||
}
|
||||
.sidebar-logo {
|
||||
@apply flex items-center gap-2 md:py-2;
|
||||
}
|
||||
|
||||
.sidebar-nav {
|
||||
@apply h-full flex-col justify-between md:flex md:gap-4;
|
||||
}
|
||||
|
||||
.sidebar-nav_elements {
|
||||
@apply hidden w-full flex-col items-start gap-2 md:flex;
|
||||
}
|
||||
|
||||
.sidebar-nav_element {
|
||||
@apply flex-center p-medium-16 w-full whitespace-nowrap rounded-full bg-cover transition-all hover:bg-white/10 hover:shadow-inner;
|
||||
}
|
||||
|
||||
.sidebar-link {
|
||||
@apply flex p-medium-16 size-full gap-4 p-4;
|
||||
}
|
||||
|
||||
/* TYPOGRAPHY */
|
||||
/* 64 */
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
import type { Metadata } from 'next';
|
||||
import { Poppins } from 'next/font/google';
|
||||
import './globals.css';
|
||||
import { ThemeProvider } from '@/components/shared/providers/themeprovider';
|
||||
import Navbar from '@/components/shared/Navbar';
|
||||
import Footer from '@/components/shared/Footer';
|
||||
import type { Metadata } from "next";
|
||||
import { Poppins } from "next/font/google";
|
||||
import "./globals.css";
|
||||
import { ThemeProvider } from "@/components/shared/providers/themeprovider";
|
||||
|
||||
const poppins = Poppins({
|
||||
weight: ['400', '600', '700', '900'],
|
||||
|
@ -22,18 +20,14 @@ export default function RootLayout({
|
|||
}>) {
|
||||
return (
|
||||
<html lang="en" suppressHydrationWarning>
|
||||
<body className={`font-sans antialiased ${poppins.className}`}>
|
||||
<body className={`antialiased ${poppins.className}`}>
|
||||
<ThemeProvider
|
||||
attribute="class"
|
||||
defaultTheme="dark"
|
||||
enableSystem
|
||||
disableTransitionOnChange
|
||||
>
|
||||
<main className="flex flex-col min-h-screen">
|
||||
<Navbar />
|
||||
<div className="flex-grow flex-1">{children}</div>
|
||||
<Footer />
|
||||
</main>
|
||||
{children}
|
||||
</ThemeProvider>
|
||||
</body>
|
||||
</html>
|
||||
|
|
64
app/login/page.tsx
Normal file
64
app/login/page.tsx
Normal file
|
@ -0,0 +1,64 @@
|
|||
"use client";
|
||||
import React, { useState } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
||||
const LoginPage = () => {
|
||||
const [username, setUsername] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
const [error, setError] = useState("");
|
||||
const router = useRouter();
|
||||
|
||||
const handleLogin = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
|
||||
const response = await fetch("/api/login", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({ username, password }),
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
router.push("/admin");
|
||||
} else {
|
||||
const data = await response.json();
|
||||
setError(data.message);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="max-w-xl h-screen flex justify-center bg-gray-900 flex-col container">
|
||||
<h1 className="text-3xl font-bold mb-4">SVRJS ADMIN PANEL</h1>
|
||||
{error && <p className="text-red-500 mb-4">{error}</p>}
|
||||
<form onSubmit={handleLogin}>
|
||||
<div className="mb-4">
|
||||
<input
|
||||
type="text"
|
||||
id="username"
|
||||
placeholder="Username"
|
||||
value={username}
|
||||
onChange={(e) => setUsername(e.target.value)}
|
||||
className="mt-1 block w-full bg-gray-800 rounded-full px-5 py-2 shadow-sm p-2"
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-4">
|
||||
<input
|
||||
type="password"
|
||||
placeholder="Password"
|
||||
id="password"
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
className="mt-1 block w-full bg-gray-800 rounded-full px-5 py-2 shadow-sm"
|
||||
/>
|
||||
</div>
|
||||
<Button type="submit" className="w-full rounded-full" size={"lg"}>
|
||||
Login
|
||||
</Button>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default LoginPage;
|
176
components/ui/form.tsx
Normal file
176
components/ui/form.tsx
Normal file
|
@ -0,0 +1,176 @@
|
|||
import * as React from "react"
|
||||
import * as LabelPrimitive from "@radix-ui/react-label"
|
||||
import { Slot } from "@radix-ui/react-slot"
|
||||
import {
|
||||
Controller,
|
||||
ControllerProps,
|
||||
FieldPath,
|
||||
FieldValues,
|
||||
FormProvider,
|
||||
useFormContext,
|
||||
} from "react-hook-form"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { Label } from "@/components/ui/label"
|
||||
|
||||
const Form = FormProvider
|
||||
|
||||
type FormFieldContextValue<
|
||||
TFieldValues extends FieldValues = FieldValues,
|
||||
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
|
||||
> = {
|
||||
name: TName
|
||||
}
|
||||
|
||||
const FormFieldContext = React.createContext<FormFieldContextValue>(
|
||||
{} as FormFieldContextValue
|
||||
)
|
||||
|
||||
const FormField = <
|
||||
TFieldValues extends FieldValues = FieldValues,
|
||||
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
|
||||
>({
|
||||
...props
|
||||
}: ControllerProps<TFieldValues, TName>) => {
|
||||
return (
|
||||
<FormFieldContext.Provider value={{ name: props.name }}>
|
||||
<Controller {...props} />
|
||||
</FormFieldContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
const useFormField = () => {
|
||||
const fieldContext = React.useContext(FormFieldContext)
|
||||
const itemContext = React.useContext(FormItemContext)
|
||||
const { getFieldState, formState } = useFormContext()
|
||||
|
||||
const fieldState = getFieldState(fieldContext.name, formState)
|
||||
|
||||
if (!fieldContext) {
|
||||
throw new Error("useFormField should be used within <FormField>")
|
||||
}
|
||||
|
||||
const { id } = itemContext
|
||||
|
||||
return {
|
||||
id,
|
||||
name: fieldContext.name,
|
||||
formItemId: `${id}-form-item`,
|
||||
formDescriptionId: `${id}-form-item-description`,
|
||||
formMessageId: `${id}-form-item-message`,
|
||||
...fieldState,
|
||||
}
|
||||
}
|
||||
|
||||
type FormItemContextValue = {
|
||||
id: string
|
||||
}
|
||||
|
||||
const FormItemContext = React.createContext<FormItemContextValue>(
|
||||
{} as FormItemContextValue
|
||||
)
|
||||
|
||||
const FormItem = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => {
|
||||
const id = React.useId()
|
||||
|
||||
return (
|
||||
<FormItemContext.Provider value={{ id }}>
|
||||
<div ref={ref} className={cn("space-y-2", className)} {...props} />
|
||||
</FormItemContext.Provider>
|
||||
)
|
||||
})
|
||||
FormItem.displayName = "FormItem"
|
||||
|
||||
const FormLabel = React.forwardRef<
|
||||
React.ElementRef<typeof LabelPrimitive.Root>,
|
||||
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root>
|
||||
>(({ className, ...props }, ref) => {
|
||||
const { error, formItemId } = useFormField()
|
||||
|
||||
return (
|
||||
<Label
|
||||
ref={ref}
|
||||
className={cn(error && "text-destructive", className)}
|
||||
htmlFor={formItemId}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
})
|
||||
FormLabel.displayName = "FormLabel"
|
||||
|
||||
const FormControl = React.forwardRef<
|
||||
React.ElementRef<typeof Slot>,
|
||||
React.ComponentPropsWithoutRef<typeof Slot>
|
||||
>(({ ...props }, ref) => {
|
||||
const { error, formItemId, formDescriptionId, formMessageId } = useFormField()
|
||||
|
||||
return (
|
||||
<Slot
|
||||
ref={ref}
|
||||
id={formItemId}
|
||||
aria-describedby={
|
||||
!error
|
||||
? `${formDescriptionId}`
|
||||
: `${formDescriptionId} ${formMessageId}`
|
||||
}
|
||||
aria-invalid={!!error}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
})
|
||||
FormControl.displayName = "FormControl"
|
||||
|
||||
const FormDescription = React.forwardRef<
|
||||
HTMLParagraphElement,
|
||||
React.HTMLAttributes<HTMLParagraphElement>
|
||||
>(({ className, ...props }, ref) => {
|
||||
const { formDescriptionId } = useFormField()
|
||||
|
||||
return (
|
||||
<p
|
||||
ref={ref}
|
||||
id={formDescriptionId}
|
||||
className={cn("text-sm text-muted-foreground", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
})
|
||||
FormDescription.displayName = "FormDescription"
|
||||
|
||||
const FormMessage = React.forwardRef<
|
||||
HTMLParagraphElement,
|
||||
React.HTMLAttributes<HTMLParagraphElement>
|
||||
>(({ className, children, ...props }, ref) => {
|
||||
const { error, formMessageId } = useFormField()
|
||||
const body = error ? String(error?.message) : children
|
||||
|
||||
if (!body) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<p
|
||||
ref={ref}
|
||||
id={formMessageId}
|
||||
className={cn("text-sm font-medium text-destructive", className)}
|
||||
{...props}
|
||||
>
|
||||
{body}
|
||||
</p>
|
||||
)
|
||||
})
|
||||
FormMessage.displayName = "FormMessage"
|
||||
|
||||
export {
|
||||
useFormField,
|
||||
Form,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormControl,
|
||||
FormDescription,
|
||||
FormMessage,
|
||||
FormField,
|
||||
}
|
26
components/ui/label.tsx
Normal file
26
components/ui/label.tsx
Normal file
|
@ -0,0 +1,26 @@
|
|||
"use client"
|
||||
|
||||
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"
|
||||
|
||||
const labelVariants = cva(
|
||||
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
|
||||
)
|
||||
|
||||
const Label = React.forwardRef<
|
||||
React.ElementRef<typeof LabelPrimitive.Root>,
|
||||
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &
|
||||
VariantProps<typeof labelVariants>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<LabelPrimitive.Root
|
||||
ref={ref}
|
||||
className={cn(labelVariants(), className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
Label.displayName = LabelPrimitive.Root.displayName
|
||||
|
||||
export { Label }
|
|
@ -1,4 +1,5 @@
|
|||
import { BadgeAlert, BarChart4, Cog, ShieldCheck } from "lucide-react";
|
||||
import { Download, Home, Settings, User } from "lucide-react";
|
||||
|
||||
export const NAVBAR = {
|
||||
centerLinks: [
|
||||
|
@ -95,7 +96,7 @@ export const questions = [
|
|||
key: "item-3",
|
||||
question: "How was SVR.JS created?",
|
||||
answer:
|
||||
"Someone in 2018 wanted to create a website, but he didn't know about setting up popular web server software like Apache httpd, NGINX, or IIS... So he created his own web server in Node.JS to serve his website! And he saved it in a file called svr.js. Since then, this web server has been gradually turned from a web server intended for one website into a general-purpose web server, which is what SVR.JS is today!",
|
||||
"Someone in 2018 wanted to create a website, but he didnt know about setting up popular web server software like Apache httpd, NGINX, or IIS... So he created his own web server in Node.JS to serve his website! And he saved it in a file called svr.js. Since then, this web server has been gradually turned from a web server intended for one website into a general-purpose web server, which is what SVR.JS is today!",
|
||||
},
|
||||
{
|
||||
key: "item-4",
|
||||
|
@ -107,7 +108,7 @@ export const questions = [
|
|||
key: "item-5",
|
||||
question: "What is Node.JS?",
|
||||
answer:
|
||||
"Node.JS is an asynchronous event-driven JavaScript runtime built on Chromium's V8 engine. Node.JS is designed to build scalable network applications.",
|
||||
"Node.JS is an asynchronous event-driven JavaScript runtime built on Chromiums V8 engine. Node.JS is designed to build scalable network applications.",
|
||||
},
|
||||
{
|
||||
key: "item-6",
|
||||
|
@ -145,6 +146,34 @@ export const FOOTERLINKS = {
|
|||
},
|
||||
};
|
||||
|
||||
export const AdminLinks = [
|
||||
{
|
||||
name: "Dashboard",
|
||||
url: "/admin",
|
||||
icon: Home,
|
||||
},
|
||||
{
|
||||
name: "Downloads",
|
||||
url: "/admin/downloads",
|
||||
icon: Download,
|
||||
},
|
||||
{
|
||||
name: "Mods",
|
||||
url: "/admin/mods",
|
||||
icon: User,
|
||||
},
|
||||
{
|
||||
name: "Logs",
|
||||
url: "/admin/changelogs",
|
||||
icon: Settings,
|
||||
},
|
||||
{
|
||||
name: "Back Home",
|
||||
url: "/",
|
||||
icon: Home,
|
||||
},
|
||||
];
|
||||
|
||||
export const TERMS_AND_CONDITIONS = `
|
||||
Last updated: 24.04.2024
|
||||
|
||||
|
|
24
lib/db.ts
Normal file
24
lib/db.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
import { MongoClient } from "mongodb";
|
||||
|
||||
if (!process.env.MONGODB_URI) {
|
||||
throw new Error('Invalid/Missing environment variable: "MONGODB_URI"');
|
||||
}
|
||||
|
||||
const uri = process.env.MONGODB_URI;
|
||||
const options = {};
|
||||
|
||||
let client;
|
||||
let clientPromise: Promise<MongoClient>;
|
||||
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
if (!(global as any)._mongoClientPromise) {
|
||||
client = new MongoClient(uri!, options);
|
||||
(global as any)._mongoClientPromise = client.connect();
|
||||
}
|
||||
clientPromise = (global as any)._mongoClientPromise;
|
||||
} else {
|
||||
client = new MongoClient(uri!, options);
|
||||
clientPromise = client.connect();
|
||||
}
|
||||
|
||||
export default clientPromise;
|
9
lib/uploadthing.ts
Normal file
9
lib/uploadthing.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
import {
|
||||
generateUploadButton,
|
||||
generateUploadDropzone,
|
||||
} from "@uploadthing/react";
|
||||
|
||||
import type { OurFileRouter } from "@/app/api/uploadthing/core";
|
||||
|
||||
export const UploadButton = generateUploadButton<OurFileRouter>();
|
||||
export const UploadDropzone = generateUploadDropzone<OurFileRouter>();
|
8
lib/validations/validation.ts
Normal file
8
lib/validations/validation.ts
Normal file
|
@ -0,0 +1,8 @@
|
|||
import { z } from "zod";
|
||||
|
||||
export const downloadSchema = z.object({
|
||||
fileName: z.string().nonempty(),
|
||||
version: z.string().nonempty(),
|
||||
downloadLink: z.string().url().nonempty(),
|
||||
fileSize: z.string().nonempty(),
|
||||
});
|
21
middleware.ts
Normal file
21
middleware.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
import { NextResponse } from "next/server";
|
||||
import type { NextRequest } from "next/server";
|
||||
|
||||
export function middleware(req: NextRequest) {
|
||||
const url = req.nextUrl.clone();
|
||||
|
||||
if (url.pathname.startsWith("/admin")) {
|
||||
const authCookie = req.cookies.get("auth");
|
||||
|
||||
if (!authCookie) {
|
||||
url.pathname = "/login";
|
||||
return NextResponse.redirect(url);
|
||||
}
|
||||
}
|
||||
|
||||
return NextResponse.next();
|
||||
}
|
||||
|
||||
export const config = {
|
||||
matcher: ["/admin/:path*"],
|
||||
};
|
698
package-lock.json
generated
698
package-lock.json
generated
|
@ -11,24 +11,33 @@
|
|||
"@fortawesome/fontawesome-svg-core": "^6.5.2",
|
||||
"@fortawesome/free-regular-svg-icons": "^6.5.2",
|
||||
"@fortawesome/react-fontawesome": "^0.2.2",
|
||||
"@hookform/resolvers": "^3.6.0",
|
||||
"@radix-ui/react-accordion": "^1.1.2",
|
||||
"@radix-ui/react-dialog": "^1.0.5",
|
||||
"@radix-ui/react-dropdown-menu": "^2.0.6",
|
||||
"@radix-ui/react-label": "^2.1.0",
|
||||
"@radix-ui/react-navigation-menu": "^1.1.4",
|
||||
"@radix-ui/react-slot": "^1.0.2",
|
||||
"@radix-ui/react-slot": "^1.1.0",
|
||||
"@radix-ui/themes": "^3.0.5",
|
||||
"@types/cookie": "^0.6.0",
|
||||
"@uploadthing/react": "^6.6.0",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.1.1",
|
||||
"cookie": "^0.6.0",
|
||||
"framer-motion": "^11.2.10",
|
||||
"lucide-react": "^0.394.0",
|
||||
"mini-svg-data-uri": "^1.4.4",
|
||||
"mongoose": "^8.4.3",
|
||||
"next": "14.2.3",
|
||||
"next-themes": "^0.3.0",
|
||||
"react": "^18",
|
||||
"react-dom": "^18",
|
||||
"react-fontawesome": "^1.7.1",
|
||||
"react-hook-form": "^7.52.0",
|
||||
"tailwind-merge": "^2.3.0",
|
||||
"tailwindcss-animate": "^1.0.7"
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"uploadthing": "^6.12.0",
|
||||
"zod": "^3.23.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20",
|
||||
|
@ -63,6 +72,16 @@
|
|||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@effect/schema": {
|
||||
"version": "0.66.16",
|
||||
"resolved": "https://registry.npmjs.org/@effect/schema/-/schema-0.66.16.tgz",
|
||||
"integrity": "sha512-sT/k5NOgKslGPzs3DUaCFuM6g2JQoIIT8jpwEorAZooplPIMK2xIspr7ECz6pp6Dc7Wz/ppXGk7HVyGZQsIYEQ==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"effect": "^3.1.3",
|
||||
"fast-check": "^3.13.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint-community/eslint-utils": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
|
||||
|
@ -198,6 +217,15 @@
|
|||
"react": ">=16.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@hookform/resolvers": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.6.0.tgz",
|
||||
"integrity": "sha512-UBcpyOX3+RR+dNnqBd0lchXpoL8p4xC21XP8H6Meb8uve5Br1GCnmg0PcBoKKqPKgGu9GHQ/oygcmPrQhetwqw==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"react-hook-form": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@humanwhocodes/config-array": {
|
||||
"version": "0.11.14",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
|
||||
|
@ -317,6 +345,15 @@
|
|||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||
}
|
||||
},
|
||||
"node_modules/@mongodb-js/saslprep": {
|
||||
"version": "1.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.7.tgz",
|
||||
"integrity": "sha512-dCHW/oEX0KJ4NjDULBo3JiOaK5+6axtpBbS+ao2ZInoAL9/YRQLhXzSNAFz7hP4nzLkIqsfYAK/PDE3+XHny0Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"sparse-bitfield": "^3.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/env": {
|
||||
"version": "14.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.3.tgz",
|
||||
|
@ -611,6 +648,25 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-alert-dialog/node_modules/@radix-ui/react-slot": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz",
|
||||
"integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/react-compose-refs": "1.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-arrow": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.0.3.tgz",
|
||||
|
@ -770,6 +826,25 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-slot": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz",
|
||||
"integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/react-compose-refs": "1.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-compose-refs": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz",
|
||||
|
@ -869,6 +944,25 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-slot": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz",
|
||||
"integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/react-compose-refs": "1.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-direction": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.0.1.tgz",
|
||||
|
@ -1012,6 +1106,30 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-form/node_modules/@radix-ui/react-label": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.0.2.tgz",
|
||||
"integrity": "sha512-N5ehvlM7qoTLx7nWPodsPYPgMzA5WM8zZChQg8nyFJKnDO5WHdba1vv5/H6IO5LtJMfD2Q3wh1qHFGNtK0w3bQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/react-primitive": "1.0.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-hover-card": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-hover-card/-/react-hover-card-1.0.7.tgz",
|
||||
|
@ -1062,18 +1180,41 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-label": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.0.2.tgz",
|
||||
"integrity": "sha512-N5ehvlM7qoTLx7nWPodsPYPgMzA5WM8zZChQg8nyFJKnDO5WHdba1vv5/H6IO5LtJMfD2Q3wh1qHFGNtK0w3bQ==",
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.0.tgz",
|
||||
"integrity": "sha512-peLblDlFw/ngk3UWq0VnYaOLy6agTZZ+MUO/WhVfm14vJGML+xH4FAl2XQGLqdefjNb7ApRg6Yn7U42ZhmYXdw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/react-primitive": "1.0.3"
|
||||
"@radix-ui/react-primitive": "2.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-label/node_modules/@radix-ui/react-primitive": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz",
|
||||
"integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-slot": "1.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
|
@ -1124,6 +1265,25 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-slot": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz",
|
||||
"integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/react-compose-refs": "1.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-navigation-menu": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-navigation-menu/-/react-navigation-menu-1.1.4.tgz",
|
||||
|
@ -1197,6 +1357,25 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-popover/node_modules/@radix-ui/react-slot": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz",
|
||||
"integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/react-compose-refs": "1.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-popper": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.1.3.tgz",
|
||||
|
@ -1299,6 +1478,25 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-primitive/node_modules/@radix-ui/react-slot": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz",
|
||||
"integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/react-compose-refs": "1.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-progress": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.0.3.tgz",
|
||||
|
@ -1460,6 +1658,25 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-slot": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz",
|
||||
"integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/react-compose-refs": "1.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-slider": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slider/-/react-slider-1.1.2.tgz",
|
||||
|
@ -1494,16 +1711,31 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-slot": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz",
|
||||
"integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==",
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz",
|
||||
"integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/react-compose-refs": "1.0.1"
|
||||
"@radix-ui/react-compose-refs": "1.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0"
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-slot/node_modules/@radix-ui/react-compose-refs": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz",
|
||||
"integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
|
@ -1658,6 +1890,25 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-slot": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz",
|
||||
"integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/react-compose-refs": "1.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-use-callback-ref": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz",
|
||||
|
@ -1909,6 +2160,11 @@
|
|||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/cookie": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
|
||||
"integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="
|
||||
},
|
||||
"node_modules/@types/json5": {
|
||||
"version": "0.0.29",
|
||||
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
|
||||
|
@ -1949,6 +2205,21 @@
|
|||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/webidl-conversions": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz",
|
||||
"integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/whatwg-url": {
|
||||
"version": "11.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz",
|
||||
"integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/webidl-conversions": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.2.0.tgz",
|
||||
|
@ -2082,6 +2353,74 @@
|
|||
"integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@uploadthing/dropzone": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@uploadthing/dropzone/-/dropzone-0.4.1.tgz",
|
||||
"integrity": "sha512-RHSpo/2kg/mrRSYQA4EKlyvkOCYWOeE2+QQYW9YiUvWCuawnTfD7DQvk8RN/nYXi1Sw7/v0NegmQpiVELVGtnA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"file-selector": "^0.6.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
||||
"solid-js": "^1.7.11",
|
||||
"svelte": "^4.2.12",
|
||||
"vue": "^3.4.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"react": {
|
||||
"optional": true
|
||||
},
|
||||
"solid-js": {
|
||||
"optional": true
|
||||
},
|
||||
"svelte": {
|
||||
"optional": true
|
||||
},
|
||||
"vue": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@uploadthing/mime-types": {
|
||||
"version": "0.2.10",
|
||||
"resolved": "https://registry.npmjs.org/@uploadthing/mime-types/-/mime-types-0.2.10.tgz",
|
||||
"integrity": "sha512-kz3F0oEgAyts25NAGXlUBCWh3mXonbSOQJFGFMawHuIgbUbnzXbe4w5WI+0XdneCbjNmikfWrdWrs8m/7HATfQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@uploadthing/react": {
|
||||
"version": "6.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@uploadthing/react/-/react-6.6.0.tgz",
|
||||
"integrity": "sha512-jLN4Oy21d0n8F6CNPl9qjEu0/Q1rnddSxny/02Lm89L/sYuR4RXfk1vBgBGPAGXBak0BO9z5eEmYURLrXXUAJQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uploadthing/dropzone": "0.4.1",
|
||||
"@uploadthing/shared": "6.7.5",
|
||||
"file-selector": "^0.6.0",
|
||||
"tailwind-merge": "^2.2.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"next": "*",
|
||||
"react": "^17.0.2 || ^18.0.0",
|
||||
"uploadthing": "6.12.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"next": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@uploadthing/shared": {
|
||||
"version": "6.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@uploadthing/shared/-/shared-6.7.5.tgz",
|
||||
"integrity": "sha512-BZXzvh6zGEt4ip//mxfXdRTNWYw9XJ6tommL6A1TEo2l8jvdNbUpPUwXnMVWBMwio2b48BO7D9V3siYIKMD4pg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uploadthing/mime-types": "0.2.10",
|
||||
"effect": "^3.1.0",
|
||||
"std-env": "^3.7.0"
|
||||
}
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.11.3",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
|
||||
|
@ -2436,6 +2775,15 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/bson": {
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/bson/-/bson-6.7.0.tgz",
|
||||
"integrity": "sha512-w2IquM5mYzYZv6rs3uN2DZTOBe2a0zXLj53TGDqwF4l6Sz/XsISrisXOJihArF9+BZ6Cq/GjVht7Sjfmri7ytQ==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=16.20.1"
|
||||
}
|
||||
},
|
||||
"node_modules/busboy": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
|
||||
|
@ -2620,6 +2968,23 @@
|
|||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/consola": {
|
||||
"version": "3.2.3",
|
||||
"resolved": "https://registry.npmjs.org/consola/-/consola-3.2.3.tgz",
|
||||
"integrity": "sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^14.18.0 || >=16.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cookie": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
|
||||
"integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
||||
|
@ -2711,7 +3076,6 @@
|
|||
"version": "4.3.5",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz",
|
||||
"integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ms": "2.1.2"
|
||||
},
|
||||
|
@ -2817,6 +3181,12 @@
|
|||
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
|
||||
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
|
||||
},
|
||||
"node_modules/effect": {
|
||||
"version": "3.3.5",
|
||||
"resolved": "https://registry.npmjs.org/effect/-/effect-3.3.5.tgz",
|
||||
"integrity": "sha512-ehDpb+3zRTYsCqDWY32rT4oxtG0BJ797+HSog+FPjiWKjNxnPgpslUIQha8CoxqFZln2ZeBRv00tzGIhUAQKsw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/emoji-regex": {
|
||||
"version": "9.2.2",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
|
||||
|
@ -3417,6 +3787,28 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-check": {
|
||||
"version": "3.19.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.19.0.tgz",
|
||||
"integrity": "sha512-CO2JX/8/PT9bDGO1iXa5h5ey1skaKI1dvecERyhH4pp3PGjwd3KIjMAXEg79Ps9nclsdt4oPbfqiAnLU0EwrAQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/dubzzz"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/fast-check"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"pure-rand": "^6.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
|
@ -3481,6 +3873,18 @@
|
|||
"node": "^10.12.0 || >=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/file-selector": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/file-selector/-/file-selector-0.6.0.tgz",
|
||||
"integrity": "sha512-QlZ5yJC0VxHxQQsQhXvBaC7VRJ2uaxTf+Tfpu4Z/OcVQJVpZO+DGU0rkoVW5ce2SccxugvpBJoMvUs59iILYdw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tslib": "^2.4.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 12"
|
||||
}
|
||||
},
|
||||
"node_modules/fill-range": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
||||
|
@ -4440,6 +4844,15 @@
|
|||
"node": ">=4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/kareem": {
|
||||
"version": "2.6.3",
|
||||
"resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz",
|
||||
"integrity": "sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/keyv": {
|
||||
"version": "4.5.4",
|
||||
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
|
||||
|
@ -4541,6 +4954,12 @@
|
|||
"react": "^16.5.1 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/memory-pager": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
|
||||
"integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/merge2": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
|
||||
|
@ -4599,11 +5018,115 @@
|
|||
"node": ">=16 || 14 >=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/mongodb": {
|
||||
"version": "6.6.2",
|
||||
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.6.2.tgz",
|
||||
"integrity": "sha512-ZF9Ugo2JCG/GfR7DEb4ypfyJJyiKbg5qBYKRintebj8+DNS33CyGMkWbrS9lara+u+h+yEOGSRiLhFO/g1s1aw==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@mongodb-js/saslprep": "^1.1.5",
|
||||
"bson": "^6.7.0",
|
||||
"mongodb-connection-string-url": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.20.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@aws-sdk/credential-providers": "^3.188.0",
|
||||
"@mongodb-js/zstd": "^1.1.0",
|
||||
"gcp-metadata": "^5.2.0",
|
||||
"kerberos": "^2.0.1",
|
||||
"mongodb-client-encryption": ">=6.0.0 <7",
|
||||
"snappy": "^7.2.2",
|
||||
"socks": "^2.7.1"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@aws-sdk/credential-providers": {
|
||||
"optional": true
|
||||
},
|
||||
"@mongodb-js/zstd": {
|
||||
"optional": true
|
||||
},
|
||||
"gcp-metadata": {
|
||||
"optional": true
|
||||
},
|
||||
"kerberos": {
|
||||
"optional": true
|
||||
},
|
||||
"mongodb-client-encryption": {
|
||||
"optional": true
|
||||
},
|
||||
"snappy": {
|
||||
"optional": true
|
||||
},
|
||||
"socks": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/mongodb-connection-string-url": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.1.tgz",
|
||||
"integrity": "sha512-XqMGwRX0Lgn05TDB4PyG2h2kKO/FfWJyCzYQbIhXUxz7ETt0I/FqHjUeqj37irJ+Dl1ZtU82uYyj14u2XsZKfg==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@types/whatwg-url": "^11.0.2",
|
||||
"whatwg-url": "^13.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mongoose": {
|
||||
"version": "8.4.3",
|
||||
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.4.3.tgz",
|
||||
"integrity": "sha512-GxPVLD+I/dxVkgcts2r2QmJJvS62/++btVj3RFt8YnHt+DSOp1Qjj62YEvgZaElwIOTcc4KGJM95X5LlrU1qQg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"bson": "^6.7.0",
|
||||
"kareem": "2.6.3",
|
||||
"mongodb": "6.6.2",
|
||||
"mpath": "0.9.0",
|
||||
"mquery": "5.0.0",
|
||||
"ms": "2.1.3",
|
||||
"sift": "17.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.20.1"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/mongoose"
|
||||
}
|
||||
},
|
||||
"node_modules/mongoose/node_modules/ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/mpath": {
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz",
|
||||
"integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mquery": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz",
|
||||
"integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"debug": "4.x"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||
"dev": true
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"node_modules/mz": {
|
||||
"version": "2.7.0",
|
||||
|
@ -5191,11 +5714,26 @@
|
|||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/pure-rand": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz",
|
||||
"integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/dubzzz"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/fast-check"
|
||||
}
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/queue-microtask": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
|
||||
|
@ -5252,6 +5790,22 @@
|
|||
"react": ">=0.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-hook-form": {
|
||||
"version": "7.52.0",
|
||||
"resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.52.0.tgz",
|
||||
"integrity": "sha512-mJX506Xc6mirzLsmXUJyqlAI3Kj9Ph2RhplYhUVffeOQSnubK2uVqBFOBJmvKikvbFV91pxVXmDiR+QMF19x6A==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12.22.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/react-hook-form"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17 || ^18 || ^19"
|
||||
}
|
||||
},
|
||||
"node_modules/react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
|
@ -5613,6 +6167,12 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/sift": {
|
||||
"version": "17.1.3",
|
||||
"resolved": "https://registry.npmjs.org/sift/-/sift-17.1.3.tgz",
|
||||
"integrity": "sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/signal-exit": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
|
||||
|
@ -5641,6 +6201,21 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/sparse-bitfield": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
|
||||
"integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"memory-pager": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/std-env": {
|
||||
"version": "3.7.0",
|
||||
"resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz",
|
||||
"integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/streamsearch": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
|
||||
|
@ -5996,6 +6571,18 @@
|
|||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tr46": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz",
|
||||
"integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"punycode": "^2.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-api-utils": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz",
|
||||
|
@ -6161,6 +6748,48 @@
|
|||
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/uploadthing": {
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/uploadthing/-/uploadthing-6.12.0.tgz",
|
||||
"integrity": "sha512-uoWG1riH6z2IHCcbMo3xnGe6p/+sx2PPOOLOsk5DeqGv5HtlY7ISauFFRXW8H+jdhevZm1n/j4Je/Z+bbIziSg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@effect/schema": "^0.66.12",
|
||||
"@uploadthing/mime-types": "0.2.10",
|
||||
"@uploadthing/shared": "6.7.5",
|
||||
"consola": "^3.2.3",
|
||||
"effect": "^3.1.0",
|
||||
"fast-check": "^3.18.0",
|
||||
"std-env": "^3.7.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.13.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"express": "*",
|
||||
"fastify": "*",
|
||||
"h3": "*",
|
||||
"next": "*",
|
||||
"tailwindcss": "*"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"express": {
|
||||
"optional": true
|
||||
},
|
||||
"fastify": {
|
||||
"optional": true
|
||||
},
|
||||
"h3": {
|
||||
"optional": true
|
||||
},
|
||||
"next": {
|
||||
"optional": true
|
||||
},
|
||||
"tailwindcss": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/uri-js": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||
|
@ -6216,6 +6845,28 @@
|
|||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
|
||||
},
|
||||
"node_modules/webidl-conversions": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
|
||||
"integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/whatwg-url": {
|
||||
"version": "13.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz",
|
||||
"integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tr46": "^4.1.1",
|
||||
"webidl-conversions": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
|
@ -6433,6 +7084,15 @@
|
|||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/zod": {
|
||||
"version": "3.23.8",
|
||||
"resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz",
|
||||
"integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/colinhacks"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
14
package.json
14
package.json
|
@ -12,26 +12,34 @@
|
|||
"@fortawesome/fontawesome-svg-core": "^6.5.2",
|
||||
"@fortawesome/free-regular-svg-icons": "^6.5.2",
|
||||
"@fortawesome/react-fontawesome": "^0.2.2",
|
||||
"@hookform/resolvers": "^3.6.0",
|
||||
"@radix-ui/react-accordion": "^1.1.2",
|
||||
"@radix-ui/react-dialog": "^1.0.5",
|
||||
"@radix-ui/react-dropdown-menu": "^2.0.6",
|
||||
"@radix-ui/react-label": "^2.1.0",
|
||||
"@radix-ui/react-navigation-menu": "^1.1.4",
|
||||
"@radix-ui/react-slot": "^1.0.2",
|
||||
"@radix-ui/react-slot": "^1.1.0",
|
||||
"@radix-ui/themes": "^3.0.5",
|
||||
"@types/cookie": "^0.6.0",
|
||||
"@uploadthing/react": "^6.6.0",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.1.1",
|
||||
"dotenv": "^16.4.5",
|
||||
"cookie": "^0.6.0",
|
||||
"framer-motion": "^11.2.10",
|
||||
"lucide-react": "^0.394.0",
|
||||
"mini-svg-data-uri": "^1.4.4",
|
||||
"mongoose": "^8.4.3",
|
||||
"next": "14.2.3",
|
||||
"next-themes": "^0.3.0",
|
||||
"nookies": "^2.5.2",
|
||||
"react": "^18",
|
||||
"react-dom": "^18",
|
||||
"react-fontawesome": "^1.7.1",
|
||||
"react-hook-form": "^7.52.0",
|
||||
"tailwind-merge": "^2.3.0",
|
||||
"tailwindcss-animate": "^1.0.7"
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"uploadthing": "^6.12.0",
|
||||
"zod": "^3.23.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20",
|
||||
|
|
Loading…
Reference in a new issue