feat: tempcommit (broken input)

This commit is contained in:
Maximilian Liebmann 2025-06-29 22:09:18 +02:00
parent 7d2d5c55e8
commit ba6d21eec5
6 changed files with 335 additions and 203 deletions

View file

@ -1,19 +1,20 @@
import { Button } from '@/components/ui/button';
import { IconProp } from '@fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { LucideProps } from 'lucide-react';
import React, { ForwardRefExoticComponent, RefAttributes } from 'react';
export function IconButton({
icon,
children,
...props
}: {
icon: IconProp;
icon?: ForwardRefExoticComponent<
Omit<LucideProps, 'ref'> & RefAttributes<SVGSVGElement>
>;
children: React.ReactNode;
} & React.ComponentProps<typeof Button>) {
return (
<Button type='button' variant='secondary' {...props}>
<FontAwesomeIcon icon={icon} className='mr-2' />
{icon && React.createElement(icon, { className: 'mr-2' })}
{children}
</Button>
);

View file

@ -1,6 +1,6 @@
import { signIn } from '@/auth';
import { IconButton } from '@/components/buttons/icon-button';
import { faOpenid } from '@fortawesome/free-brands-svg-icons';
import { Fingerprint, ScanEye } from 'lucide-react';
export default function SSOLogin({
provider,
@ -22,7 +22,7 @@ export default function SSOLogin({
className='w-full'
type='submit'
variant='secondary'
icon={faOpenid}
icon={Fingerprint}
{...props}
>
Login with {providerDisplayName}

View file

@ -62,18 +62,20 @@ export function AppSidebar() {
<>
<Sidebar collapsible='icon' variant='sidebar'>
<SidebarHeader className='overflow-hidden'>
<Logo
colorType='colored'
logoType='combo'
height={50}
className='group-data-[collapsible=icon]:hidden min-w-[203px]'
></Logo>
<Logo
colorType='colored'
logoType='submark'
height={50}
className='group-data-[collapsible=]:hidden group-data-[mobile=true]/mobile:hidden'
></Logo>
<Link href='/home'>
<Logo
colorType='colored'
logoType='combo'
height={50}
className='group-data-[collapsible=icon]:hidden min-w-[203px]'
></Logo>
<Logo
colorType='colored'
logoType='submark'
height={50}
className='group-data-[collapsible=]:hidden group-data-[mobile=true]/mobile:hidden'
></Logo>
</Link>
</SidebarHeader>
<SidebarContent className='grid grid-rows-[auto_1fr_auto]'>
<Collapsible defaultOpen className='group/collapsible'>

View file

@ -1,8 +1,8 @@
import { Input, Textarea } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import React from 'react';
import React, { ForwardRefExoticComponent, RefAttributes } from 'react';
import { Button } from '../ui/button';
import { Eye, EyeOff } from 'lucide-react';
import { Eye, EyeOff, LucideProps } from 'lucide-react';
import { cn } from '@/lib/utils';
export default function LabeledInput({
@ -12,6 +12,7 @@ export default function LabeledInput({
placeholder,
value,
name,
icon,
variantSize = 'default',
autocomplete,
error,
@ -22,11 +23,22 @@ export default function LabeledInput({
placeholder?: string;
value?: string;
name?: string;
icon?: ForwardRefExoticComponent<
Omit<LucideProps, 'ref'> & RefAttributes<SVGSVGElement>
>;
variantSize?: 'default' | 'big' | 'textarea';
autocomplete?: string;
error?: string;
} & React.InputHTMLAttributes<HTMLInputElement>) {
const [passwordVisible, setPasswordVisible] = React.useState(false);
const [inputValue, setInputValue] = React.useState(value || '');
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setInputValue(e.target.value);
if (rest.onChange) {
rest.onChange(e);
}
};
return (
<div className='grid grid-cols-1 gap-1'>
@ -50,18 +62,32 @@ export default function LabeledInput({
className={cn(
type === 'password' ? 'pr-[50px]' : '',
variantSize === 'big'
? 'h-12 file:h-10 text-lg gplaceholder:text-lg sm:text-2xl sm:placeholder:text-2xl'
? 'h-12 file:h-10 text-lg placeholder:text-lg sm:text-2xl sm:placeholder:text-2xl'
: '',
icon && inputValue === '' ? 'pl-10' : '',
'transition-all duration-300 ease-in-out',
)}
type={passwordVisible ? 'text' : type}
placeholder={placeholder}
defaultValue={value}
value={inputValue}
id={name}
name={name}
autoComplete={autocomplete}
onChange={handleInputChange}
{...rest}
/>
{icon && (
<span
className={cn(
'absolute left-3 top-1/2 -translate-y-1/2 text-muted-input transition-all duration-300 ease-in-out',
inputValue === ''
? 'opacity-100 scale-100'
: 'opacity-0 scale-75 pointer-events-none',
)}
>
{React.createElement(icon)}
</span>
)}
{type === 'password' && (
<Button
className='absolute right-0 top-0 w-[36px] h-[36px]'
@ -74,7 +100,6 @@ export default function LabeledInput({
)}
</span>
)}
{error && <p className='text-red-500 text-sm mt-1'>{error}</p>}
</div>
);

View file

@ -4,11 +4,21 @@ import React, { useState, useRef } from 'react';
import { useRouter } from 'next/navigation';
import LabeledInput from '@/components/custom-ui/labeled-input';
import { Button } from '@/components/ui/button';
import useZodForm from '@/lib/hooks/useZodForm';
import { loginSchema, registerSchema } from '@/lib/auth/validation';
import { loginAction } from '@/lib/auth/login';
import { registerAction } from '@/lib/auth/register';
import { IconButton } from '../buttons/icon-button';
import {
FileKey,
FileKey2,
LogIn,
MailOpen,
RotateCcwKey,
UserCheck,
UserPen,
UserPlus,
} from 'lucide-react';
function LoginFormElement({
setIsSignUp,
@ -56,6 +66,7 @@ function LoginFormElement({
<LabeledInput
type='text'
label='E-Mail or Username'
icon={UserCheck}
placeholder='What you are known as'
error={formState.errors.email?.message}
{...register('email')}
@ -64,16 +75,22 @@ function LoginFormElement({
<LabeledInput
type='password'
label='Password'
icon={FileKey}
placeholder="Let's hope you remember it"
error={formState.errors.password?.message}
{...register('password')}
data-cy='password-input'
/>
<div className='grid grid-rows-2 gap-2'>
<Button type='submit' variant='primary' data-cy='login-button'>
<IconButton
type='submit'
variant='primary'
data-cy='login-button'
icon={LogIn}
>
Login
</Button>
<Button
</IconButton>
<IconButton
type='button'
variant='outline_primary'
onClick={() => {
@ -81,9 +98,10 @@ function LoginFormElement({
setIsSignUp((v) => !v);
}}
data-cy='register-switch'
icon={UserPlus}
>
Sign Up
</Button>
</IconButton>
</div>
<div>
{formState.errors.root?.message && (
@ -159,6 +177,7 @@ function RegisterFormElement({
<LabeledInput
type='email'
label='E-Mail'
icon={MailOpen}
placeholder='Your email address'
autocomplete='email'
error={formState.errors.email?.message}
@ -168,6 +187,7 @@ function RegisterFormElement({
<LabeledInput
type='text'
label='Username'
icon={UserPen}
placeholder='Your username'
autocomplete='username'
error={formState.errors.username?.message}
@ -177,6 +197,7 @@ function RegisterFormElement({
<LabeledInput
type='password'
label='Password'
icon={FileKey2}
placeholder='Create a password'
autocomplete='new-password'
error={formState.errors.password?.message}
@ -186,6 +207,7 @@ function RegisterFormElement({
<LabeledInput
type='password'
label='Confirm Password'
icon={RotateCcwKey}
placeholder='Repeat your password'
autocomplete='new-password'
error={formState.errors.confirmPassword?.message}
@ -193,19 +215,25 @@ function RegisterFormElement({
data-cy='confirm-password-input'
/>
<div className='grid grid-rows-2 gap-2'>
<Button type='submit' variant='primary' data-cy='register-button'>
<IconButton
type='submit'
variant='primary'
data-cy='register-button'
icon={UserPlus}
>
Sign Up
</Button>
<Button
</IconButton>
<IconButton
type='button'
variant='outline_primary'
onClick={() => {
formRef?.current?.reset();
setIsSignUp((v) => !v);
}}
icon={LogIn}
>
Back to Login
</Button>
</IconButton>
</div>
<div>
{formState.errors.root?.message && (

View file

@ -9,7 +9,7 @@ import {
CardHeader,
CardTitle,
} from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { ScrollableSettingsWrapper } from '@/components/wrappers/settings-scroll';
import { Switch } from '@/components/ui/switch';
@ -28,8 +28,23 @@ import LabeledInput from '../custom-ui/labeled-input';
import { GroupWrapper } from '../wrappers/group-wrapper';
import ProfilePictureUpload from './profile-picture-upload';
import { LogOut } from 'lucide-react';
import { signOut } from '@/auth';
import {
CalendarArrowDown,
CalendarArrowUp,
CalendarCheck,
CalendarClock,
CalendarCog,
CalendarPlus,
CalendarPlus2,
ClockAlert,
ClockFading,
FileKey,
FileKey2,
MailOpen,
RotateCcwKey,
UserLock,
} from 'lucide-react';
import { IconButton } from '../buttons/icon-button';
export default function SettingsPage() {
const router = useRouter();
@ -46,7 +61,8 @@ export default function SettingsPage() {
<CardHeader>
<CardTitle>Account Settings</CardTitle>
</CardHeader>
<CardContent className='space-y-6 mt-2'>
<CardContent className='space-y-6 my-2'>
{/*-------------------- General Settings --------------------*/}
<GroupWrapper title='General Settings'>
<div className='space-y-4'>
<div>
@ -77,6 +93,7 @@ export default function SettingsPage() {
<LabeledInput
type='email'
label='Email Address'
icon={MailOpen}
placeholder='Your E-Mail'
defaultValue={data?.data.user.email ?? ''}
></LabeledInput>
@ -87,39 +104,42 @@ export default function SettingsPage() {
</div>
</div>
</GroupWrapper>
{/*-------------------- General Settings --------------------*/}
{/*-------------------- Reset Password --------------------*/}
<GroupWrapper title='Reset Password'>
<div className='flex items-center justify-evenly sm:flex-row flex-col gap-6'>
<div>
<LabeledInput
type='password'
label='Current Password'
placeholder='Current Password'
defaultValue={data?.data.user.first_name ?? ''}
icon={FileKey}
></LabeledInput>
</div>
<div>
<LabeledInput
type='password'
label='New Password'
placeholder='New Password'
defaultValue={data?.data.user.first_name ?? ''}
icon={FileKey2}
></LabeledInput>
</div>
<div>
<LabeledInput
type='password'
label='Repeat Password'
placeholder='Repeat Password'
defaultValue={data?.data.user.first_name ?? ''}
icon={RotateCcwKey}
></LabeledInput>
</div>
</div>
</GroupWrapper>
{/*-------------------- Reset Password --------------------*/}
{/*-------------------- Profile Picture --------------------*/}
<GroupWrapper title='Profile Picture'>
<div className='space-y-2 grid grid-cols-[1fr_auto]'>
<ProfilePictureUpload className='file:border file:rounded-md file:hover:bg-disabled-destructive' />
</div>
</GroupWrapper>
{/*-------------------- Profile Picture --------------------*/}
{/*-------------------- Regional Settings --------------------*/}
<GroupWrapper title='Regional Settings'>
<div className='space-y-2 grid sm:grid-cols-[1fr_auto] sm:flex-row gap-4'>
<div className='grid gap-1'>
@ -127,6 +147,7 @@ export default function SettingsPage() {
type='text'
label='Timezone'
placeholder='Europe/Berlin'
icon={CalendarClock}
defaultValue={data?.data.user.timezone ?? ''}
></LabeledInput>
</div>
@ -146,23 +167,26 @@ export default function SettingsPage() {
</div>
</div>
</GroupWrapper>
<div className='flex items-center justify-evenly sm:flex-row flex-col gap-6'>
<Button
onClick={() => {
deleteUser.mutate(undefined, {
onSuccess: () => {
router.push('/api/logout');
},
});
}}
variant='destructive'
>
Delete Account
</Button>
<span className='text-sm text-muted-foreground pt-1'>
Permanently delete your account and all associated data.
</span>
</div>
{/*-------------------- Regional Settings --------------------*/}
<GroupWrapper title='DANGER ZONE - INSTANT DELETE - NO CONFIRMATION'>
<div className='flex items-center justify-evenly sm:flex-row flex-col gap-6'>
<Button
onClick={() => {
deleteUser.mutate(undefined, {
onSuccess: () => {
router.push('/api/logout');
},
});
}}
variant='destructive'
>
Delete Account
</Button>
<span className='text-sm text-muted-foreground pt-1'>
Permanently delete your account and all associated data.
</span>
</div>
</GroupWrapper>
</CardContent>
</ScrollableSettingsWrapper>
</Card>
@ -175,8 +199,9 @@ export default function SettingsPage() {
<CardHeader>
<CardTitle>Notification Preferences</CardTitle>
</CardHeader>
<CardContent className='space-y-6'>
<GroupWrapper>
<CardContent className='space-y-6 my-2'>
{/*-------------------- All --------------------*/}
<GroupWrapper title='All'>
<div className='flex items-center justify-between'>
<Label
htmlFor='masterEmailNotifications'
@ -187,7 +212,8 @@ export default function SettingsPage() {
<Switch id='masterEmailNotifications' />
</div>
</GroupWrapper>
{/*-------------------- All --------------------*/}
{/*-------------------- Meetings --------------------*/}
<GroupWrapper title='Meetings'>
<div className='space-y-4'>
<div className='flex items-center justify-between space-x-2'>
@ -239,6 +265,8 @@ export default function SettingsPage() {
</div>
</div>
</GroupWrapper>
{/*-------------------- Meetings --------------------*/}
{/*-------------------- Social --------------------*/}
<GroupWrapper title='Social'>
<div className='space-y-4'>
<div className='flex items-center justify-between space-x-2'>
@ -255,6 +283,7 @@ export default function SettingsPage() {
</div>
</div>
</GroupWrapper>
{/*-------------------- Social --------------------*/}
</CardContent>
</ScrollableSettingsWrapper>
</Card>
@ -267,8 +296,39 @@ export default function SettingsPage() {
<CardHeader>
<CardTitle>Calendar & Availability</CardTitle>
</CardHeader>
<CardContent className='space-y-6'>
{/*--------------------* Calendar --------------------*/}
<CardContent className='space-y-6 my-2'>
{/*-------------------- Date & Time Format --------------------*/}
<GroupWrapper title='Date & Time Format'>
<div className='flex flex-col space-y-4'>
<div className='grid grid-cols-1 gap-1'>
<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='grid grid-cols-1 gap-1'>
<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>
</div>
</GroupWrapper>
{/*-------------------- Date & Time Format --------------------*/}
{/*-------------------- Calendar --------------------*/}
<GroupWrapper title='Calendar'>
<div className='space-y-4'>
<div className='grid grid-cols-1 gap-1'>
@ -306,9 +366,8 @@ export default function SettingsPage() {
</div>
</div>
</GroupWrapper>
{/*--------------------* Calendar --------------------*/}
{/*--------------------* Availability --------------------*/}
{/*-------------------- Calendar --------------------*/}
{/*-------------------- Availability --------------------*/}
<GroupWrapper title='Availability'>
<div className='space-y-4'>
<div className='space-y-2'>
@ -325,8 +384,9 @@ export default function SettingsPage() {
<LabeledInput
type='text'
label='Minimum Notice for Bookings'
icon={ClockAlert}
subtext='Min time before a booking can be made.'
placeholder='e.g., 1h'
placeholder='e.g. 1h'
defaultValue={''}
></LabeledInput>
</div>
@ -334,43 +394,65 @@ export default function SettingsPage() {
<LabeledInput
type='text'
label='Booking Window (days in advance)'
icon={ClockFading}
subtext='Max time in advance a booking can be made.'
placeholder='e.g., 30d'
placeholder='e.g. 30d'
defaultValue={''}
></LabeledInput>
</div>
</div>
</GroupWrapper>
{/*--------------------* Availability --------------------*/}
{/*--------------------* iCalendar Integration --------------------*/}
<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'>
<LabeledInput
type='url'
label='Import iCal Feed URL'
subtext='Max time in advance a booking can be made.'
placeholder='https://calendar.example.com/feed.ics'
defaultValue={''}
></LabeledInput>
<Button size='sm' className='mt-1'>
Add Feed
</Button>
{/*-------------------- Availability --------------------*/}
{/*-------------------- iCalendar Integration --------------------*/}
<GroupWrapper title='iCalendar Integration'>
<div className='space-y-4'>
<form
onSubmit={(e) => {
e.preventDefault();
}}
className='space-y-2'
>
<LabeledInput
type='url'
label='Import iCal Feed URL'
icon={CalendarCheck}
placeholder='https://calendar.example.com/feed.ics'
defaultValue={''}
name='icalUrl'
required
></LabeledInput>
<IconButton
type='submit'
size='sm'
className='mt-1'
variant={'secondary'}
icon={CalendarPlus}
title='Submit iCal URL'
>
Add Feed
</IconButton>
</form>
<div className='space-y-2'>
<Label>Export Your Calendar</Label>
<IconButton
variant='outline_muted'
size='sm'
icon={CalendarArrowUp}
>
Get iCal Export URL
</IconButton>
<IconButton
variant='outline_muted'
size='sm'
className='ml-2'
icon={CalendarArrowDown}
>
Download .ics File
</IconButton>
</div>
</div>
<div className='space-y-2'>
<Label>Export Your Calendar</Label>
<Button variant='outline_muted' size='sm'>
Get iCal Export URL
</Button>
<Button variant='outline_muted' size='sm' className='ml-2'>
Download .ics File
</Button>
</div>
</fieldset>
{/*--------------------* iCalendar Integration --------------------*/}
</GroupWrapper>
{/*-------------------- iCalendar Integration --------------------*/}
</CardContent>
</ScrollableSettingsWrapper>
</Card>
@ -383,79 +465,94 @@ export default function SettingsPage() {
<CardHeader>
<CardTitle>Sharing & Privacy</CardTitle>
</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>
<span 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>
</span>
<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_muted'>Manage Blocked Users</Button>
<span className='text-sm text-muted-foreground'>
Prevent specific users from seeing your calendar or booking
time.
</span>
</div>
<CardContent className='space-y-6 my-2'>
{/*-------------------- Privacy Settigs --------------------*/}
<GroupWrapper title='Privacy Settings'>
<div className='flex flex-col space-y-4'>
<div className='grid grid-cols-1 gap-1'>
<Label htmlFor='defaultVisibility'>
Default Calendar Visibility
</Label>
<span className='text-sm text-muted-foreground'>
Default setting for new friends.
</span>
<Select>
<SelectTrigger id='defaultVisibility'>
<SelectValue placeholder='Select visibility' />
</SelectTrigger>
<SelectContent>
<SelectItem value='private'>
Private (Only You)
</SelectItem>
<SelectItem value='freebusy'>Free/Busy</SelectItem>
<SelectItem value='fulldetails'>
Full Details
</SelectItem>
</SelectContent>
</Select>
</div>
<div className='grid grid-cols-1 gap-1'>
<Label htmlFor='whoCanSeeFull'>
Who Can See Your Full Calendar Details?
</Label>
<span 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>
</span>
<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='grid grid-cols-1 gap-1'>
<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-4'>
<div className='grid grid-cols-1 gap-1'>
<Label>Blocked Users</Label>
<span className='text-sm text-muted-foreground'>
Prevent specific users from seeing your calendar or
booking time.
</span>
<IconButton
variant='outline_muted'
size='sm'
icon={UserLock}
>
Manage Blocked Users
</IconButton>
</div>
</div>
</div>
</GroupWrapper>
{/*-------------------- Privacy Settigs --------------------*/}
</CardContent>
</ScrollableSettingsWrapper>
</Card>
@ -468,36 +565,15 @@ export default function SettingsPage() {
<CardHeader>
<CardTitle>Appearance</CardTitle>
</CardHeader>
<CardContent className='space-y-6'>
<div className='space-y-2'>
<Label htmlFor='theme'>Theme</Label>
<ThemePicker />
</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 className='space-y-6 my-2'>
{/*-------------------- Change Theme --------------------*/}
<GroupWrapper title='Change Theme'>
<div className='space-y-2'>
<Label htmlFor='theme'>Theme</Label>
<ThemePicker />
</div>
</GroupWrapper>
{/*-------------------- Change Theme --------------------*/}
</CardContent>
</ScrollableSettingsWrapper>
</Card>