/* * 역할별 랜딩·트랙 판정 (모바일) — 웹 src/frontend/src/lib/roleTrack.ts 로직 이식(패리티). * 우선순위: admin > ops > business > agency > visitor. 판정 불가 시 visitor(관람객) 기본. * * 웹과의 차이(모바일 계약 적응): * · 로그인 응답 user(AuthUser)에는 roleCode가 없다 → hallManager=true를 ops 신호로 사용. * (roleCode를 아는 호출부는 옵션으로 전달 가능 — /api/auth/me의 MePrincipal.roleCode 등) * · 랜딩 경로는 웹 라우트(/admin·/contractor/dashboard·/visitor·/home) 대신 모바일 라우트로 매핑. */ import type { AuthUser, EventRole, WorkspaceDto } from './types'; export type Track = 'visitor' | 'business' | 'agency' | 'ops' | 'admin'; /** 워크스페이스 역할 → 트랙(스코프 판정용). 웹 trackOf와 동일. */ export function trackOf(role: EventRole | null | undefined): Track { switch (role) { case 'ORGANIZER': case 'EXHIBITOR': return 'business'; case 'CONTRACTOR': return 'agency'; case 'HALL_MANAGER': return 'ops'; default: return 'visitor'; } } /** 랜딩 판정 입력 — 로그인 응답 user + workspaces. roleCode는 알 때만(옵션). */ export interface LandingInput { user?: (AuthUser & { roleCode?: string | null }) | null; workspaces?: WorkspaceDto[] | null; } /** * 로그인 랜딩 트랙 결정(primaryTrack 우선순위). 웹 resolveLandingTrack 이식. * roleCode('ADMIN'/'MANAGER')를 알면 웹과 동일하게 판정하고, 없으면 hallManager로 ops를 추론한다. */ export function resolveLandingTrack({ user, workspaces }: LandingInput): Track { const role = (user?.roleCode ?? '').toUpperCase(); const ws = workspaces ?? []; if (role === 'ADMIN') return 'admin'; if (role === 'MANAGER' || user?.hallManager || ws.some((w) => w.myRole === 'HALL_MANAGER')) { return 'ops'; } if (ws.some((w) => w.myRole === 'ORGANIZER' || w.myRole === 'EXHIBITOR')) return 'business'; if (ws.some((w) => w.myRole === 'CONTRACTOR')) return 'agency'; return 'visitor'; } /** * 트랙 → 로그인 직후 랜딩 라우트(모바일). * · admin/ops/business → 탭 홈(/(tabs)) — 모바일엔 별도 admin 화면 없음, 홈이 역할 진입 허브 * · agency(장치·시공) → 현장 탭(/(tabs)/field) — 체크리스트 허브 * · visitor(관람객) → 티켓 지갑(/tickets) — B2C 진입 */ export function landingPathForTrack(track: Track): string { switch (track) { case 'agency': return '/(tabs)/field'; case 'visitor': return '/tickets'; case 'admin': case 'ops': case 'business': default: return '/(tabs)'; } } /** 입력으로부터 랜딩 라우트 계산(예외 시 탭 홈 폴백). */ export function landingPathFor(input: LandingInput): string { try { return landingPathForTrack(resolveLandingTrack(input)); } catch { return '/(tabs)'; } }