update #9

Merged
Joyce merged 1 commits from implement-more-feeedback into main 2026-02-06 01:36:02 +00:00
5 changed files with 257 additions and 162 deletions

View File

@@ -156,6 +156,23 @@ export const AvailabilityHeatmapV2 = ({
}); });
}; };
// Move hooks to top level to avoid conditional hook execution error
const tzOffsetDiff = useMemo(() => {
try {
const now = new Date();
const p = parseInt(new Intl.DateTimeFormat('en-US', { timeZone: displayTimezone, hour: 'numeric', hour12: false }).format(now));
const s = parseInt(new Intl.DateTimeFormat('en-US', { timeZone: secondaryTimezone, hour: 'numeric', hour12: false }).format(now));
let diff = s - p;
if (diff > 12) diff -= 24;
if (diff < -12) diff += 24;
return diff;
} catch {
return 0;
}
}, [displayTimezone, secondaryTimezone]);
const timeColWidth = showSecondaryTimezone ? "120px" : "80px";
if (selectedParticipants.length === 0) { if (selectedParticipants.length === 0) {
return ( return (
<div className="flex flex-col items-center justify-center p-12 border-2 border-dashed border-border/50 rounded-xl bg-muted/20 animate-fade-in"> <div className="flex flex-col items-center justify-center p-12 border-2 border-dashed border-border/50 rounded-xl bg-muted/20 animate-fade-in">
@@ -245,9 +262,15 @@ export const AvailabilityHeatmapV2 = ({
<div className="overflow-auto max-h-[600px] w-full relative"> <div className="overflow-auto max-h-[600px] w-full relative">
<div className="min-w-[700px]"> <div className="min-w-[700px]">
{/* Grid Header */} {/* Grid Header */}
<div className="grid grid-cols-[80px_repeat(5,1fr)] sticky top-0 z-30 bg-card border-b border-border shadow-sm"> <div
<div className="sticky left-0 z-40 bg-card text-xs font-semibold text-muted-foreground self-center p-3 text-right border-r border-border/50"> className="grid sticky top-0 z-30 bg-card border-b border-border shadow-sm"
TIME style={{ gridTemplateColumns: `${timeColWidth} repeat(5, 1fr)` }}
>
<div className="sticky left-0 z-40 bg-card text-xs font-semibold text-muted-foreground self-center p-3 text-right border-r border-border/50 flex flex-col items-end gap-1">
<span>{formatTimezoneDisplay(displayTimezone)}</span>
{showSecondaryTimezone && (
<span className="text-[10px] text-muted-foreground/60 font-normal">{formatTimezoneDisplay(secondaryTimezone)}</span>
)}
</div> </div>
{weekDates.map(date => { {weekDates.map(date => {
const isToday = new Date().toDateString() === date.toDateString(); const isToday = new Date().toDateString() === date.toDateString();
@@ -269,27 +292,41 @@ export const AvailabilityHeatmapV2 = ({
<div className="relative"> <div className="relative">
{activeHours.map((hour) => { {activeHours.map((hour) => {
const isNight = hour < 8 || hour >= 18; const isNight = hour < 8 || hour >= 18;
// Calculate secondary time
let secondaryHour = hour + tzOffsetDiff;
if (secondaryHour >= 24) secondaryHour -= 24;
if (secondaryHour < 0) secondaryHour += 24;
return ( return (
<div <div
key={hour} key={hour}
className={cn( className={cn(
"grid grid-cols-[80px_repeat(5,1fr)] group items-stretch transition-colors border-b border-border/30 last:border-0", "grid group items-stretch transition-colors border-b border-border/30 last:border-0",
isNight ? "bg-muted/30" : "bg-card", isNight ? "bg-muted/30" : "bg-card",
"hover:bg-muted/10" "hover:bg-muted/10"
)} )}
style={{ gridTemplateColumns: `${timeColWidth} repeat(5, 1fr)` }}
> >
{/* Time Label - Sticky Left */} {/* Time Label - Sticky Left */}
<div className={cn( <div className={cn(
"text-xs text-muted-foreground font-medium text-right pr-4 py-3 flex items-center justify-end gap-1.5", "text-xs text-muted-foreground font-medium text-right pr-4 py-3 flex flex-col items-end justify-center gap-0.5",
"sticky left-0 z-20 border-r border-border/50", "sticky left-0 z-20 border-r border-border/50",
isNight ? "bg-muted/30 backdrop-blur-md" : "bg-card" isNight ? "bg-muted/30 backdrop-blur-md" : "bg-card"
)}> )}>
{isNight ? ( <div className="flex items-center gap-1.5">
<Moon className="w-3 h-3 text-slate-400/50" /> {isNight ? (
) : ( <Moon className="w-3 h-3 text-slate-400/50" />
<Sun className="w-3 h-3 text-amber-500/50" /> ) : (
<Sun className="w-3 h-3 text-amber-500/50" />
)}
<span>{formatHour(hour)}</span>
</div>
{showSecondaryTimezone && (
<span className="text-[10px] text-muted-foreground/60 font-mono">
{formatHour(secondaryHour)}
</span>
)} )}
{formatHour(hour)}
</div> </div>
{/* Days */} {/* Days */}

View File

@@ -145,6 +145,20 @@ export const ParticipantSelector = ({
className="flex-1 min-w-[100px] h-7 border-none shadow-none focus-visible:ring-0 p-0 text-sm bg-transparent placeholder:text-muted-foreground/70" className="flex-1 min-w-[100px] h-7 border-none shadow-none focus-visible:ring-0 p-0 text-sm bg-transparent placeholder:text-muted-foreground/70"
/> />
{isDropdownOpen && (
<button
onClick={(e) => {
e.stopPropagation();
setIsDropdownOpen(false);
inputRef.current?.blur();
}}
className="p-1 hover:bg-muted rounded-full transition-colors ml-1"
title="Close"
>
<X className="w-4 h-4 text-muted-foreground" />
</button>
)}
{isDropdownOpen && filteredParticipants.length > 0 && ( {isDropdownOpen && filteredParticipants.length > 0 && (
<div className="absolute top-full left-0 z-50 w-full mt-2 bg-popover border border-border rounded-lg shadow-popover animate-scale-in overflow-hidden"> <div className="absolute top-full left-0 z-50 w-full mt-2 bg-popover border border-border rounded-lg shadow-popover animate-scale-in overflow-hidden">
{filteredParticipants.map((participant, index) => ( {filteredParticipants.map((participant, index) => (

View File

@@ -11,11 +11,12 @@ interface TimezoneSelectorProps {
// Get all IANA timezones // Get all IANA timezones
const getAllTimezones = (): string[] => { const getAllTimezones = (): string[] => {
let timezones: string[] = [];
try { try {
return Intl.supportedValuesOf('timeZone'); timezones = Intl.supportedValuesOf('timeZone');
} catch { } catch {
// Fallback for older browsers // Fallback for older browsers
return [ timezones = [
'UTC', 'UTC',
'America/New_York', 'America/New_York',
'America/Chicago', 'America/Chicago',
@@ -23,6 +24,7 @@ const getAllTimezones = (): string[] => {
'America/Los_Angeles', 'America/Los_Angeles',
'America/Toronto', 'America/Toronto',
'America/Vancouver', 'America/Vancouver',
'America/Montreal',
'Europe/London', 'Europe/London',
'Europe/Paris', 'Europe/Paris',
'Europe/Berlin', 'Europe/Berlin',
@@ -33,6 +35,17 @@ const getAllTimezones = (): string[] => {
'Pacific/Auckland', 'Pacific/Auckland',
]; ];
} }
// Prioritize Montreal as requested
const priorityTimezone = 'America/Montreal';
if (!timezones.includes(priorityTimezone)) {
timezones.push(priorityTimezone);
}
return [
priorityTimezone,
...timezones.filter((tz) => tz !== priorityTimezone),
];
}; };
// Get UTC offset for a timezone // Get UTC offset for a timezone
@@ -158,7 +171,7 @@ export const TimezoneSelector = ({
No timezones found No timezones found
</div> </div>
) : ( ) : (
filteredTimezones.slice(0, 50).map((timezone) => { filteredTimezones.map((timezone) => {
const isSelected = timezone === value; const isSelected = timezone === value;
const offset = getTimezoneOffset(timezone); const offset = getTimezoneOffset(timezone);
const label = formatTimezoneLabel(timezone); const label = formatTimezoneLabel(timezone);
@@ -204,12 +217,6 @@ export const TimezoneSelector = ({
}) })
)} )}
</div> </div>
{filteredTimezones.length > 50 && (
<div className="px-4 py-2 text-xs text-muted-foreground text-center border-t border-border">
Showing 50 of {filteredTimezones.length} results
</div>
)}
</div> </div>
)} )}
</div> </div>

View File

@@ -1,17 +1,17 @@
import * as SheetPrimitive from "@radix-ui/react-dialog"; import * as React from "react"
import { cva, type VariantProps } from "class-variance-authority"; import * as SheetPrimitive from "@radix-ui/react-dialog"
import { X } from "lucide-react"; import { cva, type VariantProps } from "class-variance-authority"
import * as React from "react"; import { X } from "lucide-react"
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils"
const Sheet = SheetPrimitive.Root; const Sheet = SheetPrimitive.Root
const SheetTrigger = SheetPrimitive.Trigger; const SheetTrigger = SheetPrimitive.Trigger
const SheetClose = SheetPrimitive.Close; const SheetClose = SheetPrimitive.Close
const SheetPortal = SheetPrimitive.Portal; const SheetPortal = SheetPrimitive.Portal
const SheetOverlay = React.forwardRef< const SheetOverlay = React.forwardRef<
React.ElementRef<typeof SheetPrimitive.Overlay>, React.ElementRef<typeof SheetPrimitive.Overlay>,
@@ -19,14 +19,14 @@ const SheetOverlay = React.forwardRef<
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<SheetPrimitive.Overlay <SheetPrimitive.Overlay
className={cn( className={cn(
"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
className, className
)} )}
{...props} {...props}
ref={ref} ref={ref}
/> />
)); ))
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName; SheetOverlay.displayName = SheetPrimitive.Overlay.displayName
const sheetVariants = cva( const sheetVariants = cva(
"fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500", "fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500",
@@ -38,70 +38,101 @@ const sheetVariants = cva(
"inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom", "inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm", left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
right: right:
"inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm", "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
}, },
}, },
defaultVariants: { defaultVariants: {
side: "right", side: "right",
}, },
}, }
); )
interface SheetContentProps interface SheetContentProps
extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>, extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,
VariantProps<typeof sheetVariants> {} VariantProps<typeof sheetVariants> { }
const SheetContent = React.forwardRef<React.ElementRef<typeof SheetPrimitive.Content>, SheetContentProps>( const SheetContent = React.forwardRef<
({ side = "right", className, children, ...props }, ref) => ( React.ElementRef<typeof SheetPrimitive.Content>,
<SheetPortal> SheetContentProps
<SheetOverlay /> >(({ side = "right", className, children, ...props }, ref) => (
<SheetPrimitive.Content ref={ref} className={cn(sheetVariants({ side }), className)} {...props}> <SheetPortal>
{children} <SheetOverlay />
<SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity data-[state=open]:bg-secondary hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none"> <SheetPrimitive.Content
<X className="h-4 w-4" /> ref={ref}
<span className="sr-only">Close</span> className={cn(sheetVariants({ side }), className)}
</SheetPrimitive.Close> {...props}
</SheetPrimitive.Content> >
</SheetPortal> {children}
), <SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary">
); <X className="h-4 w-4" />
SheetContent.displayName = SheetPrimitive.Content.displayName; <span className="sr-only">Close</span>
</SheetPrimitive.Close>
</SheetPrimitive.Content>
</SheetPortal>
))
SheetContent.displayName = SheetPrimitive.Content.displayName
const SheetHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => ( const SheetHeader = ({
<div className={cn("flex flex-col space-y-2 text-center sm:text-left", className)} {...props} /> className,
); ...props
SheetHeader.displayName = "SheetHeader"; }: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn(
"flex flex-col space-y-2 text-center sm:text-left",
className
)}
{...props}
/>
)
SheetHeader.displayName = "SheetHeader"
const SheetFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => ( const SheetFooter = ({
<div className={cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className)} {...props} /> className,
); ...props
SheetFooter.displayName = "SheetFooter"; }: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn(
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
className
)}
{...props}
/>
)
SheetFooter.displayName = "SheetFooter"
const SheetTitle = React.forwardRef< const SheetTitle = React.forwardRef<
React.ElementRef<typeof SheetPrimitive.Title>, React.ElementRef<typeof SheetPrimitive.Title>,
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title> React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<SheetPrimitive.Title ref={ref} className={cn("text-lg font-semibold text-foreground", className)} {...props} /> <SheetPrimitive.Title
)); ref={ref}
SheetTitle.displayName = SheetPrimitive.Title.displayName; className={cn("text-lg font-semibold text-foreground", className)}
{...props}
/>
))
SheetTitle.displayName = SheetPrimitive.Title.displayName
const SheetDescription = React.forwardRef< const SheetDescription = React.forwardRef<
React.ElementRef<typeof SheetPrimitive.Description>, React.ElementRef<typeof SheetPrimitive.Description>,
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Description> React.ComponentPropsWithoutRef<typeof SheetPrimitive.Description>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<SheetPrimitive.Description ref={ref} className={cn("text-sm text-muted-foreground", className)} {...props} /> <SheetPrimitive.Description
)); ref={ref}
SheetDescription.displayName = SheetPrimitive.Description.displayName; className={cn("text-sm text-muted-foreground", className)}
{...props}
/>
))
SheetDescription.displayName = SheetPrimitive.Description.displayName
export { export {
Sheet, Sheet,
SheetPortal,
SheetOverlay,
SheetTrigger,
SheetClose, SheetClose,
SheetContent, SheetContent,
SheetDescription,
SheetFooter,
SheetHeader, SheetHeader,
SheetOverlay, SheetFooter,
SheetPortal,
SheetTitle, SheetTitle,
SheetTrigger, SheetDescription,
}; }

View File

@@ -16,6 +16,11 @@ import {
PopoverContent, PopoverContent,
PopoverTrigger, PopoverTrigger,
} from '@/components/ui/popover'; } from '@/components/ui/popover';
import {
Sheet,
SheetContent,
SheetTrigger,
} from '@/components/ui/sheet';
import { import {
AlertDialog, AlertDialog,
AlertDialogAction, AlertDialogAction,
@@ -62,8 +67,8 @@ interface SettingsState {
const defaultSettings: SettingsState = { const defaultSettings: SettingsState = {
showPartialAvailability: false, showPartialAvailability: false,
displayTimezone: getUserTimezone(), displayTimezone: getUserTimezone(),
showSecondaryTimezone: false, showSecondaryTimezone: true,
secondaryTimezone: 'America/Toronto', // Company timezone as default secondary secondaryTimezone: 'America/Montreal', // Company timezone as default secondary
}; };
function apiToParticipant(p: ParticipantAPI): Participant { function apiToParticipant(p: ParticipantAPI): Participant {
@@ -90,7 +95,7 @@ const Index = ({ defaultTab = 'schedule' }: IndexProps) => {
const [availabilitySlots, setAvailabilitySlots] = useState<TimeSlot[]>([]); const [availabilitySlots, setAvailabilitySlots] = useState<TimeSlot[]>([]);
const [selectedSlot, setSelectedSlot] = useState<TimeSlot | null>(null); const [selectedSlot, setSelectedSlot] = useState<TimeSlot | null>(null);
const [isModalOpen, setIsModalOpen] = useState(false); const [isModalOpen, setIsModalOpen] = useState(false);
const [useRedesign, setUseRedesign] = useState(false); const [useRedesign, setUseRedesign] = useState(true);
const [settings, setSettings] = useState<SettingsState>(defaultSettings); const [settings, setSettings] = useState<SettingsState>(defaultSettings);
const [weekOffset, setWeekOffset] = useState(0); const [weekOffset, setWeekOffset] = useState(0);
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
@@ -316,110 +321,111 @@ const Index = ({ defaultTab = 'schedule' }: IndexProps) => {
> >
<RefreshCw className={`w-5 h-5 ${isSyncing ? 'animate-spin' : ''}`} /> <RefreshCw className={`w-5 h-5 ${isSyncing ? 'animate-spin' : ''}`} />
</Button> </Button>
<Popover> <Sheet>
<PopoverTrigger asChild> <SheetTrigger asChild>
<Button variant="ghost" size="icon"> <Button variant="ghost" size="icon">
<Settings className="w-5 h-5" /> <Settings className="w-5 h-5" />
</Button> </Button>
</PopoverTrigger> </SheetTrigger>
<PopoverContent className="w-80" align="end"> <SheetContent side="right" className="w-[300px] sm:w-[350px]">
<div className="space-y-4"> <div className="space-y-6 py-4">
<h4 className="font-medium">Settings</h4> <div className="space-y-2">
<h4 className="font-semibold text-lg tracking-tight">Settings</h4>
<div className="flex items-center justify-between gap-4 pb-4 border-b border-border"> <p className="text-sm text-muted-foreground">
<Label htmlFor="use-redesign" className="text-sm cursor-pointer font-medium text-primary"> Configure your calendar preferences.
Try New Design </p>
</Label>
<Switch
id="use-redesign"
checked={useRedesign}
onCheckedChange={setUseRedesign}
/>
</div> </div>
<div className="flex items-center justify-between gap-4"> <div className="space-y-4">
<Label htmlFor="partial-availability" className="text-sm cursor-pointer"> <div className="flex items-center justify-between gap-4 pb-4 border-b border-border">
Show partial availability <Label htmlFor="use-redesign" className="text-sm cursor-pointer font-medium text-primary">
</Label> Try New Design
<Switch
id="partial-availability"
checked={settings.showPartialAvailability}
onCheckedChange={(checked) =>
setSettings((prev) => ({ ...prev, showPartialAvailability: checked }))
}
/>
</div>
<p className="text-xs text-muted-foreground">
When enabled, shows time slots where only some participants are available.
</p>
<div className="border-t border-border pt-4">
<div className="flex items-center justify-between gap-4">
<Label htmlFor="secondary-timezone" className="text-sm cursor-pointer">
Show secondary timezone
</Label> </Label>
<Switch <Switch
id="secondary-timezone" id="use-redesign"
checked={settings.showSecondaryTimezone} checked={useRedesign}
onCheckedChange={setUseRedesign}
/>
</div>
<div className="flex items-center justify-between gap-4">
<div className="space-y-0.5">
<Label htmlFor="partial-availability" className="text-sm font-medium cursor-pointer">
Partial Availability
</Label>
<p className="text-xs text-muted-foreground">
Show slots where some are busy
</p>
</div>
<Switch
id="partial-availability"
checked={settings.showPartialAvailability}
onCheckedChange={(checked) => onCheckedChange={(checked) =>
setSettings((prev) => ({ ...prev, showSecondaryTimezone: checked })) setSettings((prev) => ({ ...prev, showPartialAvailability: checked }))
} }
/> />
</div> </div>
{settings.showSecondaryTimezone && (
<div className="mt-3"> <div className="border-t border-border pt-4 space-y-4">
<Label className="text-xs text-muted-foreground mb-2 block"> <div className="flex items-center justify-between gap-4">
Secondary timezone <Label htmlFor="secondary-timezone" className="text-sm cursor-pointer">
Show secondary timezone
</Label> </Label>
<TimezoneSelector <Switch
value={settings.secondaryTimezone} id="secondary-timezone"
onChange={(tz) => setSettings((prev) => ({ ...prev, secondaryTimezone: tz }))} checked={settings.showSecondaryTimezone}
onCheckedChange={(checked) =>
setSettings((prev) => ({ ...prev, showSecondaryTimezone: checked }))
}
/> />
</div> </div>
)} {settings.showSecondaryTimezone && (
<p className="text-xs text-muted-foreground mt-2"> <div className="space-y-2">
Display times in two timezones side by side. <Label className="text-xs text-muted-foreground block">
</p> Secondary timezone
</div> </Label>
<TimezoneSelector
value={settings.secondaryTimezone}
onChange={(tz) => setSettings((prev) => ({ ...prev, secondaryTimezone: tz }))}
/>
</div>
)}
</div>
<div className="border-t border-border pt-4"> <div className="border-t border-border pt-4">
<AlertDialog> <AlertDialog>
<AlertDialogTrigger asChild> <AlertDialogTrigger asChild>
<Button <Button
variant="destructive" variant="destructive"
size="sm" size="sm"
className="w-full" className="w-full"
>
Clear All Bookings
</Button>
</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Clear all bookings?</AlertDialogTitle>
<AlertDialogDescription>
This will remove all scheduled meetings from the system.
This action cannot be undone. Calendar invites already
sent will not be affected.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction
onClick={handleClearBookings}
className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
> >
Clear All Clear All Bookings
</AlertDialogAction> </Button>
</AlertDialogFooter> </AlertDialogTrigger>
</AlertDialogContent> <AlertDialogContent>
</AlertDialog> <AlertDialogHeader>
<p className="text-xs text-muted-foreground mt-2"> <AlertDialogTitle>Clear all bookings?</AlertDialogTitle>
Remove all scheduled meetings from the system. <AlertDialogDescription>
</p> This will remove all scheduled meetings. This cannot be undone.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction
onClick={handleClearBookings}
className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
>
Clear All
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</div>
</div> </div>
</div> </div>
</PopoverContent> </SheetContent>
</Popover> </Sheet>
</div> </div>
<h2 className="text-3xl font-bold text-foreground mb-2"> <h2 className="text-3xl font-bold text-foreground mb-2">
Schedule a Meeting Schedule a Meeting
@@ -482,7 +488,7 @@ const Index = ({ defaultTab = 'schedule' }: IndexProps) => {
</div> </div>
</TabsContent> </TabsContent>
</Tabs> </Tabs>
</main> </main >
<ScheduleModal <ScheduleModal
isOpen={isModalOpen} isOpen={isModalOpen}
@@ -495,7 +501,7 @@ const Index = ({ defaultTab = 'schedule' }: IndexProps) => {
displayTimezone={settings.displayTimezone} displayTimezone={settings.displayTimezone}
onSuccess={loadAvailability} onSuccess={loadAvailability}
/> />
</div> </div >
); );
}; };