From fe5645c818cb70062dc678fdd6ca57858b87d99e Mon Sep 17 00:00:00 2001 From: Linus Rath <139418639+rathlinus@users.noreply.github.com> Date: Fri, 12 Jun 2026 00:15:54 +0200 Subject: [PATCH] refactor: redesign custom recurrence editor to match modal UI --- components/calendar/recurrence-editor.tsx | 312 ++++++++++------------ 1 file changed, 134 insertions(+), 178 deletions(-) diff --git a/components/calendar/recurrence-editor.tsx b/components/calendar/recurrence-editor.tsx index 94a4fa6a..6bec12f5 100644 --- a/components/calendar/recurrence-editor.tsx +++ b/components/calendar/recurrence-editor.tsx @@ -2,7 +2,6 @@ import { useState } from "react"; import { useLocale, useTranslations } from "next-intl"; -import { X } from "lucide-react"; import { addYears, format } from "date-fns"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; @@ -19,13 +18,6 @@ const WEEKDAYS: string[] = ["mo", "tu", "we", "th", "fr", "sa", "su"]; const DAY_TO_REF_DATE: Record = { mo: 1, tu: 2, we: 3, th: 4, fr: 5, sa: 6, su: 7 }; const INDEX_TO_DAY = ["su", "mo", "tu", "we", "th", "fr", "sa"]; -const FREQ_LABEL_KEYS: Record = { - daily: "recurrence.editor_freq_day", - weekly: "recurrence.editor_freq_week", - monthly: "recurrence.editor_freq_month", - yearly: "recurrence.editor_freq_year", -}; - const UNIT_LABEL_KEYS: Record = { daily: "recurrence.editor_unit_days", weekly: "recurrence.editor_unit_weeks", @@ -217,7 +209,7 @@ export function RecurrenceEditor({ rule, eventStart, onSave, onCancel }: Recurre ); }; - const handleSave = () => { + const buildRule = (): CalendarRecurrenceRule => { const built: CalendarRecurrenceRule = { "@type": "RecurrenceRule", frequency, @@ -252,134 +244,110 @@ export function RecurrenceEditor({ rule, eventStart, onSave, onCancel }: Recurre } } - onSave(built); + return built; }; - const selectCls = "rounded-md border border-input bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring disabled:opacity-50"; + const handleSave = () => onSave(buildRule()); + + const summary = buildRecurrenceSummary(buildRule(), t, locale); + + const selectCls = "rounded-md border border-input bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring"; return ( -
-
-
+
+
+ {t("recurrence.editor_every")} + { + const n = parseInt(e.target.value, 10); + setIntervalValue(Number.isFinite(n) ? Math.max(1, n) : 1); + }} + className="w-16 shrink-0" + aria-label={t("recurrence.editor_every")} + /> + +
+ + {frequency === "weekly" && ( +
+ {WEEKDAYS.map((day) => ( ))}
- -
+ )} -
-

{t("recurrence.editor_repeats_on")}

+ {frequency === "yearly" && (
- {t("recurrence.editor_every")} - { - const n = parseInt(e.target.value, 10); - setIntervalValue(Number.isFinite(n) ? Math.max(1, n) : 1); - }} - className="w-20" - aria-label={t("recurrence.editor_every")} - /> - {t(UNIT_LABEL_KEYS[frequency])} -
- - {frequency === "weekly" && ( -
- {WEEKDAYS.map((day) => ( - + {capitalize(t("recurrence.editor_in"))} + +
+ )} - {frequency === "yearly" && ( -
- {t("recurrence.editor_in")} - -
- )} - - {(frequency === "monthly" || frequency === "yearly") && ( -
- -
+ + )} +
+ )} -
-

{t("recurrence.editor_ends")}

- -