feat(event-dialog): redesign with glass-strong styling, icon-decorated inputs, and Cancel button

- Apply glass-strong to DialogContent
- Add LucideMapPin and CalendarIcon/Clock icons to input fields
- Replace native checkbox with Checkbox + Label component
- Unify allDay date inputs into single relative-positioned blocks
- Add Cancel button to DialogFooter
- Rename Save to Create for new events
This commit is contained in:
2026-04-08 00:56:49 -04:00
parent e000d41474
commit a26787a026

View File

@@ -1,5 +1,9 @@
"use client";
import { CalendarIcon, Clock, LucideMapPin } from "lucide-react";
import { RecurrencePicker } from "@/components/recurrence-picker"; import { RecurrencePicker } from "@/components/recurrence-picker";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import { import {
Dialog, Dialog,
DialogContent, DialogContent,
@@ -9,6 +13,7 @@ import {
DialogTitle, DialogTitle,
} from "@/components/ui/dialog"; } from "@/components/ui/dialog";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
interface EventDialogProps { interface EventDialogProps {
open: boolean; open: boolean;
@@ -64,35 +69,47 @@ export const EventDialog = ({
return ( return (
<Dialog open={open} onOpenChange={handleOpenChange}> <Dialog open={open} onOpenChange={handleOpenChange}>
<DialogContent> <DialogContent className="glass-strong max-w-md">
<DialogHeader> <DialogHeader>
<DialogTitle>{editingId ? "Edit Event" : "Add Event"}</DialogTitle> <DialogTitle className="text-base">
{editingId ? "Edit Event" : "New Event"}
</DialogTitle>
<DialogDescription className="sr-only"> <DialogDescription className="sr-only">
Fill in the event details below. Title and start date are required. Fill in the event details below. Title and start date are required.
</DialogDescription> </DialogDescription>
</DialogHeader> </DialogHeader>
<div className="space-y-3">
<Input <Input
id="event-title" id="event-title"
name="title" name="title"
placeholder="Title" placeholder="Event title"
value={title} value={title}
onChange={(e) => setTitle(e.target.value)} onChange={(e) => setTitle(e.target.value)}
className="font-medium"
/> />
<textarea <textarea
id="event-description" id="event-description"
name="description" name="description"
className="border rounded p-2 w-full" className="flex field-sizing-content min-h-[60px] max-h-40 w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm placeholder:text-muted-foreground/50 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring resize-none"
placeholder="Description" placeholder="Add a description..."
value={description} value={description}
onChange={(e) => setDescription(e.target.value)} onChange={(e) => setDescription(e.target.value)}
/> />
<div className="grid grid-cols-2 gap-3">
<div className="relative">
<LucideMapPin className="absolute left-3 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-muted-foreground/50" />
<Input <Input
id="event-location" id="event-location"
name="location" name="location"
placeholder="Location" placeholder="Location"
value={location} value={location}
onChange={(e) => setLocation(e.target.value)} onChange={(e) => setLocation(e.target.value)}
className="pl-8"
/> />
</div>
<Input <Input
id="event-url" id="event-url"
name="url" name="url"
@@ -100,47 +117,74 @@ export const EventDialog = ({
value={url} value={url}
onChange={(e) => setUrl(e.target.value)} onChange={(e) => setUrl(e.target.value)}
/> />
<RecurrencePicker value={recurrenceRule} onChange={setRecurrenceRule} /> </div>
<label className="flex items-center gap-2 mt-2" htmlFor="event-all-day"> <RecurrencePicker
<input value={recurrenceRule}
id="event-all-day" onChange={setRecurrenceRule}
name="allDay"
type="checkbox"
checked={allDay}
onChange={(e) => setAllDay(e.target.checked)}
/> />
All day event
</label> <div className="flex items-center gap-2 py-1">
<Checkbox
id="event-all-day"
checked={allDay}
onCheckedChange={(checked) => setAllDay(checked === true)}
/>
<Label
htmlFor="event-all-day"
className="text-sm font-normal cursor-pointer"
>
All day
</Label>
</div>
<div className="space-y-2">
<div className="relative">
<CalendarIcon className="absolute left-3 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-muted-foreground/50 pointer-events-none" />
{!allDay ? ( {!allDay ? (
<>
<Input <Input
type="datetime-local" type="datetime-local"
value={start} value={start}
onChange={(e) => setStart(e.target.value)} onChange={(e) => setStart(e.target.value)}
className="pl-8"
placeholder="Start"
/> />
<Input
type="datetime-local"
value={end}
onChange={(e) => setEnd(e.target.value)}
/>
</>
) : ( ) : (
<>
<Input <Input
type="date" type="date"
value={start ? start.split("T")[0] : ""} value={start ? start.split("T")[0] : ""}
onChange={(e) => setStart(e.target.value)} onChange={(e) => setStart(e.target.value)}
className="pl-8"
/> />
)}
</div>
<div className="relative">
<Clock className="absolute left-3 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-muted-foreground/50 pointer-events-none" />
{!allDay ? (
<Input
type="datetime-local"
value={end}
onChange={(e) => setEnd(e.target.value)}
className="pl-8"
placeholder="End"
/>
) : (
<Input <Input
type="date" type="date"
value={end ? end.split("T")[0] : ""} value={end ? end.split("T")[0] : ""}
onChange={(e) => setEnd(e.target.value)} onChange={(e) => setEnd(e.target.value)}
className="pl-8"
/> />
</>
)} )}
<DialogFooter> </div>
<Button onClick={onSave}>{editingId ? "Update" : "Save"}</Button> </div>
</div>
<DialogFooter className="gap-2 sm:gap-0">
<Button variant="ghost" onClick={() => handleOpenChange(false)}>
Cancel
</Button>
<Button onClick={onSave}>{editingId ? "Update" : "Create"}</Button>
</DialogFooter> </DialogFooter>
</DialogContent> </DialogContent>
</Dialog> </Dialog>