From afd59acf5de987c3f32a05ccbc644b6d53f8004c Mon Sep 17 00:00:00 2001 From: Christopher Arraya Date: Sun, 30 Jul 2023 01:01:08 -0400 Subject: [PATCH] feat: supabase psql setup + projects functionality --- app/api/projects/route.ts | 83 +++++++ app/projects/[id]/page.tsx | 0 app/projects/page.tsx | 189 ++++++++++++++++ components/ui/dialog.tsx | 123 +++++++++++ lib/prisma.ts | 5 + package.json | 3 + pnpm-lock.yaml | 383 +++++++++++++++++++++++++++++++- prisma/schema.prisma | 433 ++++++++++++++++++++++++++++++++++++- types/models.ts | 7 + types/supabase.ts | 282 ++++++++++++++++++++++++ 10 files changed, 1502 insertions(+), 6 deletions(-) create mode 100644 app/api/projects/route.ts create mode 100644 app/projects/[id]/page.tsx create mode 100644 app/projects/page.tsx create mode 100644 components/ui/dialog.tsx create mode 100644 lib/prisma.ts create mode 100644 types/models.ts create mode 100644 types/supabase.ts diff --git a/app/api/projects/route.ts b/app/api/projects/route.ts new file mode 100644 index 0000000..1cf36fa --- /dev/null +++ b/app/api/projects/route.ts @@ -0,0 +1,83 @@ +import { createRouteHandlerClient } from "@supabase/auth-helpers-nextjs"; +import { Database } from "@/types/supabase"; +import prisma from "@/lib/prisma"; +import { NextResponse, NextRequest } from "next/server"; +import { revalidatePath } from "next/cache"; +import { cookies } from "next/headers"; + +export async function GET(req: NextRequest) { + try { + const supabase = createRouteHandlerClient({ cookies }); + + const { + data: { session }, + } = await supabase.auth.getSession(); + + if (!session) { + throw new Error("Unauthorized"); + } + + const userProjects = await prisma.userProfile.findUnique({ + where: { id: session.user.id }, + include: { UserProfile_Project: { include: { Project: true } } }, + }); + + const res = userProjects?.UserProfile_Project.map((relation) => ({ + ...relation.Project, + id: String(relation.Project.id), + })); + + const path = req.nextUrl.searchParams.get("path") || "/"; + revalidatePath(path); + + return NextResponse.json(res, { status: 200 }); + } catch (err: any) { + return NextResponse.json({ message: err.message }, { status: 401 }); + } finally { + await prisma.$disconnect(); + } +} + +export async function POST(req: NextRequest) { + try { + const supabase = createRouteHandlerClient({ cookies }); + + const { + data: { session }, + } = await supabase.auth.getSession(); + + if (!session) { + throw new Error("Unauthorized"); + } + + const { title, description, github, stack } = await req.json(); + + const newProject = await prisma.project.create({ + data: { + title, + description, + github, + stack, + }, + }); + + await prisma.userProfile_Project.create({ + data: { + userProfileId: session.user.id, + projectId: newProject.id, + }, + }); + + const res = { + ...newProject, + id: String(newProject.id), + }; + + return NextResponse.json(res, { status: 201 }); + } catch (err: any) { + console.log(err); + return NextResponse.json({ message: err.message }, { status: 500 }); + } finally { + await prisma.$disconnect(); + } +} diff --git a/app/projects/[id]/page.tsx b/app/projects/[id]/page.tsx new file mode 100644 index 0000000..e69de29 diff --git a/app/projects/page.tsx b/app/projects/page.tsx new file mode 100644 index 0000000..78feda0 --- /dev/null +++ b/app/projects/page.tsx @@ -0,0 +1,189 @@ +"use client"; +import { useState, useEffect } from "react"; +import { Project } from "@/types/models"; +import { Button, buttonVariants } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog"; +import { + Form, + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "@/components/ui/form"; +import { useForm } from "react-hook-form"; +import { zodResolver } from "@hookform/resolvers/zod"; +import * as z from "zod"; + +const projectSchema = z.object({ + title: z.string().min(3, "Title must be at least 3 characters"), + description: z.string().min(10, "Description must be at least 10 characters"), + github: z.string().url("Invalid URL").optional(), + stack: z.string().array(), +}); + +export default function Projects() { + const [projects, setProjects] = useState([]); + const [stackInput, setStackInput] = useState(""); + const [loading, setLoading] = useState(true); + const [open, setOpen] = useState(false); + const form = useForm>({ + resolver: zodResolver(projectSchema), + defaultValues: { + title: "", + description: "", + github: "", + stack: [], + }, + }); + + const { setValue } = form; + + const fetchProjects = async () => { + try { + setLoading(true); + const res = await fetch("/api/projects"); + if (!res.ok) throw new Error("HTTP status " + res.status); + const data = await res.json(); + setProjects(data); + setLoading(false); + } catch (err) { + console.error("Failed to fetch projects:", err); + } + }; + + useEffect(() => { + fetchProjects(); + }, []); + + async function handleSubmit(values: z.infer) { + console.log(values); + try { + console.log(); + const res = await fetch("/api/projects", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(values), + }); + + if (!res.ok) throw new Error("HTTP status " + res.status); + const newProject = await res.json(); + setProjects([...projects, newProject]); + setOpen(false); + } catch (err) { + console.error("Failed to create project:", err); + } + } + + const keyHandler = (e: React.KeyboardEvent) => { + if (e.key === "Enter" || e.key === "Tab") { + e.preventDefault(); + setValue("stack", [...form.getValues("stack"), stackInput]); + setStackInput(""); + } + }; + + return ( +
+

Projects

+ + + Open + + + + Add Project + +
+ + ( + + Project Title + + + + + + )} + /> + ( + + Project Description + + + + + + )} + /> + ( + + Github Repository URL + + + + + + )} + /> + ( + + Tech Stack + + setStackInput(e.target.value)} + onKeyDown={keyHandler} + /> + + + + )} + /> + + + +
+
+
+
+ {loading ? ( +

Loading...

+ ) : ( +
+ {projects.map((project) => ( +
+

{project.title}

+

{project.description}

+
+ ))} +
+ )} +
+ ); +} diff --git a/components/ui/dialog.tsx b/components/ui/dialog.tsx new file mode 100644 index 0000000..2f33766 --- /dev/null +++ b/components/ui/dialog.tsx @@ -0,0 +1,123 @@ +"use client" + +import * as React from "react" +import * as DialogPrimitive from "@radix-ui/react-dialog" +import { X } from "lucide-react" + +import { cn } from "@/lib/utils" + +const Dialog = DialogPrimitive.Root + +const DialogTrigger = DialogPrimitive.Trigger + +const DialogPortal = ({ + className, + ...props +}: DialogPrimitive.DialogPortalProps) => ( + +) +DialogPortal.displayName = DialogPrimitive.Portal.displayName + +const DialogOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogOverlay.displayName = DialogPrimitive.Overlay.displayName + +const DialogContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + {children} + + + Close + + + +)) +DialogContent.displayName = DialogPrimitive.Content.displayName + +const DialogHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +DialogHeader.displayName = "DialogHeader" + +const DialogFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +DialogFooter.displayName = "DialogFooter" + +const DialogTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogTitle.displayName = DialogPrimitive.Title.displayName + +const DialogDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogDescription.displayName = DialogPrimitive.Description.displayName + +export { + Dialog, + DialogTrigger, + DialogContent, + DialogHeader, + DialogFooter, + DialogTitle, + DialogDescription, +} diff --git a/lib/prisma.ts b/lib/prisma.ts new file mode 100644 index 0000000..b5bf6ce --- /dev/null +++ b/lib/prisma.ts @@ -0,0 +1,5 @@ +import { PrismaClient } from "@prisma/client"; + +const prisma = new PrismaClient(); + +export default prisma; diff --git a/package.json b/package.json index 4f22eaf..4f88710 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,8 @@ }, "dependencies": { "@hookform/resolvers": "^3.1.1", + "@prisma/client": "5.0.0", + "@radix-ui/react-dialog": "^1.0.4", "@radix-ui/react-label": "^2.0.2", "@radix-ui/react-slot": "^1.0.2", "@supabase/auth-helpers-nextjs": "^0.7.3", @@ -28,6 +30,7 @@ "react": "18.2.0", "react-dom": "18.2.0", "react-hook-form": "^7.45.2", + "swr": "^2.2.0", "tailwind-merge": "^1.14.0", "tailwindcss": "3.3.3", "tailwindcss-animate": "^1.0.6", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c014bc8..a36b6c4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,12 @@ dependencies: '@hookform/resolvers': specifier: ^3.1.1 version: 3.1.1(react-hook-form@7.45.2) + '@prisma/client': + specifier: 5.0.0 + version: 5.0.0(prisma@5.0.0) + '@radix-ui/react-dialog': + specifier: ^1.0.4 + version: 1.0.4(@types/react-dom@18.2.7)(@types/react@18.2.16)(react-dom@18.2.0)(react@18.2.0) '@radix-ui/react-label': specifier: ^2.0.2 version: 2.0.2(@types/react-dom@18.2.7)(@types/react@18.2.16)(react-dom@18.2.0)(react@18.2.0) @@ -62,6 +68,9 @@ dependencies: react-hook-form: specifier: ^7.45.2 version: 7.45.2(react@18.2.0) + swr: + specifier: ^2.2.0 + version: 2.2.0(react@18.2.0) tailwind-merge: specifier: ^1.14.0 version: 1.14.0 @@ -328,10 +337,33 @@ packages: tslib: 2.6.1 dev: false + /@prisma/client@5.0.0(prisma@5.0.0): + resolution: {integrity: sha512-XlO5ELNAQ7rV4cXIDJUNBEgdLwX3pjtt9Q/RHqDpGf43szpNJx2hJnggfFs7TKNx0cOFsl6KJCSfqr5duEU/bQ==} + engines: {node: '>=16.13'} + requiresBuild: true + peerDependencies: + prisma: '*' + peerDependenciesMeta: + prisma: + optional: true + dependencies: + '@prisma/engines-version': 4.17.0-26.6b0aef69b7cdfc787f822ecd7cdc76d5f1991584 + prisma: 5.0.0 + dev: false + + /@prisma/engines-version@4.17.0-26.6b0aef69b7cdfc787f822ecd7cdc76d5f1991584: + resolution: {integrity: sha512-HHiUF6NixsldsP3JROq07TYBLEjXFKr6PdH8H4gK/XAoTmIplOJBCgrIUMrsRAnEuGyRoRLXKXWUb943+PFoKQ==} + dev: false + /@prisma/engines@5.0.0: resolution: {integrity: sha512-kyT/8fd0OpWmhAU5YnY7eP31brW1q1YrTGoblWrhQJDiN/1K+Z8S1kylcmtjqx5wsUGcP1HBWutayA/jtyt+sg==} requiresBuild: true - dev: true + + /@radix-ui/primitive@1.0.1: + resolution: {integrity: sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==} + dependencies: + '@babel/runtime': 7.22.6 + dev: false /@radix-ui/react-compose-refs@1.0.1(@types/react@18.2.16)(react@18.2.0): resolution: {integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==} @@ -347,6 +379,131 @@ packages: react: 18.2.0 dev: false + /@radix-ui/react-context@1.0.1(@types/react@18.2.16)(react@18.2.0): + resolution: {integrity: sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.22.6 + '@types/react': 18.2.16 + react: 18.2.0 + dev: false + + /@radix-ui/react-dialog@1.0.4(@types/react-dom@18.2.7)(@types/react@18.2.16)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-hJtRy/jPULGQZceSAP2Re6/4NpKo8im6V8P2hUqZsdFiSL8l35kYsw3qbRI6Ay5mQd2+wlLqje770eq+RJ3yZg==} + 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 + dependencies: + '@babel/runtime': 7.22.6 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.16)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.16)(react@18.2.0) + '@radix-ui/react-dismissable-layer': 1.0.4(@types/react-dom@18.2.7)(@types/react@18.2.16)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.2.16)(react@18.2.0) + '@radix-ui/react-focus-scope': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.16)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.2.16)(react@18.2.0) + '@radix-ui/react-portal': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.16)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.7)(@types/react@18.2.16)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.16)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-slot': 1.0.2(@types/react@18.2.16)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.16)(react@18.2.0) + '@types/react': 18.2.16 + '@types/react-dom': 18.2.7 + aria-hidden: 1.2.3 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-remove-scroll: 2.5.5(@types/react@18.2.16)(react@18.2.0) + dev: false + + /@radix-ui/react-dismissable-layer@1.0.4(@types/react-dom@18.2.7)(@types/react@18.2.16)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-7UpBa/RKMoHJYjie1gkF1DlK8l1fdU/VKDpoS3rCCo8YBJR294GwcEHyxHw72yvphJ7ld0AXEcSLAzY2F/WyCg==} + 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 + dependencies: + '@babel/runtime': 7.22.6 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.16)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.16)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.16)(react@18.2.0) + '@radix-ui/react-use-escape-keydown': 1.0.3(@types/react@18.2.16)(react@18.2.0) + '@types/react': 18.2.16 + '@types/react-dom': 18.2.7 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@radix-ui/react-focus-guards@1.0.1(@types/react@18.2.16)(react@18.2.0): + resolution: {integrity: sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.22.6 + '@types/react': 18.2.16 + react: 18.2.0 + dev: false + + /@radix-ui/react-focus-scope@1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.16)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-upXdPfqI4islj2CslyfUBNlaJCPybbqRHAi1KER7Isel9Q2AtSJ0zRBZv8mWQiFXD2nyAJ4BhC3yXgZ6kMBSrQ==} + 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 + dependencies: + '@babel/runtime': 7.22.6 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.16)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.16)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.16)(react@18.2.0) + '@types/react': 18.2.16 + '@types/react-dom': 18.2.7 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@radix-ui/react-id@1.0.1(@types/react@18.2.16)(react@18.2.0): + resolution: {integrity: sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.22.6 + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.16)(react@18.2.0) + '@types/react': 18.2.16 + react: 18.2.0 + dev: false + /@radix-ui/react-label@2.0.2(@types/react-dom@18.2.7)(@types/react@18.2.16)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-N5ehvlM7qoTLx7nWPodsPYPgMzA5WM8zZChQg8nyFJKnDO5WHdba1vv5/H6IO5LtJMfD2Q3wh1qHFGNtK0w3bQ==} peerDependencies: @@ -368,6 +525,49 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /@radix-ui/react-portal@1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.16)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-xLYZeHrWoPmA5mEKEfZZevoVRK/Q43GfzRXkWV6qawIWWK8t6ifIiLQdd7rmQ4Vk1bmI21XhqF9BN3jWf+phpA==} + 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 + dependencies: + '@babel/runtime': 7.22.6 + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.16)(react-dom@18.2.0)(react@18.2.0) + '@types/react': 18.2.16 + '@types/react-dom': 18.2.7 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@radix-ui/react-presence@1.0.1(@types/react-dom@18.2.7)(@types/react@18.2.16)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==} + 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 + dependencies: + '@babel/runtime': 7.22.6 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.16)(react@18.2.0) + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.16)(react@18.2.0) + '@types/react': 18.2.16 + '@types/react-dom': 18.2.7 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-primitive@1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.16)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==} peerDependencies: @@ -404,6 +604,64 @@ packages: react: 18.2.0 dev: false + /@radix-ui/react-use-callback-ref@1.0.1(@types/react@18.2.16)(react@18.2.0): + resolution: {integrity: sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.22.6 + '@types/react': 18.2.16 + react: 18.2.0 + dev: false + + /@radix-ui/react-use-controllable-state@1.0.1(@types/react@18.2.16)(react@18.2.0): + resolution: {integrity: sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.22.6 + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.16)(react@18.2.0) + '@types/react': 18.2.16 + react: 18.2.0 + dev: false + + /@radix-ui/react-use-escape-keydown@1.0.3(@types/react@18.2.16)(react@18.2.0): + resolution: {integrity: sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.22.6 + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.16)(react@18.2.0) + '@types/react': 18.2.16 + react: 18.2.0 + dev: false + + /@radix-ui/react-use-layout-effect@1.0.1(@types/react@18.2.16)(react@18.2.0): + resolution: {integrity: sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.22.6 + '@types/react': 18.2.16 + react: 18.2.0 + dev: false + /@rushstack/eslint-patch@1.3.2: resolution: {integrity: sha512-V+MvGwaHH03hYhY+k6Ef/xKd6RYlc4q8WBx+2ANmipHJcKuktNcI/NgEsJgdSUF6Lw32njT6OnrRsKYCdgHjYw==} dev: false @@ -646,6 +904,13 @@ packages: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} dev: false + /aria-hidden@1.2.3: + resolution: {integrity: sha512-xcLxITLe2HYa1cnYnwCjkOO1PqUHQpozB8x9AR0OgWN2woOBi5kSDVxKfd0b7sb1hw5qFeJhXm9H1nu3xSfLeQ==} + engines: {node: '>=10'} + dependencies: + tslib: 2.6.1 + dev: false + /aria-query@5.3.0: resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} dependencies: @@ -1012,6 +1277,10 @@ packages: engines: {node: '>=6'} dev: false + /detect-node-es@1.1.0: + resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==} + dev: false + /didyoumean@1.2.2: resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} dev: false @@ -1586,6 +1855,11 @@ packages: has-symbols: 1.0.3 dev: false + /get-nonce@1.0.1: + resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==} + engines: {node: '>=6'} + dev: false + /get-stream@6.0.1: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} @@ -1800,6 +2074,12 @@ packages: side-channel: 1.0.4 dev: false + /invariant@2.2.4: + resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==} + dependencies: + loose-envify: 1.4.0 + dev: false + /is-array-buffer@3.0.2: resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} dependencies: @@ -2501,7 +2781,6 @@ packages: requiresBuild: true dependencies: '@prisma/engines': 5.0.0 - dev: true /prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} @@ -2543,6 +2822,58 @@ packages: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} dev: false + /react-remove-scroll-bar@2.3.4(@types/react@18.2.16)(react@18.2.0): + resolution: {integrity: sha512-63C4YQBUt0m6ALadE9XV56hV8BgJWDmmTPY758iIJjfQKt2nYwoUrPk0LXRXcB/yIj82T1/Ixfdpdk68LwIB0A==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@types/react': 18.2.16 + react: 18.2.0 + react-style-singleton: 2.2.1(@types/react@18.2.16)(react@18.2.0) + tslib: 2.6.1 + dev: false + + /react-remove-scroll@2.5.5(@types/react@18.2.16)(react@18.2.0): + resolution: {integrity: sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@types/react': 18.2.16 + react: 18.2.0 + react-remove-scroll-bar: 2.3.4(@types/react@18.2.16)(react@18.2.0) + react-style-singleton: 2.2.1(@types/react@18.2.16)(react@18.2.0) + tslib: 2.6.1 + use-callback-ref: 1.3.0(@types/react@18.2.16)(react@18.2.0) + use-sidecar: 1.1.2(@types/react@18.2.16)(react@18.2.0) + dev: false + + /react-style-singleton@2.2.1(@types/react@18.2.16)(react@18.2.0): + resolution: {integrity: sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@types/react': 18.2.16 + get-nonce: 1.0.1 + invariant: 2.2.4 + react: 18.2.0 + tslib: 2.6.1 + dev: false + /react@18.2.0: resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} engines: {node: '>=0.10.0'} @@ -2824,6 +3155,15 @@ packages: engines: {node: '>= 0.4'} dev: false + /swr@2.2.0(react@18.2.0): + resolution: {integrity: sha512-AjqHOv2lAhkuUdIiBu9xbuettzAzWXmCEcLONNKJRba87WAefz8Ca9d6ds/SzrPc235n1IxWYdhJ2zF3MNUaoQ==} + peerDependencies: + react: ^16.11.0 || ^17.0.0 || ^18.0.0 + dependencies: + react: 18.2.0 + use-sync-external-store: 1.2.0(react@18.2.0) + dev: false + /synckit@0.8.5: resolution: {integrity: sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==} engines: {node: ^14.18.0 || >=16.0.0} @@ -3045,6 +3385,45 @@ packages: punycode: 2.3.0 dev: false + /use-callback-ref@1.3.0(@types/react@18.2.16)(react@18.2.0): + resolution: {integrity: sha512-3FT9PRuRdbB9HfXhEq35u4oZkvpJ5kuYbpqhCfmiZyReuRgpnhDlbr2ZEnnuS0RrJAPn6l23xjFg9kpDM+Ms7w==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@types/react': 18.2.16 + react: 18.2.0 + tslib: 2.6.1 + dev: false + + /use-sidecar@1.1.2(@types/react@18.2.16)(react@18.2.0): + resolution: {integrity: sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': ^16.9.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@types/react': 18.2.16 + detect-node-es: 1.1.0 + react: 18.2.0 + tslib: 2.6.1 + dev: false + + /use-sync-external-store@1.2.0(react@18.2.0): + resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + dependencies: + react: 18.2.0 + dev: false + /utf-8-validate@5.0.10: resolution: {integrity: sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==} engines: {node: '>=6.14.2'} diff --git a/prisma/schema.prisma b/prisma/schema.prisma index d205f42..e5aba43 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -1,11 +1,436 @@ -// This is your Prisma schema file, -// learn more about it in the docs: https://pris.ly/d/prisma-schema - generator client { - provider = "prisma-client-js" + provider = "prisma-client-js" + previewFeatures = ["multiSchema"] } datasource db { provider = "postgresql" url = env("DATABASE_URL") + schemas = ["auth", "public"] +} + +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +model audit_log_entries { + instance_id String? @db.Uuid + id String @id @db.Uuid + payload Json? @db.Json + created_at DateTime? @db.Timestamptz(6) + ip_address String @default("") @db.VarChar(64) + + @@index([instance_id], map: "audit_logs_instance_id_idx") + @@schema("auth") +} + +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +model flow_state { + id String @id @db.Uuid + user_id String? @db.Uuid + auth_code String + code_challenge_method code_challenge_method + code_challenge String + provider_type String + provider_access_token String? + provider_refresh_token String? + created_at DateTime? @db.Timestamptz(6) + updated_at DateTime? @db.Timestamptz(6) + authentication_method String + + @@index([created_at(sort: Desc)]) + @@index([auth_code], map: "idx_auth_code") + @@index([user_id, authentication_method], map: "idx_user_id_auth_method") + @@schema("auth") +} + +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +model identities { + id String + user_id String @db.Uuid + identity_data Json + provider String + last_sign_in_at DateTime? @db.Timestamptz(6) + created_at DateTime? @db.Timestamptz(6) + updated_at DateTime? @db.Timestamptz(6) + email String? @default(dbgenerated("lower((identity_data ->> 'email'::text))")) + users users @relation(fields: [user_id], references: [id], onDelete: Cascade, onUpdate: NoAction) + + @@id([provider, id]) + @@index([email]) + @@index([user_id]) + @@schema("auth") +} + +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +model instances { + id String @id @db.Uuid + uuid String? @db.Uuid + raw_base_config String? + created_at DateTime? @db.Timestamptz(6) + updated_at DateTime? @db.Timestamptz(6) + + @@schema("auth") +} + +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +model mfa_amr_claims { + session_id String @db.Uuid + created_at DateTime @db.Timestamptz(6) + updated_at DateTime @db.Timestamptz(6) + authentication_method String + id String @id(map: "amr_id_pk") @db.Uuid + sessions sessions @relation(fields: [session_id], references: [id], onDelete: Cascade, onUpdate: NoAction) + + @@unique([session_id, authentication_method], map: "mfa_amr_claims_session_id_authentication_method_pkey") + @@schema("auth") +} + +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +model mfa_challenges { + id String @id @db.Uuid + factor_id String @db.Uuid + created_at DateTime @db.Timestamptz(6) + verified_at DateTime? @db.Timestamptz(6) + ip_address String @db.Inet + mfa_factors mfa_factors @relation(fields: [factor_id], references: [id], onDelete: Cascade, onUpdate: NoAction, map: "mfa_challenges_auth_factor_id_fkey") + + @@index([created_at(sort: Desc)], map: "mfa_challenge_created_at_idx") + @@schema("auth") +} + +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +model mfa_factors { + id String @id @db.Uuid + user_id String @db.Uuid + friendly_name String? + factor_type factor_type + status factor_status + created_at DateTime @db.Timestamptz(6) + updated_at DateTime @db.Timestamptz(6) + secret String? + mfa_challenges mfa_challenges[] + users users @relation(fields: [user_id], references: [id], onDelete: Cascade, onUpdate: NoAction) + + @@index([user_id, created_at], map: "factor_id_created_at_idx") + @@schema("auth") +} + +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +model refresh_tokens { + instance_id String? @db.Uuid + id BigInt @id @default(autoincrement()) + token String? @unique(map: "refresh_tokens_token_unique") @db.VarChar(255) + user_id String? @db.VarChar(255) + revoked Boolean? + created_at DateTime? @db.Timestamptz(6) + updated_at DateTime? @db.Timestamptz(6) + parent String? @db.VarChar(255) + session_id String? @db.Uuid + sessions sessions? @relation(fields: [session_id], references: [id], onDelete: Cascade, onUpdate: NoAction) + + @@index([instance_id]) + @@index([instance_id, user_id]) + @@index([parent]) + @@index([session_id, revoked]) + @@index([updated_at(sort: Desc)]) + @@schema("auth") +} + +/// This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/check-constraints for more info. +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +model saml_providers { + id String @id @db.Uuid + sso_provider_id String @db.Uuid + entity_id String @unique + metadata_xml String + metadata_url String? + attribute_mapping Json? + created_at DateTime? @db.Timestamptz(6) + updated_at DateTime? @db.Timestamptz(6) + sso_providers sso_providers @relation(fields: [sso_provider_id], references: [id], onDelete: Cascade, onUpdate: NoAction) + + @@index([sso_provider_id]) + @@schema("auth") +} + +/// This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/check-constraints for more info. +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +model saml_relay_states { + id String @id @db.Uuid + sso_provider_id String @db.Uuid + request_id String + for_email String? + redirect_to String? + from_ip_address String? @db.Inet + created_at DateTime? @db.Timestamptz(6) + updated_at DateTime? @db.Timestamptz(6) + sso_providers sso_providers @relation(fields: [sso_provider_id], references: [id], onDelete: Cascade, onUpdate: NoAction) + + @@index([created_at(sort: Desc)]) + @@index([for_email]) + @@index([sso_provider_id]) + @@schema("auth") +} + +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +model schema_migrations { + version String @id @db.VarChar(255) + + @@schema("auth") +} + +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +model sessions { + id String @id @db.Uuid + user_id String @db.Uuid + created_at DateTime? @db.Timestamptz(6) + updated_at DateTime? @db.Timestamptz(6) + factor_id String? @db.Uuid + aal aal_level? + not_after DateTime? @db.Timestamptz(6) + mfa_amr_claims mfa_amr_claims[] + refresh_tokens refresh_tokens[] + users users @relation(fields: [user_id], references: [id], onDelete: Cascade, onUpdate: NoAction) + + @@index([not_after(sort: Desc)]) + @@index([user_id]) + @@index([user_id, created_at], map: "user_id_created_at_idx") + @@schema("auth") +} + +/// This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/check-constraints for more info. +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +/// This model contains an expression index which requires additional setup for migrations. Visit https://pris.ly/d/expression-indexes for more info. +/// This model contains an expression index which requires additional setup for migrations. Visit https://pris.ly/d/expression-indexes for more info. +/// This model contains an expression index which requires additional setup for migrations. Visit https://pris.ly/d/expression-indexes for more info. +/// This model contains an expression index which requires additional setup for migrations. Visit https://pris.ly/d/expression-indexes for more info. +model sso_domains { + id String @id @db.Uuid + sso_provider_id String @db.Uuid + domain String + created_at DateTime? @db.Timestamptz(6) + updated_at DateTime? @db.Timestamptz(6) + sso_providers sso_providers @relation(fields: [sso_provider_id], references: [id], onDelete: Cascade, onUpdate: NoAction) + + @@index([sso_provider_id]) + @@schema("auth") +} + +/// This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/check-constraints for more info. +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +/// This model contains an expression index which requires additional setup for migrations. Visit https://pris.ly/d/expression-indexes for more info. +/// This model contains an expression index which requires additional setup for migrations. Visit https://pris.ly/d/expression-indexes for more info. +/// This model contains an expression index which requires additional setup for migrations. Visit https://pris.ly/d/expression-indexes for more info. +/// This model contains an expression index which requires additional setup for migrations. Visit https://pris.ly/d/expression-indexes for more info. +model sso_providers { + id String @id @db.Uuid + resource_id String? + created_at DateTime? @db.Timestamptz(6) + updated_at DateTime? @db.Timestamptz(6) + saml_providers saml_providers[] + saml_relay_states saml_relay_states[] + sso_domains sso_domains[] + + @@schema("auth") +} + +/// This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/check-constraints for more info. +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +/// This model contains an expression index which requires additional setup for migrations. Visit https://pris.ly/d/expression-indexes for more info. +/// This model contains an expression index which requires additional setup for migrations. Visit https://pris.ly/d/expression-indexes for more info. +/// This model contains an expression index which requires additional setup for migrations. Visit https://pris.ly/d/expression-indexes for more info. +/// This model contains an expression index which requires additional setup for migrations. Visit https://pris.ly/d/expression-indexes for more info. +model users { + instance_id String? @db.Uuid + id String @id @db.Uuid + aud String? @db.VarChar(255) + role String? @db.VarChar(255) + email String? @db.VarChar(255) + encrypted_password String? @db.VarChar(255) + email_confirmed_at DateTime? @db.Timestamptz(6) + invited_at DateTime? @db.Timestamptz(6) + confirmation_token String? @db.VarChar(255) + confirmation_sent_at DateTime? @db.Timestamptz(6) + recovery_token String? @db.VarChar(255) + recovery_sent_at DateTime? @db.Timestamptz(6) + email_change_token_new String? @db.VarChar(255) + email_change String? @db.VarChar(255) + email_change_sent_at DateTime? @db.Timestamptz(6) + last_sign_in_at DateTime? @db.Timestamptz(6) + raw_app_meta_data Json? + raw_user_meta_data Json? + is_super_admin Boolean? + created_at DateTime? @db.Timestamptz(6) + updated_at DateTime? @db.Timestamptz(6) + phone String? @unique + phone_confirmed_at DateTime? @db.Timestamptz(6) + phone_change String? @default("") + phone_change_token String? @default("") @db.VarChar(255) + phone_change_sent_at DateTime? @db.Timestamptz(6) + confirmed_at DateTime? @default(dbgenerated("LEAST(email_confirmed_at, phone_confirmed_at)")) @db.Timestamptz(6) + email_change_token_current String? @default("") @db.VarChar(255) + email_change_confirm_status Int? @default(0) @db.SmallInt + banned_until DateTime? @db.Timestamptz(6) + reauthentication_token String? @default("") @db.VarChar(255) + reauthentication_sent_at DateTime? @db.Timestamptz(6) + is_sso_user Boolean @default(false) + deleted_at DateTime? @db.Timestamptz(6) + identities identities[] + mfa_factors mfa_factors[] + sessions sessions[] + UserProfile UserProfile? + + @@index([instance_id]) + @@schema("auth") +} + +model UserProfile { + id String @id @db.Uuid + created_at DateTime? @default(now()) @db.Timestamptz(6) + email String @db.VarChar + pfp String? @default("https://xsgames.co/randomusers/avatar.php?g=pixel") + bio String? + strengths String[] @db.VarChar + Comment Comment[] + users users @relation(fields: [id], references: [id], onDelete: NoAction, onUpdate: NoAction) + UserProfile_Project UserProfile_Project[] + UserProfile_Task UserProfile_Task[] + UserProfile_Team UserProfile_Team[] + + @@schema("public") +} + +model Comment { + id BigInt @id @default(autoincrement()) + created_at DateTime? @default(now()) @db.Timestamptz(6) + message String + authorId String @db.Uuid + taskId BigInt + UserProfile UserProfile @relation(fields: [authorId], references: [id], onDelete: Cascade, onUpdate: NoAction) + Task Task @relation(fields: [taskId], references: [id], onDelete: Cascade, onUpdate: NoAction) + + @@schema("public") +} + +model Feature { + id BigInt @id @default(autoincrement()) + created_at DateTime? @default(now()) @db.Timestamptz(6) + description String @db.VarChar + projectId BigInt + Project Project @relation(fields: [projectId], references: [id], onDelete: Cascade, onUpdate: NoAction) + + @@schema("public") +} + +model Project { + id BigInt @id @default(autoincrement()) + created_at DateTime? @default(now()) @db.Timestamptz(6) + title String @db.VarChar + description String @db.VarChar + github String? @db.VarChar + stack String[] @db.VarChar + Feature Feature[] + Task Task[] + Team Team[] + UserProfile_Project UserProfile_Project[] + + @@schema("public") +} + +model Subtask { + id BigInt @id @default(autoincrement()) + created_at DateTime? @default(now()) @db.Timestamptz(6) + description String @db.VarChar + taskId BigInt + Task Task @relation(fields: [taskId], references: [id], onDelete: Cascade, onUpdate: NoAction) + + @@schema("public") +} + +model Task { + id BigInt @id @default(autoincrement()) + created_at DateTime? @default(now()) @db.Timestamptz(6) + description String @db.VarChar + projectId BigInt + status String? @default("todo") @db.VarChar + priority String? @db.VarChar + dueDate DateTime? @db.Timestamptz(6) + teamId BigInt? + tags String[] @db.VarChar + Comment Comment[] + Subtask Subtask[] + Project Project @relation(fields: [projectId], references: [id], onDelete: Cascade, onUpdate: NoAction) + Team Team? @relation(fields: [teamId], references: [id], onDelete: NoAction, onUpdate: NoAction) + UserProfile_Task UserProfile_Task[] + + @@schema("public") +} + +model Team { + id BigInt @id @default(autoincrement()) + created_at DateTime? @default(now()) @db.Timestamptz(6) + name String @db.VarChar + projectId BigInt + Task Task[] + Project Project @relation(fields: [projectId], references: [id], onDelete: Cascade, onUpdate: NoAction) + UserProfile_Team UserProfile_Team[] + + @@schema("public") +} + +model UserProfile_Project { + id BigInt @id @default(autoincrement()) + userProfileId String @db.Uuid + projectId BigInt + Project Project @relation(fields: [projectId], references: [id], onDelete: NoAction, onUpdate: NoAction) + UserProfile UserProfile @relation(fields: [userProfileId], references: [id], onDelete: NoAction, onUpdate: NoAction) + + @@schema("public") +} + +model UserProfile_Task { + id BigInt @id @default(autoincrement()) + userProfileId String @db.Uuid + taskId BigInt + Task Task @relation(fields: [taskId], references: [id], onDelete: NoAction, onUpdate: NoAction) + UserProfile UserProfile @relation(fields: [userProfileId], references: [id], onDelete: NoAction, onUpdate: NoAction) + + @@schema("public") +} + +model UserProfile_Team { + id BigInt @id @default(autoincrement()) + userProfileId String @db.Uuid + teamId BigInt + Team Team @relation(fields: [teamId], references: [id], onDelete: NoAction, onUpdate: NoAction) + UserProfile UserProfile @relation(fields: [userProfileId], references: [id], onDelete: NoAction, onUpdate: NoAction) + + @@schema("public") +} + +enum aal_level { + aal1 + aal2 + aal3 + + @@schema("auth") +} + +enum code_challenge_method { + s256 + plain + + @@schema("auth") +} + +enum factor_status { + unverified + verified + + @@schema("auth") +} + +enum factor_type { + totp + webauthn + + @@schema("auth") } diff --git a/types/models.ts b/types/models.ts new file mode 100644 index 0000000..b8cb5a9 --- /dev/null +++ b/types/models.ts @@ -0,0 +1,7 @@ +export type Project = { + id: string; + title: string; + description: string; + github: string; + stack: string[]; +}; diff --git a/types/supabase.ts b/types/supabase.ts new file mode 100644 index 0000000..c0471ae --- /dev/null +++ b/types/supabase.ts @@ -0,0 +1,282 @@ +export type Json = + | string + | number + | boolean + | null + | { [key: string]: Json | undefined } + | Json[] + +export interface Database { + public: { + Tables: { + _ProjectToUser: { + Row: { + A: string + B: string + } + Insert: { + A: string + B: string + } + Update: { + A?: string + B?: string + } + Relationships: [ + { + foreignKeyName: "_ProjectToUser_A_fkey" + columns: ["A"] + referencedRelation: "Project" + referencedColumns: ["id"] + }, + { + foreignKeyName: "_ProjectToUser_B_fkey" + columns: ["B"] + referencedRelation: "User" + referencedColumns: ["id"] + } + ] + } + Comment: { + Row: { + authorId: string + content: string + createdAt: string + id: string + taskId: string + } + Insert: { + authorId: string + content: string + createdAt?: string + id: string + taskId: string + } + Update: { + authorId?: string + content?: string + createdAt?: string + id?: string + taskId?: string + } + Relationships: [ + { + foreignKeyName: "Comment_authorId_fkey" + columns: ["authorId"] + referencedRelation: "User" + referencedColumns: ["id"] + }, + { + foreignKeyName: "Comment_taskId_fkey" + columns: ["taskId"] + referencedRelation: "Task" + referencedColumns: ["id"] + } + ] + } + Feature: { + Row: { + description: string + id: string + projectId: string + } + Insert: { + description: string + id: string + projectId: string + } + Update: { + description?: string + id?: string + projectId?: string + } + Relationships: [ + { + foreignKeyName: "Feature_projectId_fkey" + columns: ["projectId"] + referencedRelation: "Project" + referencedColumns: ["id"] + } + ] + } + Project: { + Row: { + description: string + githubURL: string | null + id: string + name: string + techStack: string[] | null + } + Insert: { + description: string + githubURL?: string | null + id: string + name: string + techStack?: string[] | null + } + Update: { + description?: string + githubURL?: string | null + id?: string + name?: string + techStack?: string[] | null + } + Relationships: [] + } + Subtask: { + Row: { + description: string + id: string + taskId: string + } + Insert: { + description: string + id: string + taskId: string + } + Update: { + description?: string + id?: string + taskId?: string + } + Relationships: [ + { + foreignKeyName: "Subtask_taskId_fkey" + columns: ["taskId"] + referencedRelation: "Task" + referencedColumns: ["id"] + } + ] + } + Task: { + Row: { + assigneeId: string | null + description: string + dueDate: string | null + id: string + priority: string | null + projectId: string + status: string | null + tags: string[] | null + teamId: string | null + } + Insert: { + assigneeId?: string | null + description: string + dueDate?: string | null + id: string + priority?: string | null + projectId: string + status?: string | null + tags?: string[] | null + teamId?: string | null + } + Update: { + assigneeId?: string | null + description?: string + dueDate?: string | null + id?: string + priority?: string | null + projectId?: string + status?: string | null + tags?: string[] | null + teamId?: string | null + } + Relationships: [ + { + foreignKeyName: "Task_assigneeId_fkey" + columns: ["assigneeId"] + referencedRelation: "User" + referencedColumns: ["id"] + }, + { + foreignKeyName: "Task_projectId_fkey" + columns: ["projectId"] + referencedRelation: "Project" + referencedColumns: ["id"] + }, + { + foreignKeyName: "Task_teamId_fkey" + columns: ["teamId"] + referencedRelation: "Team" + referencedColumns: ["id"] + } + ] + } + Team: { + Row: { + id: string + name: string + projectId: string + } + Insert: { + id: string + name: string + projectId: string + } + Update: { + id?: string + name?: string + projectId?: string + } + Relationships: [ + { + foreignKeyName: "Team_projectId_fkey" + columns: ["projectId"] + referencedRelation: "Project" + referencedColumns: ["id"] + } + ] + } + User: { + Row: { + description: string | null + email: string + firebaseID: string + id: string + profilePic: string + strengths: string[] | null + teamID: string | null + } + Insert: { + description?: string | null + email: string + firebaseID: string + id: string + profilePic?: string + strengths?: string[] | null + teamID?: string | null + } + Update: { + description?: string | null + email?: string + firebaseID?: string + id?: string + profilePic?: string + strengths?: string[] | null + teamID?: string | null + } + Relationships: [ + { + foreignKeyName: "User_teamID_fkey" + columns: ["teamID"] + referencedRelation: "Team" + referencedColumns: ["id"] + } + ] + } + } + Views: { + [_ in never]: never + } + Functions: { + [_ in never]: never + } + Enums: { + [_ in never]: never + } + CompositeTypes: { + [_ in never]: never + } + } +}