'use client'; import { FunctionComponent, useState } from 'react'; import { Box, CircularProgress, Paper, Stack, Typography } from '@mui/material'; import { useRouter } from 'next/navigation'; import { useLocale, useTranslations } from 'next-intl'; import AppIcon from '@/components/common/AppIcon'; import { AppButton } from '@/components'; import { APP_ROLES, type AppRole } from '@/constants'; import { useSelectRole } from '@/services/auth'; import { resolveRoleDestination } from '@/services/auth/routing'; import type { PublicRole } from '@/services/auth/types'; import { AUTH_CARD_MAX_WIDTH } from './constants'; import BrandMark from './BrandMark'; interface SelectRoleProps { /** Login intent carried from A1/B1 — pre-selects the matching option. Admin is never offered. */ initialRole?: AppRole; } // 'family' (a household under one roof) reads as "receiving care"; 'visits' (a clinical-visit // glyph) reads as "nurse professional" — a house icon for the nurse option was the prior defect. const ROLE_OPTIONS: ReadonlyArray<{ role: PublicRole; icon: string }> = [ { role: 'customer', icon: 'family' }, { role: 'nurse', icon: 'visits' }, ]; /** * First-use role picker for a brand-new user whose `/me` has no public role. Selecting one calls * `me/select_role` (which rotates the token so the new claim lands), then routes into that app. * Admin roles are internal-only and never selectable here. * @component SelectRole */ const SelectRole: FunctionComponent = ({ initialRole }) => { const t = useTranslations('auth'); const router = useRouter(); const locale = useLocale(); const selectRole = useSelectRole(); const preset: PublicRole = initialRole === APP_ROLES.NURSE ? 'nurse' : 'customer'; const [selected, setSelected] = useState(preset); const confirm = () => { selectRole.mutate(selected, { onSuccess: (me) => router.replace(`/${locale}${resolveRoleDestination(me, selected)}`), }); }; return ( {t('select_role_title')} {t('select_role_subtitle')} {ROLE_OPTIONS.map(({ role, icon }) => { const isSelected = selected === role; return ( setSelected(role)} onKeyDown={(event) => { if (event.key === 'Enter' || event.key === ' ') { event.preventDefault(); setSelected(role); } }} elevation={0} sx={{ p: 2.5, cursor: 'pointer', display: 'flex', alignItems: 'center', gap: 2, border: '2px solid', borderColor: isSelected ? 'primary.main' : 'divider', borderRadius: 'var(--bal-radius-md)', // Selection is never color-only: the soft fill pairs with a check glyph below. bgcolor: isSelected ? 'var(--bal-primary-soft)' : 'transparent', transition: 'background-color var(--bal-motion-base) var(--bal-easing-standard), border-color var(--bal-motion-base) var(--bal-easing-standard)', }} > {t(`role_${role}`)} {t(`role_${role}_desc`)} ); })} {t('role_add_later_note')} : undefined} > {t('continue')} ); }; export default SelectRole;