Modify the order confirmation modal title in both Arabic and English locale files to a generic confirmation message, resolving a UI redundancy where the item name was displayed twice.
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: d2a9850b-3afa-47aa-b54b-73a5f14c5ac6
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/UggHvbd
Replit-Helium-Checkpoint-Created: true
Backend (artifacts/api-server):
- Added hasReceivePermission() and refactored DELETE /orders/:id into a
shared authorizeAndDeleteOrder() helper so single and bulk paths use
the same authorization rules.
- Added POST /orders/bulk-delete returning { deletedIds, failedIds } with
per-id authorization, dedup, and best-effort partial success.
- Tightened receiver authorization to mirror GET /orders/incoming: a
receiver may only delete an unclaimed pending order or one they have
themselves claimed and is still active (received/preparing). Another
receiver's claimed order, and any terminal order, return 403 even at
the API layer. Code, comments and OpenAPI description now agree.
API spec (lib/api-spec/openapi.yaml):
- New /orders/bulk-delete operation with BulkDeleteServiceOrdersBody and
BulkDeleteServiceOrdersResponse schemas. Updated DELETE /orders/{id}
description. Regenerated react-query hooks via codegen — both
useDeleteServiceOrder and useBulkDeleteServiceOrders are used by the UI.
UI (artifacts/tx-os/src/pages/orders-incoming.tsx):
- Per-card checkbox visible at all times (RTL-safe leading edge).
- Per-card trash icon for single delete.
- Section-scoped Select-all (مين / unclaimed) with tri-state
all/some(indeterminate)/none and shadcn Checkbox.
- Sticky bottom bulk action bar shows selected count + Clear selection +
destructive Delete.
- Single AlertDialog used by both per-card and bulk paths, with
pluralized confirmation copy. Single delete calls DELETE /orders/:id;
multi delete calls POST /orders/bulk-delete; partial-failure surfaces
via toast.
i18n: New incomingOrders keys in ar.json and en.json (select, selectAll,
clearSelection, selectedCount, delete, deleteConfirmTitle/Body, deleted,
deleteFailed, deletePartial) with pluralization in both languages.
Tests:
- artifacts/api-server/tests/service-orders.test.mjs: receivers can
delete pending/received/preparing; receivers cannot delete terminal
(completed/cancelled); bulk-delete with mixed authorized / unknown /
dedup / unauthenticated cases.
- artifacts/tx-os/tests/order-incoming-delete.spec.mjs (new Playwright):
bulk-delete two unclaimed orders shrinks the list by 2; per-card
trash on a claimed order deletes one. Both pass.
Pre-existing executive-meetings PDF/font test failures are unrelated.
Follow-ups proposed: #398 (Undo for incoming-order deletes), #399
(safer notification handling in bulk-delete).
Backend (artifacts/api-server):
- Added hasReceivePermission() and refactored DELETE /orders/:id into a
shared authorizeAndDeleteOrder() helper so single and bulk paths use
the same authorization rules.
- Added POST /orders/bulk-delete returning { deletedIds, failedIds } with
per-id authorization, dedup, and best-effort partial success.
- Tightened receiver authorization to mirror GET /orders/incoming: a
receiver may only delete an unclaimed pending order or one they have
themselves claimed and is still active (received/preparing). Another
receiver's claimed order, and any terminal order, return 403 even at
the API layer. Code, comments and OpenAPI description now agree.
API spec (lib/api-spec/openapi.yaml):
- New /orders/bulk-delete operation with BulkDeleteServiceOrdersBody and
BulkDeleteServiceOrdersResponse schemas. Updated DELETE /orders/{id}
description. Regenerated react-query hooks via codegen — both
useDeleteServiceOrder and useBulkDeleteServiceOrders are used by the UI.
UI (artifacts/tx-os/src/pages/orders-incoming.tsx):
- Per-card checkbox visible at all times (RTL-safe leading edge).
- Per-card trash icon for single delete.
- Section-scoped Select-all (مين / unclaimed) with tri-state
all/some(indeterminate)/none and shadcn Checkbox.
- Sticky bottom bulk action bar shows selected count + Clear selection +
destructive Delete.
- Single AlertDialog used by both per-card and bulk paths, with
pluralized confirmation copy. Single delete calls DELETE /orders/:id;
multi delete calls POST /orders/bulk-delete; partial-failure surfaces
via toast.
i18n: New incomingOrders keys in ar.json and en.json (select, selectAll,
clearSelection, selectedCount, delete, deleteConfirmTitle/Body, deleted,
deleteFailed, deletePartial) with pluralization in both languages.
Tests:
- artifacts/api-server/tests/service-orders.test.mjs: receivers can
delete pending/received/preparing; receivers cannot delete terminal
(completed/cancelled); bulk-delete with mixed authorized / unknown /
dedup / unauthenticated cases.
- artifacts/tx-os/tests/order-incoming-delete.spec.mjs (new Playwright):
bulk-delete two unclaimed orders shrinks the list by 2; per-card
trash on a claimed order deletes one. Both pass.
Pre-existing executive-meetings PDF/font test failures are unrelated.
Follow-ups proposed: #398 (Undo for incoming-order deletes), #399
(safer notification handling in bulk-delete).
Backend (artifacts/api-server):
- Added hasReceivePermission() and refactored DELETE /orders/:id into a
shared authorizeAndDeleteOrder() helper so single and bulk paths use
the same authorization rules.
- Added POST /orders/bulk-delete returning { deletedIds, failedIds } with
per-id authorization, dedup, and best-effort partial success.
- Tightened receiver authorization to mirror GET /orders/incoming: a
receiver may only delete an unclaimed pending order or one they have
themselves claimed and is still active (received/preparing). Another
receiver's claimed order, and any terminal order, return 403 even at
the API layer. Code, comments and OpenAPI description now agree.
API spec (lib/api-spec/openapi.yaml):
- New /orders/bulk-delete operation with BulkDeleteServiceOrdersBody and
BulkDeleteServiceOrdersResponse schemas. Updated DELETE /orders/{id}
description. Regenerated react-query hooks via codegen — both
useDeleteServiceOrder and useBulkDeleteServiceOrders are used by the UI.
UI (artifacts/tx-os/src/pages/orders-incoming.tsx):
- Per-card checkbox visible at all times (RTL-safe leading edge).
- Per-card trash icon for single delete.
- Section-scoped Select-all (مين / unclaimed) with tri-state
all/some(indeterminate)/none and shadcn Checkbox.
- Sticky bottom bulk action bar shows selected count + Clear selection +
destructive Delete.
- Single AlertDialog used by both per-card and bulk paths, with
pluralized confirmation copy. Single delete calls DELETE /orders/:id;
multi delete calls POST /orders/bulk-delete; partial-failure surfaces
via toast.
i18n: New incomingOrders keys in ar.json and en.json (select, selectAll,
clearSelection, selectedCount, delete, deleteConfirmTitle/Body, deleted,
deleteFailed, deletePartial) with pluralization in both languages.
Tests:
- artifacts/api-server/tests/service-orders.test.mjs: receivers can
delete pending/received/preparing; receivers cannot delete terminal
(completed/cancelled); bulk-delete with mixed authorized / unknown /
dedup / unauthenticated cases.
- artifacts/tx-os/tests/order-incoming-delete.spec.mjs (new Playwright):
bulk-delete two unclaimed orders shrinks the list by 2; per-card
trash on a claimed order deletes one. Both pass.
Pre-existing executive-meetings PDF/font test failures are unrelated.
Follow-ups proposed: #398 (Undo for incoming-order deletes), #399
(safer notification handling in bulk-delete).
Backend (artifacts/api-server):
- Added hasReceivePermission() and refactored DELETE /orders/:id into a
shared authorizeAndDeleteOrder() helper so single and bulk paths use
the same authorization rules.
- Added POST /orders/bulk-delete returning { deletedIds, failedIds } with
per-id authorization, dedup, and best-effort partial success.
- Tightened receiver authorization: receivers may only delete orders
currently in the incoming queue (pending/received/preparing). Terminal
orders remain the owner's cleanup responsibility. Code, comments and
OpenAPI description now agree.
API spec (lib/api-spec/openapi.yaml):
- New /orders/bulk-delete operation with BulkDeleteServiceOrdersBody and
BulkDeleteServiceOrdersResponse schemas. Updated DELETE /orders/{id}
description. Regenerated react-query hooks via codegen — both
useDeleteServiceOrder and useBulkDeleteServiceOrders are used by the UI.
UI (artifacts/tx-os/src/pages/orders-incoming.tsx):
- Per-card checkbox visible at all times (RTL-safe leading edge).
- Per-card trash icon for single delete.
- Section-scoped Select-all (مين / unclaimed) with tri-state
all/some(indeterminate)/none and shadcn Checkbox.
- Sticky bottom bulk action bar shows selected count + Clear selection +
destructive Delete.
- Single AlertDialog used by both per-card and bulk paths, with
pluralized confirmation copy. Single delete calls DELETE /orders/:id;
multi delete calls POST /orders/bulk-delete; partial-failure surfaces
via toast.
i18n: New incomingOrders keys in ar.json and en.json (select, selectAll,
clearSelection, selectedCount, delete, deleteConfirmTitle/Body, deleted,
deleteFailed, deletePartial) with pluralization in both languages.
Tests:
- artifacts/api-server/tests/service-orders.test.mjs: receivers can
delete pending/received/preparing; receivers cannot delete terminal
(completed/cancelled); bulk-delete with mixed authorized / unknown /
dedup / unauthenticated cases.
- artifacts/tx-os/tests/order-incoming-delete.spec.mjs (new Playwright):
bulk-delete two unclaimed orders shrinks the list by 2; per-card
trash on a claimed order deletes one. Both pass.
Pre-existing executive-meetings PDF/font test failures are unrelated.
Follow-ups proposed: #398 (Undo for incoming-order deletes), #399
(safer notification handling in bulk-delete).
Backend (artifacts/api-server):
- Added hasReceivePermission() helper and refactored DELETE /orders/:id
into shared authorizeAndDeleteOrder() so single and bulk paths use the
same authorization rules.
- Added POST /orders/bulk-delete returning { deletedIds, failedIds } with
per-id authorization, dedup, and best-effort partial success.
- Tightened receiver authorization (per code review): receivers may only
delete pending/received/preparing orders; terminal (completed/cancelled)
orders remain the owner's cleanup responsibility. OpenAPI description
and the implementation now agree.
API spec (lib/api-spec/openapi.yaml):
- New /orders/bulk-delete operation with BulkDeleteServiceOrdersBody and
BulkDeleteServiceOrdersResponse schemas; updated DELETE /orders/{id}
description. Regenerated react-query hooks via codegen — useBulkDelete
ServiceOrders is now available.
UI (artifacts/tx-os/src/pages/orders-incoming.tsx):
- Selection mode toggle in the page header (RTL-safe).
- Per-card Checkbox plus a Select-all control.
- Sticky bottom action bar with destructive Delete and selected count.
- AlertDialog confirmation using pluralized i18n keys; toast surfaces
partial-failure results when some ids couldn't be deleted.
i18n: New incomingOrders keys in ar.json and en.json (select, selectAll,
clearSelection, selectedCount, delete, deleteConfirmTitle/Body, deleted,
deleteFailed, deletePartial) with pluralization.
Tests: Added two new tests in service-orders.test.mjs covering receiver
delete on incoming queue, receiver forbidden on terminal orders, and
bulk-delete with mixed authorized / unknown / dedup / unauthenticated
cases. Both pass. Pre-existing executive-meetings PDF/font test failures
are unrelated.
Regenerated artifacts/tx-os/public/service-images/saudi-coffee.png
with a sharper prompt that explicitly names a handleless Saudi
finjan (small flared white porcelain cup with a thin gold patterned
rim, no handle) and a clear warm brown coffee color for both the
pour and the liquid in the cup. Strengthened the negative prompt
against handled cups, mugs, amber/orange liquid, and tea so the new
image no longer reads as "tea in a teacup".
Same path as before, so no DB change is needed — the existing
services.image_url ("service-images/saudi-coffee.png") on row id=2
keeps pointing at the new file.
No code, schema, locale, or test changes. Pre-existing `test`
workflow failure is unrelated.
Regenerated artifacts/tx-os/public/service-images/saudi-coffee.png
with a sharper prompt that explicitly names a handleless Saudi
finjan (small flared white porcelain cup with a thin gold patterned
rim, no handle) and a clear warm brown coffee color for both the
pour and the liquid in the cup. Strengthened the negative prompt
against handled cups, mugs, amber/orange liquid, and tea so the new
image no longer reads as "tea in a teacup".
Same path as before, so no DB change is needed — the existing
services.image_url ("service-images/saudi-coffee.png") on row id=2
keeps pointing at the new file.
No code, schema, locale, or test changes. Pre-existing `test`
workflow failure is unrelated.
Two small follow-ups on Task #394 polish:
1. Regenerated artifacts/tx-os/public/service-images/saudi-coffee.png
with a tighter prompt — just the brass dallah pouring brown
coffee into a small white finjan, soft beige background, no
dates/cardamom/garnish. Same path so no DB change needed.
2. Shrunk the "إضافة ملاحظات / Add notes" toggle in
OrderServiceModal: replaced the chunky outline Button with a
small ghost text-link style (text-xs, muted, pencil icon size 12,
underline-on-hover). It now reads as a secondary affordance and
sits below the service-preview row, well clear of the dialog's
absolute close (X) at right-4 top-4 — no overlap in either AR or
EN.
Behavior unchanged: data-testid="order-notes-toggle" preserved,
tapping still expands and focuses the textarea, hide link still
collapses without losing typed text.
Verification:
- pnpm --filter @workspace/tx-os typecheck → passes.
- The pre-existing `test` workflow failure is unrelated to this
change.
Three small UX fixes on the Services screen:
1. Renamed service id=2 to "قهوة سعودي" / "Saudi Coffee" and swapped
the thumbnail to a new clear brown image (small dallah pouring
into a finjan with cardamom + a date) saved at
public/service-images/saudi-coffee.png. The legacy
arabic-coffee.png is left in place so any cached references keep
loading.
2. Renamed service id=2450 Arabic name to "بلاك كوفي" (English
"Black Coffee" unchanged).
3. OrderServiceModal now opens with the notes textarea collapsed and
not mounted, so iPad/Safari no longer auto-pops the keyboard. A
small outline "إضافة ملاحظات / Add notes" button (with pencil
icon) expands it and focuses the textarea on demand. While
expanded, a small "إخفاء / Hide" link collapses it again without
clearing typed text. If initialNotes is non-empty when the dialog
opens, it starts expanded. Submission behavior unchanged.
Verified DB state after updates:
id=2 name_ar=قهوة سعودي name_en=Saudi Coffee image_url=service-images/saudi-coffee.png
id=2450 name_ar=بلاك كوفي name_en=Black Coffee image_url=service-images/black-coffee.png
Added i18n keys services.addNotes / services.hideNotes to ar.json
and en.json. Added data-testid="order-notes-toggle" and
data-testid="order-notes-textarea" for future tests.
`pnpm --filter @workspace/tx-os typecheck` passes. The pre-existing
`test` workflow failure is unrelated to this change.
Three small UX fixes on the Services screen:
1. Renamed service id=2 to "قهوة سعودي" / "Saudi Coffee" and swapped
the thumbnail to a new clear brown image (small dallah pouring
into a finjan with cardamom + a date) saved at
public/service-images/saudi-coffee.png. The legacy
arabic-coffee.png is left in place so any cached references keep
loading.
2. Renamed service id=2450 Arabic name to "بلاك كوفي" (English
"Black Coffee" unchanged).
3. OrderServiceModal now opens with the notes textarea collapsed and
not mounted, so iPad/Safari no longer auto-pops the keyboard. A
small outline "إضافة ملاحظات / Add notes" button (with pencil
icon) expands it and focuses the textarea on demand. While
expanded, a small "إخفاء / Hide" link collapses it again without
clearing typed text. If initialNotes is non-empty when the dialog
opens, it starts expanded. Submission behavior unchanged.
Verified DB state after updates:
id=2 name_ar=قهوة سعودي name_en=Saudi Coffee image_url=service-images/saudi-coffee.png
id=2450 name_ar=بلاك كوفي name_en=Black Coffee image_url=service-images/black-coffee.png
Added i18n keys services.addNotes / services.hideNotes to ar.json
and en.json. Added data-testid="order-notes-toggle" and
data-testid="order-notes-textarea" for future tests.
`pnpm --filter @workspace/tx-os typecheck` passes. The pre-existing
`test` workflow failure is unrelated to this change.
Three small UX fixes on the Services screen:
1. Renamed service id=2 to "قهوة سعودي" / "Saudi Coffee" and swapped
the thumbnail to a new clear brown image (small dallah pouring
into a finjan with cardamom + a date) saved at
public/service-images/saudi-coffee.png. The legacy
arabic-coffee.png is left in place so any cached references keep
loading.
2. Renamed service id=2450 Arabic name to "بلاك كوفي" (English
"Black Coffee" unchanged).
3. OrderServiceModal now opens with the notes textarea collapsed and
not mounted, so iPad/Safari no longer auto-pops the keyboard. A
small outline "إضافة ملاحظات / Add notes" button (with pencil
icon) expands it and focuses the textarea on demand. While
expanded, a small "إخفاء / Hide" link collapses it again without
clearing typed text. If initialNotes is non-empty when the dialog
opens, it starts expanded. Submission behavior unchanged.
Verified DB state after updates:
id=2 name_ar=قهوة سعودي name_en=Saudi Coffee image_url=service-images/saudi-coffee.png
id=2450 name_ar=بلاك كوفي name_en=Black Coffee image_url=service-images/black-coffee.png
Added i18n keys services.addNotes / services.hideNotes to ar.json
and en.json. Added data-testid="order-notes-toggle" and
data-testid="order-notes-textarea" for future tests.
`pnpm --filter @workspace/tx-os typecheck` passes. The pre-existing
`test` workflow failure is unrelated to this change.
Three small UX fixes on the Services screen:
1. Renamed service id=2 to "قهوة سعودي" / "Saudi Coffee" and swapped
the thumbnail to a new clear brown image (small dallah pouring
into a finjan with cardamom + a date) saved at
public/service-images/saudi-coffee.png. The legacy
arabic-coffee.png is left in place so any cached references keep
loading.
2. Renamed service id=2450 Arabic name to "بلاك كوفي" (English
"Black Coffee" unchanged).
3. OrderServiceModal now opens with the notes textarea collapsed and
not mounted, so iPad/Safari no longer auto-pops the keyboard. A
small outline "إضافة ملاحظات / Add notes" button (with pencil
icon) expands it and focuses the textarea on demand. While
expanded, a small "إخفاء / Hide" link collapses it again without
clearing typed text. If initialNotes is non-empty when the dialog
opens, it starts expanded. Submission behavior unchanged.
Verified DB state after updates:
id=2 name_ar=قهوة سعودي name_en=Saudi Coffee image_url=service-images/saudi-coffee.png
id=2450 name_ar=بلاك كوفي name_en=Black Coffee image_url=service-images/black-coffee.png
Added i18n keys services.addNotes / services.hideNotes to ar.json
and en.json. Added data-testid="order-notes-toggle" and
data-testid="order-notes-textarea" for future tests.
`pnpm --filter @workspace/tx-os typecheck` passes. The pre-existing
`test` workflow failure is unrelated to this change.
User reported a flood of chimes when opening Tx OS while several
notifications were pending. Two complementary fixes:
1. Player throttle bumped from 600 ms → 3000 ms in
artifacts/tx-os/src/lib/notification-sounds.ts. Bursts of real-time
events now produce a single chime instead of several overlapping ones.
2. Socket warmup gate added in
artifacts/tx-os/src/hooks/use-notifications-socket.ts:
- Track connectedAtRef (useRef<number>), set on effect mount and on
each socket "connect" event using performance.now().
- In the notification_created handler, after mute / per-channel
gates but before notificationPlayer.play(...), suppress
audio + vibration when within the 3 s warmup window.
- UI/badge invalidation still runs — only sound is silenced during
the warmup, so the user sees notifications appear without an
alarm-like welcome.
All existing gates preserved (global mute, per-channel sound/vibration,
autoplay-blocked toast hint, per-meeting playedRef dedupe).
No deviations. tx-os typecheck passes.
Moved the live HeaderClock from the actions cluster (next to the Export
PDF button) to the geometric center of the top header row.
Implementation:
- Made the header row container `relative`.
- Removed `<HeaderClock />` from the trailing actions `<div>`.
- Added an absolutely-positioned overlay (`absolute inset-x-0 top-0
bottom-0 flex items-center justify-center pointer-events-none`)
containing the clock, with the inner wrapper restoring
`pointer-events-auto`. This keeps the clock visually centered
regardless of whether the title or actions on either side are wider.
- Kept all #391 behaviors: `hidden sm:flex`, `print:hidden`, 1s tick,
ar/en locale formatting, palette text-[#0B1E3F], tabular-nums,
data-testid="em-header-clock".
No deviation from plan. tx-os typecheck passes.
Added a `HeaderClock` component to artifacts/tx-os/src/pages/executive-meetings.tsx
that renders next to the "Export PDF" button in the sticky page header.
- Updates every 1s via setInterval (cleared on unmount)
- Locale-aware formatting via Intl.DateTimeFormat (ar / en) with hour12
- Hidden on <sm screens (`hidden sm:flex`) and on print
- Uses existing palette (text-[#0B1E3F]) + Clock lucide icon
- tabular-nums to prevent jitter as digits change
- data-testid="em-header-clock" for future tests
No deviations from plan. tx-os typecheck passes.
Removed the `document.visibilityState === "visible"` early-return from
two playback paths so notification sounds fire even when the Tx OS tab
is the active foreground tab:
- `use-notifications-socket.ts` — order + meeting socket events.
- `upcoming-meeting-alert.tsx` — 5-min upcoming-meeting alert chime.
All other gates remain unchanged: global mute, per-channel sound and
vibration toggles, the ~600ms throttle in the audio player, and the
per-meeting `playedRef` dedupe by `meetingId`.
Verified `pnpm --filter @workspace/tx-os typecheck` passes.
DB
- Added user pref columns; vibration is per-channel
(vibrationEnabledOrder + vibrationEnabledMeeting). Defaults: ding/chime
sounds, vibration on, mute off. Volume uses the device system level —
no persisted volume field.
API
- PATCH /auth/me/notification-preferences (requireAuth, whitelisted partial
update, integer guard for volume). buildAuthUser exposes all new fields.
- OpenAPI spec updated; orval client + zod regenerated.
Frontend
- Static sound library: 8 short WAV assets under public/sounds/ + manifest
(notification-sound-manifest.ts) mapping id -> labelKey -> URL.
- HTMLAudio-based player (notification-sounds.ts) with throttle, unlock,
cache, and AUTOPLAY_BLOCKED_EVENT dispatch when play is denied pre-gesture.
- Settings popover: global mute + slot tabs (orders/meetings) with
per-channel sound + per-channel vibration + per-channel toggle, sound list
with one-tap previews. Concurrency-safe optimistic updates (monotonic seq
counter). RTL-correct toggle knob transforms.
- QuickMuteButton: one-tap topbar mute control (Volume2/VolumeX) with
confirmation toast.
- useAudioUnlock: unlocks audio on first interaction.
- useAutoplayHint: toasts a localized "click anywhere to enable" hint when
the player reports a blocked play attempt.
- Socket hook plays the right per-channel sound + vibration on
notification_created (orders, executive_meeting) when the tab is hidden.
- UpcomingMeetingAlert: plays meeting reminder once per new eligible
meeting (deduped by meetingId, survives 30s polling refetches). Skipped
when the tab is currently visible — sound only fires when backgrounded.
- AR/EN translations added.
Pre-existing TS errors in executive-meetings.ts (font_settings) and
pre-existing test workflow failures are unrelated.
DB
- Added 7 user pref columns; vibration is now per-channel
(vibrationEnabledOrder + vibrationEnabledMeeting). Defaults: ding/chime
sounds, vibration on, mute off, volume 70.
API
- PATCH /auth/me/notification-preferences (requireAuth, whitelisted partial
update, integer guard for volume). buildAuthUser exposes all new fields.
- OpenAPI spec updated; orval client + zod regenerated.
Frontend
- Static sound library: 8 short WAV assets under public/sounds/ + manifest
(notification-sound-manifest.ts) mapping id -> labelKey -> URL.
- HTMLAudio-based player (notification-sounds.ts) with throttle, unlock,
cache, and AUTOPLAY_BLOCKED_EVENT dispatch when play is denied pre-gesture.
- Settings popover: global mute, volume, slot tabs (orders/meetings) with
per-channel sound + per-channel vibration + per-channel toggle, sound list
with one-tap previews. Concurrency-safe optimistic updates (monotonic seq
counter). RTL-correct toggle knob transforms.
- QuickMuteButton: one-tap topbar mute control (Volume2/VolumeX) with
confirmation toast.
- useAudioUnlock: unlocks audio on first interaction.
- useAutoplayHint: toasts a localized "click anywhere to enable" hint when
the player reports a blocked play attempt.
- Socket hook plays the right per-channel sound + vibration on
notification_created (orders, executive_meeting) when the tab is hidden.
- UpcomingMeetingAlert: plays meeting reminder once per new eligible
meeting (deduped by meetingId, survives 30s polling refetches).
- AR/EN translations added.
Pre-existing TS errors in executive-meetings.ts (font_settings) and
pre-existing test workflow failures are unrelated.
- DB: 7 new user prefs (sound per slot, per-type toggles, vibration, mute, volume).
- API: PATCH /auth/me/notification-preferences with whitelisted partial update,
integer guard for volume, and hydrated AuthUser response. AuthUser now exposes
the 7 new fields.
- Frontend: Web Audio synth library (8 sounds), settings popover with global
mute/vibration/volume/per-type toggles, slot tabs, sound preview buttons,
shift+click on bell for quick mute. Concurrency-safe optimistic updates with
monotonic seq counter. RTL-correct toggle knob transforms.
- Socket hook plays sound on notification_created (orders/meetings only) when
tab is hidden, respecting global mute and per-type toggles.
- Audio unlock hook mounted globally to satisfy autoplay restrictions.
- AR/EN translations added.
Pre-existing TS errors in executive-meetings.ts (font_settings) and pre-existing
test failures in test workflow are unrelated to this task.
Update localization files and executive-meetings.tsx to implement sequential bulk deletion with progress tracking and cancellation, mirroring the UX of the bulk duplicate feature.
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 3a577026-2b09-48ef-a405-e40e0b782577
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/UggHvbd
Replit-Helium-Checkpoint-Created: true
Integrates a progress bar and cancel functionality into the bulk duplicate process for executive meetings, migrating from `Promise.allSettled` to a sequential loop to prevent race conditions and updating UI components and localization files.
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 7c55644f-4e59-4e78-a127-9aec1a90ebaf
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/UggHvbd
Replit-Helium-Checkpoint-Created: true
Add zoom and fullscreen controls to the executive meeting schedule page, including zoom in/out buttons, a fullscreen toggle, and Escape key handling for exiting fullscreen. The heading height calculation has been removed and hardcoded to 0px.
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 608173c1-6210-41cf-be7d-3a913963059f
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/jwG0a8d
Replit-Helium-Checkpoint-Created: true
Corrected a variable name typo from `langRaw` to `lang` in the server-side PDF filename generation logic for `executive-meetings.ts`, ensuring consistent use of Arabic day names in the output filename.
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: a6cafe17-82fd-43c4-b54f-d2d57f431b99
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/EWwamzQ
Replit-Helium-Checkpoint-Created: true
Modify `buildAttendeesHtml` to use `htmlToSafeHtml` for preserving attendee name formatting, adjust PDF header layout for centered title and logo, and relocate "recorded by" text.
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 4dd3128f-949f-491c-9f30-425e81521e82
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/EWwamzQ
Replit-Helium-Checkpoint-Created: true