Compare commits

...

24 commits

Author SHA1 Message Date
fbf504d448 fix: standardize quotes and formatting in Select, Separator, and Switch components
All checks were successful
container-scan / Container Scan (pull_request) Successful in 2m35s
docker-build / docker (pull_request) Successful in 16m34s
2025-05-11 16:48:41 +02:00
40fd42db32 feat: added tabs to settings window and created general settings window design 2025-05-11 16:43:27 +02:00
d547a93a40 feat: add ScrollableSettingsWrapper component for scrollable settings 2025-05-11 16:37:08 +02:00
ec66b94f64 feat: add Radix UI Select, Separator, and Switch components 2025-05-11 16:37:08 +02:00
41a08a4c37 feat: implement Settings page with tabs 2025-05-11 16:37:08 +02:00
42f299c27e feat: implement Settings page with tabs 2025-05-11 16:37:08 +02:00
fc273906bd feat: add Radix UI Label component and update dependencies 2025-05-11 16:37:08 +02:00
4c31fc459f fix: standardize quotes and formatting in Tabs component 2025-05-11 16:37:08 +02:00
90b088b7c3 fix: update middleware to redirect authenticated users to home
Automatically redirectis authenticated users from root path ('/') to the '/home' page.
2025-05-11 16:37:08 +02:00
ed6eb6f022 chore(deps): pin ghcr.io/di0ik/forgejo_runner_container docker tag to 672aee9 2025-05-11 16:37:08 +02:00
bfe6317954 fix(deps): update dependency lucide-react to ^0.509.0 2025-05-11 16:37:08 +02:00
29a1dd8d7c feat: add Radix UI Tabs component and update dependencies 2025-05-11 16:37:08 +02:00
b795d6a66a feat: add Tabs component with Radix UI integration 2025-05-11 16:37:08 +02:00
e3a53aa1ce fix(deps): update dependency next-auth to v5.0.0-beta.28 2025-05-11 16:37:08 +02:00
235d2cefc3 fix: dont try to remove already removed tags 2025-05-11 16:37:08 +02:00
e99a637435 fix: make repo to lower workflow step posix compatible 2025-05-11 16:37:08 +02:00
99eb22d471 fix: set container image in workflow files 2025-05-11 16:37:08 +02:00
7605936335 fix: keep some build caches to speed up builds 2025-05-11 16:37:08 +02:00
a3b6e85766 chore: remove docker installs from workflows 2025-05-11 16:37:08 +02:00
90474882ea chore: add Docker cleanup steps to workflows 2025-05-11 16:37:08 +02:00
e0b0dd05dc fix: add missing env variable to docker-compose
added the missing AUTH_URL variable to the example docker-compose.yml
2025-05-11 16:37:08 +02:00
2bb330245f chore(ci): remove sha_ tags from build docker images 2025-05-11 16:37:08 +02:00
bbdecc8b2f chore(ci): example environment variables
add example environment variables to docker-compose.yml to prevent errors
2025-05-11 16:37:08 +02:00
66cc84d634 chore(ci): Add labels to docker image 2025-05-11 16:37:08 +02:00
16 changed files with 1258 additions and 41 deletions

View file

@ -9,22 +9,11 @@ jobs:
name: Container Scan
runs-on: docker
container:
image: node:22-bullseye@sha256:ed0338dd02fd86861a59dc1cbc2e12152f3a93c4ce5933d347d6677232000dc7
image: ghcr.io/di0ik/forgejo_runner_container:main@sha256:672aee9a5dfc35531db3a218ad9486eb5c5d7d9ac10bdcba13110470c10403ee
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- name: Install Docker
run: |
apt-get update
apt-get install -y ca-certificates curl
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
apt-get update
apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
- name: Build an image from Dockerfile
run: docker build -t git.dominikstahl.dev/dhbw-we/meetup:${{ github.sha }} .
@ -41,3 +30,9 @@ jobs:
uses: forgejo/upload-artifact@v4
with:
path: trivy-report.json
- name: Clean up Docker
run: |
docker builder prune -af --keep-storage 2GB
docker rmi $(docker images --filter=reference="git.dominikstahl.dev/dhbw-we/meetup:*" -q)
docker image prune -f

View file

@ -12,18 +12,9 @@ on:
jobs:
docker:
runs-on: docker
container:
image: ghcr.io/di0ik/forgejo_runner_container:main@sha256:672aee9a5dfc35531db3a218ad9486eb5c5d7d9ac10bdcba13110470c10403ee
steps:
- name: Install Docker
run: |
apt-get update
apt-get install -y ca-certificates curl
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
apt-get update
apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
- name: Login to Docker Hub
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3
with:
@ -46,14 +37,14 @@ jobs:
- name: lowercase repo name
run: |
echo "REPO=${GITHUB_REPOSITORY,,}" >>${GITHUB_ENV}
echo "REPO=$(echo $GITHUB_REPOSITORY | tr '[:upper:]' '[:lower:]')" >>${GITHUB_ENV}
- name: Build and push (pull_request)
uses: docker/build-push-action@14487ce63c7a62a4a324b0bfb37086795e31c6c1 # v6
if: github.event_name == 'pull_request'
with:
push: true
tags: git.dominikstahl.dev/${{ env.REPO }}:sha_${{ github.sha }},git.dominikstahl.dev/${{ env.REPO }}:${{ steps.get-ref.outputs.tag}}
tags: git.dominikstahl.dev/${{ env.REPO }}:${{ steps.get-ref.outputs.tag}}
- name: Build and push (push_tag)
uses: docker/build-push-action@14487ce63c7a62a4a324b0bfb37086795e31c6c1 # v6
@ -67,4 +58,9 @@ jobs:
if: github.event_name == 'push' && github.ref_type == 'branch'
with:
push: true
tags: git.dominikstahl.dev/${{ env.REPO }}:sha_${{ github.sha }},git.dominikstahl.dev/${{ env.REPO }}:main
tags: git.dominikstahl.dev/${{ env.REPO }}:${{ steps.get-ref.outputs.tag }}
- name: Clean up Docker
run: |
docker builder prune -af --keep-storage 2GB
docker image prune -f

View file

@ -27,6 +27,10 @@ COPY --from=builder /app/public ./public
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
LABEL org.opencontainers.image.source="https://git.dominikstahl.dev/DHBW-WE/MeetUp"
LABEL org.opencontainers.image.title="MeetUp"
LABEL org.opencontainers.image.description="A web application for managing meetups"
EXPOSE 3000
ENV HOSTNAME="0.0.0.0"

View file

@ -3,5 +3,9 @@ services:
build:
context: .
dockerfile: Dockerfile
image: git.dominikstahl.dev/dhbw-we/meetup:main
ports:
- '3000:3000'
environment:
- AUTH_SECRET=secret
- AUTH_URL=http://localhost:3000

View file

@ -15,10 +15,16 @@
"@fortawesome/free-regular-svg-icons": "^6.7.2",
"@fortawesome/free-solid-svg-icons": "^6.7.2",
"@fortawesome/react-fontawesome": "^0.2.2",
"@radix-ui/react-label": "^2.1.6",
"@radix-ui/react-scroll-area": "^1.2.8",
"@radix-ui/react-select": "^2.2.4",
"@radix-ui/react-separator": "^1.1.6",
"@radix-ui/react-slot": "^1.2.2",
"@radix-ui/react-switch": "^1.2.4",
"@radix-ui/react-tabs": "^1.1.11",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"lucide-react": "^0.508.0",
"lucide-react": "^0.509.0",
"next": "15.3.2",
"next-auth": "^5.0.0-beta.25",
"next-themes": "^0.4.6",

View file

@ -1,10 +1,12 @@
import { Logout } from '@/components/user/sso-logout-button';
import { RedirectButton } from '@/components/user/redirect-button';
export default function Home() {
return (
<div>
<h1>Home</h1>
<Logout />
<RedirectButton redirectUrl='/settings' buttonText='Settings' />
</div>
);
}

486
src/app/settings/page.tsx Normal file
View file

@ -0,0 +1,486 @@
//import { RedirectButton } from '@/components/user/redirect-button';
import { Button } from '@/components/ui/button';
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { ScrollableSettingsWrapper } from '@/components/wrappers/settings-scroll'; // Adjust path as needed
import { Switch } from '@/components/ui/switch'; // Assuming you have this or will create/import it
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@/components/ui/select'; // Assuming you have this
/*export default function Settings() {
return (
<div>
<h1>Settings</h1>
<RedirectButton redirectUrl='/home' buttonText='Home' />
</div>
);
}*/
export default function SettingsPage() {
return (
<div className='fixed inset-0 flex items-center justify-center p-4 bg-background/50 backdrop-blur-sm'>
<div className='rounded-lg border bg-card text-card-foreground shadow-xl max-w-[700px] w-full h-auto max-h-[calc(100vh-2rem)] flex flex-col'>
<Tabs
defaultValue='general'
className='w-full flex flex-col flex-grow min-h-0'
>
<TabsList className='grid w-full grid-cols-3 sm:grid-cols-5'>
<TabsTrigger value='general'>Account</TabsTrigger>
<TabsTrigger value='notifications'>Notifications</TabsTrigger>
<TabsTrigger value='calendarAvailability'>Calendar</TabsTrigger>
<TabsTrigger value='sharingPrivacy'>Privacy</TabsTrigger>
<TabsTrigger value='appearance'>Appearance</TabsTrigger>
</TabsList>
<TabsContent value='general' className='flex-grow overflow-hidden'>
<Card className='h-full flex flex-col border-0 shadow-none rounded-none'>
<ScrollableSettingsWrapper>
<CardHeader>
<CardTitle>Account Settings</CardTitle>
<CardDescription>
Manage your account details and preferences.
</CardDescription>
</CardHeader>
<CardContent className='space-y-6'>
<div className='space-y-2'>
<Label htmlFor='displayName'>Display Name</Label>
<Input id='displayName' placeholder='Your Name' />
</div>
<div className='space-y-2'>
<Label htmlFor='email'>Email Address</Label>
<Input
id='email'
type='email'
placeholder='your.email@example.com'
readOnly
value='user-email@example.com'
/>
<p className='text-sm text-muted-foreground'>
Email is managed by your SSO provider.
</p>
</div>
<div className='space-y-2'>
<Label htmlFor='profilePicture'>Profile Picture</Label>
<Input id='profilePicture' type='file' />
<p className='text-sm text-muted-foreground'>
Upload a new profile picture.
</p>
</div>
<div className='space-y-2'>
<Label htmlFor='timezone'>Timezone</Label>
<Input id='displayName' placeholder='Europe/Berlin' />
</div>
<div className='space-y-2'>
<Label htmlFor='language'>Language</Label>
<Select>
<SelectTrigger id='language'>
<SelectValue placeholder='Select language' />
</SelectTrigger>
<SelectContent>
<SelectItem value='en'>English</SelectItem>
<SelectItem value='de'>German</SelectItem>
</SelectContent>
</Select>
</div>
<div className='pt-4'>
<Button variant='destructive'>Delete Account</Button>
<p className='text-sm text-muted-foreground pt-1'>
Permanently delete your account and all associated data.
</p>
</div>
</CardContent>
</ScrollableSettingsWrapper>
<CardFooter className='mt-auto border-t pt-4 flex justify-between'>
<Button variant='secondary'>Exit</Button>
<Button>Save Changes</Button>
</CardFooter>
</Card>
</TabsContent>
<TabsContent
value='notifications'
className='flex-grow overflow-hidden'
>
<Card className='h-full flex flex-col border-0 shadow-none rounded-none'>
<ScrollableSettingsWrapper>
<CardHeader>
<CardTitle>Notification Preferences</CardTitle>
<CardDescription>
Choose how you want to be notified.
</CardDescription>
</CardHeader>
<CardContent className='space-y-6'>
<div className='flex items-center justify-between space-x-2 p-3 rounded-md border'>
<Label
htmlFor='masterEmailNotifications'
className='font-normal'
>
Enable All Email Notifications
</Label>
<Switch id='masterEmailNotifications' />
</div>
<div className='space-y-4 pl-2 border-l-2 ml-2'>
<div className='flex items-center justify-between space-x-2'>
<Label
htmlFor='newMeetingBookings'
className='font-normal'
>
New Meeting Bookings
</Label>
<Switch id='newMeetingBookings' />
</div>
<div className='flex items-center justify-between space-x-2'>
<Label
htmlFor='meetingConfirmations'
className='font-normal'
>
Meeting Confirmations/Cancellations
</Label>
<Switch id='meetingConfirmations' />
</div>
<div className='flex items-center justify-between space-x-2'>
<Label
htmlFor='enableMeetingReminders'
className='font-normal'
>
Meeting Reminders
</Label>
<Switch id='enableMeetingReminders' />
</div>
<div className='space-y-2 pl-6'>
<Label htmlFor='remindBefore'>Remind me before</Label>
<Select>
<SelectTrigger id='remindBefore'>
<SelectValue placeholder='Select reminder time' />
</SelectTrigger>
<SelectContent>
<SelectItem value='15m'>15 minutes</SelectItem>
<SelectItem value='30m'>30 minutes</SelectItem>
<SelectItem value='1h'>1 hour</SelectItem>
<SelectItem value='1d'>1 day</SelectItem>
</SelectContent>
</Select>
</div>
<div className='flex items-center justify-between space-x-2'>
<Label htmlFor='friendRequests' className='font-normal'>
Friend Requests
</Label>
<Switch id='friendRequests' />
</div>
<div className='flex items-center justify-between space-x-2'>
<Label htmlFor='groupUpdates' className='font-normal'>
Group Invitations/Updates
</Label>
<Switch id='groupUpdates' />
</div>
</div>
</CardContent>
</ScrollableSettingsWrapper>
<CardFooter className='mt-auto border-t pt-4 flex justify-between'>
<Button variant='secondary'>Exit</Button>
<Button>Save Changes</Button>
</CardFooter>
</Card>
</TabsContent>
<TabsContent
value='calendarAvailability'
className='flex-grow overflow-hidden'
>
<Card className='h-full flex flex-col border-0 shadow-none rounded-none'>
<ScrollableSettingsWrapper>
<CardHeader>
<CardTitle>Calendar & Availability</CardTitle>
<CardDescription>
Manage your calendar display, default availability, and iCal
integrations.
</CardDescription>
</CardHeader>
<CardContent className='space-y-6'>
<fieldset className='space-y-4 p-4 border rounded-md'>
<legend className='text-sm font-medium px-1'>
Display
</legend>
<div className='space-y-2'>
<Label htmlFor='defaultCalendarView'>
Default Calendar View
</Label>
<Select>
<SelectTrigger id='defaultCalendarView'>
<SelectValue placeholder='Select view' />
</SelectTrigger>
<SelectContent>
<SelectItem value='day'>Day</SelectItem>
<SelectItem value='week'>Week</SelectItem>
<SelectItem value='month'>Month</SelectItem>
</SelectContent>
</Select>
</div>
<div className='space-y-2'>
<Label htmlFor='weekStartsOn'>Week Starts On</Label>
<Select>
<SelectTrigger id='weekStartsOn'>
<SelectValue placeholder='Select day' />
</SelectTrigger>
<SelectContent>
<SelectItem value='sunday'>Sunday</SelectItem>
<SelectItem value='monday'>Monday</SelectItem>
</SelectContent>
</Select>
</div>
<div className='flex items-center justify-between space-x-2'>
<Label htmlFor='showWeekends' className='font-normal'>
Show Weekends
</Label>
<Switch id='showWeekends' defaultChecked />
</div>
</fieldset>
<fieldset className='space-y-4 p-4 border rounded-md'>
<legend className='text-sm font-medium px-1'>
Availability
</legend>
<div className='space-y-2'>
<Label>Working Hours</Label>
<p className='text-sm text-muted-foreground'>
Define your typical available hours (e.g.,
Monday-Friday, 9 AM - 5 PM).
</p>
<Button variant='outline' size='sm'>
Set Working Hours
</Button>
</div>
<div className='space-y-2'>
<Label htmlFor='minNoticeBooking'>
Minimum Notice for Bookings
</Label>
<p className='text-sm text-muted-foreground'>
Min time before a booking can be made.
</p>
<div className='space-y-2'>
<Input
id='bookingWindow'
type='text'
placeholder='e.g., 1h'
/>
</div>
</div>
<div className='space-y-2'>
<Label htmlFor='bookingWindow'>
Booking Window (days in advance)
</Label>
<p className='text-sm text-muted-foreground'>
Max time in advance a booking can be made.
</p>
<Input
id='bookingWindow'
type='number'
placeholder='e.g., 30d'
/>
</div>
</fieldset>
<fieldset className='space-y-4 p-4 border rounded-md'>
<legend className='text-sm font-medium px-1'>
iCalendar Integration
</legend>
<div className='space-y-2'>
<Label htmlFor='icalImport'>Import iCal Feed URL</Label>
<Input
id='icalImport'
type='url'
placeholder='https://calendar.example.com/feed.ics'
/>
<Button size='sm' className='mt-1'>
Add Feed
</Button>
</div>
<div className='space-y-2'>
<Label>Export Your Calendar</Label>
<Button variant='outline' size='sm'>
Get iCal Export URL
</Button>
<Button variant='outline' size='sm' className='ml-2'>
Download .ics File
</Button>
</div>
</fieldset>
</CardContent>
</ScrollableSettingsWrapper>
<CardFooter className='mt-auto border-t pt-4 flex justify-between'>
<Button variant='secondary'>Exit</Button>
<Button>Save Changes</Button>
</CardFooter>
</Card>
</TabsContent>
<TabsContent
value='sharingPrivacy'
className='flex-grow overflow-hidden'
>
<Card className='h-full flex flex-col border-0 shadow-none rounded-none'>
<ScrollableSettingsWrapper>
<CardHeader>
<CardTitle>Sharing & Privacy</CardTitle>
<CardDescription>
Control who can see your calendar and book time with you.
</CardDescription>
</CardHeader>
<CardContent className='space-y-6'>
<div className='space-y-2'>
<Label htmlFor='defaultVisibility'>
Default Calendar Visibility
</Label>
<Select>
<SelectTrigger id='defaultVisibility'>
<SelectValue placeholder='Select visibility' />
</SelectTrigger>
<SelectContent>
<SelectItem value='private'>
Private (Only You)
</SelectItem>
<SelectItem value='freebusy'>
Free/Busy for Friends
</SelectItem>
<SelectItem value='fulldetails'>
Full Details for Friends
</SelectItem>
</SelectContent>
</Select>
</div>
<div className='space-y-2'>
<Label htmlFor='whoCanSeeFull'>
Who Can See Your Full Calendar Details?
</Label>
<p className='text-sm text-muted-foreground'>
(Override for Default Visibility)
<br />
<span className='text-sm text-muted-foreground'>
This setting will override the default visibility for
your calendar. You can set specific friends or groups to
see your full calendar details.
</span>
</p>
<Select>
<SelectTrigger id='whoCanSeeFull'>
<SelectValue placeholder='Select audience' />
</SelectTrigger>
<SelectContent>
<SelectItem value='me'>Only Me</SelectItem>
<SelectItem value='friends'>My Friends</SelectItem>
<SelectItem value='specific'>
Specific Friends/Groups (manage separately)
</SelectItem>
</SelectContent>
</Select>
</div>
<div className='space-y-2'>
<Label htmlFor='whoCanBook'>
Who Can Book Time With You?
</Label>
<Select>
<SelectTrigger id='whoCanBook'>
<SelectValue placeholder='Select audience' />
</SelectTrigger>
<SelectContent>
<SelectItem value='none'>No One</SelectItem>
<SelectItem value='friends'>My Friends</SelectItem>
<SelectItem value='specific'>
Specific Friends/Groups (manage separately)
</SelectItem>
</SelectContent>
</Select>
</div>
<div className='space-y-2'>
<Label>Blocked Users</Label>
<Button variant='outline'>Manage Blocked Users</Button>
<p className='text-sm text-muted-foreground'>
Prevent specific users from seeing your calendar or
booking time.
</p>
</div>
</CardContent>
</ScrollableSettingsWrapper>
<CardFooter className='mt-auto border-t pt-4 flex justify-between'>
<Button variant='secondary'>Exit</Button>
<Button>Save Changes</Button>
</CardFooter>
</Card>
</TabsContent>
<TabsContent value='appearance' className='flex-grow overflow-hidden'>
<Card className='h-full flex flex-col border-0 shadow-none rounded-none'>
<ScrollableSettingsWrapper>
<CardHeader>
<CardTitle>Appearance</CardTitle>
<CardDescription>
Customize the look and feel of the application.
</CardDescription>
</CardHeader>
<CardContent className='space-y-6'>
<div className='space-y-2'>
<Label htmlFor='theme'>Theme</Label>
<Select>
<SelectTrigger id='theme'>
<SelectValue placeholder='Select theme' />
</SelectTrigger>
<SelectContent>
<SelectItem value='light'>Light</SelectItem>
<SelectItem value='dark'>Dark</SelectItem>
<SelectItem value='system'>System Default</SelectItem>
</SelectContent>
</Select>
</div>
<div className='space-y-2'>
<Label htmlFor='dateFormat'>Date Format</Label>
<Select>
<SelectTrigger id='dateFormat'>
<SelectValue placeholder='Select date format' />
</SelectTrigger>
<SelectContent>
<SelectItem value='ddmmyyyy'>DD/MM/YYYY</SelectItem>
<SelectItem value='mmddyyyy'>MM/DD/YYYY</SelectItem>
<SelectItem value='yyyymmdd'>YYYY-MM-DD</SelectItem>
</SelectContent>
</Select>
</div>
<div className='space-y-2'>
<Label htmlFor='timeFormat'>Time Format</Label>
<Select>
<SelectTrigger id='timeFormat'>
<SelectValue placeholder='Select time format' />
</SelectTrigger>
<SelectContent>
<SelectItem value='24h'>24-hour</SelectItem>
<SelectItem value='12h'>12-hour</SelectItem>
</SelectContent>
</Select>
</div>
</CardContent>
</ScrollableSettingsWrapper>
<CardFooter className='mt-auto border-t pt-4 flex justify-between'>
<Button variant='secondary'>Exit</Button>
<Button>Save Changes</Button>
</CardFooter>
</Card>
</TabsContent>
</Tabs>
</div>
</div>
);
}

View file

@ -0,0 +1,24 @@
'use client';
import * as React from 'react';
import * as LabelPrimitive from '@radix-ui/react-label';
import { cn } from '@/lib/utils';
function Label({
className,
...props
}: React.ComponentProps<typeof LabelPrimitive.Root>) {
return (
<LabelPrimitive.Root
data-slot='label'
className={cn(
'flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50',
className,
)}
{...props}
/>
);
}
export { Label };

View file

@ -0,0 +1,185 @@
'use client';
import * as React from 'react';
import * as SelectPrimitive from '@radix-ui/react-select';
import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from 'lucide-react';
import { cn } from '@/lib/utils';
function Select({
...props
}: React.ComponentProps<typeof SelectPrimitive.Root>) {
return <SelectPrimitive.Root data-slot='select' {...props} />;
}
function SelectGroup({
...props
}: React.ComponentProps<typeof SelectPrimitive.Group>) {
return <SelectPrimitive.Group data-slot='select-group' {...props} />;
}
function SelectValue({
...props
}: React.ComponentProps<typeof SelectPrimitive.Value>) {
return <SelectPrimitive.Value data-slot='select-value' {...props} />;
}
function SelectTrigger({
className,
size = 'default',
children,
...props
}: React.ComponentProps<typeof SelectPrimitive.Trigger> & {
size?: 'sm' | 'default';
}) {
return (
<SelectPrimitive.Trigger
data-slot='select-trigger'
data-size={size}
className={cn(
"border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className,
)}
{...props}
>
{children}
<SelectPrimitive.Icon asChild>
<ChevronDownIcon className='size-4 opacity-50' />
</SelectPrimitive.Icon>
</SelectPrimitive.Trigger>
);
}
function SelectContent({
className,
children,
position = 'popper',
...props
}: React.ComponentProps<typeof SelectPrimitive.Content>) {
return (
<SelectPrimitive.Portal>
<SelectPrimitive.Content
data-slot='select-content'
className={cn(
'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border shadow-md',
position === 'popper' &&
'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',
className,
)}
position={position}
{...props}
>
<SelectScrollUpButton />
<SelectPrimitive.Viewport
className={cn(
'p-1',
position === 'popper' &&
'h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1',
)}
>
{children}
</SelectPrimitive.Viewport>
<SelectScrollDownButton />
</SelectPrimitive.Content>
</SelectPrimitive.Portal>
);
}
function SelectLabel({
className,
...props
}: React.ComponentProps<typeof SelectPrimitive.Label>) {
return (
<SelectPrimitive.Label
data-slot='select-label'
className={cn('text-muted-foreground px-2 py-1.5 text-xs', className)}
{...props}
/>
);
}
function SelectItem({
className,
children,
...props
}: React.ComponentProps<typeof SelectPrimitive.Item>) {
return (
<SelectPrimitive.Item
data-slot='select-item'
className={cn(
"focus:bg-accent focus:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
className,
)}
{...props}
>
<span className='absolute right-2 flex size-3.5 items-center justify-center'>
<SelectPrimitive.ItemIndicator>
<CheckIcon className='size-4' />
</SelectPrimitive.ItemIndicator>
</span>
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
</SelectPrimitive.Item>
);
}
function SelectSeparator({
className,
...props
}: React.ComponentProps<typeof SelectPrimitive.Separator>) {
return (
<SelectPrimitive.Separator
data-slot='select-separator'
className={cn('bg-border pointer-events-none -mx-1 my-1 h-px', className)}
{...props}
/>
);
}
function SelectScrollUpButton({
className,
...props
}: React.ComponentProps<typeof SelectPrimitive.ScrollUpButton>) {
return (
<SelectPrimitive.ScrollUpButton
data-slot='select-scroll-up-button'
className={cn(
'flex cursor-default items-center justify-center py-1',
className,
)}
{...props}
>
<ChevronUpIcon className='size-4' />
</SelectPrimitive.ScrollUpButton>
);
}
function SelectScrollDownButton({
className,
...props
}: React.ComponentProps<typeof SelectPrimitive.ScrollDownButton>) {
return (
<SelectPrimitive.ScrollDownButton
data-slot='select-scroll-down-button'
className={cn(
'flex cursor-default items-center justify-center py-1',
className,
)}
{...props}
>
<ChevronDownIcon className='size-4' />
</SelectPrimitive.ScrollDownButton>
);
}
export {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectLabel,
SelectScrollDownButton,
SelectScrollUpButton,
SelectSeparator,
SelectTrigger,
SelectValue,
};

View file

@ -0,0 +1,28 @@
'use client';
import * as React from 'react';
import * as SeparatorPrimitive from '@radix-ui/react-separator';
import { cn } from '@/lib/utils';
function Separator({
className,
orientation = 'horizontal',
decorative = true,
...props
}: React.ComponentProps<typeof SeparatorPrimitive.Root>) {
return (
<SeparatorPrimitive.Root
data-slot='separator-root'
decorative={decorative}
orientation={orientation}
className={cn(
'bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px',
className,
)}
{...props}
/>
);
}
export { Separator };

View file

@ -0,0 +1,31 @@
'use client';
import * as React from 'react';
import * as SwitchPrimitive from '@radix-ui/react-switch';
import { cn } from '@/lib/utils';
function Switch({
className,
...props
}: React.ComponentProps<typeof SwitchPrimitive.Root>) {
return (
<SwitchPrimitive.Root
data-slot='switch'
className={cn(
'peer data-[state=checked]:bg-primary data-[state=unchecked]:bg-input focus-visible:border-ring focus-visible:ring-ring/50 dark:data-[state=unchecked]:bg-input/80 inline-flex h-[1.15rem] w-8 shrink-0 items-center rounded-full border border-transparent shadow-xs transition-all outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50',
className,
)}
{...props}
>
<SwitchPrimitive.Thumb
data-slot='switch-thumb'
className={cn(
'bg-background dark:data-[state=unchecked]:bg-foreground dark:data-[state=checked]:bg-primary-foreground pointer-events-none block size-4 rounded-full ring-0 transition-transform data-[state=checked]:translate-x-[calc(100%-2px)] data-[state=unchecked]:translate-x-0',
)}
/>
</SwitchPrimitive.Root>
);
}
export { Switch };

View file

@ -0,0 +1,66 @@
'use client';
import * as React from 'react';
import * as TabsPrimitive from '@radix-ui/react-tabs';
import { cn } from '@/lib/utils';
function Tabs({
className,
...props
}: React.ComponentProps<typeof TabsPrimitive.Root>) {
return (
<TabsPrimitive.Root
data-slot='tabs'
className={cn('flex flex-col gap-2', className)}
{...props}
/>
);
}
function TabsList({
className,
...props
}: React.ComponentProps<typeof TabsPrimitive.List>) {
return (
<TabsPrimitive.List
data-slot='tabs-list'
className={cn(
'bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px]',
className,
)}
{...props}
/>
);
}
function TabsTrigger({
className,
...props
}: React.ComponentProps<typeof TabsPrimitive.Trigger>) {
return (
<TabsPrimitive.Trigger
data-slot='tabs-trigger'
className={cn(
"data-[state=active]:bg-background dark:data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 text-foreground dark:text-muted-foreground inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className,
)}
{...props}
/>
);
}
function TabsContent({
className,
...props
}: React.ComponentProps<typeof TabsPrimitive.Content>) {
return (
<TabsPrimitive.Content
data-slot='tabs-content'
className={cn('flex-1 outline-none', className)}
{...props}
/>
);
}
export { Tabs, TabsList, TabsTrigger, TabsContent };

View file

@ -0,0 +1,16 @@
import { Button } from '../ui/button';
import Link from 'next/link';
export function RedirectButton({
redirectUrl,
buttonText,
}: {
redirectUrl: string;
buttonText: string;
}) {
return (
<Link href={redirectUrl}>
<Button>{buttonText}</Button>
</Link>
);
}

View file

@ -0,0 +1,16 @@
import React from 'react';
interface ScrollableContentWrapperProps {
children: React.ReactNode;
className?: string;
}
export const ScrollableSettingsWrapper: React.FC<
ScrollableContentWrapperProps
> = ({ children, className = '' }) => {
return (
<div className={`h-[500px] overflow-y-auto space-y-2 ${className}`}>
{children}
</div>
);
};

View file

@ -8,6 +8,9 @@ export default auth((req) => {
) {
const newUrl = new URL('/login', req.nextUrl.origin);
return Response.redirect(newUrl);
} else if (req.auth != null && req.nextUrl.pathname === '/') {
const newUrl = new URL('/home', req.nextUrl.origin);
return Response.redirect(newUrl);
}
});

383
yarn.lock
View file

@ -15,10 +15,10 @@
"@jridgewell/gen-mapping" "^0.3.5"
"@jridgewell/trace-mapping" "^0.3.24"
"@auth/core@0.39.0":
version "0.39.0"
resolved "https://registry.yarnpkg.com/@auth/core/-/core-0.39.0.tgz#39468332bdd6d710f859dcfb6597618f6d99efff"
integrity sha512-jusviw/sUSfAh6S/wjY5tRmJOq0Itd3ImF+c/b4HB9DfmfChtcfVJTNJeqCeExeCG8oh4PBKRsMQJsn2W6NhFQ==
"@auth/core@0.39.1":
version "0.39.1"
resolved "https://registry.yarnpkg.com/@auth/core/-/core-0.39.1.tgz#2b42697154f29b9f8c4c76f6978ed94ea6e19219"
integrity sha512-McD8slui0oOA1pjR5sPjLPl5Zm//nLP/8T3kr8hxIsvNLvsiudYvPHhDFPjh1KcZ2nFxCkZmP6bRxaaPd/AnLA==
dependencies:
"@panva/hkdf" "^1.2.1"
jose "^6.0.6"
@ -239,6 +239,33 @@
"@eslint/core" "^0.13.0"
levn "^0.4.1"
"@floating-ui/core@^1.7.0":
version "1.7.0"
resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.7.0.tgz#1aff27a993ea1b254a586318c29c3b16ea0f4d0a"
integrity sha512-FRdBLykrPPA6P76GGGqlex/e7fbe0F1ykgxHYNXQsH/iTEtjMj/f9bpY5oQqbjt5VgZvgz/uKXbGuROijh3VLA==
dependencies:
"@floating-ui/utils" "^0.2.9"
"@floating-ui/dom@^1.0.0":
version "1.7.0"
resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.7.0.tgz#f9f83ee4fee78ac23ad9e65b128fc11a27857532"
integrity sha512-lGTor4VlXcesUMh1cupTUTDoCxMb0V6bm3CnxHzQcw8Eaf1jQbgQX4i02fYgT0vJ82tb5MZ4CZk1LRGkktJCzg==
dependencies:
"@floating-ui/core" "^1.7.0"
"@floating-ui/utils" "^0.2.9"
"@floating-ui/react-dom@^2.0.0":
version "2.1.2"
resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.1.2.tgz#a1349bbf6a0e5cb5ded55d023766f20a4d439a31"
integrity sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==
dependencies:
"@floating-ui/dom" "^1.0.0"
"@floating-ui/utils@^0.2.9":
version "0.2.9"
resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.9.tgz#50dea3616bc8191fb8e112283b49eaff03e78429"
integrity sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==
"@fortawesome/fontawesome-common-types@6.7.2":
version "6.7.2"
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.7.2.tgz#7123d74b0c1e726794aed1184795dbce12186470"
@ -625,18 +652,287 @@
dependencies:
"@prisma/debug" "6.7.0"
"@radix-ui/number@1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/number/-/number-1.1.1.tgz#7b2c9225fbf1b126539551f5985769d0048d9090"
integrity sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==
"@radix-ui/primitive@1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.1.2.tgz#83f415c4425f21e3d27914c12b3272a32e3dae65"
integrity sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==
"@radix-ui/react-arrow@1.1.6":
version "1.1.6"
resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.1.6.tgz#4b460fdbc1ac097a4964e04ca404c25c2f6d7d3f"
integrity sha512-2JMfHJf/eVnwq+2dewT3C0acmCWD3XiVA1Da+jTDqo342UlU13WvXtqHhG+yJw5JeQmu4ue2eMy6gcEArLBlcw==
dependencies:
"@radix-ui/react-primitive" "2.1.2"
"@radix-ui/react-collection@1.1.6":
version "1.1.6"
resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-1.1.6.tgz#fecf74475e4660ee99c7eb1ebfa5ccfb1a219fe4"
integrity sha512-PbhRFK4lIEw9ADonj48tiYWzkllz81TM7KVYyyMMw2cwHO7D5h4XKEblL8NlaRisTK3QTe6tBEhDccFUryxHBQ==
dependencies:
"@radix-ui/react-compose-refs" "1.1.2"
"@radix-ui/react-context" "1.1.2"
"@radix-ui/react-primitive" "2.1.2"
"@radix-ui/react-slot" "1.2.2"
"@radix-ui/react-compose-refs@1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz#a2c4c47af6337048ee78ff6dc0d090b390d2bb30"
integrity sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==
"@radix-ui/react-slot@^1.2.2":
"@radix-ui/react-context@1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.1.2.tgz#61628ef269a433382c364f6f1e3788a6dc213a36"
integrity sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==
"@radix-ui/react-direction@1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-direction/-/react-direction-1.1.1.tgz#39e5a5769e676c753204b792fbe6cf508e550a14"
integrity sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==
"@radix-ui/react-dismissable-layer@1.1.9":
version "1.1.9"
resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.9.tgz#46e025ba6e6f403677e22fbb7d99b63cf7b32bca"
integrity sha512-way197PiTvNp+WBP7svMJasHl+vibhWGQDb6Mgf5mhEWJkgb85z7Lfl9TUdkqpWsf8GRNmoopx9ZxCyDzmgRMQ==
dependencies:
"@radix-ui/primitive" "1.1.2"
"@radix-ui/react-compose-refs" "1.1.2"
"@radix-ui/react-primitive" "2.1.2"
"@radix-ui/react-use-callback-ref" "1.1.1"
"@radix-ui/react-use-escape-keydown" "1.1.1"
"@radix-ui/react-focus-guards@1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.2.tgz#4ec9a7e50925f7fb661394460045b46212a33bed"
integrity sha512-fyjAACV62oPV925xFCrH8DR5xWhg9KYtJT4s3u54jxp+L/hbpTY2kIeEFFbFe+a/HCE94zGQMZLIpVTPVZDhaA==
"@radix-ui/react-focus-scope@1.1.6":
version "1.1.6"
resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.6.tgz#a265c5f2c6fa4365cb16bdf4fee69e36b62f728a"
integrity sha512-r9zpYNUQY+2jWHWZGyddQLL9YHkM/XvSFHVcWs7bdVuxMAnCwTAuy6Pf47Z4nw7dYcUou1vg/VgjjrrH03VeBw==
dependencies:
"@radix-ui/react-compose-refs" "1.1.2"
"@radix-ui/react-primitive" "2.1.2"
"@radix-ui/react-use-callback-ref" "1.1.1"
"@radix-ui/react-id@1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-1.1.1.tgz#1404002e79a03fe062b7e3864aa01e24bd1471f7"
integrity sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==
dependencies:
"@radix-ui/react-use-layout-effect" "1.1.1"
"@radix-ui/react-label@^2.1.6":
version "2.1.6"
resolved "https://registry.yarnpkg.com/@radix-ui/react-label/-/react-label-2.1.6.tgz#45ebd1381996d0311d199781bed15a092c7978dd"
integrity sha512-S/hv1mTlgcPX2gCTJrWuTjSXf7ER3Zf7zWGtOprxhIIY93Qin3n5VgNA0Ez9AgrK/lEtlYgzLd4f5x6AVar4Yw==
dependencies:
"@radix-ui/react-primitive" "2.1.2"
"@radix-ui/react-popper@1.2.6":
version "1.2.6"
resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.2.6.tgz#227d2882f19d80933796525c7bbd0d3ddf699ac0"
integrity sha512-7iqXaOWIjDBfIG7aq8CUEeCSsQMLFdn7VEE8TaFz704DtEzpPHR7w/uuzRflvKgltqSAImgcmxQ7fFX3X7wasg==
dependencies:
"@floating-ui/react-dom" "^2.0.0"
"@radix-ui/react-arrow" "1.1.6"
"@radix-ui/react-compose-refs" "1.1.2"
"@radix-ui/react-context" "1.1.2"
"@radix-ui/react-primitive" "2.1.2"
"@radix-ui/react-use-callback-ref" "1.1.1"
"@radix-ui/react-use-layout-effect" "1.1.1"
"@radix-ui/react-use-rect" "1.1.1"
"@radix-ui/react-use-size" "1.1.1"
"@radix-ui/rect" "1.1.1"
"@radix-ui/react-portal@1.1.8":
version "1.1.8"
resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.1.8.tgz#0181e85bc0d8c67229dd8cf198204f5f4cc7c09c"
integrity sha512-hQsTUIn7p7fxCPvao/q6wpbxmCwgLrlz+nOrJgC+RwfZqWY/WN+UMqkXzrtKbPrF82P43eCTl3ekeKuyAQbFeg==
dependencies:
"@radix-ui/react-primitive" "2.1.2"
"@radix-ui/react-use-layout-effect" "1.1.1"
"@radix-ui/react-presence@1.1.4":
version "1.1.4"
resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.1.4.tgz#253ac0ad4946c5b4a9c66878335f5cf07c967ced"
integrity sha512-ueDqRbdc4/bkaQT3GIpLQssRlFgWaL/U2z/S31qRwwLWoxHLgry3SIfCwhxeQNbirEUXFa+lq3RL3oBYXtcmIA==
dependencies:
"@radix-ui/react-compose-refs" "1.1.2"
"@radix-ui/react-use-layout-effect" "1.1.1"
"@radix-ui/react-primitive@2.1.2":
version "2.1.2"
resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-2.1.2.tgz#03f64f957719c761d22c2f92cc43ffb64bd42cc8"
integrity sha512-uHa+l/lKfxuDD2zjN/0peM/RhhSmRjr5YWdk/37EnSv1nJ88uvG85DPexSm8HdFQROd2VdERJ6ynXbkCFi+APw==
dependencies:
"@radix-ui/react-slot" "1.2.2"
"@radix-ui/react-roving-focus@1.1.9":
version "1.1.9"
resolved "https://registry.yarnpkg.com/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.9.tgz#37fcacb7dfcc9ea45401b2dd07bd97ccbb8911b2"
integrity sha512-ZzrIFnMYHHCNqSNCsuN6l7wlewBEq0O0BCSBkabJMFXVO51LRUTq71gLP1UxFvmrXElqmPjA5VX7IqC9VpazAQ==
dependencies:
"@radix-ui/primitive" "1.1.2"
"@radix-ui/react-collection" "1.1.6"
"@radix-ui/react-compose-refs" "1.1.2"
"@radix-ui/react-context" "1.1.2"
"@radix-ui/react-direction" "1.1.1"
"@radix-ui/react-id" "1.1.1"
"@radix-ui/react-primitive" "2.1.2"
"@radix-ui/react-use-callback-ref" "1.1.1"
"@radix-ui/react-use-controllable-state" "1.2.2"
"@radix-ui/react-scroll-area@^1.2.8":
version "1.2.8"
resolved "https://registry.yarnpkg.com/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.8.tgz#98a11fe9ca086e403d5c8b5b4c8f781439b45e68"
integrity sha512-K5h1RkYA6M0Sn61BV5LQs686zqBsSC0sGzL4/Gw4mNnjzrQcGSc6YXfC6CRFNaGydSdv5+M8cb0eNsOGo0OXtQ==
dependencies:
"@radix-ui/number" "1.1.1"
"@radix-ui/primitive" "1.1.2"
"@radix-ui/react-compose-refs" "1.1.2"
"@radix-ui/react-context" "1.1.2"
"@radix-ui/react-direction" "1.1.1"
"@radix-ui/react-presence" "1.1.4"
"@radix-ui/react-primitive" "2.1.2"
"@radix-ui/react-use-callback-ref" "1.1.1"
"@radix-ui/react-use-layout-effect" "1.1.1"
"@radix-ui/react-select@^2.2.4":
version "2.2.4"
resolved "https://registry.yarnpkg.com/@radix-ui/react-select/-/react-select-2.2.4.tgz#56eeffd9d5ee23392bba4635e7ae3f381ada793d"
integrity sha512-/OOm58Gil4Ev5zT8LyVzqfBcij4dTHYdeyuF5lMHZ2bIp0Lk9oETocYiJ5QC0dHekEQnK6L/FNJCceeb4AkZ6Q==
dependencies:
"@radix-ui/number" "1.1.1"
"@radix-ui/primitive" "1.1.2"
"@radix-ui/react-collection" "1.1.6"
"@radix-ui/react-compose-refs" "1.1.2"
"@radix-ui/react-context" "1.1.2"
"@radix-ui/react-direction" "1.1.1"
"@radix-ui/react-dismissable-layer" "1.1.9"
"@radix-ui/react-focus-guards" "1.1.2"
"@radix-ui/react-focus-scope" "1.1.6"
"@radix-ui/react-id" "1.1.1"
"@radix-ui/react-popper" "1.2.6"
"@radix-ui/react-portal" "1.1.8"
"@radix-ui/react-primitive" "2.1.2"
"@radix-ui/react-slot" "1.2.2"
"@radix-ui/react-use-callback-ref" "1.1.1"
"@radix-ui/react-use-controllable-state" "1.2.2"
"@radix-ui/react-use-layout-effect" "1.1.1"
"@radix-ui/react-use-previous" "1.1.1"
"@radix-ui/react-visually-hidden" "1.2.2"
aria-hidden "^1.2.4"
react-remove-scroll "^2.6.3"
"@radix-ui/react-separator@^1.1.6":
version "1.1.6"
resolved "https://registry.yarnpkg.com/@radix-ui/react-separator/-/react-separator-1.1.6.tgz#e58500b0e54ba71023955175c7897542bf143271"
integrity sha512-Izof3lPpbCfTM7WDta+LRkz31jem890VjEvpVRoWQNKpDUMMVffuyq854XPGP1KYGWWmjmYvHvPFeocWhFCy1w==
dependencies:
"@radix-ui/react-primitive" "2.1.2"
"@radix-ui/react-slot@1.2.2", "@radix-ui/react-slot@^1.2.2":
version "1.2.2"
resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.2.2.tgz#18e6533e778a2051edc2ad0773da8e22f03f626a"
integrity sha512-y7TBO4xN4Y94FvcWIOIh18fM4R1A8S4q1jhoz4PNzOoHsFcN8pogcFmZrTYAm4F9VRUrWP/Mw7xSKybIeRI+CQ==
dependencies:
"@radix-ui/react-compose-refs" "1.1.2"
"@radix-ui/react-switch@^1.2.4":
version "1.2.4"
resolved "https://registry.yarnpkg.com/@radix-ui/react-switch/-/react-switch-1.2.4.tgz#3318007c4147df69c04141aa7a77c034baea7169"
integrity sha512-yZCky6XZFnR7pcGonJkr9VyNRu46KcYAbyg1v/gVVCZUr8UJ4x+RpncC27hHtiZ15jC+3WS8Yg/JSgyIHnYYsQ==
dependencies:
"@radix-ui/primitive" "1.1.2"
"@radix-ui/react-compose-refs" "1.1.2"
"@radix-ui/react-context" "1.1.2"
"@radix-ui/react-primitive" "2.1.2"
"@radix-ui/react-use-controllable-state" "1.2.2"
"@radix-ui/react-use-previous" "1.1.1"
"@radix-ui/react-use-size" "1.1.1"
"@radix-ui/react-tabs@^1.1.11":
version "1.1.11"
resolved "https://registry.yarnpkg.com/@radix-ui/react-tabs/-/react-tabs-1.1.11.tgz#9dc002ea6f8ad6830bc20f349afdc57c6039009c"
integrity sha512-4FiKSVoXqPP/KfzlB7lwwqoFV6EPwkrrqGp9cUYXjwDYHhvpnqq79P+EPHKcdoTE7Rl8w/+6s9rTlsfXHES9GA==
dependencies:
"@radix-ui/primitive" "1.1.2"
"@radix-ui/react-context" "1.1.2"
"@radix-ui/react-direction" "1.1.1"
"@radix-ui/react-id" "1.1.1"
"@radix-ui/react-presence" "1.1.4"
"@radix-ui/react-primitive" "2.1.2"
"@radix-ui/react-roving-focus" "1.1.9"
"@radix-ui/react-use-controllable-state" "1.2.2"
"@radix-ui/react-use-callback-ref@1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz#62a4dba8b3255fdc5cc7787faeac1c6e4cc58d40"
integrity sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==
"@radix-ui/react-use-controllable-state@1.2.2":
version "1.2.2"
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz#905793405de57d61a439f4afebbb17d0645f3190"
integrity sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==
dependencies:
"@radix-ui/react-use-effect-event" "0.0.2"
"@radix-ui/react-use-layout-effect" "1.1.1"
"@radix-ui/react-use-effect-event@0.0.2":
version "0.0.2"
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz#090cf30d00a4c7632a15548512e9152217593907"
integrity sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==
dependencies:
"@radix-ui/react-use-layout-effect" "1.1.1"
"@radix-ui/react-use-escape-keydown@1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz#b3fed9bbea366a118f40427ac40500aa1423cc29"
integrity sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==
dependencies:
"@radix-ui/react-use-callback-ref" "1.1.1"
"@radix-ui/react-use-layout-effect@1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz#0c4230a9eed49d4589c967e2d9c0d9d60a23971e"
integrity sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==
"@radix-ui/react-use-previous@1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz#1a1ad5568973d24051ed0af687766f6c7cb9b5b5"
integrity sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==
"@radix-ui/react-use-rect@1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz#01443ca8ed071d33023c1113e5173b5ed8769152"
integrity sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==
dependencies:
"@radix-ui/rect" "1.1.1"
"@radix-ui/react-use-size@1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz#6de276ffbc389a537ffe4316f5b0f24129405b37"
integrity sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==
dependencies:
"@radix-ui/react-use-layout-effect" "1.1.1"
"@radix-ui/react-visually-hidden@1.2.2":
version "1.2.2"
resolved "https://registry.yarnpkg.com/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.2.tgz#aa6d0f95b0cd50f08b02393d25132f52ca7861dc"
integrity sha512-ORCmRUbNiZIv6uV5mhFrhsIKw4UX/N3syZtyqvry61tbGm4JlgQuSn0hk5TwCARsCjkcnuRkSdCE3xfb+ADHew==
dependencies:
"@radix-ui/react-primitive" "2.1.2"
"@radix-ui/rect@1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-1.1.1.tgz#78244efe12930c56fd255d7923865857c41ac8cb"
integrity sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==
"@rtsao/scc@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8"
@ -1015,6 +1311,13 @@ argparse@^2.0.1:
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
aria-hidden@^1.2.4:
version "1.2.4"
resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.2.4.tgz#b78e383fdbc04d05762c78b4a25a501e736c4522"
integrity sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==
dependencies:
tslib "^2.0.0"
aria-query@^5.3.2:
version "5.3.2"
resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.2.tgz#93f81a43480e33a338f19163a3d10a50c01dcd59"
@ -1417,6 +1720,11 @@ detect-libc@^2.0.4:
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.4.tgz#f04715b8ba815e53b4d8109655b6508a6865a7e8"
integrity sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==
detect-node-es@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493"
integrity sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==
doctrine@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d"
@ -2056,6 +2364,11 @@ get-intrinsic@^1.2.4, get-intrinsic@^1.2.5, get-intrinsic@^1.2.6, get-intrinsic@
hasown "^2.0.2"
math-intrinsics "^1.1.0"
get-nonce@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/get-nonce/-/get-nonce-1.0.1.tgz#fdf3f0278073820d2ce9426c18f07481b1e0cdf3"
integrity sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==
get-proto@^1.0.0, get-proto@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1"
@ -2604,10 +2917,10 @@ loose-envify@^1.4.0:
dependencies:
js-tokens "^3.0.0 || ^4.0.0"
lucide-react@^0.508.0:
version "0.508.0"
resolved "https://registry.yarnpkg.com/lucide-react/-/lucide-react-0.508.0.tgz#9155465e2051bb42a0ebb2d806f25a8b7125225f"
integrity sha512-gcP16PnexqtOFrTtv98kVsGzTfnbPekzZiQfByi2S89xfk7E/4uKE1USZqccIp58v42LqkO7MuwpCqshwSrJCg==
lucide-react@^0.509.0:
version "0.509.0"
resolved "https://registry.yarnpkg.com/lucide-react/-/lucide-react-0.509.0.tgz#faf65740f603708fd09d21fabf88950d362dbf8c"
integrity sha512-xCJHn6Uh5qF6PGml25vveCTrHJZcqS1G1MVzWZK54ZQsOiCVJk4fwY3oyo5EXS2S+aqvTpWYIfJN+PesJ0quxg==
magic-string@^0.30.17:
version "0.30.17"
@ -2713,11 +3026,11 @@ negotiator@^1.0.0:
integrity sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==
next-auth@^5.0.0-beta.25:
version "5.0.0-beta.27"
resolved "https://registry.yarnpkg.com/next-auth/-/next-auth-5.0.0-beta.27.tgz#dff4cbedc07dc3e6a88148ffd8bdd41c1e87ff13"
integrity sha512-/QtP9C0C99YpEuBEJqMaDXH3ISWMgObQalwVZEoC7sskaIPhv5fQl6fXS/rXJQKqLY6MNJ42rqjqmRdoXZH2EQ==
version "5.0.0-beta.28"
resolved "https://registry.yarnpkg.com/next-auth/-/next-auth-5.0.0-beta.28.tgz#6a7673f858980aaa92668d5c41e5ec3d800866bc"
integrity sha512-2RDR1h3DJb4nizcd5UBBwC2gtyP7j/jTvVLvEtDaFSKUWNfou3Gek2uTNHSga/Q4I/GF+OJobA4mFbRaWJgIDQ==
dependencies:
"@auth/core" "0.39.0"
"@auth/core" "0.39.1"
next-themes@^0.4.6:
version "0.4.6"
@ -3033,6 +3346,33 @@ react-is@^16.13.1:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
react-remove-scroll-bar@^2.3.7:
version "2.3.8"
resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz#99c20f908ee467b385b68a3469b4a3e750012223"
integrity sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==
dependencies:
react-style-singleton "^2.2.2"
tslib "^2.0.0"
react-remove-scroll@^2.6.3:
version "2.6.3"
resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.6.3.tgz#df02cde56d5f2731e058531f8ffd7f9adec91ac2"
integrity sha512-pnAi91oOk8g8ABQKGF5/M9qxmmOPxaAnopyTHYfqYEwJhyFrbbBtHuSgtKEoH0jpcxx5o3hXqH1mNd9/Oi+8iQ==
dependencies:
react-remove-scroll-bar "^2.3.7"
react-style-singleton "^2.2.3"
tslib "^2.1.0"
use-callback-ref "^1.3.3"
use-sidecar "^1.1.3"
react-style-singleton@^2.2.2, react-style-singleton@^2.2.3:
version "2.2.3"
resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.2.3.tgz#4265608be69a4d70cfe3047f2c6c88b2c3ace388"
integrity sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==
dependencies:
get-nonce "^1.0.0"
tslib "^2.0.0"
react@^19.0.0:
version "19.1.0"
resolved "https://registry.yarnpkg.com/react/-/react-19.1.0.tgz#926864b6c48da7627f004795d6cce50e90793b75"
@ -3499,7 +3839,7 @@ tsconfig-paths@^3.15.0:
minimist "^1.2.6"
strip-bom "^3.0.0"
tslib@^2.4.0, tslib@^2.8.0:
tslib@^2.0.0, tslib@^2.1.0, tslib@^2.4.0, tslib@^2.8.0:
version "2.8.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f"
integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==
@ -3624,6 +3964,21 @@ uri-js@^4.2.2:
dependencies:
punycode "^2.1.0"
use-callback-ref@^1.3.3:
version "1.3.3"
resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.3.tgz#98d9fab067075841c5b2c6852090d5d0feabe2bf"
integrity sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==
dependencies:
tslib "^2.0.0"
use-sidecar@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.1.3.tgz#10e7fd897d130b896e2c546c63a5e8233d00efdb"
integrity sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==
dependencies:
detect-node-es "^1.1.0"
tslib "^2.0.0"
vary@^1, vary@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"