import { useT } from "@agent-native/core/client/i18n"; import type { AvailabilityConfig, DaySchedule } from "@shared/api"; import { useState, useEffect } from "react"; import { toast } from "sonner"; import { CloudUpgrade } from "@/components/CloudUpgrade"; import { TimezoneCombobox } from "@/components/TimezoneCombobox"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Switch } from "@/components/ui/switch"; import { useAvailability, useUpdateAvailability, } from "@/hooks/use-availability"; import { useDbStatus } from "@/hooks/use-db-status"; import { copyTextToClipboard } from "@/lib/clipboard"; type DayName = keyof AvailabilityConfig["weeklySchedule"]; const DAYS: { key: DayName }[] = [ { key: "monday" }, { key: "tuesday" }, { key: "wednesday" }, { key: "thursday" }, { key: "friday" }, { key: "saturday" }, { key: "sunday" }, ]; const DEFAULT_SCHEDULE: DaySchedule = { enabled: false, slots: [{ start: "09:00", end: "17:00" }], }; export default function AvailabilitySettings() { const t = useT(); const { data: availability } = useAvailability(); const updateAvailability = useUpdateAvailability(); const [schedule, setSchedule] = useState< AvailabilityConfig["weeklySchedule"] >({ monday: { ...DEFAULT_SCHEDULE, enabled: true }, tuesday: { ...DEFAULT_SCHEDULE, enabled: true }, wednesday: { ...DEFAULT_SCHEDULE, enabled: true }, thursday: { ...DEFAULT_SCHEDULE, enabled: true }, friday: { ...DEFAULT_SCHEDULE, enabled: true }, saturday: { ...DEFAULT_SCHEDULE }, sunday: { ...DEFAULT_SCHEDULE }, }); const [bufferMinutes, setBufferMinutes] = useState(15); const [minNoticeHours, setMinNoticeHours] = useState(1); const [maxAdvanceDays, setMaxAdvanceDays] = useState(60); const [slotDuration, setSlotDuration] = useState(30); const [bookingSlug, setBookingSlug] = useState("meeting"); const [timezone, setTimezone] = useState("America/New_York"); const { isLocal } = useDbStatus(); const [showCloudUpgrade, setShowCloudUpgrade] = useState(false); async function handleCopyBookingLink() { if (isLocal) { setShowCloudUpgrade(true); return; } const url = `${window.location.origin}/book/${bookingSlug}`; if (await copyTextToClipboard(url)) { toast.success(t("bookingLinks.bookingLinkCopied")); return; } toast.error(t("common.clipboardUnavailable")); } useEffect(() => { if (availability) { setSchedule(availability.weeklySchedule); setBufferMinutes(availability.bufferMinutes); setMinNoticeHours(availability.minNoticeHours); setMaxAdvanceDays(availability.maxAdvanceDays); setSlotDuration(availability.slotDurationMinutes); setBookingSlug(availability.bookingPageSlug); setTimezone(availability.timezone); } }, [availability]); function updateDay(day: DayName, updates: Partial) { setSchedule((prev) => ({ ...prev, [day]: { ...prev[day], ...updates }, })); } function updateDaySlot(day: DayName, field: "start" | "end", value: string) { setSchedule((prev) => ({ ...prev, [day]: { ...prev[day], slots: [{ ...prev[day].slots[0], [field]: value }], }, })); } function handleSave() { updateAvailability.mutate( { timezone, weeklySchedule: schedule, bufferMinutes, minNoticeHours, maxAdvanceDays, slotDurationMinutes: slotDuration, bookingPageSlug: bookingSlug, }, { onSuccess: () => toast.success(t("bookingLinks.availabilitySaved")), onError: () => toast.error(t("bookingLinks.availabilitySaveFailed")), }, ); } function dayLabel(day: DayName) { switch (day) { case "monday": return t("bookingLinks.days.monday"); case "tuesday": return t("bookingLinks.days.tuesday"); case "wednesday": return t("bookingLinks.days.wednesday"); case "thursday": return t("bookingLinks.days.thursday"); case "friday": return t("bookingLinks.days.friday"); case "saturday": return t("bookingLinks.days.saturday"); case "sunday": return t("bookingLinks.days.sunday"); } } return (

{t("bookingLinks.availability")}

{t("bookingLinks.availabilityDescription")}

{/* Weekly Schedule */} {t("bookingLinks.weeklySchedule")} {t("bookingLinks.weeklyScheduleDescription")}

{t("bookingLinks.timezoneHelp")}

{DAYS.map(({ key }) => { const day = schedule[key]; const slot = day.slots[0] ?? { start: "09:00", end: "17:00" }; return (
updateDay(key, { enabled: checked }) } /> {dayLabel(key)}
{day.enabled ? (
updateDaySlot(key, "start", e.target.value) } className="w-28 sm:w-32" /> {t("bookingLinks.to")} updateDaySlot(key, "end", e.target.value) } className="w-28 sm:w-32" />
) : ( {t("bookingLinks.unavailable")} )}
); })}
{/* Booking Settings */} {t("bookingLinks.bookingRules")} {t("bookingLinks.bookingRulesDescription")}
setBufferMinutes(Number(e.target.value))} min={0} />
setMinNoticeHours(Number(e.target.value))} min={0} />
setMaxAdvanceDays(Number(e.target.value))} min={1} />
setSlotDuration(Number(e.target.value))} min={5} />
/book/ setBookingSlug(e.target.value)} placeholder="meeting" />
{showCloudUpgrade && (
setShowCloudUpgrade(false)} />
)}
); }