import { JobsPageViewModel, type JobsListItem } from './JobsPageViewModel'; import { SimulationService } from '../services/simulation.service'; import type { SimulationPersonalityInterface } from '../models/simulation-personality.interface'; export interface SimulatorInterviewItem { id: string; title: string; companyName: string; dateLabel: string; completed: boolean; durationMinutes: number | null; personality: string; } interface RecordLike { [key: string]: unknown; } function asRecord(value: unknown): RecordLike | null { return typeof value === 'object' && value !== null ? (value as RecordLike) : null; } function asString(value: unknown): string { return typeof value === 'string' ? value : ''; } function asNumber(value: unknown): number | null { return typeof value === 'number' ? value : null; } function parseBoolean(value: unknown): boolean | null { if (typeof value === 'boolean') { return value; } if (typeof value === 'string') { const normalized = value.toLowerCase(); if (normalized === 'completed' || normalized === 'done' || normalized === 'true') { return true; } if (normalized === 'incomplete' || normalized === 'pending' || normalized === 'false') { return false; } } return null; } function formatDate(value: string): string { if (!value) { return ''; } const parsed = new Date(value); if (Number.isNaN(parsed.getTime())) { return ''; } return new Intl.DateTimeFormat('da-DK', { day: '2-digit', month: 'short', year: 'numeric', }).format(parsed); } function mapInterview(item: unknown, index: number): SimulatorInterviewItem | null { const source = asRecord(item); if (!source) { return null; } const id = asString(source.id) || asString(source.interview_id) || `interview-${index}`; const title = asString(source.job_name) || asString(source.job_title) || asString(source.title) || 'Interview'; const companyName = asString(source.company_name) || asString(source.companyName) || 'Ukendt virksomhed'; const dateRaw = asString(source.interview_date) || asString(source.created_at) || asString(source.updated_at) || asString(source.date); const completed = parseBoolean(source.is_completed) ?? parseBoolean(source.completed) ?? parseBoolean(source.status) ?? true; const durationMinutes = asNumber(source.duration_minutes) ?? asNumber(source.duration) ?? asNumber(source.length_minutes); const personality = asString(source.personality_name) || asString(source.simulation_personality_name) || asString(source.personality) || 'Professionel'; return { id, title, companyName, dateLabel: formatDate(dateRaw), completed, durationMinutes, personality, }; } export class SimulatorViewModel { constructor( private readonly jobsViewModel: JobsPageViewModel = new JobsPageViewModel(), private readonly simulationService: SimulationService = new SimulationService(), ) {} async getCandidateProfile(): Promise<{ imageUrl?: string; name: string }> { return this.jobsViewModel.getCandidateProfile(); } async getJobs(): Promise { try { return await this.jobsViewModel.getTabItems('jobs'); } catch { return []; } } async getPersonalities(): Promise { try { const list = await this.simulationService.listSimulationPersonalities(); return Array.isArray(list) ? list : []; } catch { return []; } } async getInterviews(limit: number = 12): Promise { try { const payload = await this.simulationService.listInterviews(limit, 0); const root = asRecord(payload); const list = Array.isArray(root?.interviews) ? root.interviews : (Array.isArray(payload) ? payload : []); return list .map((item, index) => mapInterview(item, index)) .filter((item): item is SimulatorInterviewItem => Boolean(item)); } catch { return []; } } }