wacrm/src/components
Arnas Donauskas 2e911d5e5a
fix(multi-user): share whatsapp_config + templates by account
Reported by @ArnasDon: a teammate accepting an invite landed in the
shared account but the WhatsApp Config tab still showed "not
connected." Inbox banner read "WhatsApp not connected" too.

Cause: PR 8 of the multi-user series converted the *webhook* and
the *automations/flows engines* to account-scoped lookups, but
left every user-facing API route + UI page still filtering by
`user_id`. Post-017 `whatsapp_config` and `message_templates` are
account-scoped (one row per account, with `account_id NOT NULL`),
so `.eq('user_id', user.id)` returned zero rows for any teammate
who didn't personally save the config — including everyone who
joined via invite.

This PR completes the conversion across the user-facing surface.

Surface (11 files)
- `src/components/settings/whatsapp-config.tsx` — read accountId
  from `useAuth()`; trigger fetch on profile-ready, not just
  user-ready; pass accountId through to the supabase query.
- `src/app/(dashboard)/inbox/page.tsx` — resolve account_id from
  profiles, query whatsapp_config by account_id for the
  connected-banner state.
- `src/app/api/whatsapp/config/route.ts` — GET/POST/DELETE all
  resolve account_id from profile. The phone_number_id collision
  check (service-role) now compares against `account_id`, not
  `user_id` — two accounts still can't share a Meta number, two
  teammates in one account share one row by design. INSERT
  populates `account_id` (tenancy) + `user_id` (audit).
- `src/app/api/whatsapp/config/verify-registration/route.ts` —
  same conversion.
- `src/app/api/whatsapp/send/route.ts` — conversation,
  whatsapp_config, message_templates lookups all switch to
  account_id; rate-limit key stays per-user.
- `src/app/api/whatsapp/react/route.ts` — conversation +
  whatsapp_config switch to account_id.
- `src/app/api/whatsapp/broadcast/route.ts` — whatsapp_config +
  message_templates + broadcasts switch to account_id.
- `src/app/api/whatsapp/media/[mediaId]/route.ts` — config
  lookup switches to account_id.
- `src/app/api/whatsapp/templates/submit/route.ts` — config
  lookup + every message_templates SELECT/upsert now uses
  account_id. The upsert ROW gains `account_id` so the
  NOT NULL constraint added by migration 017 stops rejecting
  new templates (this was an incidental bug — every new
  template post-017 would have been broken regardless of
  multi-user).
- `src/app/api/whatsapp/templates/sync/route.ts` — same.
- `src/app/api/whatsapp/templates/[id]/route.ts` PATCH +
  DELETE — same.

Pattern at every route:

  const { data: profile } = await supabase
    .from('profiles')
    .select('account_id')
    .eq('user_id', user.id)
    .maybeSingle()
  const accountId = profile?.account_id as string | undefined
  if (!accountId) return 403

then every downstream `.eq('user_id', user.id)` → `.eq('account_id', accountId)`.

Known follow-up not in this PR
- `message_templates` still has its UNIQUE index on
  `(user_id, name, language)` from migration 014; the submit
  upsert's `onConflict` targets that same triple. As a result,
  two teammates can still INSERT same-named templates without
  conflicting. The fix needs a small migration (drop legacy
  index, add `(account_id, name, language)` index, switch the
  `onConflict` target) — TODO comment left in the route file so
  it's not forgotten.

Verification
- `npm run lint`      → 0 errors (same 19 pre-existing warnings)
- `npm run typecheck` → clean
- `npm test`          → 366/366 pass
- `npm run build`     → succeeds

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 14:01:46 +03:00
..
auth feat(auth): extend useAuth with account context + RequireRole + useCan 2026-05-31 17:58:53 +03:00
automations feat(theme): sweep remaining violet-* → primary across all surfaces 2026-05-22 17:00:32 +03:00
broadcasts chore(templates): polish pass from senior backend / FE / UX review 2026-05-29 17:50:11 +02:00
contacts feat(theme): sweep remaining violet-* → primary across all surfaces 2026-05-22 17:00:32 +03:00
dashboard feat(dashboard): adopt Tremor for charts — first integration 2026-05-31 14:42:10 +03:00
flows perf(db,webhook): backend follow-ups from the multi-user review 2026-05-31 19:18:58 +03:00
inbox feat(ui): front-end correctness pass from multi-user review (S1,S2,S6-S8,P8,P9) 2026-05-31 19:33:28 +03:00
layout Revert "feat(i18n): re-attempt next-intl with hardened artifact tracing" 2026-05-31 21:05:34 +03:00
pipelines feat(theme): sweep remaining violet-* → primary across all surfaces 2026-05-22 17:00:32 +03:00
settings fix(multi-user): share whatsapp_config + templates by account 2026-06-01 14:01:46 +03:00
tremor feat(dashboard): adopt Tremor for charts — first integration 2026-05-31 14:42:10 +03:00
ui feat(ui): front-end correctness pass from multi-user review (S1,S2,S6-S8,P8,P9) 2026-05-31 19:33:28 +03:00