diff --git a/artifacts/tx-os/src/pages/executive-meetings.tsx b/artifacts/tx-os/src/pages/executive-meetings.tsx index 14f86615..30d47cef 100644 --- a/artifacts/tx-os/src/pages/executive-meetings.tsx +++ b/artifacts/tx-os/src/pages/executive-meetings.tsx @@ -47,7 +47,6 @@ import { type TimePicker12hHandle, } from "@/components/time-picker-12h"; import { Label } from "@/components/ui/label"; -import { Textarea } from "@/components/ui/textarea"; import { Dialog, DialogContent, @@ -4821,13 +4820,20 @@ function ManageSection({ async function save(timeOverrides?: { startTime: string; endTime: string }) { if (!editing) return; - if (!editing.titleAr.trim() || !editing.titleEn.trim()) { + if (!editing.titleAr.trim()) { toast({ title: t("executiveMeetings.manage.errors.titleRequired"), variant: "destructive", }); return; } + // #322: the English-title input was removed from the dialog, so + // there is no way for the user to set a separate English value + // anymore. Always mirror the Arabic title — otherwise editing the + // Arabic title on an existing meeting would leave a stale English + // copy on the server. The API requires `titleEn` (min length 1) + // on POST, and PATCH will update it on every save. + const titleEn = editing.titleAr.trim(); // Prefer the dialog-supplied canonical values from the time // picker's commit() result over the controlled `editing.*` // state — the picker's onChange suppresses ambiguous/invalid @@ -4843,7 +4849,7 @@ function ManageSection({ setSaving(true); const body: Record = { titleAr: editing.titleAr.trim(), - titleEn: editing.titleEn.trim(), + titleEn, meetingDate: editing.meetingDate, startTime, endTime, @@ -5106,8 +5112,6 @@ function SortableAttendeeRow({ onMoveUp, onMoveDown, onChangeName, - onChangeTitle, - onChangeAttendanceType, onRemove, }: { attendee: Attendee; @@ -5117,8 +5121,6 @@ function SortableAttendeeRow({ onMoveUp: () => void; onMoveDown: () => void; onChangeName: (v: string) => void; - onChangeTitle: (v: string) => void; - onChangeAttendanceType: (v: Attendee["attendanceType"]) => void; onRemove: () => void; }) { const sid = attendee._sid ?? `__missing-sid-${index}`; @@ -5195,8 +5197,13 @@ function SortableAttendeeRow({ {t("executiveMeetings.manage.attendees.subheadingBadge")} )} + {/* #322: name is the only attendee field exposed in the dialog. + The parenthesized title and the internal/virtual/external + select were removed; existing rows keep their stored values + and new rows default to title=null + attendanceType="internal" + (see addAttendee). */} onChangeName(e.target.value)} /> - {!isSub && ( - onChangeTitle(e.target.value)} - data-testid={`em-attendee-title-${index}`} - /> - )} - @@ -5434,9 +5415,6 @@ function MeetingFormDialog({ data-testid="em-form-titleAr" /> - - update("titleEn", e.target.value)} /> - - - update("location", e.target.value)} /> - - - update("meetingUrl", e.target.value)} - /> - - - - - - - - - update("isHighlighted", v)} - /> - - -