From 60533b9ceb681d8350a7326a572a3f2e1abc5517 Mon Sep 17 00:00:00 2001 From: riyadhafraa <49757212-riyadhafraa@users.noreply.replit.com> Date: Sun, 3 May 2026 09:50:53 +0000 Subject: [PATCH] #322 Simplify Add/Edit Meeting dialog and attendee rows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Trim the إضافة اجتماع / تعديل اجتماع dialog and attendee rows in artifacts/tx-os/src/pages/executive-meetings.tsx down to the fields the user actually fills in. MeetingFormDialog - Removed FormRows: titleEn, location, meetingUrl, platform, status, isHighlighted, notes. - Kept titleAr, meetingDate, dailyNumber, startTime, endTime, and the attendees section. - Save validation now only requires titleAr. - titleEn is always mirrored from titleAr on save. The English input is gone, so there is no way to keep an independent English title; always syncing avoids leaving a stale server-side titleEn after the Arabic title is edited. The API still receives a non-empty titleEn so POST validation (min length 1) is satisfied. - MeetingFormState, emptyMeetingForm, and openEdit are unchanged so hidden fields (location, notes, platform, status, isHighlighted, meetingUrl) round-trip through the save body and existing data is preserved on edit. SortableAttendeeRow - Removed the parenthesized title Input and the internal/virtual/external Select. - Dropped the now-unused onChangeTitle / onChangeAttendanceType props from the component signature and the call site. - Existing attendees keep their stored title and attendanceType; new attendees added via addAttendee continue to default to title=null and attendanceType="internal" so the schedule's grouping keeps working. Cleanup - Removed the now-unused Textarea import (only the notes field used it). Switch is still imported because it is used elsewhere in the file. Code review found two issues that were fixed before completion: - Mirroring made deterministic (always sync) instead of blank-only fallback. - Orphaned Textarea import removed. No DB schema, API, schedule view, Manage list, audit, notifications, or translation changes. --- .../tx-os/src/pages/executive-meetings.tsx | 116 +++--------------- 1 file changed, 20 insertions(+), 96 deletions(-) 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)} - /> - - -