#596 صلاحية الرئيس: حذف بحث الاجتماعات + زر الإعدادات

Two changes to artifacts/tx-os/src/pages/executive-meetings.tsx,
both gated on `isPresidentView` so non-president users are unaffected.

1. Schedule search hidden for the President
   - Wrapped <SearchToggle> in ScheduleSection (L2945) in
     {!isPresidentView && (...)}.
   - Kept searchQuery state + meetingMatchesSearch wiring intact:
     when query is "" the filter is a no-op, so the President sees
     the full day's meetings, and the box reappears for anyone else.

2. Gear button so the President can reach Settings (font controls)
   - Added an icon-only gear button (SettingsIcon, lucide-react —
     already imported) in the header right-side block (L1113),
     visible only when isPresidentView && section === "schedule".
     data-testid="em-president-settings".
   - Added an icon+label "back to schedule" button (ArrowRight for
     RTL / ArrowLeft for LTR) shown when isPresidentView &&
     section === "settings". data-testid="em-president-back-to-schedule".
   - Relaxed the force-schedule effect (L966) so the President is
     only redirected when section is neither "schedule" nor
     "settings" — otherwise the gear tap would bounce back instantly.
   - Sub-nav stays hidden (`!isPresidentView` on the SECTIONS map
     is unchanged). Gear is the only entry point.
   - No backend, no new i18n keys (reuses
     executiveMeetings.nav.settings / .schedule).
   - FontSettingsSection already renders for canRead users, and
     canEditGlobalFontSettings stays as the API reports it — no
     extra client-side gate.

`pnpm --filter @workspace/tx-os exec tsc --noEmit` clean.
This commit is contained in:
riyadhafraa
2026-05-18 11:36:01 +00:00
parent 599fc91e16
commit c80b1ce085
@@ -961,7 +961,12 @@ function ExecutiveMeetingsPageInner() {
// their role flips on mid-session, so they never get stuck on a now-
// hidden tab.
useEffect(() => {
if (isPresidentView && section !== "schedule") {
// #596: President is normally pinned to "schedule", but we now
// expose a gear-icon entry point to "settings" in the header so
// they can edit their own font. Allow that one extra section here,
// otherwise this effect would immediately bounce them back the
// moment they tap the gear.
if (isPresidentView && section !== "schedule" && section !== "settings") {
setSection("schedule");
}
}, [isPresidentView, section]);
@@ -1098,6 +1103,43 @@ function ExecutiveMeetingsPageInner() {
<span className="hidden sm:inline">{t("executiveMeetings.exportPdf")}</span>
</Button>
)}
{/* #596: President's only entry point to Settings (font
family/size/etc). The full sub-nav stays hidden for
them; a single gear button switches to the settings
section, and a back arrow returns to the schedule. */}
{isPresidentView && section === "schedule" && (
<Button
variant="outline"
size="sm"
className="w-9 px-0"
onClick={() => setSection("settings")}
aria-label={t("executiveMeetings.nav.settings")}
title={t("executiveMeetings.nav.settings")}
data-testid="em-president-settings"
>
<SettingsIcon className="w-4 h-4" />
</Button>
)}
{isPresidentView && section === "settings" && (
<Button
variant="outline"
size="sm"
className="gap-1.5"
onClick={() => setSection("schedule")}
aria-label={t("executiveMeetings.nav.schedule")}
title={t("executiveMeetings.nav.schedule")}
data-testid="em-president-back-to-schedule"
>
{isRtl ? (
<ArrowRight className="w-4 h-4" />
) : (
<ArrowLeft className="w-4 h-4" />
)}
<span className="hidden sm:inline">
{t("executiveMeetings.nav.schedule")}
</span>
</Button>
)}
</div>
</div>
@@ -2894,14 +2936,19 @@ function ScheduleSection({
)}
</button>
)}
<SearchToggle
searchQuery={searchQuery}
onSearchChange={setSearchQuery}
placeholder={t("executiveMeetings.schedule.searchPlaceholder")}
ariaLabel={t("executiveMeetings.schedule.searchAria")}
clearLabel={t("executiveMeetings.schedule.searchClear")}
isRtl={isRtl}
/>
{/* #596: President view hides the search box (presentation-
style focus). The underlying searchQuery state stays "" so
meetingMatchesSearch is a no-op and the full day shows. */}
{!isPresidentView && (
<SearchToggle
searchQuery={searchQuery}
onSearchChange={setSearchQuery}
placeholder={t("executiveMeetings.schedule.searchPlaceholder")}
ariaLabel={t("executiveMeetings.schedule.searchAria")}
clearLabel={t("executiveMeetings.schedule.searchClear")}
isRtl={isRtl}
/>
)}
<label className="flex items-center gap-2 text-sm">
<span className="text-muted-foreground">{t("executiveMeetings.date")}</span>
<input