/** * UserProfile Domain Entity * * Represents the authenticated user's profile data. * Encapsulates personal information and email verification state. * * @layer Domain */ import { type SupportedLocale, DEFAULT_LOCALE, CompanyType } from '@archer/domain'; interface UserProfileProps { id: string; email: string; firstName: string; lastName: string; phone?: string; locale: SupportedLocale; timezone: string; emailNotVerified: boolean; companyType?: CompanyType; isProfileComplete: boolean; missingProfileFields: string[]; } export interface ProfileFormData { firstName: string; lastName: string; phone: string; locale: SupportedLocale; timezone: string; } export class UserProfile { private constructor(private readonly props: UserProfileProps) {} static fromApi(data: { id: string; email: string; firstName?: string; lastName?: string; phone?: string; locale?: string; timezone?: string; emailNotVerified?: boolean; companyType?: CompanyType; isProfileComplete?: boolean; missingProfileFields?: string[]; }): UserProfile { return new UserProfile({ id: data.id, email: data.email, firstName: data.firstName || '', lastName: data.lastName || '', phone: data.phone, locale: (data.locale as SupportedLocale) || DEFAULT_LOCALE, timezone: data.timezone || 'Europe/Berlin', emailNotVerified: data.emailNotVerified ?? false, companyType: data.companyType, isProfileComplete: data.isProfileComplete ?? false, missingProfileFields: data.missingProfileFields ?? [], }); } get id(): string { return this.props.id; } get email(): string { return this.props.email; } get firstName(): string { return this.props.firstName; } get lastName(): string { return this.props.lastName; } get phone(): string | undefined { return this.props.phone; } get locale(): SupportedLocale { return this.props.locale; } get timezone(): string { return this.props.timezone; } get emailNotVerified(): boolean { return this.props.emailNotVerified; } get emailVerified(): boolean { return !this.props.emailNotVerified; } get displayName(): string { const parts = [this.props.firstName, this.props.lastName].filter(Boolean); return parts.length > 0 ? parts.join(' ') : this.props.email; } get initials(): string { const parts = [this.props.firstName, this.props.lastName].filter(Boolean); if (parts.length === 0) return '?'; return parts.map((n) => n.charAt(0).toUpperCase()).join(''); } get localeLabel(): string { const map: Record = { de: 'Deutsch', en: 'English' }; return map[this.props.locale] || this.props.locale; } get companyType(): CompanyType | undefined { return this.props.companyType; } get isPersonal(): boolean { return this.props.companyType === CompanyType.PERSONAL; } get isProfileComplete(): boolean { return this.props.isProfileComplete; } get missingProfileFields(): string[] { return this.props.missingProfileFields; } toFormData(): ProfileFormData { return { firstName: this.props.firstName, lastName: this.props.lastName, phone: this.props.phone || '', locale: this.props.locale, timezone: this.props.timezone, }; } }