- getDashboardData aggregates open jobs, pending-action jobs, unread
notifications, pending finance totals, approved connection count, recent
jobs (up to 8) and recent notifications (up to 5) — single Promise.all so
the dashboard renders in one round-trip.
- Four stat cards, each a Link to the relevant module; tone (positive /
negative) flips between clinic (payable) and lab (receivable).
- Clinic users with zero approved connections see a 'Bağlantı Kur' prompt
card so they don't get stuck on /jobs/new.
- Recent jobs table is role-aware: lab sees Klinik column + 'Son Gelen
İşler' header, clinic sees Laboratuvar column + 'Son Giden İşler' header.
- Recent notifications panel with read/unread dot, clickable header arrow
to /notifications.
- ActiveContext now carries 'kind' (mirror of TenantSettings.kind) so we no
longer reach into ctx.settings?.kind in callers.
Previously, signing in with a kind toggle when the account had no
tenant_settings row in the lab database returned 'Bu hesap için kayıt
bulunamadı'. For a freshly-imported isletmem user that has never opened
DLS, the right behaviour is onboarding — not a dead end.
resolveTenantOnLogin now distinguishes three states:
- no_tenants → redirect /onboarding?kind=<pill> (session stays)
- mismatch → real error naming the existing kind, session rolled back
- matched → existing tenant set as active, /dashboard
Onboarding page accepts ?kind= and the workspace form pre-selects it, so
the user keeps their login pill choice without re-picking. Also fixed the
'teams.total > 0' redirect — it now requires a tenant_settings row before
sending users off to /dashboard, otherwise users with cross-app teams but
no DLS workspace would bounce.
Sign-in form now has a Klinik / Laboratuvar pill toggle (defaults to clinic).
The selected kind is posted alongside email+password; the server action
resolves the user's memberships, picks a tenant_settings row matching the
chosen kind, and sets it as active. If no matching tenant exists the session
is rolled back with a clear error.
Invite-flow logins skip the kind check — invite code drives team assignment.