This commit is contained in:
Sebastien Castiel
2023-12-06 17:47:41 -05:00
parent 12b1cdb52a
commit e747ec3ea0
9 changed files with 368 additions and 186 deletions

View File

@@ -16,6 +16,7 @@
"@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-select": "^2.0.0",
"@radix-ui/react-slot": "^1.0.2",
"@radix-ui/react-tabs": "^1.0.4",
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
"lucide-react": "^0.290.0",

View File

@@ -0,0 +1,41 @@
import { BalancesList } from '@/app/groups/[groupId]/balances-list'
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from '@/components/ui/card'
import { getGroup, getGroupExpenses } from '@/lib/api'
import { getBalances } from '@/lib/balances'
import { notFound } from 'next/navigation'
export default async function GroupPage({
params: { groupId },
}: {
params: { groupId: string }
}) {
const group = await getGroup(groupId)
if (!group) notFound()
const expenses = await getGroupExpenses(groupId)
const balances = getBalances(expenses)
return (
<Card className="mb-4">
<CardHeader>
<CardTitle>Balances</CardTitle>
<CardDescription>
This is the amount that each participant paid or was paid for.
</CardDescription>
</CardHeader>
<CardContent>
<BalancesList
balances={balances}
participants={group.participants}
currency={group.currency}
/>
</CardContent>
</Card>
)
}

View File

@@ -0,0 +1,114 @@
import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from '@/components/ui/card'
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from '@/components/ui/table'
import { getGroup, getGroupExpenses } from '@/lib/api'
import { ChevronRight, Plus } from 'lucide-react'
import Link from 'next/link'
import { notFound } from 'next/navigation'
export default async function GroupExpensesPage({
params: { groupId },
}: {
params: { groupId: string }
}) {
const group = await getGroup(groupId)
if (!group) notFound()
const expenses = await getGroupExpenses(groupId)
return (
<Card className="mb-4">
<div className="flex flex-1">
<CardHeader className="flex-1">
<CardTitle>Expenses</CardTitle>
<CardDescription>
Here are the expenses that you created for your group.
</CardDescription>
</CardHeader>
<CardHeader>
<Button asChild size="icon">
<Link href={`/groups/${groupId}/expenses/create`}>
<Plus />
</Link>
</Button>
</CardHeader>
</div>
<CardContent className="p-0">
{expenses.length > 0 ? (
<Table>
<TableHeader>
<TableRow>
<TableHead>Title</TableHead>
<TableHead>Paid by</TableHead>
<TableHead>Paid for</TableHead>
<TableHead className="text-right">Amount</TableHead>
<TableHead className="w-0"></TableHead>
</TableRow>
</TableHeader>
<TableBody>
{expenses.map((expense) => (
<TableRow key={expense.id}>
<TableCell>{expense.title}</TableCell>
<TableCell>
<Badge variant="secondary">
{
group.participants.find(
(p) => p.id === expense.paidById,
)?.name
}
</Badge>
</TableCell>
<TableCell className="flex flex-wrap gap-1">
{expense.paidFor.map((paidFor, index) => (
<Badge variant="secondary" key={index}>
{
group.participants.find(
(p) => p.id === paidFor.participantId,
)?.name
}
</Badge>
))}
</TableCell>
<TableCell className="text-right tabular-nums whitespace-nowrap">
{group.currency} {expense.amount.toFixed(2)}
</TableCell>
<TableCell>
<Button
size="icon"
variant="link"
className="-my-2"
asChild
>
<Link
href={`/groups/${groupId}/expenses/${expense.id}/edit`}
>
<ChevronRight className="w-4 h-4" />
</Link>
</Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
) : (
<div className="p-6">Your group doesnt have any expense yet.</div>
)}
</CardContent>
</Card>
)
}

View File

@@ -0,0 +1,30 @@
'use client'
import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs'
import { usePathname, useRouter } from 'next/navigation'
type Props = {
groupId: string
}
export function GroupTabs({ groupId }: Props) {
const pathname = usePathname()
const value =
pathname.replace(/\/groups\/[^\/]+\/([^/]+).*/, '$1') || 'expenses'
const router = useRouter()
return (
<Tabs
value={value}
className="mb-4"
onValueChange={(value) => {
router.push(`/groups/${groupId}/${value}`)
}}
>
<TabsList>
<TabsTrigger value="expenses">Expenses</TabsTrigger>
<TabsTrigger value="balances">Balances</TabsTrigger>
<TabsTrigger value="edit">Settings</TabsTrigger>
</TabsList>
</Tabs>
)
}

View File

@@ -1,6 +1,8 @@
import { GroupTabs } from '@/app/groups/[groupId]/group-tabs'
import { SaveGroupLocally } from '@/app/groups/[groupId]/save-recent-group'
import { Button } from '@/components/ui/button'
import { getGroup } from '@/lib/api'
import { ChevronLeft, Edit } from 'lucide-react'
import { ChevronLeft } from 'lucide-react'
import Link from 'next/link'
import { notFound } from 'next/navigation'
import { PropsWithChildren } from 'react'
@@ -24,19 +26,15 @@ export default async function GroupLayout({
</Button>
</div>
<div className="flex justify-between items-baseline mb-4">
<h1 className="font-bold text-2xl">
<Link href={`/groups/${groupId}`}>{group.name}</Link>
</h1>
<h1 className="font-bold text-2xl mb-4">
<Link href={`/groups/${groupId}`}>{group.name}</Link>
</h1>
<Button variant="outline" asChild size="icon">
<Link href={`/groups/${groupId}/edit`}>
<Edit className="w-4 h-4" />
</Link>
</Button>
</div>
<GroupTabs groupId={groupId} />
{children}
<SaveGroupLocally group={{ id: group.id, name: group.name }} />
</>
)
}

View File

@@ -1,137 +1,9 @@
import { BalancesList } from '@/app/groups/[groupId]/balances-list'
import { SaveGroupLocally } from '@/app/groups/[groupId]/save-recent-group'
import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from '@/components/ui/card'
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from '@/components/ui/table'
import { getGroup, getGroupExpenses } from '@/lib/api'
import { getBalances } from '@/lib/balances'
import { ChevronRight, Plus } from 'lucide-react'
import Link from 'next/link'
import { notFound } from 'next/navigation'
import { redirect } from 'next/navigation'
export default async function GroupPage({
params: { groupId },
}: {
params: { groupId: string }
}) {
const group = await getGroup(groupId)
if (!group) notFound()
const expenses = await getGroupExpenses(groupId)
const balances = getBalances(expenses)
return (
<>
<Card className="mb-4">
<div className="flex flex-1">
<CardHeader className="flex-1">
<CardTitle>Expenses</CardTitle>
<CardDescription>
Here are the expenses that you created for your group.
</CardDescription>
</CardHeader>
<CardHeader>
<Button asChild size="icon">
<Link href={`/groups/${groupId}/expenses/create`}>
<Plus />
</Link>
</Button>
</CardHeader>
</div>
<CardContent className="p-0">
{expenses.length > 0 ? (
<Table>
<TableHeader>
<TableRow>
<TableHead>Title</TableHead>
<TableHead>Paid by</TableHead>
<TableHead>Paid for</TableHead>
<TableHead className="text-right">Amount</TableHead>
<TableHead className="w-0"></TableHead>
</TableRow>
</TableHeader>
<TableBody>
{expenses.map((expense) => (
<TableRow key={expense.id}>
<TableCell>{expense.title}</TableCell>
<TableCell>
<Badge variant="secondary">
{
group.participants.find(
(p) => p.id === expense.paidById,
)?.name
}
</Badge>
</TableCell>
<TableCell className="flex flex-wrap gap-1">
{expense.paidFor.map((paidFor, index) => (
<Badge variant="secondary" key={index}>
{
group.participants.find(
(p) => p.id === paidFor.participantId,
)?.name
}
</Badge>
))}
</TableCell>
<TableCell className="text-right tabular-nums whitespace-nowrap">
{group.currency} {expense.amount.toFixed(2)}
</TableCell>
<TableCell>
<Button
size="icon"
variant="link"
className="-my-2"
asChild
>
<Link
href={`/groups/${groupId}/expenses/${expense.id}/edit`}
>
<ChevronRight className="w-4 h-4" />
</Link>
</Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
) : (
<div className="p-6">Your group doesnt have any expense yet.</div>
)}
</CardContent>
</Card>
<Card className="mb-4">
<CardHeader>
<CardTitle>Balances</CardTitle>
<CardDescription>
This is the amount that each participant paid or was paid for.
</CardDescription>
</CardHeader>
<CardContent>
<BalancesList
balances={balances}
participants={group.participants}
currency={group.currency}
/>
</CardContent>
</Card>
<SaveGroupLocally group={{ id: group.id, name: group.name }} />
</>
)
redirect(`/groups/${groupId}/expenses`)
}

View File

@@ -14,7 +14,7 @@ export default function RootLayout({
}) {
return (
<html lang="en">
<body className="bg-slate-50">
<body className="">
<ProgressBar />
<div className="max-w-screen-md mx-auto p-4">{children}</div>
</body>

View File

@@ -0,0 +1,55 @@
"use client"
import * as React from "react"
import * as TabsPrimitive from "@radix-ui/react-tabs"
import { cn } from "@/lib/utils"
const Tabs = TabsPrimitive.Root
const TabsList = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.List>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>
>(({ className, ...props }, ref) => (
<TabsPrimitive.List
ref={ref}
className={cn(
"inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground",
className
)}
{...props}
/>
))
TabsList.displayName = TabsPrimitive.List.displayName
const TabsTrigger = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>
>(({ className, ...props }, ref) => (
<TabsPrimitive.Trigger
ref={ref}
className={cn(
"inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm",
className
)}
{...props}
/>
))
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName
const TabsContent = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>
>(({ className, ...props }, ref) => (
<TabsPrimitive.Content
ref={ref}
className={cn(
"mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
className
)}
{...props}
/>
))
TabsContent.displayName = TabsPrimitive.Content.displayName
export { Tabs, TabsList, TabsTrigger, TabsContent }

159
yarn.lock
View File

@@ -151,6 +151,46 @@
resolved "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.0.0.tgz"
integrity sha512-HQKi159jCz4SRsPesVCiNN6tPSAFUkOuSkpJsqYTIlbHLKr1mD6be/J0TvWV6fwJekj81bZV9V/Tgx3C2HO9lA==
"@next/swc-darwin-x64@14.0.0":
version "14.0.0"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-14.0.0.tgz#6f628a1a13b4bc09c0450bb171703f60ca7a6c56"
integrity sha512-4YyQLMSaCgX/kgC1jjF3s3xSoBnwHuDhnF6WA1DWNEYRsbOOPWjcYhv8TKhRe2ApdOam+VfQSffC4ZD+X4u1Cg==
"@next/swc-linux-arm64-gnu@14.0.0":
version "14.0.0"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.0.0.tgz#0088f3d13b253657333b6aced57e1e278452e766"
integrity sha512-io7fMkJ28Glj7SH8yvnlD6naIhRDnDxeE55CmpQkj3+uaA2Hko6WGY2pT5SzpQLTnGGnviK85cy8EJ2qsETj/g==
"@next/swc-linux-arm64-musl@14.0.0":
version "14.0.0"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.0.0.tgz#44d7c9be63dfdea2d4feeba515a8c80ca56f2d87"
integrity sha512-nC2h0l1Jt8LEzyQeSs/BKpXAMe0mnHIMykYALWaeddTqCv5UEN8nGO3BG8JAqW/Y8iutqJsaMe2A9itS0d/r8w==
"@next/swc-linux-x64-gnu@14.0.0":
version "14.0.0"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.0.0.tgz#064b7ca6da98ca7468ae5d97370e73a8bc2eee76"
integrity sha512-Wf+WjXibJQ7hHXOdNOmSMW5bxeJHVf46Pwb3eLSD2L76NrytQlif9NH7JpHuFlYKCQGfKfgSYYre5rIfmnSwQw==
"@next/swc-linux-x64-musl@14.0.0":
version "14.0.0"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.0.0.tgz#c2a66bd7d5f54a3a5faa14ff9bce93a507d2135d"
integrity sha512-WTZb2G7B+CTsdigcJVkRxfcAIQj7Lf0ipPNRJ3vlSadU8f0CFGv/ST+sJwF5eSwIe6dxKoX0DG6OljDBaad+rg==
"@next/swc-win32-arm64-msvc@14.0.0":
version "14.0.0"
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.0.0.tgz#a657568bc1bf6f3bfabc07034342ef1942f14e31"
integrity sha512-7R8/x6oQODmNpnWVW00rlWX90sIlwluJwcvMT6GXNIBOvEf01t3fBg0AGURNKdTJg2xNuP7TyLchCL7Lh2DTiw==
"@next/swc-win32-ia32-msvc@14.0.0":
version "14.0.0"
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.0.0.tgz#fe27ae6c165d6d74bf80f7dc37d67401c2148518"
integrity sha512-RLK1nELvhCnxaWPF07jGU4x3tjbyx2319q43loZELqF0+iJtKutZ+Lk8SVmf/KiJkYBc7Cragadz7hb3uQvz4g==
"@next/swc-win32-x64-msvc@14.0.0":
version "14.0.0"
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.0.0.tgz#fef677c3f4b62443e0b02d3d59440f6b0b8eb1f4"
integrity sha512-g6hLf1SUko+hnnaywQQZzzb3BRecQsoKkF3o/C+F+dOA4w/noVAJngUVkfwF0+2/8FzNznM7ofM6TGZO9svn7w==
"@nodelib/fs.scandir@2.1.5":
version "2.1.5"
resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz"
@@ -159,7 +199,7 @@
"@nodelib/fs.stat" "2.0.5"
run-parallel "^1.1.9"
"@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.5":
"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2":
version "2.0.5"
resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz"
integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
@@ -345,6 +385,22 @@
"@babel/runtime" "^7.13.10"
"@radix-ui/react-slot" "1.0.2"
"@radix-ui/react-roving-focus@1.0.4":
version "1.0.4"
resolved "https://registry.yarnpkg.com/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.4.tgz#e90c4a6a5f6ac09d3b8c1f5b5e81aab2f0db1974"
integrity sha512-2mUg5Mgcu001VkGy+FfzZyzbmuUWzgWkj3rvv4yu+mLw03+mTzbxZHvfcGyFp2b8EkQeMkpRQ5FiA2Vr2O6TeQ==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/primitive" "1.0.1"
"@radix-ui/react-collection" "1.0.3"
"@radix-ui/react-compose-refs" "1.0.1"
"@radix-ui/react-context" "1.0.1"
"@radix-ui/react-direction" "1.0.1"
"@radix-ui/react-id" "1.0.1"
"@radix-ui/react-primitive" "1.0.3"
"@radix-ui/react-use-callback-ref" "1.0.1"
"@radix-ui/react-use-controllable-state" "1.0.1"
"@radix-ui/react-select@^2.0.0":
version "2.0.0"
resolved "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.0.0.tgz"
@@ -373,7 +429,7 @@
aria-hidden "^1.1.1"
react-remove-scroll "2.5.5"
"@radix-ui/react-slot@^1.0.2", "@radix-ui/react-slot@1.0.2":
"@radix-ui/react-slot@1.0.2", "@radix-ui/react-slot@^1.0.2":
version "1.0.2"
resolved "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz"
integrity sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==
@@ -381,6 +437,21 @@
"@babel/runtime" "^7.13.10"
"@radix-ui/react-compose-refs" "1.0.1"
"@radix-ui/react-tabs@^1.0.4":
version "1.0.4"
resolved "https://registry.yarnpkg.com/@radix-ui/react-tabs/-/react-tabs-1.0.4.tgz#993608eec55a5d1deddd446fa9978d2bc1053da2"
integrity sha512-egZfYY/+wRNCflXNHx+dePvnz9FbmssDTJBtgRfDY7e8SE5oIo3Py2eCB1ckAbh1Q7cQ/6yJZThJ++sgbxibog==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/primitive" "1.0.1"
"@radix-ui/react-context" "1.0.1"
"@radix-ui/react-direction" "1.0.1"
"@radix-ui/react-id" "1.0.1"
"@radix-ui/react-presence" "1.0.1"
"@radix-ui/react-primitive" "1.0.3"
"@radix-ui/react-roving-focus" "1.0.4"
"@radix-ui/react-use-controllable-state" "1.0.1"
"@radix-ui/react-use-callback-ref@1.0.1":
version "1.0.1"
resolved "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz"
@@ -488,14 +559,14 @@
resolved "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.9.tgz"
integrity sha512-n1yyPsugYNSmHgxDFjicaI2+gCNjsBck8UX9kuofAKlc0h1bL+20oSF72KeNaW2DUlesbEVCFgyV2dPGTiY42g==
"@types/react-dom@*", "@types/react-dom@^18":
"@types/react-dom@^18":
version "18.2.14"
resolved "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.14.tgz"
integrity sha512-V835xgdSVmyQmI1KLV2BEIUgqEuinxp9O4G6g3FqO/SqLac049E53aysv0oEFD2kHfejeKU+ZqL2bcFWj9gLAQ==
dependencies:
"@types/react" "*"
"@types/react@*", "@types/react@^16.8.0 || ^17.0.0 || ^18.0.0", "@types/react@^16.9.0 || ^17.0.0 || ^18.0.0", "@types/react@^18":
"@types/react@*", "@types/react@^18":
version "18.2.33"
resolved "https://registry.npmjs.org/@types/react/-/react-18.2.33.tgz"
integrity sha512-v+I7S+hu3PIBoVkKGpSYYpiBT1ijqEzWpzQD62/jm4K74hPpSP7FF9BnKG6+fg2+62weJYkkBWDJlZt5JO/9hg==
@@ -569,7 +640,7 @@ acorn-jsx@^5.3.2:
resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz"
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", acorn@^8.9.0:
acorn@^8.9.0:
version "8.11.2"
resolved "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz"
integrity sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==
@@ -778,7 +849,7 @@ braces@^3.0.2, braces@~3.0.2:
dependencies:
fill-range "^7.0.1"
browserslist@^4.21.10, "browserslist@>= 4.21.0":
browserslist@^4.21.10:
version "4.22.1"
resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz"
integrity sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==
@@ -854,7 +925,7 @@ client-only@0.0.1:
resolved "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz"
integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==
clsx@^2.0.0, clsx@2.0.0:
clsx@2.0.0, clsx@^2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz"
integrity sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==
@@ -1145,7 +1216,7 @@ eslint-module-utils@^2.7.4, eslint-module-utils@^2.8.0:
dependencies:
debug "^3.2.7"
eslint-plugin-import@*, eslint-plugin-import@^2.28.1:
eslint-plugin-import@^2.28.1:
version "2.29.0"
resolved "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.0.tgz"
integrity sha512-QPOO5NO6Odv5lpoTkddtutccQjysJuFxoPS7fAHO+9m9udNHvTCPSAMW9zGAYj8lAIdr40I8yPCdUYrncXtrwg==
@@ -1230,7 +1301,7 @@ eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4
resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz"
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
eslint@*, "eslint@^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8", "eslint@^3 || ^4 || ^5 || ^6 || ^7 || ^8", "eslint@^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0", "eslint@^6.0.0 || ^7.0.0 || >=8.0.0", "eslint@^7.0.0 || ^8.0.0", "eslint@^7.23.0 || ^8.0.0", eslint@^8:
eslint@^8:
version "8.52.0"
resolved "https://registry.npmjs.org/eslint/-/eslint-8.52.0.tgz"
integrity sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==
@@ -1467,18 +1538,6 @@ glob-to-regexp@^0.4.1:
resolved "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz"
integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==
glob@^7.1.3:
version "7.2.3"
resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz"
integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
dependencies:
fs.realpath "^1.0.0"
inflight "^1.0.4"
inherits "2"
minimatch "^3.1.1"
once "^1.3.0"
path-is-absolute "^1.0.0"
glob@7.1.6:
version "7.1.6"
resolved "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz"
@@ -1503,6 +1562,18 @@ glob@7.1.7:
once "^1.3.0"
path-is-absolute "^1.0.0"
glob@^7.1.3:
version "7.2.3"
resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz"
integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
dependencies:
fs.realpath "^1.0.0"
inflight "^1.0.4"
inherits "2"
minimatch "^3.1.1"
once "^1.3.0"
path-is-absolute "^1.0.0"
globals@^13.19.0:
version "13.23.0"
resolved "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz"
@@ -1973,16 +2044,16 @@ minimist@^1.2.0, minimist@^1.2.6:
resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz"
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
ms@^2.1.1:
version "2.1.3"
resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
ms@2.1.2:
version "2.1.2"
resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
ms@^2.1.1:
version "2.1.3"
resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
mz@^2.7.0:
version "2.7.0"
resolved "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz"
@@ -2002,7 +2073,16 @@ natural-compare@^1.4.0:
resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz"
integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
"next@>= 13.0.0", next@14.0.0:
next13-progressbar@^1.1.1:
version "1.1.1"
resolved "https://registry.npmjs.org/next13-progressbar/-/next13-progressbar-1.1.1.tgz"
integrity sha512-8BTeft/1KLNkaJCKGXYK5SSkKmTBkg7MogH0z+huw+YP2deXKuZ/iqGamvWmhDS+dcCNs5Chdb8KhNTybn2zLA==
dependencies:
"@types/nprogress" "^0.2.0"
nprogress "^0.2.0"
prop-types "^15.8.1"
next@14.0.0:
version "14.0.0"
resolved "https://registry.npmjs.org/next/-/next-14.0.0.tgz"
integrity sha512-J0jHKBJpB9zd4+c153sair0sz44mbaCHxggs8ryVXSFBuBqJ8XdE9/ozoV85xGh2VnSjahwntBZZgsihL9QznA==
@@ -2025,15 +2105,6 @@ natural-compare@^1.4.0:
"@next/swc-win32-ia32-msvc" "14.0.0"
"@next/swc-win32-x64-msvc" "14.0.0"
next13-progressbar@^1.1.1:
version "1.1.1"
resolved "https://registry.npmjs.org/next13-progressbar/-/next13-progressbar-1.1.1.tgz"
integrity sha512-8BTeft/1KLNkaJCKGXYK5SSkKmTBkg7MogH0z+huw+YP2deXKuZ/iqGamvWmhDS+dcCNs5Chdb8KhNTybn2zLA==
dependencies:
"@types/nprogress" "^0.2.0"
nprogress "^0.2.0"
prop-types "^15.8.1"
node-releases@^2.0.13:
version "2.0.13"
resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz"
@@ -2258,7 +2329,7 @@ postcss-value-parser@^4.0.0, postcss-value-parser@^4.2.0:
resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz"
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
postcss@^8, postcss@^8.0.0, postcss@^8.1.0, postcss@^8.2.14, postcss@^8.4.21, postcss@^8.4.23, postcss@>=8.0.9, postcss@8.4.31:
postcss@8.4.31, postcss@^8, postcss@^8.4.23:
version "8.4.31"
resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz"
integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==
@@ -2277,12 +2348,12 @@ prettier-plugin-organize-imports@^3.2.3:
resolved "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-3.2.3.tgz"
integrity sha512-KFvk8C/zGyvUaE3RvxN2MhCLwzV6OBbFSkwZ2OamCrs9ZY4i5L77jQ/w4UmUr+lqX8qbaqVq6bZZkApn+IgJSg==
prettier@^3.0.3, prettier@>=2.0:
prettier@^3.0.3:
version "3.0.3"
resolved "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz"
integrity sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==
prisma@*, prisma@^5.6.0:
prisma@^5.6.0:
version "5.6.0"
resolved "https://registry.npmjs.org/prisma/-/prisma-5.6.0.tgz"
integrity sha512-EEaccku4ZGshdr2cthYHhf7iyvCcXqwJDvnoQRAJg5ge2Tzpv0e2BaMCp+CbbDUwoVTzwgOap9Zp+d4jFa2O9A==
@@ -2308,7 +2379,7 @@ queue-microtask@^1.2.2:
resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz"
integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
"react-dom@^16.8 || ^17.0 || ^18.0", react-dom@^18, react-dom@^18.2.0, react-dom@>=16.8.0:
react-dom@^18:
version "18.2.0"
resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz"
integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==
@@ -2316,7 +2387,7 @@ queue-microtask@^1.2.2:
loose-envify "^1.1.0"
scheduler "^0.23.0"
react-hook-form@^7.0.0, react-hook-form@^7.47.0:
react-hook-form@^7.47.0:
version "7.47.0"
resolved "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.47.0.tgz"
integrity sha512-F/TroLjTICipmHeFlMrLtNLceO2xr1jU3CyiNla5zdwsGUGu2UOxxR4UyJgLlhMwLW/Wzp4cpJ7CPfgJIeKdSg==
@@ -2354,7 +2425,7 @@ react-style-singleton@^2.2.1:
invariant "^2.2.4"
tslib "^2.0.0"
"react@^16.5.1 || ^17.0.0 || ^18.0.0", "react@^16.8 || ^17.0 || ^18.0", "react@^16.8.0 || ^17 || ^18", "react@^16.8.0 || ^17.0.0 || ^18.0.0", react@^18, react@^18.2.0, "react@>= 16.8.0 || 17.x.x || ^18.0.0-0", "react@>= 18.0.0", react@>=16.8.0:
react@^18:
version "18.2.0"
resolved "https://registry.npmjs.org/react/-/react-18.2.0.tgz"
integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
@@ -2642,7 +2713,7 @@ tailwindcss-animate@^1.0.7:
resolved "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz"
integrity sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==
tailwindcss@^3, "tailwindcss@>=3.0.0 || insiders":
tailwindcss@^3:
version "3.3.5"
resolved "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.5.tgz"
integrity sha512-5SEZU4J7pxZgSkv7FP1zY8i2TIAOooNZ1e/OGtxIEv6GltpoiXUqWvLy89+a10qYTB1N5Ifkuw9lqQkN9sscvA==
@@ -2777,7 +2848,7 @@ typed-array-length@^1.0.4:
for-each "^0.3.3"
is-typed-array "^1.1.9"
typescript@^5, typescript@>=2.9, typescript@>=3.3.1, typescript@>=4.2.0:
typescript@^5:
version "5.2.2"
resolved "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz"
integrity sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==