Task #389: Notification sounds + vibration with per-user customization

- 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.
This commit is contained in:
Riyadh
2026-05-05 08:13:38 +00:00
parent f7b8de4eab
commit 876719f0eb
14 changed files with 1042 additions and 1 deletions
+2
View File
@@ -65,6 +65,7 @@ import {
type HomeClockSize,
} from "@/components/clock";
import { ClockStylePicker } from "@/components/clock-style-picker";
import { NotificationSettingsPicker } from "@/components/notification-settings";
type IconName = keyof typeof LucideIcons;
function isIconName(x: string): x is IconName {
@@ -495,6 +496,7 @@ export default function HomePage() {
currentStyle={user?.clockStyle ?? null}
currentHour12={user?.clockHour12 ?? null}
/>
<NotificationSettingsPicker />
<button
onClick={toggleLanguage}
aria-label="Toggle language"