@flusys/ng-auth 9.1.1 → 9.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/flusys-ng-auth-administration-page.component-DmN4KqiR.mjs.map +1 -1
- package/fesm2022/{flusys-ng-auth-social-callback-page.component-gTD7_LJY.mjs → flusys-ng-auth-social-callback-page.component-uE6vIUtK.mjs} +3 -1
- package/fesm2022/{flusys-ng-auth-social-callback-page.component-gTD7_LJY.mjs.map → flusys-ng-auth-social-callback-page.component-uE6vIUtK.mjs.map} +1 -1
- package/fesm2022/{flusys-ng-auth-social-config-page.component-DpGmcb9n.mjs → flusys-ng-auth-social-config-page.component-DQvkiR7M.mjs} +1 -3
- package/fesm2022/flusys-ng-auth-social-config-page.component-DQvkiR7M.mjs.map +1 -0
- package/fesm2022/{flusys-ng-auth-user-form.component-CM9UYc0q.mjs → flusys-ng-auth-user-form.component-C5ncAjU9.mjs} +4 -4
- package/fesm2022/{flusys-ng-auth-user-form.component-CM9UYc0q.mjs.map → flusys-ng-auth-user-form.component-C5ncAjU9.mjs.map} +1 -1
- package/fesm2022/{flusys-ng-auth-user-list.component-Bew7gz-H.mjs → flusys-ng-auth-user-list.component-BNYmRTlN.mjs} +2 -2
- package/fesm2022/{flusys-ng-auth-user-list.component-Bew7gz-H.mjs.map → flusys-ng-auth-user-list.component-BNYmRTlN.mjs.map} +1 -1
- package/fesm2022/flusys-ng-auth.mjs +30 -17
- package/fesm2022/flusys-ng-auth.mjs.map +1 -1
- package/package.json +5 -5
- package/types/flusys-ng-auth.d.ts +3 -1
- package/fesm2022/flusys-ng-auth-social-config-page.component-DpGmcb9n.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flusys-ng-auth.mjs","names":[],"sources":["../../../projects/ng-auth/enums/social-provider.enum.ts","../../../projects/ng-auth/interfaces/auth.interface.ts","../../../projects/ng-auth/services/auth-api.service.ts","../../../projects/ng-auth/services/auth-state.service.ts","../../../projects/ng-auth/services/auth-init.service.ts","../../../projects/ng-auth/services/branch-api.service.ts","../../../projects/ng-auth/services/company-api.service.ts","../../../projects/ng-auth/constants/auth-endpoints.const.ts","../../../projects/ng-auth/services/social-auth-api.service.ts","../../../projects/ng-auth/services/social-auth-config-api.service.ts","../../../projects/ng-auth/services/token-refresh-state.service.ts","../../../projects/ng-auth/providers/auth-extension.providers.ts","../../../projects/ng-auth/services/password-policy.service.ts","../../../projects/ng-auth/services/email-policy.service.ts","../../../projects/ng-auth/services/user-api.service.ts","../../../projects/ng-auth/services/user-permission-api.service.ts","../../../projects/ng-auth/guards/auth.guard.ts","../../../projects/ng-auth/interceptors/auth.interceptor.ts","../../../projects/ng-auth/interceptors/token-refresh.interceptor.ts","../../../projects/ng-auth/constants/messages.ts","../../../projects/ng-auth/routes/auth.routes.ts","../../../projects/ng-auth/adapters/auth-layout-providers.adapter.ts","../../../projects/ng-auth/adapters/auth-shared-providers.adapter.ts","../../../projects/ng-auth/providers/auth-layout.providers.ts","../../../projects/ng-auth/providers/auth-providers.ts","../../../projects/ng-auth/components/branch-permitted-users-dialog.component.ts","../../../projects/ng-auth/components/company-permitted-users-dialog.component.ts","../../../projects/ng-auth/components/social-login-buttons.component.ts","../../../projects/ng-auth/components/user-branch-permission-dialog.component.ts","../../../projects/ng-auth/components/user-company-permission-dialog.component.ts"],"sourcesContent":["export enum SocialProviderEnum {\n GOOGLE = 'google',\n FACEBOOK = 'facebook',\n LINKEDIN = 'linkedin',\n MICROSOFT = 'microsoft',\n}\n\nexport const SOCIAL_PROVIDERS = [\n SocialProviderEnum.GOOGLE,\n SocialProviderEnum.FACEBOOK,\n SocialProviderEnum.LINKEDIN,\n SocialProviderEnum.MICROSOFT,\n] as const;\n","import { ISingleResponse } from '@flusys/ng-shared';\n\nexport interface ILoginRequest {\n email: string;\n password: string;\n rememberMe?: boolean;\n}\n\nexport interface IRegistrationRequest {\n name: string;\n email: string;\n password: string;\n phone?: string;\n companySlug?: string;\n branchSlug?: string;\n newCompanyName?: string;\n newCompanyPhone?: string;\n newCompanyAddress?: string;\n additionalFields?: Record<string, unknown>;\n}\n\nexport interface ISelectRequest {\n sessionId: string;\n companyId: string;\n branchId: string;\n rememberMe?: boolean;\n}\n\nexport interface ISwitchCompanyRequest {\n companyId: string;\n branchId: string;\n}\n\nexport interface IChangePasswordRequest {\n currentPassword: string;\n newPassword: string;\n}\n\nexport interface IUserInfo {\n id: string;\n email: string;\n name?: string;\n phone?: string | null;\n profilePictureId?: string | null;\n companyId?: string;\n branchId?: string;\n companyLogoId?: string;\n branchLogoId?: string;\n}\n\nexport interface ICompanyInfo {\n id: string;\n name: string;\n slug?: string;\n logoId?: string | null;\n}\n\nexport interface IBranchInfo {\n id: string;\n name: string;\n slug?: string;\n logoId?: string | null;\n}\n\nexport interface IBranchSelectionInfo {\n id: string;\n name: string;\n slug: string;\n logoId?: string | null;\n parentId?: string | null;\n serial?: number | null;\n displayParentId?: string | null;\n}\n\nexport interface ICompanyWithBranches {\n id: string;\n name: string;\n slug: string;\n logoId?: string | null;\n branches: IBranchSelectionInfo[];\n}\n\n// ─── Data-level interfaces (what's inside `data`) ─────────────────────────────\n\nexport interface ILoginData {\n accessToken: string;\n refreshToken?: string;\n user: IUserInfo;\n company?: ICompanyInfo;\n branch?: IBranchInfo;\n}\n\nexport interface IMeData {\n user: IUserInfo;\n company?: ICompanyInfo;\n branch?: IBranchInfo;\n}\n\nexport interface IRegistrationData {\n accessToken?: string;\n refreshToken?: string;\n user: IUserInfo;\n company?: ICompanyInfo;\n branch?: IBranchInfo;\n requiresEmailVerification?: boolean;\n}\n\nexport interface ICompanySelectionData {\n requiresSelection: true;\n sessionId: string;\n expiresAt: Date | string;\n user: IUserInfo;\n companies: ICompanyWithBranches[];\n}\n\nexport interface IEmailVerificationData {\n requiresEmailVerification: true;\n email: string;\n}\n\n// ─── API response type aliases (FLUSYS envelope via ISingleResponse) ──────────\n\nexport type ILoginResponse = ISingleResponse<ILoginData>;\nexport type IMeResponse = ISingleResponse<IMeData>;\nexport type IRegistrationResponse = ISingleResponse<IRegistrationData>;\nexport type ICompanySelectionResponse = ISingleResponse<ICompanySelectionData>;\nexport type ILoginRequiresEmailVerification = ISingleResponse<IEmailVerificationData>;\nexport type IRefreshTokenResponse = ISingleResponse<{ accessToken: string }>;\n\n// ─── Union type for login endpoint response ────────────────────────────────────\n\nexport type AuthResponse = ISingleResponse<ILoginData | ICompanySelectionData | IEmailVerificationData>;\n\n// ─── Type guards ───────────────────────────────────────────────────────────────\n\nexport function isEmailVerificationRequired(response: AuthResponse): response is ILoginRequiresEmailVerification {\n return !!response.data && 'requiresEmailVerification' in response.data && response.data.requiresEmailVerification === true;\n}\n\nexport function isCompanySelectionResponse(response: AuthResponse): response is ICompanySelectionResponse {\n return !!response.data && 'requiresSelection' in response.data && response.data.requiresSelection === true;\n}\n\nexport function isLoginResponse(response: AuthResponse): response is ILoginResponse {\n return !!response.data && 'accessToken' in response.data;\n}\n","import { HttpClient } from '@angular/common/http';\nimport { inject, Service } from '@angular/core';\nimport { APP_CONFIG, getServiceUrl } from '@flusys/ng-core';\nimport { IMessageResponse, ISingleResponse } from '@flusys/ng-shared';\nimport { Observable } from 'rxjs';\nimport {\n AuthResponse,\n IBranchSelectionInfo,\n IChangePasswordRequest,\n ICompanyInfo,\n ILoginRequest,\n IMeResponse,\n IRefreshTokenResponse,\n IRegistrationRequest,\n IRegistrationResponse,\n ISelectRequest,\n ILoginResponse,\n ISwitchCompanyRequest,\n} from '../interfaces/auth.interface';\n\n@Service()\nexport class AuthApiService {\n private readonly appConfig = inject(APP_CONFIG);\n private readonly http = inject(HttpClient);\n private readonly baseUrl: string;\n\n constructor() {\n this.baseUrl = getServiceUrl(this.appConfig, 'auth');\n }\n\n login(data: ILoginRequest): Observable<AuthResponse> {\n return this.http.post<AuthResponse>(`${this.baseUrl}/login`, data);\n }\n\n register(data: IRegistrationRequest): Observable<IRegistrationResponse> {\n return this.http.post<IRegistrationResponse>(`${this.baseUrl}/register`, data);\n }\n\n select(data: ISelectRequest): Observable<ILoginResponse> {\n return this.http.post<ILoginResponse>(`${this.baseUrl}/select`, data);\n }\n\n switchCompany(data: ISwitchCompanyRequest): Observable<ILoginResponse> {\n return this.http.post<ILoginResponse>(`${this.baseUrl}/switch-company`, data);\n }\n\n getCompanies(): Observable<ISingleResponse<ICompanyInfo[]>> {\n return this.http.post<ISingleResponse<ICompanyInfo[]>>(`${this.baseUrl}/get-my-companies`, {});\n }\n\n getCompanyBranches(companyId: string): Observable<ISingleResponse<IBranchSelectionInfo[]>> {\n return this.http.post<ISingleResponse<IBranchSelectionInfo[]>>(`${this.baseUrl}/get-my-company-branches`, { companyId });\n }\n\n refresh(): Observable<IRefreshTokenResponse> {\n return this.http.post<IRefreshTokenResponse>(`${this.baseUrl}/refresh`, {});\n }\n\n me(): Observable<IMeResponse> {\n return this.http.post<IMeResponse>(`${this.baseUrl}/me`, {});\n }\n\n logout(): Observable<IMessageResponse> {\n return this.http.post<IMessageResponse>(`${this.baseUrl}/logout`, {});\n }\n\n changePassword(data: IChangePasswordRequest): Observable<IMessageResponse> {\n return this.http.post<IMessageResponse>(`${this.baseUrl}/change-password`, data);\n }\n\n forgotPassword(email: string): Observable<IMessageResponse> {\n return this.http.post<IMessageResponse>(`${this.baseUrl}/forgot-password`, { email });\n }\n\n resetPassword(token: string, newPassword: string): Observable<IMessageResponse> {\n return this.http.post<IMessageResponse>(`${this.baseUrl}/reset-password`, { token, newPassword });\n }\n\n resendVerification(email: string): Observable<IMessageResponse> {\n return this.http.post<IMessageResponse>(`${this.baseUrl}/resend-verification`, { email });\n }\n\n verifyEmail(token: string): Observable<IMessageResponse | IRegistrationResponse> {\n return this.http.post<IMessageResponse | IRegistrationResponse>(`${this.baseUrl}/verify-email`, { token });\n }\n}\n","import { computed, effect, inject, signal, Service } from '@angular/core';\nimport { Router } from '@angular/router';\nimport { APP_CONFIG } from '@flusys/ng-core';\nimport {\n PermissionValidatorService,\n PlatformService,\n} from '@flusys/ng-shared';\nimport {\n IBranchInfo,\n ICompanyInfo,\n ICompanySelectionData,\n ICompanyWithBranches,\n ILoginData,\n IUserInfo,\n} from '../interfaces/auth.interface';\n\n/**\n * Storage keys (static constants)\n * NOTE: Access token is NOT stored - kept in memory only for security (XSS protection)\n * Only token expiry is stored to know when refresh is needed on page load\n */\nconst STORAGE = {\n TOKEN_EXPIRY: 'tokenExpiresAt', // Store expiry time, not the token itself\n COMPANY_ID: 'selectedCompanyId',\n BRANCH_ID: 'selectedBranchId',\n} as const;\n\nconst SAVED_USER_NAME_KEY = 'savedUserName';\n\n/**\n * Auth State Service\n * Minimal signal-based state management for authentication\n */\n@Service()\nexport class AuthStateService {\n // DI Injection\n private readonly appConfig = inject(APP_CONFIG);\n private readonly router = inject(Router);\n private readonly platform = inject(PlatformService);\n private readonly permissionValidator = inject(PermissionValidatorService);\n\n // Core State (private writable, public readonly)\n private readonly _user = signal<IUserInfo | null>(null);\n private readonly _accessToken = signal<string>(''); // Memory-only, not persisted\n private readonly _tokenExpiresAt = signal<number | null>(null); // Token expiry timestamp\n private readonly _company = signal<ICompanyInfo | null>(null);\n private readonly _branch = signal<IBranchInfo | null>(null);\n\n readonly user = this._user.asReadonly();\n readonly accessToken = this._accessToken.asReadonly();\n readonly tokenExpiresAt = this._tokenExpiresAt.asReadonly();\n readonly company = this._company.asReadonly();\n readonly branch = this._branch.asReadonly();\n\n // Company Selection State (temporary during login flow)\n private readonly _selectionSessionId = signal<string | null>(null);\n private readonly _availableCompanies = signal<ICompanyWithBranches[]>([]);\n\n readonly selectionSessionId = this._selectionSessionId.asReadonly();\n readonly availableCompanies = this._availableCompanies.asReadonly();\n\n // Computed States\n readonly isAuthenticated = computed(\n () => !!this._accessToken() && !!this._user(),\n );\n readonly requiresCompanySelection = computed(\n () => !!this._selectionSessionId() && this._availableCompanies().length > 0,\n );\n readonly userName = computed(() => this._user()?.name ?? 'User');\n readonly companyName = computed(() => this._company()?.name ?? '');\n readonly branchName = computed(() => this._branch()?.name ?? '');\n\n /**\n * Check if token is expired or will expire soon (within 30 seconds).\n * Used to proactively refresh token before requests fail.\n */\n readonly isTokenExpired = computed(() => {\n const expiresAt = this._tokenExpiresAt();\n if (!expiresAt) return true;\n // Consider expired 30 seconds before actual expiry\n return Date.now() >= expiresAt - 30000;\n });\n\n // Config-derived states\n readonly tenantId = computed(\n () => this.appConfig.multiTenant.tenantId ?? null,\n );\n\n constructor() {\n // Auto-persist token expiry (NOT the token itself - security)\n effect(() => {\n const expiresAt = this._tokenExpiresAt();\n expiresAt\n ? this.store(STORAGE.TOKEN_EXPIRY, expiresAt.toString())\n : this.remove(STORAGE.TOKEN_EXPIRY);\n });\n\n // Auto-persist company/branch IDs\n effect(() => {\n const companyId = this._company()?.id;\n const branchId = this._branch()?.id;\n companyId\n ? this.store(STORAGE.COMPANY_ID, companyId)\n : this.remove(STORAGE.COMPANY_ID);\n branchId\n ? this.store(STORAGE.BRANCH_ID, branchId)\n : this.remove(STORAGE.BRANCH_ID);\n });\n\n // Persist display name for the login page's \"welcome back\" greeting\n effect(() => {\n const user = this._user();\n const name = user?.name?.trim() || user?.email;\n if (name) this.store(SAVED_USER_NAME_KEY, name);\n });\n\n // Load initial state from storage (expiry only, not token)\n this.loadFromStorage();\n }\n\n // ==========================================================================\n // State Management\n // ==========================================================================\n\n setLoginState(data: ILoginData): void {\n this._accessToken.set(data.accessToken);\n this._user.set(data.user);\n this._company.set(data.company ?? null);\n this._branch.set(data.branch ?? null);\n const expiry = this.decodeTokenExpiry(data.accessToken);\n this._tokenExpiresAt.set(expiry);\n this.clearSelectionState();\n }\n\n setSelectionState(data: ICompanySelectionData): void {\n this._selectionSessionId.set(data.sessionId);\n this._availableCompanies.set(data.companies);\n this._user.set(data.user);\n }\n\n clearSelectionState(): void {\n this._selectionSessionId.set(null);\n this._availableCompanies.set([]);\n }\n\n resetState(): void {\n this._user.set(null);\n this._accessToken.set('');\n this._tokenExpiresAt.set(null);\n this._company.set(null);\n this._branch.set(null);\n this.clearSelectionState();\n Object.values(STORAGE).forEach((key) => this.remove(key));\n this.permissionValidator.clearPermissions();\n }\n\n // ==========================================================================\n // Individual Setters (for external use where needed)\n // ==========================================================================\n\n setUser(user: IUserInfo | null): void {\n this._user.set(user);\n }\n\n setAccessToken(token: string): void {\n this._accessToken.set(token);\n // Decode token to get expiry time\n const expiry = this.decodeTokenExpiry(token);\n this._tokenExpiresAt.set(expiry);\n }\n\n setCompany(company: ICompanyInfo | null): void {\n this._company.set(company);\n }\n\n setBranch(branch: IBranchInfo | null): void {\n this._branch.set(branch);\n }\n\n // ==========================================================================\n // Navigation Helpers\n // ==========================================================================\n\n navigateToLogin(returnUrl?: string): void {\n this.router.navigate(\n ['/auth/login'],\n returnUrl ? { queryParams: { returnUrl } } : {},\n );\n }\n\n navigateAfterLogin(returnUrl?: string): void {\n // Validate returnUrl to prevent open redirect attacks\n const safeUrl = this.isValidReturnUrl(returnUrl) ? returnUrl : '/';\n this.router.navigateByUrl(safeUrl);\n }\n\n /** Validates a return URL to prevent open redirect attacks */\n private isValidReturnUrl(url: string | undefined): url is string {\n if (!url) return false;\n // Must start with '/' and not contain protocol indicators\n return url.startsWith('/') && !url.includes('://') && !url.startsWith('//');\n }\n\n // Storage accessors (used by components)\n getStoredCompanyId(): string | null {\n return this.get(STORAGE.COMPANY_ID);\n }\n\n getStoredBranchId(): string | null {\n return this.get(STORAGE.BRANCH_ID);\n }\n\n getSavedUserName(): string | null {\n return this.get(SAVED_USER_NAME_KEY);\n }\n\n // Storage helpers\n private loadFromStorage(): void {\n if (this.platform.isServer) return;\n // Load token expiry (NOT the token - it's memory-only for security)\n const expiryStr = this.get(STORAGE.TOKEN_EXPIRY);\n if (expiryStr) {\n this._tokenExpiresAt.set(parseInt(expiryStr, 10));\n }\n }\n\n /**\n * Decode JWT expiry without verification (client-side only).\n * Returns expiry timestamp in milliseconds.\n */\n private decodeTokenExpiry(token: string): number | null {\n try {\n if (!token) return null;\n const payload = token.split('.')[1];\n if (!payload) return null;\n // Convert base64url to base64 and add padding\n const base64 = payload.replace(/-/g, '+').replace(/_/g, '/');\n const padded = base64 + '='.repeat((4 - (base64.length % 4)) % 4);\n const decoded = JSON.parse(atob(padded));\n return decoded.exp ? decoded.exp * 1000 : null; // Convert to milliseconds\n } catch {\n return null;\n }\n }\n\n private store(key: string, value: string): void {\n if (!this.platform.isServer) localStorage.setItem(key, value);\n }\n\n private get(key: string): string | null {\n return !this.platform.isServer ? localStorage.getItem(key) : null;\n }\n\n private remove(key: string): void {\n if (!this.platform.isServer) localStorage.removeItem(key);\n }\n}\n","import { inject, signal, Service } from '@angular/core';\nimport { APP_CONFIG } from '@flusys/ng-core';\nimport {\n catchError,\n finalize,\n map,\n Observable,\n of,\n shareReplay,\n switchMap,\n tap,\n timeout,\n} from 'rxjs';\nimport { AuthApiService } from './auth-api.service';\nimport { AuthStateService } from './auth-state.service';\n\n@Service()\nexport class AuthInitService {\n private readonly authState = inject(AuthStateService);\n private readonly authApi = inject(AuthApiService);\n private readonly appConfig = inject(APP_CONFIG);\n\n private readonly _initialized = signal(false);\n readonly initialized = this._initialized.asReadonly();\n\n private initializationCache$: Observable<boolean> | null = null;\n\n initialize(): Observable<boolean> {\n if (this.authState.isAuthenticated() && this.authState.user()) {\n this._initialized.set(true);\n return of(true);\n }\n\n if (this.authState.requiresCompanySelection()) {\n this._initialized.set(true);\n return of(false);\n }\n\n if (this._initialized()) {\n return of(this.authState.isAuthenticated());\n }\n\n if (this.initializationCache$) {\n return this.initializationCache$;\n }\n\n this.initializationCache$ = this.authApi.refresh().pipe(\n timeout(5000),\n switchMap((refreshResponse) => {\n const accessToken = refreshResponse.data?.accessToken;\n if (!accessToken) return of(false);\n this.authState.setAccessToken(accessToken);\n return this.authApi.me().pipe(\n map((meResponse) => {\n const meData = meResponse.data;\n if (!meData) return false;\n const { user, company, branch } = meData;\n\n this.authState.setUser(user);\n\n if (this.appConfig.enableCompanyFeature) {\n this.authState.setCompany(company ?? null);\n this.authState.setBranch(branch ?? null);\n }\n\n return true;\n }),\n );\n }),\n\n tap(() => {\n this._initialized.set(true);\n }),\n\n catchError((err) => {\n this._initialized.set(true);\n\n const errorKey: string = err?.error?.messageKey ?? '';\n\n const companyErrorKeys = new Set([\n 'auth.company.required',\n 'auth.company.not.found',\n 'auth.company.no.access',\n 'auth.branch.not.found',\n 'auth.branch.no.access',\n ]);\n\n const isCompanyError = companyErrorKeys.has(errorKey);\n\n if (isCompanyError && this.appConfig.enableCompanyFeature) {\n this.authState.setUser(null);\n this.authState.setCompany(null);\n this.authState.setBranch(null);\n } else {\n this.authState.resetState();\n }\n\n return of(false);\n }),\n\n shareReplay({ bufferSize: 1, refCount: true }),\n\n finalize(() => {\n this.initializationCache$ = null;\n }),\n );\n\n return this.initializationCache$;\n }\n}\n","import { Service } from '@angular/core';\nimport { ApiResourceService } from '@flusys/ng-shared';\nimport {\n IBranch,\n ICreateBranchRequest,\n IUpdateBranchRequest,\n} from '../interfaces/branch.interface';\n\n/**\n * Branch API Service\n * Signal-based service for branch CRUD operations\n */\n@Service()\nexport class BranchApiService extends ApiResourceService<\n ICreateBranchRequest | IUpdateBranchRequest,\n IBranch\n> {\n constructor() {\n super('branch', 'administration');\n }\n\n fetchByCompany(companyId: string, search = ''): void {\n this.fetchList(search, { filter: { companyId } });\n }\n}\n","import { Service } from '@angular/core';\nimport { ApiResourceService } from '@flusys/ng-shared';\nimport {\n ICompany,\n ICreateCompanyRequest,\n IUpdateCompanyRequest,\n} from '../interfaces/company.interface';\n\n/**\n * Company API Service\n * Signal-based service for company CRUD operations\n */\n@Service()\nexport class CompanyApiService extends ApiResourceService<\n ICreateCompanyRequest | IUpdateCompanyRequest,\n ICompany\n> {\n constructor() {\n super('company', 'administration');\n }\n}\n","/**\n * Authentication API Endpoints\n *\n * Centralized endpoint definitions to prevent inconsistencies across interceptors\n * and services. All auth-related endpoints should be referenced from here.\n */\nexport const AUTH_ENDPOINTS = {\n LOGIN: '/auth/login',\n LOGOUT: '/auth/logout',\n REFRESH: '/auth/refresh',\n REGISTER: '/auth/register',\n ME: '/auth/me',\n SELECT: '/auth/select',\n SWITCH_COMPANY: '/auth/switch-company',\n CHANGE_PASSWORD: '/auth/change-password',\n VERIFY_EMAIL: '/auth/verify-email',\n FORGOT_PASSWORD: '/auth/forgot-password',\n RESET_PASSWORD: '/auth/reset-password',\n RESEND_VERIFICATION: '/auth/resend-verification',\n SOCIAL_CALLBACK: '/auth/social/callback',\n} as const;\n\n/** Check if a URL matches a specific endpoint */\nexport function isEndpoint(url: string, endpoint: string): boolean {\n return url.includes(endpoint);\n}\n","import { HttpClient } from '@angular/common/http';\nimport { inject, Service } from '@angular/core';\nimport { APP_CONFIG, getServiceUrl } from '@flusys/ng-core';\nimport { ISingleResponse, PlatformService } from '@flusys/ng-shared';\nimport { Observable } from 'rxjs';\nimport { AUTH_ENDPOINTS } from '../constants/auth-endpoints.const';\nimport { SocialProviderEnum } from '../enums/social-provider.enum';\nimport { AuthResponse } from '../interfaces/auth.interface';\nimport {\n ISocialAuthorization,\n ISocialCallbackRequest,\n ISocialProviderInfo,\n} from '../interfaces/social-auth.interface';\n\n/** Round-trips the pre-login returnUrl through the OAuth redirect, which cannot carry it itself. */\nexport const SOCIAL_RETURN_URL_KEY = 'flusys_social_return_url';\n\n@Service()\nexport class SocialAuthApiService {\n private readonly appConfig = inject(APP_CONFIG);\n private readonly http = inject(HttpClient);\n private readonly platform = inject(PlatformService);\n private readonly baseUrl = getServiceUrl(this.appConfig, 'auth');\n\n get redirectUri(): string {\n if (this.platform.isServer) return '';\n return `${window.location.origin}${AUTH_ENDPOINTS.SOCIAL_CALLBACK}`;\n }\n\n /** Called before redirecting to the provider, so the callback page can resume where the user left off. */\n saveReturnUrl(returnUrl: string): void {\n if (this.platform.isServer) return;\n if (returnUrl) sessionStorage.setItem(SOCIAL_RETURN_URL_KEY, returnUrl);\n else sessionStorage.removeItem(SOCIAL_RETURN_URL_KEY);\n }\n\n /** Reads and clears the returnUrl saved by {@link saveReturnUrl}. */\n consumeReturnUrl(): string {\n if (this.platform.isServer) return '';\n const returnUrl = sessionStorage.getItem(SOCIAL_RETURN_URL_KEY) ?? '';\n sessionStorage.removeItem(SOCIAL_RETURN_URL_KEY);\n return returnUrl;\n }\n\n getProviders(): Observable<ISingleResponse<ISocialProviderInfo[]>> {\n return this.http.post<ISingleResponse<ISocialProviderInfo[]>>(\n `${this.baseUrl}/social/providers`,\n { redirectUri: this.redirectUri },\n );\n }\n\n authorize(\n provider: SocialProviderEnum,\n ): Observable<ISingleResponse<ISocialAuthorization>> {\n return this.http.post<ISingleResponse<ISocialAuthorization>>(\n `${this.baseUrl}/social/authorize`,\n { provider, redirectUri: this.redirectUri },\n );\n }\n\n callback(request: ISocialCallbackRequest): Observable<AuthResponse> {\n return this.http.post<AuthResponse>(\n `${this.baseUrl}/social/callback`,\n request,\n );\n }\n}\n","import { Service } from '@angular/core';\nimport { ApiResourceService } from '@flusys/ng-shared';\nimport {\n ICreateSocialAuthConfigDto,\n ISocialAuthConfig,\n IUpdateSocialAuthConfigDto,\n} from '../interfaces/social-auth.interface';\n\n@Service()\nexport class SocialAuthConfigApiService extends ApiResourceService<\n ICreateSocialAuthConfigDto | IUpdateSocialAuthConfigDto,\n ISocialAuthConfig\n> {\n constructor() {\n super('social-config', 'auth');\n }\n}\n","import { signal, Service } from '@angular/core';\nimport { BehaviorSubject } from 'rxjs';\n\n/**\n * Token Refresh State Service\n * Manages token refresh state for SSR-safe request queuing.\n * Uses BehaviorSubject for RxJS interop (multi-subscriber async coordination).\n */\n@Service()\nexport class TokenRefreshStateService {\n private readonly _isRefreshing = signal(false);\n readonly isRefreshing = this._isRefreshing.asReadonly();\n\n private readonly _refreshTokenSubject = new BehaviorSubject<string | null>(null);\n readonly refreshTokenSubject$ = this._refreshTokenSubject.asObservable();\n\n startRefresh(): void {\n this._isRefreshing.set(true);\n this._refreshTokenSubject.next(null);\n }\n\n completeRefresh(newToken: string): void {\n this._isRefreshing.set(false);\n this._refreshTokenSubject.next(newToken);\n }\n\n failRefresh(): void {\n this._isRefreshing.set(false);\n }\n}\n","import { InjectionToken, Injector, TemplateRef, Type } from '@angular/core';\nimport { ILogicNode } from '@flusys/ng-shared';\nimport { Observable } from 'rxjs';\nimport { IUser } from '../interfaces/user.interface';\n\nexport interface IEmailValidationConfig {\n pattern?: RegExp;\n message?: string;\n messageKey?: string;\n messageParam?: Record<string, string | number>;\n}\n\nexport interface IPasswordValidationConfig {\n minLength?: number;\n maxLength?: number;\n requireUppercase?: boolean;\n requireLowercase?: boolean;\n requireNumbers?: boolean;\n requireSpecialChars?: boolean;\n pattern?: RegExp;\n message?: string;\n messageKey?: string;\n messageParam?: Record<string, string | number>;\n}\n\nexport interface IAuthValidationConfig {\n email?: IEmailValidationConfig;\n password?: IPasswordValidationConfig;\n}\n\nexport const AUTH_VALIDATION_CONFIG = new InjectionToken<IAuthValidationConfig>(\n 'AUTH_VALIDATION_CONFIG',\n);\n\nexport interface IRegistrationFieldTemplateContext {\n field: IRegistrationExtraField;\n value: unknown;\n updateValue: (value: unknown) => void;\n}\n\nexport const REGISTRATION_FIELD_CONTEXT =\n new InjectionToken<IRegistrationFieldTemplateContext>(\n 'REGISTRATION_FIELD_CONTEXT',\n );\n\nexport interface IRegistrationExtraField {\n key: string;\n label: string;\n labelKey?: string;\n type:\n | 'text'\n | 'number'\n | 'select'\n | 'checkbox'\n | 'textarea'\n | 'date'\n | 'template';\n placeholder?: string;\n placeholderKey?: string;\n required?: boolean;\n defaultValue?: unknown;\n options?: Array<{ label: string; labelKey?: string; value: unknown }>;\n pattern?: RegExp;\n validationMessage?: string;\n validationMessageKey?: string;\n validationMessageParam?: Record<string, string | number>;\n order?: number;\n containerClass?: string;\n template?: TemplateRef<IRegistrationFieldTemplateContext>;\n component?: Type<unknown>;\n injector?: Injector;\n}\n\nexport interface IRegistrationExtensionProvider {\n getExtraFields(): IRegistrationExtraField[];\n transformRegistrationData?(\n data: Record<string, unknown>,\n ): Record<string, unknown>;\n validateExtraFields?(data: Record<string, unknown>): string | null;\n}\n\nexport const AUTH_REGISTRATION_EXTENSION =\n new InjectionToken<IRegistrationExtensionProvider>(\n 'AUTH_REGISTRATION_EXTENSION',\n );\n\nexport interface IUserListExtraColumn {\n key: string;\n header: string;\n headerKey?: string;\n field?: string;\n template?: TemplateRef<{ $implicit: IUser }>;\n styleClass?: string;\n width?: string;\n sortable?: boolean;\n order?: number;\n}\n\nexport interface IUserListExtraAction {\n key: string;\n label: string;\n labelKey?: string;\n icon: string;\n severity?: 'info' | 'success' | 'warn' | 'danger' | 'secondary' | 'contrast';\n permission?: string;\n onClick: (user: IUser) => void;\n isVisible?: (user: IUser) => boolean;\n isDisabled?: (user: IUser) => boolean;\n order?: number;\n}\n\nexport interface IUserListExtensionProvider {\n getExtraColumns(): IUserListExtraColumn[];\n getExtraActions(): IUserListExtraAction[];\n enrichUserData?(users: IUser[]): Observable<IUser[]>;\n}\n\nexport const AUTH_USER_LIST_EXTENSION =\n new InjectionToken<IUserListExtensionProvider>('AUTH_USER_LIST_EXTENSION');\n\nexport interface IProfileExtraSection {\n key: string;\n title: string;\n titleKey?: string;\n icon?: string;\n order?: number;\n component?: Type<unknown>;\n template?: TemplateRef<{ user: IUser }>;\n collapsible?: boolean;\n collapsed?: boolean;\n editPermission?: string | ILogicNode;\n}\n\nexport interface IProfileFieldTemplateContext {\n field: IProfileExtraField;\n value: unknown;\n updateValue: (value: unknown) => void;\n}\n\nexport const PROFILE_FIELD_CONTEXT =\n new InjectionToken<IProfileFieldTemplateContext>('PROFILE_FIELD_CONTEXT');\n\nexport interface IProfileExtraField {\n key: string;\n label: string;\n labelKey?: string;\n type:\n | 'text'\n | 'number'\n | 'select'\n | 'checkbox'\n | 'textarea'\n | 'date'\n | 'template';\n placeholder?: string;\n placeholderKey?: string;\n editable?: boolean;\n required?: boolean;\n options?: Array<{ label: string; labelKey?: string; value: unknown }>;\n pattern?: RegExp;\n validationMessage?: string;\n validationMessageKey?: string;\n validationMessageParam?: Record<string, string | number>;\n order?: number;\n sectionKey?: string;\n template?: TemplateRef<IProfileFieldTemplateContext>;\n component?: Type<unknown>;\n injector?: Injector;\n}\n\nexport interface IProfileExtensionProvider {\n getExtraSections?(): IProfileExtraSection[];\n getExtraFields?(): IProfileExtraField[];\n getExtraFieldValues?(userId: string): Observable<Record<string, unknown>>;\n saveExtraFieldValues?(\n userId: string,\n data: Record<string, unknown>,\n ): Observable<void>;\n validateExtraFields?(data: Record<string, unknown>): string | null;\n}\n\nexport const AUTH_PROFILE_EXTENSION =\n new InjectionToken<IProfileExtensionProvider>('AUTH_PROFILE_EXTENSION');\n\nexport interface IUserFormFieldTemplateContext {\n field: IUserFormExtraField;\n value: unknown;\n updateValue: (value: unknown) => void;\n}\n\nexport const USER_FORM_FIELD_CONTEXT =\n new InjectionToken<IUserFormFieldTemplateContext>('USER_FORM_FIELD_CONTEXT');\n\nexport interface IUserFormExtraField {\n key: string;\n label: string;\n labelKey?: string;\n type:\n | 'text'\n | 'number'\n | 'select'\n | 'checkbox'\n | 'textarea'\n | 'date'\n | 'template';\n placeholder?: string;\n placeholderKey?: string;\n required?: boolean;\n options?: Array<{ label: string; labelKey?: string; value: unknown }>;\n pattern?: RegExp;\n validationMessage?: string;\n validationMessageKey?: string;\n validationMessageParam?: Record<string, string | number>;\n order?: number;\n template?: TemplateRef<IUserFormFieldTemplateContext>;\n component?: Type<unknown>;\n injector?: Injector;\n}\n\nexport interface IUserFormExtensionProvider {\n getExtraFields?(): IUserFormExtraField[];\n getExtraFieldValues?(userId: string): Observable<Record<string, unknown>>;\n saveExtraFieldValues?(\n userId: string,\n data: Record<string, unknown>,\n ): Observable<void>;\n validateExtraFields?(data: Record<string, unknown>): string | null;\n}\n\nexport const AUTH_USER_FORM_EXTENSION =\n new InjectionToken<IUserFormExtensionProvider>('AUTH_USER_FORM_EXTENSION');\n\nexport type UserDetailViewMode = 'dialog' | 'sidebar' | 'page';\n\nexport interface IUserDetailViewConfig {\n viewMode: UserDetailViewMode;\n allowEdit?: boolean;\n width?: string;\n component?: Type<unknown>;\n tabs?: Array<{\n key: string;\n label: string;\n labelKey?: string;\n icon?: string;\n component?: Type<unknown>;\n template?: TemplateRef<{ user: IUser }>;\n }>;\n}\n\nexport const AUTH_USER_DETAIL_CONFIG =\n new InjectionToken<IUserDetailViewConfig>('AUTH_USER_DETAIL_CONFIG');\n\nconst PASSWORD_SPECIAL_CHAR_PATTERN = /[!@#$%^&*()_+\\-=[\\]{};':\"\\\\|,.<>/?~`]/;\n\nexport const DEFAULT_PASSWORD_VALIDATION = {\n minLength: 8,\n maxLength: 128,\n requireUppercase: true,\n requireLowercase: true,\n requireNumbers: true,\n requireSpecialChars: true,\n} as const satisfies IPasswordValidationConfig;\n\nexport function resolvePasswordValidation(\n config?: IPasswordValidationConfig | null,\n): IPasswordValidationConfig {\n const overrides = Object.fromEntries(\n Object.entries(config ?? {}).filter(([, value]) => value !== undefined),\n );\n return { ...DEFAULT_PASSWORD_VALIDATION, ...overrides };\n}\n\nexport function validatePassword(\n password: string,\n config: IPasswordValidationConfig = DEFAULT_PASSWORD_VALIDATION,\n): string | null {\n const rules = resolvePasswordValidation(config);\n const fail = (key: string): string => rules.messageKey ?? rules.message ?? key;\n\n if (password.length < (rules.minLength ?? 0)) {\n return fail('auth.validation.password.min.length');\n }\n if (rules.maxLength && password.length > rules.maxLength) {\n return fail('auth.validation.password.max.length');\n }\n\n if (rules.pattern) {\n return rules.pattern.test(password) ? null : fail('auth.validation.password.pattern');\n }\n if (rules.requireUppercase && !/[A-Z]/.test(password)) {\n return fail('auth.validation.password.require.uppercase');\n }\n if (rules.requireLowercase && !/[a-z]/.test(password)) {\n return fail('auth.validation.password.require.lowercase');\n }\n if (rules.requireNumbers && !/\\d/.test(password)) {\n return fail('auth.validation.password.require.number');\n }\n if (rules.requireSpecialChars && !PASSWORD_SPECIAL_CHAR_PATTERN.test(password)) {\n return fail('auth.validation.password.require.special');\n }\n\n return null;\n}\n\nexport function validateEmail(\n email: string,\n config?: IEmailValidationConfig,\n): string | null {\n const pattern = config?.pattern ?? /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n if (pattern.test(email)) return null;\n return config?.messageKey ?? config?.message ?? 'shared.invalid.email';\n}\n","import { inject, Service } from '@angular/core';\nimport { TranslateService } from '@flusys/ng-shared';\nimport {\n AUTH_VALIDATION_CONFIG,\n DEFAULT_PASSWORD_VALIDATION,\n resolvePasswordValidation,\n validatePassword,\n} from '../providers/auth-extension.providers';\n\n@Service()\nexport class PasswordPolicyService {\n private readonly config = inject(AUTH_VALIDATION_CONFIG, { optional: true });\n private readonly translateAdapter = inject(TranslateService, { optional: true });\n\n private readonly rules = resolvePasswordValidation(this.config?.password);\n readonly minLength = this.rules.minLength ?? DEFAULT_PASSWORD_VALIDATION.minLength;\n private readonly maxLength = this.rules.maxLength ?? DEFAULT_PASSWORD_VALIDATION.maxLength;\n\n validate(password: string): string | null {\n if (!password) return null;\n const key = validatePassword(password, this.rules);\n if (!key) return null;\n const params = { min: this.minLength, max: this.maxLength, ...this.rules.messageParam };\n return this.translateAdapter?.translate(key, params) ?? key;\n }\n}\n","import { inject, Service } from '@angular/core';\nimport { TranslateService } from '@flusys/ng-shared';\nimport { AUTH_VALIDATION_CONFIG, validateEmail } from '../providers/auth-extension.providers';\n\n@Service()\nexport class EmailPolicyService {\n private readonly config = inject(AUTH_VALIDATION_CONFIG, { optional: true })?.email;\n private readonly translateAdapter = inject(TranslateService, { optional: true });\n\n validate(email: string): string | null {\n if (!email) return null;\n const key = validateEmail(email, this.config);\n if (!key) return null;\n return this.translateAdapter?.translate(key, this.config?.messageParam) ?? key;\n }\n}\n","import { Service } from '@angular/core';\nimport {\n ApiResourceService,\n IFilterData,\n IListResponse,\n ISingleResponse,\n IUserBasicInfo,\n} from '@flusys/ng-shared';\nimport { Observable } from 'rxjs';\nimport {\n ICreateUserRequest,\n IUpdateUserRequest,\n IUser,\n} from '../interfaces/user.interface';\n\n/**\n * User API Service\n * Signal-based service for user CRUD operations\n */\n@Service()\nexport class UserApiService extends ApiResourceService<\n ICreateUserRequest | IUpdateUserRequest,\n IUser\n> {\n constructor() {\n super('users', 'administration');\n }\n\n updateProfile(data: IUpdateUserRequest): Observable<ISingleResponse<IUser>> {\n return this.http.post<ISingleResponse<IUser>>(\n `${this.baseUrl}/profile`,\n data,\n );\n }\n\n lookup(\n filter: IFilterData,\n search = '',\n ): Observable<IListResponse<IUserBasicInfo>> {\n const params = search ? { q: search } : undefined;\n return this.http.post<IListResponse<IUserBasicInfo>>(\n `${this.baseUrl}/lookup`,\n filter,\n params ? { params } : undefined,\n );\n }\n}\n","import { HttpClient } from '@angular/common/http';\nimport { inject, Service } from '@angular/core';\nimport { APP_CONFIG, getServiceUrl, IAppConfig } from '@flusys/ng-core';\nimport { IMessageResponse, ISingleResponse } from '@flusys/ng-shared';\nimport { Observable } from 'rxjs';\nimport {\n IAssignUserBranchRequest,\n IAssignUserCompanyRequest,\n IBranchPermittedUser,\n ICompanyPermittedUser,\n IUserBranchPermission,\n IUserCompanyPermission,\n} from '../interfaces/user-permission.interface';\n\n/**\n * User Permission API Service\n * Handles user-company and user-branch permission assignments.\n * Endpoint: POST /administration/permissions/*\n */\n@Service()\nexport class UserPermissionApiService {\n private readonly appConfig = inject<IAppConfig>(APP_CONFIG);\n private readonly http = inject(HttpClient);\n private readonly baseUrl = `${getServiceUrl(this.appConfig, 'administration')}/permissions`;\n\n // Company Permissions\n assignUserCompanies(data: IAssignUserCompanyRequest): Observable<IMessageResponse> {\n return this.http.post<IMessageResponse>(`${this.baseUrl}/user-company/assign`, data);\n }\n\n assignUserToCompany(userId: string, companyId: string): Observable<IMessageResponse> {\n return this.assignUserCompanies({ userId, items: [{ targetId: companyId, isAdd: true }] });\n }\n\n revokeUserFromCompany(userId: string, companyId: string): Observable<IMessageResponse> {\n return this.assignUserCompanies({ userId, items: [{ targetId: companyId, isAdd: false }] });\n }\n\n getUserCompanies(userId: string): Observable<ISingleResponse<IUserCompanyPermission[]>> {\n return this.http.post<ISingleResponse<IUserCompanyPermission[]>>(`${this.baseUrl}/get-user-company`, { userId });\n }\n\n // Branch Permissions\n assignUserBranches(data: IAssignUserBranchRequest): Observable<IMessageResponse> {\n return this.http.post<IMessageResponse>(`${this.baseUrl}/user-branch/assign`, data);\n }\n\n assignUserToBranch(userId: string, branchId: string): Observable<IMessageResponse> {\n return this.assignUserBranches({ userId, items: [{ targetId: branchId, isAdd: true }] });\n }\n\n revokeUserFromBranch(userId: string, branchId: string): Observable<IMessageResponse> {\n return this.assignUserBranches({ userId, items: [{ targetId: branchId, isAdd: false }] });\n }\n\n getUserBranches(userId: string, companyId?: string): Observable<ISingleResponse<IUserBranchPermission[]>> {\n return this.http.post<ISingleResponse<IUserBranchPermission[]>>(`${this.baseUrl}/get-user-branch`, {\n userId,\n ...(companyId && { companyId }),\n });\n }\n\n // Reverse Lookups (target -> users)\n\n getCompanyUsers(companyId: string): Observable<ISingleResponse<ICompanyPermittedUser[]>> {\n return this.http.post<ISingleResponse<ICompanyPermittedUser[]>>(`${this.baseUrl}/get-company-users`, {\n companyId,\n });\n }\n\n getBranchUsers(branchId: string): Observable<ISingleResponse<IBranchPermittedUser[]>> {\n return this.http.post<ISingleResponse<IBranchPermittedUser[]>>(`${this.baseUrl}/get-branch-users`, {\n branchId,\n });\n }\n}\n","import { inject } from '@angular/core';\nimport { CanActivateFn, Router, UrlTree } from '@angular/router';\nimport { APP_CONFIG } from '@flusys/ng-core';\nimport { Observable, of } from 'rxjs';\nimport { catchError, map } from 'rxjs/operators';\nimport { AUTH_ENDPOINTS } from '../constants/auth-endpoints.const';\nimport { AuthInitService } from '../services/auth-init.service';\nimport { AuthStateService } from '../services/auth-state.service';\n\nfunction isValidReturnUrl(url: unknown): url is string {\n if (typeof url !== 'string' || !url) return false;\n return url.startsWith('/') && !url.includes('://') && !url.startsWith('//');\n}\n\n/** Protects routes requiring authentication */\nexport const authGuard: CanActivateFn = (_route, state) => {\n const authState = inject(AuthStateService);\n const router = inject(Router);\n const appConfig = inject(APP_CONFIG);\n\n if (!authState.isAuthenticated()) {\n return router.createUrlTree([AUTH_ENDPOINTS.LOGIN], { queryParams: { returnUrl: state.url } });\n }\n\n if (appConfig.enableCompanyFeature) {\n if (authState.requiresCompanySelection() || !authState.company()) {\n return router.createUrlTree([AUTH_ENDPOINTS.LOGIN], { queryParams: { returnUrl: state.url } });\n }\n }\n\n return true;\n};\n\n/** Protects auth routes from authenticated users, restores session first */\nexport const guestGuard: CanActivateFn = (route): boolean | UrlTree | Observable<boolean | UrlTree> => {\n const authState = inject(AuthStateService);\n const authInit = inject(AuthInitService);\n const router = inject(Router);\n const appConfig = inject(APP_CONFIG);\n\n const checkAndRedirect = (): boolean | UrlTree => {\n if (authState.requiresCompanySelection()) return true;\n\n if (authState.isAuthenticated()) {\n if (appConfig.enableCompanyFeature && !authState.company()) return true;\n const returnUrl = route.queryParams['returnUrl'];\n return router.createUrlTree([isValidReturnUrl(returnUrl) ? returnUrl : '/']);\n }\n\n return true;\n };\n\n if (authInit.initialized()) return checkAndRedirect();\n\n return authInit.initialize().pipe(\n map(() => checkAndRedirect()),\n catchError(() => of(true)),\n );\n};\n\n/** Protects routes requiring company feature to be enabled */\nexport const companyFeatureGuard: CanActivateFn = () => {\n const router = inject(Router);\n const appConfig = inject(APP_CONFIG);\n\n if (!appConfig.enableCompanyFeature) return router.createUrlTree(['/']);\n return true;\n};\n\n/** Protects routes requiring email feature to be enabled */\nexport const emailFeatureGuard: CanActivateFn = () => {\n const router = inject(Router);\n const appConfig = inject(APP_CONFIG);\n\n if (!appConfig.services.email?.enabled) return router.createUrlTree([AUTH_ENDPOINTS.LOGIN]);\n return true;\n};\n\n/** Protects routes requiring sign-up feature to be enabled */\nexport const signUpFeatureGuard: CanActivateFn = () => {\n const router = inject(Router);\n const appConfig = inject(APP_CONFIG);\n\n if (appConfig.enableSignUp === false) return router.createUrlTree([AUTH_ENDPOINTS.LOGIN]);\n return true;\n};\n","import { HttpEvent, HttpHandlerFn, HttpRequest } from '@angular/common/http';\nimport { inject } from '@angular/core';\nimport { APP_CONFIG } from '@flusys/ng-core';\nimport { CookieService } from '@flusys/ng-shared';\nimport { Observable } from 'rxjs';\nimport { AUTH_ENDPOINTS, isEndpoint } from '../constants/auth-endpoints.const';\nimport { AuthStateService } from '../services/auth-state.service';\n\n/** Endpoints that need withCredentials for cookie handling */\nconst COOKIE_ENDPOINTS = [\n AUTH_ENDPOINTS.LOGIN,\n AUTH_ENDPOINTS.LOGOUT,\n AUTH_ENDPOINTS.REFRESH,\n AUTH_ENDPOINTS.REGISTER,\n AUTH_ENDPOINTS.SELECT,\n AUTH_ENDPOINTS.SWITCH_COMPANY,\n AUTH_ENDPOINTS.VERIFY_EMAIL,\n AUTH_ENDPOINTS.SOCIAL_CALLBACK,\n] as const;\n\n/**\n * Auth Interceptor - Adds auth headers and cookie credentials to requests\n */\nexport function authInterceptor(\n req: HttpRequest<unknown>,\n next: HttpHandlerFn,\n): Observable<HttpEvent<unknown>> {\n const authState = inject(AuthStateService);\n const cookieService = inject(CookieService);\n const appConfig = inject(APP_CONFIG);\n\n const headers: Record<string, string> = {};\n\n // Add tenant header if multi-tenant mode\n if (appConfig.multiTenant.enabled) {\n const tenantId = authState.tenantId();\n if (tenantId) {\n headers[appConfig.multiTenant.tenantHeader] = tenantId;\n }\n }\n\n // Add Bearer token if available\n const token = authState.accessToken();\n if (token) {\n headers['Authorization'] = `Bearer ${token}`;\n }\n\n // Check if this endpoint needs withCredentials for cookies\n const needsCredentials = COOKIE_ENDPOINTS.some((ep) => isEndpoint(req.url, ep));\n\n if (needsCredentials) {\n headers['cookie'] = cookieService.get();\n return next(req.clone({ withCredentials: true, setHeaders: headers }));\n }\n\n if (Object.keys(headers).length > 0) {\n return next(req.clone({ setHeaders: headers }));\n }\n\n return next(req);\n}\n","import { isPlatformBrowser } from '@angular/common';\nimport {\n HttpErrorResponse,\n HttpEvent,\n HttpHandlerFn,\n HttpRequest,\n} from '@angular/common/http';\nimport { inject, PLATFORM_ID } from '@angular/core';\nimport { TranslateService } from '@flusys/ng-shared';\nimport { MessageService } from '@flusys/ng-ui';\nimport {\n catchError,\n filter,\n Observable,\n switchMap,\n take,\n throwError,\n} from 'rxjs';\nimport { AUTH_ENDPOINTS, isEndpoint } from '../constants/auth-endpoints.const';\nimport { AuthApiService } from '../services/auth-api.service';\nimport { AuthStateService } from '../services/auth-state.service';\nimport { TokenRefreshStateService } from '../services/token-refresh-state.service';\n\n/** Token Refresh Interceptor - Proactive and reactive token refresh with request queuing */\nexport function tokenRefreshInterceptor(\n req: HttpRequest<unknown>,\n next: HttpHandlerFn,\n): Observable<HttpEvent<unknown>> {\n const authState = inject(AuthStateService);\n const authApi = inject(AuthApiService);\n const messageService = inject(MessageService);\n const platformId = inject(PLATFORM_ID);\n const isBrowser = isPlatformBrowser(platformId);\n const refreshState = inject(TokenRefreshStateService);\n const translateAdapter = inject(TranslateService, { optional: true });\n const t = (key: string) => translateAdapter?.translate(key) ?? key;\n\n // Skip refresh for these endpoints to prevent infinite loops\n const isRefreshRequest = isEndpoint(req.url, AUTH_ENDPOINTS.REFRESH);\n const isLoginRequest = isEndpoint(req.url, AUTH_ENDPOINTS.LOGIN);\n const isSelectRequest = isEndpoint(req.url, AUTH_ENDPOINTS.SELECT);\n const isRegisterRequest = isEndpoint(req.url, AUTH_ENDPOINTS.REGISTER);\n const isSocialCallbackRequest = isEndpoint(\n req.url,\n AUTH_ENDPOINTS.SOCIAL_CALLBACK,\n );\n\n // Don't intercept auth-related endpoints\n if (\n isRefreshRequest ||\n isLoginRequest ||\n isSelectRequest ||\n isRegisterRequest ||\n isSocialCallbackRequest\n ) {\n return next(req);\n }\n\n // PROACTIVE REFRESH: Check if token is expired or expiring soon\n if (authState.isTokenExpired() && authState.tokenExpiresAt() !== null) {\n // Token is expired/expiring - refresh proactively before request\n return handleTokenRefresh(\n req,\n next,\n authState,\n authApi,\n messageService,\n isBrowser,\n refreshState,\n t,\n );\n }\n\n // Token is valid - proceed with request, handle 401 reactively\n return next(req).pipe(\n catchError((error: HttpErrorResponse) => {\n // Only handle 401 errors\n if (error.status !== 401) {\n return throwError(() => error);\n }\n\n // Handle 401 by refreshing token\n return handleTokenRefresh(\n req,\n next,\n authState,\n authApi,\n messageService,\n isBrowser,\n refreshState,\n t,\n );\n }),\n );\n}\n\nfunction handleTokenRefresh(\n req: HttpRequest<unknown>,\n next: HttpHandlerFn,\n authState: AuthStateService,\n authApi: AuthApiService,\n messageService: MessageService,\n isBrowser: boolean,\n refreshState: TokenRefreshStateService,\n t: (key: string) => string,\n): Observable<HttpEvent<unknown>> {\n if (refreshState.isRefreshing()) {\n return refreshState.refreshTokenSubject$.pipe(\n filter((token) => token !== null),\n take(1),\n switchMap((token) =>\n next(req.clone({ setHeaders: { Authorization: `Bearer ${token}` } })),\n ),\n );\n }\n\n refreshState.startRefresh();\n\n return authApi.refresh().pipe(\n switchMap((response) => {\n const newToken = response.data!.accessToken;\n authState.setAccessToken(newToken);\n refreshState.completeRefresh(newToken);\n return next(\n req.clone({ setHeaders: { Authorization: `Bearer ${newToken}` } }),\n );\n }),\n catchError((refreshError) => {\n refreshState.failRefresh();\n return handleRefreshFailure(\n authState,\n messageService,\n isBrowser,\n refreshError,\n t,\n );\n }),\n );\n}\n\nfunction handleRefreshFailure(\n authState: AuthStateService,\n messageService: MessageService,\n isBrowser: boolean,\n error: HttpErrorResponse,\n t: (key: string) => string,\n): Observable<never> {\n if (isBrowser) {\n const detailKey = error?.error?.messageKey;\n messageService.add({\n severity: 'error',\n summary: t('auth.session.expired.title'),\n detail: t(detailKey),\n });\n }\n authState.resetState();\n authState.navigateToLogin();\n\n return throwError(() => error);\n}\n","export const AUTH_MESSAGES: Record<string, string> = {\n // AUTH_MESSAGES (API keys)\n 'auth.login.success': 'Login successful',\n 'auth.login.requires.selection':\n 'Please select a company and branch to continue',\n 'auth.login.invalid.credentials': 'Invalid email or password',\n 'auth.login.email.not.verified': 'Please verify your email before logging in',\n 'auth.login.account.deactivated': 'Your account has been deactivated',\n 'auth.logout.success': 'Logged out successfully',\n 'auth.register.success': 'Account created successfully',\n 'auth.register.failed': 'Registration failed. Please try again.',\n 'auth.refresh.success': 'Token refreshed successfully',\n 'auth.me.success': 'User info retrieved successfully',\n 'auth.select.success': 'Company selected successfully',\n 'auth.switch.company.success': 'Company switched successfully',\n 'auth.register.email.exists': 'Email already exists',\n 'auth.register.account.deleted':\n 'This account has been permanently deleted. Please contact your system administrator.',\n 'auth.register.company.already.assigned': 'Company already assigned',\n 'auth.password.change.success': 'Password changed successfully',\n 'auth.password.change.invalid.current': 'Current password is incorrect',\n 'auth.password.change.current.required': 'Current password is required',\n 'auth.password.reset.email.sent': 'Password reset email sent',\n 'auth.password.reset.success': 'Password reset successfully',\n 'auth.token.too.large': 'Refresh token too large (≈{{size}} bytes)',\n 'auth.company.list.success': 'User companies retrieved successfully',\n 'auth.company.not.found': 'Company not found',\n 'auth.company.required': 'Company is required',\n 'auth.company.feature.not.enabled':\n 'This feature is not enabled for your company',\n 'auth.branch.list.success': 'Company branches retrieved successfully',\n 'auth.branch.no.access': 'No access to this branch',\n 'auth.branch.not.found': 'Branch not found',\n 'auth.email.not.configured': 'Email service is not configured',\n 'auth.email.send.failed': 'Failed to send email',\n 'auth.session.invalid': 'Invalid session. Please login again.',\n 'auth.session.not.available': 'Session not available',\n 'auth.profile.access.denied': 'Access to profile denied',\n 'auth.profile.sections.not.supported': 'Profile sections not supported',\n 'auth.logout.service.unavailable': 'Logout service unavailable',\n 'auth.password.reset.token.expired': 'Password reset token has expired',\n 'auth.password.reset.token.used':\n 'Password reset token has already been used',\n\n // EMAIL_VERIFICATION_MESSAGES (API keys)\n 'email.verification.sent': 'Verification email sent',\n 'email.verification.success': 'Email verified successfully',\n 'email.verification.token.invalid': 'Invalid verification token',\n 'email.verification.token.expired': 'Verification token has expired',\n 'email.verification.not.enabled': 'Email verification is not enabled',\n 'email.verification.resend.success': 'Verification email resent successfully',\n\n // User CRUD messages (API keys)\n 'user.create.success': 'User created successfully',\n 'user.create.many.success': '{{count}} users created successfully',\n 'user.get.success': 'User retrieved successfully',\n 'user.get.by.ids.success': 'Users retrieved successfully by Ids',\n 'user.update.success': 'User updated successfully',\n 'user.update.many.success': '{{count}} users updated successfully',\n 'user.get.by.filter.success': 'Users retrieved successfully by filter',\n 'user.get.all.success': 'Users retrieved successfully',\n 'user.delete.success': 'User deleted successfully',\n 'user.restore.success': 'User restored successfully',\n 'user.not.found': 'User not found',\n 'user.profile.update.success': 'Profile updated successfully',\n 'user.profile.extras.success': 'Profile extras retrieved successfully',\n 'user.profile.sections.success': 'Profile sections retrieved successfully',\n 'user.profile.section.data.success':\n 'Profile section data retrieved successfully',\n 'user.profile.section.update.success': 'Profile section updated successfully',\n 'user.profile.completion.success':\n 'Profile completion retrieved successfully',\n 'user.email.verify.success': 'Email verified successfully',\n 'user.phone.verify.success': 'Phone verified successfully',\n 'user.status.update.success': 'User status updated successfully',\n 'user.lookup.success': 'Users retrieved successfully',\n\n // Company CRUD messages (API keys)\n 'company.create.success': 'Company created successfully',\n 'company.create.many.success': '{{count}} companies created successfully',\n 'company.get.success': 'Company retrieved successfully',\n 'company.get.by.ids.success': 'Companies retrieved successfully by Ids',\n 'company.get.by.filter.success': 'Companies retrieved successfully by filter',\n 'company.update.success': 'Company updated successfully',\n 'company.update.many.success': '{{count}} companies updated successfully',\n 'company.get.all.success': 'Companies retrieved successfully',\n 'company.delete.success': 'Company deleted successfully',\n 'company.restore.success': 'Company restored successfully',\n 'company.readonly.delete.forbidden': 'Cannot delete readonly company(ies): {{names}}',\n\n // Branch CRUD messages (API keys)\n 'branch.create.success': 'Branch created successfully',\n 'branch.create.many.success': '{{count}} branches created successfully',\n 'branch.get.success': 'Branch retrieved successfully',\n 'branch.get.by.ids.success': 'Branches retrieved successfully by Ids',\n 'branch.get.by.filter.success': 'Branches retrieved successfully by filter',\n 'branch.update.success': 'Branch updated successfully',\n 'branch.update.many.success': '{{count}} branches updated successfully',\n 'branch.get.all.success': 'Branches retrieved successfully',\n 'branch.delete.success': 'Branch deleted successfully',\n 'branch.restore.success': 'Branch restored successfully',\n 'branch.readonly.delete.forbidden': 'Cannot delete readonly branch(es): {{names}}',\n 'branch.invalid.parent': 'Parent branch must belong to the same company',\n 'branch.circular.parent': 'A branch cannot be moved under itself or its descendants',\n\n // USER_PERMISSION_MESSAGES (API keys)\n 'user.permission.company.list.success':\n 'User companies retrieved successfully',\n 'user.permission.branch.list.success': 'User branches retrieved successfully',\n 'user.permission.batch.success':\n 'Processed {{added}} additions and {{removed}} removals',\n 'user.permission.already.assigned': 'User already assigned to this {{type}}',\n 'user.permission.not.found': '{{type}} permission not found',\n\n // === UI KEYS — AUTH DOMAIN (AUTH_ROUTES: login, register, forgot-password, reset-password, verify-email) ===\n\n // pages/login/login-page.component.ts\n 'auth.login.welcome': 'Welcome!',\n 'auth.login.welcome.back': 'Welcome back, {{name}}!',\n 'auth.login.sign.in.to.continue': 'Sign in to continue to your account',\n 'auth.email.label': 'Email Address',\n 'auth.email.placeholder': 'Enter email address',\n 'auth.password.label': 'Password',\n 'auth.password.placeholder': 'Enter your password',\n 'auth.field.remember.me': 'Remember me',\n 'auth.password.forgot': 'Forgot Password?',\n 'auth.login.sign.in': 'Sign In',\n 'auth.login.no.account': \"Don't have an account?\",\n 'auth.login.sign.up': 'Sign Up',\n 'auth.login.verify.email.message': 'Please verify your email !',\n 'auth.verify.resend': 'Resend Verification Email',\n 'auth.login.back.to.sign.in': 'Back to Sign In',\n 'auth.login.select.company': 'Select Company',\n 'auth.login.select.company.message':\n 'Please select a company and branch to continue',\n 'auth.login.select.company.option': 'Select a company',\n 'auth.login.branch.label': 'Branch',\n 'auth.login.select.branch.option': 'Select a branch',\n 'auth.login.remember.selection': 'Remember my selection',\n 'auth.validation.password.min.length':\n 'Password must be at least {{min}} characters',\n 'auth.validation.email.required': 'Email is required',\n 'auth.validation.password.required': 'Password is required',\n 'auth.validation.password.max.length': 'Password must be at most {{max}} characters',\n 'auth.validation.password.pattern': 'Password does not meet requirements',\n 'auth.validation.password.require.uppercase':\n 'Password must contain at least one uppercase letter',\n 'auth.validation.password.require.lowercase':\n 'Password must contain at least one lowercase letter',\n 'auth.validation.password.require.number':\n 'Password must contain at least one number',\n 'auth.validation.password.require.special':\n 'Password must contain at least one special character',\n 'auth.validation.company.required': 'Please select a company',\n 'auth.validation.branch.required': 'Please select a branch',\n 'auth.login.title': 'Login',\n 'auth.session.expired': 'Your session has expired. Please login again.',\n\n // pages/forgot-password/forgot-password-page.component.ts\n 'auth.forgot.password.title': 'Forgot Password',\n 'auth.forgot.password.subtitle':\n 'Enter your email address and we will send you a reset link.',\n 'auth.forgot.password.send.reset.link': 'Send Reset Link',\n 'auth.forgot.password.remember.password': 'Remember your password?',\n 'auth.forgot.password.check.email': 'Check Your Email',\n 'auth.forgot.password.email.sent.to':\n 'We sent a password reset link to {{email}}',\n 'auth.forgot.password.didnt.receive': \"Didn't receive the email?\",\n 'auth.forgot.password.try.again': 'Try Again',\n\n // pages/register/register-page.component.ts\n 'auth.register.create.account': 'Create Account',\n 'auth.register.subtitle': 'Fill in your details to create an account.',\n 'auth.register.signup.disabled': 'New account registration is currently disabled.',\n 'auth.register.full.name': 'Full Name',\n 'auth.register.name.placeholder': 'Enter your full name',\n 'auth.phone.label': 'Phone Number',\n 'auth.phone.placeholder': 'Enter phone number',\n 'auth.register.confirm.password': 'Confirm Password',\n 'auth.register.confirm.password.placeholder': 'Confirm your password',\n 'auth.register.passwords.do.not.match': 'Passwords do not match',\n 'auth.register.company.details': 'Company Details',\n 'auth.register.join.default.company': 'Join Default Company',\n 'auth.register.join.or.create.company': 'Join or Create Company',\n 'auth.register.create.new.company': 'Create New Company',\n 'auth.register.company.code': 'Company Code',\n 'auth.register.preconfigured.company': 'Pre-configured Company',\n 'auth.register.company.code.placeholder': 'Enter company code',\n 'auth.register.enter.company.code': 'Enter company code to join',\n 'auth.register.branch.code': 'Branch Code',\n 'auth.register.preconfigured.branch': 'Pre-configured Branch',\n 'auth.register.branch.code.placeholder': 'Enter branch code',\n 'auth.register.company.name': 'Company Name',\n 'auth.register.company.name.placeholder': 'Enter company name',\n 'auth.address.label': 'Address',\n 'auth.address.placeholder': 'Enter address',\n 'auth.register.already.have.account': 'Already have an account?',\n 'auth.validation.name.min.length': 'Name must be at least {{min}} characters',\n 'auth.validation.confirm.password.required': 'Please confirm your password',\n\n // pages/verify-email/verify-email-page.component.ts\n 'auth.verify.email.verifying': 'Verifying Email',\n 'auth.verify.email.please.wait':\n 'Please wait while we verify your email address...',\n 'auth.verify.email.success': 'Email Verified',\n 'auth.verify.email.success.message':\n 'Your email has been verified successfully. You can now login to your account.',\n 'auth.verify.email.failed': 'Verification Failed',\n 'auth.verify.email.invalid.link':\n 'This verification link is invalid or has expired.',\n 'auth.verify.email.resend.email': 'Resend Verification Email',\n 'auth.verify.email.resend.title': 'Resend Verification',\n 'auth.verify.email.resend.subtitle':\n 'Enter your email to receive a new verification link.',\n 'auth.verify.email.resend': 'Resend Email',\n 'auth.verify.email.sent': 'Verification email sent. Please check your inbox.',\n\n // pages/reset-password/reset-password-page.component.ts\n 'auth.reset.password.title': 'Reset Password',\n 'auth.reset.password.subtitle': 'Enter your new password below.',\n 'auth.reset.password.new.password': 'New Password',\n 'auth.reset.password.new.password.placeholder': 'Enter your new password',\n 'auth.reset.password.confirm.password': 'Confirm Password',\n 'auth.reset.password.confirm.password.placeholder':\n 'Confirm your new password',\n 'auth.reset.password.reset.password': 'Reset Password',\n 'auth.reset.password.success': 'Password Reset Successful',\n 'auth.reset.password.success.message':\n 'Your password has been reset successfully. You can now login with your new password.',\n 'auth.reset.password.invalid.link': 'Invalid Reset Link',\n 'auth.reset.password.invalid.link.message':\n 'This password reset link is invalid or has expired.',\n 'auth.reset.password.request.new.link': 'Request New Link',\n\n // === UI KEYS — PROFILE DOMAIN (PROFILE_ROUTES) ===\n\n // pages/profile/profile-page.component.ts\n 'profile.title': 'Profile',\n 'profile.subtitle': 'Manage your account settings and preferences.',\n 'profile.storage.not.enabled':\n 'Profile picture upload is not available. Storage service is not configured.',\n 'profile.name.label': 'Full Name',\n 'profile.name.placeholder': 'Enter your full name',\n 'profile.phone.label': 'Phone',\n 'profile.phone.placeholder': 'Enter phone number',\n 'profile.additional.info': 'Additional Information',\n 'profile.employment.info': 'Employment Information',\n 'profile.managed.by.admin': 'This field is managed by an administrator.',\n 'profile.security': 'Security',\n 'profile.current.password': 'Current Password',\n 'profile.current.password.placeholder': 'Enter current password',\n 'profile.new.password': 'New Password',\n 'profile.confirm.password': 'Confirm New Password',\n 'profile.confirm.password.placeholder': 'Confirm new password',\n 'profile.change.password': 'Change Password',\n 'profile.company.branch': 'Company & Branch',\n 'profile.branch.label': 'Branch',\n 'profile.actions.label': 'Direct Actions',\n 'profile.actions.none.assigned': 'No actions assigned',\n 'profile.permissions.label': 'My Permissions',\n 'profile.roles.label': 'Roles',\n 'profile.roles.none.assigned': 'No roles assigned',\n\n // === UI KEYS — ADMINISTRATIVE DOMAIN (ADMINISTRATION_ROUTES: users, company, branch) ===\n\n // components/user-company-permission-dialog.component.ts\n 'administrative.permission.manage.company': 'Manage Company Permissions',\n 'administrative.permission.user': 'User',\n 'administrative.company.no.companies': 'No companies found',\n\n // components/user-branch-permission-dialog.component.ts\n 'administrative.permission.manage.branch': 'Manage Branch Permissions',\n 'administrative.company.select': 'Select Company',\n 'administrative.permission.no.company':\n 'This user has no company permissions assigned.',\n 'administrative.permission.assign.company.first':\n 'Assign company permissions first before managing branch access.',\n 'administrative.permission.select.company.for.branches':\n 'Please select a company to view branches.',\n 'administrative.branch.no.branches': 'No branches found',\n\n // pages/administration/administration-page.component.ts\n 'administrative.title': 'Administration',\n 'administrative.subtitle': 'Manage users, companies, and branches',\n 'administrative.user.title': 'Users',\n 'administrative.company.title': 'Companies',\n 'administrative.branch.title': 'Branches',\n\n // pages/branch/branch-form.component.ts\n 'administrative.branch.new': 'New Branch',\n 'administrative.branch.edit': 'Edit Branch',\n 'administrative.branch.name': 'Branch Name',\n 'administrative.branch.name.placeholder': 'Enter branch name',\n 'administrative.branch.slug': 'Branch Slug',\n 'administrative.branch.slug.placeholder': 'Enter branch slug',\n 'administrative.branch.parent': 'Parent Branch',\n 'administrative.branch.select.parent': 'Select parent branch (optional)',\n 'administrative.email.label': 'Email',\n 'administrative.email.placeholder': 'Enter email address',\n 'administrative.phone.label': 'Phone',\n 'administrative.phone.placeholder': 'Enter phone number',\n 'administrative.address.label': 'Address',\n 'administrative.address.placeholder': 'Enter address',\n 'administrative.branch.slug.required': 'Branch slug is required',\n\n // pages/branch/branch-list.component.ts\n 'administrative.branch.add': 'Add Branch',\n 'administrative.branch.add.child': 'Add Sub-branch',\n 'administrative.branch.confirm.delete.with.children':\n 'Are you sure you want to delete \"{{name}}\"? Its {{count}} sub-branch(es) will also be deleted.',\n 'administrative.branch.select.company.first': 'Please select a company first',\n 'administrative.branch.delete.title': 'Delete Branch',\n\n // pages/company/company-form.component.ts\n 'administrative.company.edit': 'Edit Company',\n 'administrative.company.new': 'New Company',\n 'administrative.company.name': 'Company Name',\n 'administrative.company.name.placeholder': 'Enter company name',\n 'administrative.company.slug': 'Company Slug',\n 'administrative.company.slug.placeholder': 'Enter company slug',\n 'administrative.company.website': 'Website',\n 'administrative.company.website.placeholder': 'Enter website URL',\n 'administrative.company.slug.required': 'Company slug is required',\n\n // pages/company/company-list.component.ts\n 'administrative.company.add': 'Add Company',\n 'administrative.branch.view.branches': 'View Branches',\n 'administrative.company.delete.title': 'Delete Company',\n\n // components/company-permitted-users-dialog.component.ts, components/branch-permitted-users-dialog.component.ts\n 'administrative.permission.view.users': 'View Users',\n 'administrative.permission.no.users': 'No users found',\n 'administrative.permission.remove': 'Remove Access',\n 'administrative.permission.remove.confirm':\n 'Remove access for {{name}}?',\n\n // pages/users/user-form.component.ts\n 'administrative.user.edit': 'Edit User',\n 'administrative.user.new': 'New User',\n 'administrative.user.name': 'Name',\n 'administrative.user.name.placeholder': 'Enter full name',\n 'administrative.user.password': 'Password',\n 'administrative.user.password.optional': '(leave blank to keep current)',\n 'administrative.user.password.placeholder': 'Enter password',\n 'administrative.user.email.verified': 'Email Verified',\n 'administrative.user.auto.assign.to':\n 'New user will be automatically assigned to',\n\n // pages/users/user-list.component.ts\n 'administrative.user.add': 'Add User',\n 'administrative.permission.company.permissions': 'Company Permissions',\n 'administrative.permission.branch.permissions': 'Branch Permissions',\n 'administrative.user.no.users': 'No users found',\n 'administrative.user.details': 'User Details',\n 'administrative.user.delete.title': 'Delete User',\n\n // Social sign-in API keys\n 'auth.social.providers.success': 'Social providers retrieved successfully',\n 'auth.social.authorize.success': 'Authorization URL generated successfully',\n 'auth.social.login.success': 'Signed in successfully',\n 'auth.social.provider.disabled': 'Social sign-in with {{provider}} is not enabled',\n 'auth.social.provider.not.configured':\n 'Social sign-in with {{provider}} is missing its client credentials',\n 'auth.social.state.invalid':\n 'Social sign-in session is invalid or has expired',\n 'auth.social.redirect.uri.mismatch':\n 'Redirect URI does not match the one the sign-in started with',\n 'auth.social.exchange.failed': 'Social sign-in with {{provider}} failed',\n 'auth.social.profile.incomplete':\n '{{provider}} did not return an account identifier',\n 'auth.social.account.not.linked':\n 'No account is linked to this {{provider}} profile',\n 'auth.social.company.required':\n 'No account is linked to this {{provider}} profile. Please sign up manually and join or create a company first, then social sign-in will work.',\n 'auth.social.email.required': '{{provider}} did not share an email address',\n 'auth.social.email.not.verified':\n '{{provider}} has not verified this email address',\n 'auth.social.account.deleted':\n 'This account has been permanently deleted. Please contact your system administrator.',\n\n // components/social-login-buttons.component.ts\n 'auth.social.continue.with': 'or continue with',\n 'auth.social.provider.google': 'Google',\n 'auth.social.provider.facebook': 'Facebook',\n 'auth.social.provider.linkedin': 'LinkedIn',\n 'auth.social.provider.microsoft': 'Microsoft',\n\n // pages/social-callback/social-callback-page.component.ts\n 'auth.social.signing.in': 'Signing you in...',\n 'auth.social.failed': 'Social sign-in failed',\n\n // pages/social-config/social-config-page.component.ts (API keys)\n 'social.config.provider.already.configured':\n 'Social provider \"{{provider}}\" is already configured',\n 'social.config.credentials.required':\n 'Client ID and client secret are required for {{provider}}',\n 'social.config.title': 'Social Config',\n 'social.config.subtitle':\n 'Enable the providers users may sign in with, and hold their credentials',\n 'social.config.redirect.uri': 'Redirect URI',\n 'social.config.client.id': 'Client ID',\n 'social.config.client.secret': 'Client Secret',\n 'social.config.client.secret.unchanged': 'Unchanged - leave blank to keep the saved secret',\n 'social.config.tenant.id': 'Directory (tenant) ID',\n 'social.config.tenant.id.example': 'common',\n 'social.config.scopes': 'Scopes',\n 'social.config.scopes.placeholder': 'Leave blank to use the provider defaults',\n 'social.config.save.success': 'Social sign-in settings saved',\n 'social.config.provider.hint.google': 'Google Cloud console, OAuth 2.0 client ID',\n 'social.config.provider.hint.facebook': 'Meta for Developers, Facebook Login app',\n 'social.config.provider.hint.linkedin': 'LinkedIn developers, Sign In with LinkedIn',\n 'social.config.provider.hint.microsoft': 'Microsoft Entra ID, app registration',\n};\n","import { inject } from '@angular/core';\nimport { Routes } from '@angular/router';\nimport { APP_CONFIG, isCompanyFeatureEnabled } from '@flusys/ng-core';\nimport {\n BRANCH_PERMISSIONS,\n COMPANY_PERMISSIONS,\n PermissionValidatorService,\n permissionGuard,\n resolveTranslationModule,\n SHARED_MESSAGES,\n SOCIAL_AUTH_CONFIG_PERMISSIONS,\n USER_PERMISSIONS,\n} from '@flusys/ng-shared';\nimport { AUTH_MESSAGES } from '../constants/messages';\nimport {\n authGuard,\n companyFeatureGuard,\n emailFeatureGuard,\n guestGuard,\n signUpFeatureGuard,\n} from '../guards/auth.guard';\n\n/**\n * Resolves which administration tab the current user should land on when\n * navigating to the bare `/administration` route. Mirrors the tab\n * visibility order in AdministrationPageComponent.visibleTabs so the\n * redirect never points at a tab the user can't actually see.\n */\nfunction resolveAdministrationDefaultTab(): string {\n const permissionValidator = inject(PermissionValidatorService);\n const companyFeatureEnabled = isCompanyFeatureEnabled(inject(APP_CONFIG));\n\n if (permissionValidator.hasPermission(USER_PERMISSIONS.READ)) {\n return 'users';\n }\n\n if (\n companyFeatureEnabled &&\n permissionValidator.hasPermission(COMPANY_PERMISSIONS.READ)\n ) {\n return 'company';\n }\n\n if (\n companyFeatureEnabled &&\n permissionValidator.hasPermission(BRANCH_PERMISSIONS.READ)\n ) {\n return 'branch';\n }\n\n if (permissionValidator.hasPermission(SOCIAL_AUTH_CONFIG_PERMISSIONS.READ)) {\n return 'social-config';\n }\n\n return 'users';\n}\n\n/**\n * Auth Routes Configuration\n * Public routes for authentication (login, register, etc.)\n *\n * Note: Company selection is now handled within the login page as a multi-step flow.\n */\nexport const AUTH_ROUTES: Routes = [\n {\n path: '',\n resolve: {\n translations: resolveTranslationModule({\n modules: ['auth', 'shared'],\n fallbackMessages: { ...AUTH_MESSAGES, ...SHARED_MESSAGES },\n }),\n },\n children: [\n {\n path: 'login',\n loadComponent: () =>\n import('../pages/login/login-page.component').then(\n (m) => m.LoginPageComponent,\n ),\n canActivate: [guestGuard],\n },\n {\n path: 'register',\n loadComponent: () =>\n import('../pages/register/register-page.component').then(\n (m) => m.RegisterPageComponent,\n ),\n canActivate: [signUpFeatureGuard, guestGuard],\n },\n {\n path: 'forgot-password',\n loadComponent: () =>\n import('../pages/forgot-password/forgot-password-page.component').then(\n (m) => m.ForgotPasswordPageComponent,\n ),\n canActivate: [emailFeatureGuard, guestGuard],\n },\n {\n path: 'reset-password',\n loadComponent: () =>\n import('../pages/reset-password/reset-password-page.component').then(\n (m) => m.ResetPasswordPageComponent,\n ),\n canActivate: [emailFeatureGuard, guestGuard],\n },\n {\n path: 'social/callback',\n loadComponent: () =>\n import('../pages/social-callback/social-callback-page.component').then(\n (m) => m.SocialCallbackPageComponent,\n ),\n },\n {\n path: 'verify-email',\n loadComponent: () =>\n import('../pages/verify-email/verify-email-page.component').then(\n (m) => m.VerifyEmailPageComponent,\n ),\n canActivate: [emailFeatureGuard],\n },\n {\n path: '',\n redirectTo: 'login',\n pathMatch: 'full',\n },\n ],\n },\n];\n\n/**\n * Administration Routes Configuration\n * Protected routes for company, branch, user management and permissions\n * Uses tabbed interface - all under /administration with child routes\n */\nexport const ADMINISTRATION_ROUTES: Routes = [\n {\n path: '',\n canActivate: [authGuard],\n resolve: {\n translations: resolveTranslationModule({\n modules: ['auth', 'administrative'],\n fallbackMessages: { ...AUTH_MESSAGES, ...SHARED_MESSAGES },\n }),\n },\n loadComponent: () =>\n import('../pages/administration/administration-page.component').then(\n (m) => m.AdministrationPageComponent,\n ),\n children: [\n // Users tab\n {\n path: 'users',\n canActivate: [permissionGuard(USER_PERMISSIONS.READ)],\n children: [\n {\n path: '',\n loadComponent: () =>\n import('../pages/users/user-list.component').then(\n (m) => m.UserListComponent,\n ),\n },\n {\n path: 'new',\n loadComponent: () =>\n import('../pages/users/user-form.component').then(\n (m) => m.UserFormComponent,\n ),\n },\n {\n path: ':id',\n loadComponent: () =>\n import('../pages/users/user-form.component').then(\n (m) => m.UserFormComponent,\n ),\n },\n ],\n },\n // Company tab (requires company feature)\n {\n path: 'company',\n canActivate: [\n companyFeatureGuard,\n permissionGuard(COMPANY_PERMISSIONS.READ),\n ],\n children: [\n {\n path: '',\n loadComponent: () =>\n import('../pages/company/company-list.component').then(\n (m) => m.CompanyListComponent,\n ),\n },\n {\n path: 'new',\n loadComponent: () =>\n import('../pages/company/company-form.component').then(\n (m) => m.CompanyFormComponent,\n ),\n },\n {\n path: ':id',\n loadComponent: () =>\n import('../pages/company/company-form.component').then(\n (m) => m.CompanyFormComponent,\n ),\n },\n ],\n },\n // Branch tab (requires company feature)\n {\n path: 'branch',\n canActivate: [\n companyFeatureGuard,\n permissionGuard(BRANCH_PERMISSIONS.READ),\n ],\n children: [\n {\n path: '',\n loadComponent: () =>\n import('../pages/branch/branch-list.component').then(\n (m) => m.BranchListComponent,\n ),\n },\n {\n path: 'new',\n loadComponent: () =>\n import('../pages/branch/branch-form.component').then(\n (m) => m.BranchFormComponent,\n ),\n },\n {\n path: ':id',\n loadComponent: () =>\n import('../pages/branch/branch-form.component').then(\n (m) => m.BranchFormComponent,\n ),\n },\n ],\n },\n // Social sign-in provider credentials tab\n {\n path: 'social-config',\n canActivate: [permissionGuard(SOCIAL_AUTH_CONFIG_PERMISSIONS.READ)],\n loadComponent: () =>\n import('../pages/social-config/social-config-page.component').then(\n (m) => m.SocialConfigPageComponent,\n ),\n },\n // Default redirect to the first tab the user has permission to see\n {\n path: '',\n redirectTo: () => resolveAdministrationDefaultTab(),\n pathMatch: 'full',\n },\n ],\n },\n];\n\n/**\n * Profile Routes Configuration\n * Protected route for user profile management\n */\nexport const PROFILE_ROUTES: Routes = [\n {\n path: '',\n canActivate: [authGuard],\n resolve: {\n translations: resolveTranslationModule({\n modules: ['auth', 'profile'],\n fallbackMessages: { ...AUTH_MESSAGES, ...SHARED_MESSAGES },\n }),\n },\n loadComponent: () =>\n import('../pages/profile/profile-page.component').then(\n (m) => m.ProfilePageComponent,\n ),\n },\n];\n","import { computed, inject, Signal, Service } from '@angular/core';\nimport { Router } from '@angular/router';\nimport {\n IBranchInfo,\n ICompanyInfo,\n ILayoutAuthApi,\n ILayoutAuthState,\n IUserInfo as ILayoutUserInfo,\n} from '@flusys/ng-layout';\nimport { Observable } from 'rxjs';\nimport { map, tap } from 'rxjs/operators';\nimport { AuthApiService } from '../services/auth-api.service';\nimport { AuthStateService } from '../services/auth-state.service';\n\n/**\n * Auth Layout Provider Adapters\n *\n * Implements provider interfaces from ng-layout using ng-auth services.\n * Bridges auth state and API to layout components.\n *\n * @example\n * // In app.config.ts\n * import { provideAuthLayoutIntegration } from '@flusys/ng-auth';\n * providers: [...provideAuthLayoutIntegration()]\n */\n\n// =============================================================================\n// Layout State Adapter\n// =============================================================================\n\n@Service()\nexport class AuthLayoutStateAdapter implements ILayoutAuthState {\n private readonly authState = inject(AuthStateService);\n\n readonly currentCompanyInfo: Signal<ICompanyInfo | null> = computed(() => {\n const company = this.authState.company();\n if (company) {\n return {\n id: company.id,\n name: company.name,\n slug: company.slug ?? '',\n imageId: company.logoId ?? '',\n };\n }\n return null;\n });\n\n readonly currentBranchInfo: Signal<IBranchInfo | null> = computed(() => {\n const branch = this.authState.branch();\n if (branch) {\n return {\n id: branch.id,\n name: branch.name,\n slug: branch.slug ?? '',\n imageId: branch.logoId ?? undefined,\n };\n }\n return null;\n });\n\n readonly loginUserData: Signal<ILayoutUserInfo | null> = computed(() => {\n const user = this.authState.user();\n if (user) {\n return {\n id: user.id,\n name: user.name ?? this.authState.userName(),\n email: user.email,\n };\n }\n return null;\n });\n}\n\n// =============================================================================\n// Layout API Adapter\n// =============================================================================\n\n@Service()\nexport class AuthLayoutApiAdapter implements ILayoutAuthApi {\n private readonly authApi = inject(AuthApiService);\n private readonly authState = inject(AuthStateService);\n private readonly router = inject(Router);\n\n logOut(): Observable<unknown> {\n return this.authApi.logout().pipe(\n tap(() => {\n this.authState.resetState();\n }),\n );\n }\n\n navigateLogin(withUrl?: boolean): void {\n if (withUrl) {\n const currentUrl = this.router.url;\n this.authState.navigateToLogin(currentUrl);\n } else {\n this.authState.navigateToLogin();\n }\n }\n\n switchCompany(companyId: string, branchId: string): Observable<unknown> {\n return this.authApi.switchCompany({ companyId, branchId }).pipe(\n tap(() => {\n window.location.reload();\n }),\n );\n }\n\n getMyCompanies(): Observable<ICompanyInfo[]> {\n return this.authApi.getCompanies().pipe(\n map((response) =>\n (response.data || []).map((company) => ({\n id: company.id,\n name: company.name,\n slug: company.slug ?? '',\n imageId: company.logoId ?? '',\n })),\n ),\n );\n }\n\n getMyCompanyBranches(companyId: string): Observable<IBranchInfo[]> {\n return this.authApi.getCompanyBranches(companyId).pipe(\n map((response) =>\n (response.data || []).map((branch) => ({\n id: branch.id,\n name: branch.name,\n slug: branch.slug ?? '',\n imageId: branch.logoId ?? undefined,\n parentId: branch.parentId ?? null,\n serial: branch.serial ?? null,\n displayParentId: branch.displayParentId,\n })),\n ),\n );\n }\n}\n","import { inject, Signal, Service } from '@angular/core';\nimport {\n IAuthStateProvider,\n IBranchBasicInfo,\n ICompanyApiProvider,\n ICompanyBasicInfo,\n IListResponse,\n ISingleResponse,\n IUserBasicInfo,\n IUserBranchPermission,\n IUserCompanyInfo,\n IUserPermissionProvider,\n IUserProvider,\n} from '@flusys/ng-shared';\nimport { from, map, Observable } from 'rxjs';\nimport { AuthInitService } from '../services/auth-init.service';\nimport { AuthStateService } from '../services/auth-state.service';\nimport { BranchApiService } from '../services/branch-api.service';\nimport { CompanyApiService } from '../services/company-api.service';\nimport { UserApiService } from '../services/user-api.service';\nimport { UserPermissionApiService } from '../services/user-permission-api.service';\n\n/**\n * Auth Shared Provider Adapters\n *\n * Implements provider interfaces from ng-shared using ng-auth services.\n * Allows IAM, Storage, and Form-Builder packages to access auth data\n * without depending on ng-auth directly.\n *\n * @example\n * // In app.config.ts\n * import { provideAuthProviders } from '@flusys/ng-auth';\n * providers: [...provideAuthProviders()]\n */\n\nfunction emptyListResponse<T>(): IListResponse<T> {\n return {\n success: true,\n message: '',\n data: [],\n meta: { total: 0, page: 0, pageSize: 0, count: 0 },\n };\n}\n\nfunction mapListResponse<TSource, TTarget>(\n response: IListResponse<TSource>,\n mapper: (item: TSource) => TTarget,\n): IListResponse<TTarget> {\n return {\n success: response.success,\n message: response.message,\n messageKey: response.messageKey,\n messageVariables: response.messageVariables,\n data: (response.data ?? []).map(mapper),\n meta: response.meta,\n };\n}\n\n// =============================================================================\n// User Provider Adapter\n// =============================================================================\n\n@Service({ autoProvided: false })\nexport class AuthUserProviderAdapter implements IUserProvider {\n private readonly userApi = inject(UserApiService);\n\n getUsers(filter?: {\n page?: number;\n pageSize?: number;\n search?: string;\n isActive?: boolean;\n [key: string]: unknown;\n }): Observable<IListResponse<IUserBasicInfo>> {\n const { search, page, pageSize, isActive, ...extraFilters } = filter || {};\n\n const apiFilter = {\n pagination: {\n currentPage: page ?? 0,\n pageSize: pageSize ?? 50,\n },\n filter: {\n ...(isActive !== undefined && { isActive }),\n\n // ✅ include all additional dynamic filters\n ...Object.fromEntries(\n Object.entries(extraFilters).filter(\n ([_, v]) => v !== undefined && v !== null,\n ),\n ),\n },\n sort: { name: 'ASC' as const },\n };\n\n return this.userApi.lookup(apiFilter, search ?? '').pipe(\n map((response) =>\n mapListResponse(response, (user) => ({\n id: user.id,\n name: user.name || user.email,\n email: user.email,\n })),\n ),\n );\n }\n\n getUsersByIds(ids: string[]): Observable<IListResponse<IUserBasicInfo>> {\n if (ids.length === 0) {\n return from(Promise.resolve(emptyListResponse<IUserBasicInfo>()));\n }\n\n return from(this.userApi.findByIds(ids, ['id', 'name', 'email'])).pipe(\n map((response) =>\n mapListResponse(response, (user) => ({\n id: user.id,\n name: user.name || user.email,\n email: user.email,\n })),\n ),\n );\n }\n}\n\n// =============================================================================\n// Company API Provider Adapter\n// =============================================================================\n\n@Service({ autoProvided: false })\nexport class AuthCompanyApiProviderAdapter implements ICompanyApiProvider {\n private readonly companyApi = inject(CompanyApiService);\n private readonly branchApi = inject(BranchApiService);\n\n getCompanies(filter?: {\n page?: number;\n pageSize?: number;\n search?: string;\n }): Observable<IListResponse<ICompanyBasicInfo>> {\n const apiFilter = {\n pagination: {\n currentPage: filter?.page ?? 0,\n pageSize: filter?.pageSize ?? 50,\n },\n sort: { name: 'ASC' as const },\n };\n\n return from(this.companyApi.getAll(apiFilter, filter?.search ?? '')).pipe(\n map((response) =>\n mapListResponse(response, (company) => ({\n id: company.id,\n name: company.name,\n slug: company.slug,\n })),\n ),\n );\n }\n\n getCompaniesByIds(ids: string[]): Observable<IListResponse<ICompanyBasicInfo>> {\n if (ids.length === 0) {\n return from(Promise.resolve(emptyListResponse<ICompanyBasicInfo>()));\n }\n\n return from(this.companyApi.findByIds(ids, ['id', 'name', 'slug'])).pipe(\n map((response) =>\n mapListResponse(response, (company) => ({\n id: company.id,\n name: company.name,\n slug: company.slug,\n })),\n ),\n );\n }\n\n getBranchesByIds(ids: string[]): Observable<IListResponse<IBranchBasicInfo>> {\n if (ids.length === 0) {\n return from(Promise.resolve(emptyListResponse<IBranchBasicInfo>()));\n }\n\n return from(this.branchApi.findByIds(ids, ['id', 'name'])).pipe(\n map((response) =>\n mapListResponse(response, (branch) => ({ id: branch.id, name: branch.name })),\n ),\n );\n }\n}\n\n// =============================================================================\n// User Permission Provider Adapter\n// =============================================================================\n\n@Service({ autoProvided: false })\nexport class AuthUserPermissionProviderAdapter implements IUserPermissionProvider {\n private readonly userPermissionApi = inject(UserPermissionApiService);\n\n getUserBranchPermissions(\n userId: string,\n companyId?: string,\n ): Observable<ISingleResponse<IUserBranchPermission[]>> {\n return this.userPermissionApi.getUserBranches(userId, companyId);\n }\n\n getUserCompanyPermissions(userId: string): Observable<ISingleResponse<IUserCompanyInfo[]>> {\n return this.userPermissionApi.getUserCompanies(userId).pipe(\n map((response) => ({\n ...response,\n data: (response.data ?? []).map((c) => ({ id: c.companyId, name: c.companyName })),\n })),\n );\n }\n}\n\n// =============================================================================\n// Auth State Provider Adapter\n// =============================================================================\n\n@Service({ autoProvided: false })\nexport class AuthStateProviderAdapter implements IAuthStateProvider {\n private readonly authState = inject(AuthStateService);\n private readonly authInit = inject(AuthInitService);\n\n get isAuthenticated(): Signal<boolean> {\n return this.authState.isAuthenticated;\n }\n\n initialize(): Observable<void> {\n return this.authInit.initialize().pipe(map(() => undefined));\n }\n}\n","import { Provider } from '@angular/core';\nimport { LAYOUT_AUTH_API, LAYOUT_AUTH_STATE } from '@flusys/ng-layout';\nimport { AuthLayoutApiAdapter, AuthLayoutStateAdapter } from '../adapters/auth-layout-providers.adapter';\n\n/** Provides auth integration for ng-layout */\nexport function provideAuthLayoutIntegration(): Provider[] {\n return [\n { provide: LAYOUT_AUTH_STATE, useClass: AuthLayoutStateAdapter },\n { provide: LAYOUT_AUTH_API, useClass: AuthLayoutApiAdapter },\n ];\n}\n","import { Provider } from '@angular/core';\nimport { AUTH_STATE_PROVIDER, COMPANY_API_PROVIDER, USER_PERMISSION_PROVIDER, USER_PROVIDER } from '@flusys/ng-shared';\nimport {\n AuthCompanyApiProviderAdapter,\n AuthStateProviderAdapter,\n AuthUserPermissionProviderAdapter,\n AuthUserProviderAdapter,\n} from '../adapters/auth-shared-providers.adapter';\n\n/** Provides auth implementations for ng-shared provider interfaces */\nexport function provideAuthProviders(): Provider[] {\n return [\n { provide: USER_PROVIDER, useClass: AuthUserProviderAdapter },\n { provide: COMPANY_API_PROVIDER, useClass: AuthCompanyApiProviderAdapter },\n { provide: USER_PERMISSION_PROVIDER, useClass: AuthUserPermissionProviderAdapter },\n { provide: AUTH_STATE_PROVIDER, useClass: AuthStateProviderAdapter },\n ];\n}\n","import { Component, effect, inject, input, output, signal } from '@angular/core';\nimport {\n ConfirmationService,\n DialogComponent,\n FButtonDirective,\n MessageService,\n ProgressSpinnerComponent,\n TooltipDirective,\n UiIconComponent,\n} from '@flusys/ng-ui';\nimport {\n HasPermissionDirective,\n TranslatePipe,\n TranslateService,\n USER_PERMISSIONS,\n} from '@flusys/ng-shared';\nimport { firstValueFrom } from 'rxjs';\nimport { IBranch } from '../interfaces/branch.interface';\nimport { IBranchPermittedUser } from '../interfaces/user-permission.interface';\nimport { UserPermissionApiService } from '../services/user-permission-api.service';\n\n/**\n * Read-only viewer for users permitted against a branch, with a remove-only\n * action per user. Assigning new users stays on the user-centric permission\n * flow (`UserBranchPermissionDialogComponent`) — this dialog intentionally\n * has no \"add\" affordance.\n */\n@Component({\n selector: 'lib-branch-permitted-users-dialog',\n imports: [\n DialogComponent,\n FButtonDirective,\n ProgressSpinnerComponent,\n TooltipDirective,\n UiIconComponent,\n HasPermissionDirective,\n TranslatePipe,\n ],\n template: `\n <f-dialog\n [visible]=\"visible()\"\n [modal]=\"true\"\n [closable]=\"true\"\n [breakpoints]=\"{ '960px': '90vw', '640px': '95vw' }\"\n [style]=\"{ width: '50vw', maxWidth: '600px' }\"\n [header]=\"'administrative.permission.view.users' | translate\"\n (onHide)=\"onClose()\"\n >\n <div class=\"mb-4\">\n <p class=\"text-sm text-muted-color\">\n {{ 'administrative.branch.title' | translate }}:\n <strong>{{ branch()?.name }}</strong>\n </p>\n </div>\n\n @if (isLoading()) {\n <div class=\"flex justify-center items-center py-8\">\n <f-progressspinner />\n </div>\n } @else {\n <div class=\"flex flex-col gap-3\">\n @for (user of users(); track user.id) {\n <div\n class=\"flex items-center justify-between p-3 border border-surface rounded\"\n >\n <div>\n <div class=\"font-semibold\">{{ user.userName }}</div>\n <div class=\"text-sm text-muted-color\">{{ user.userEmail }}</div>\n </div>\n <button\n fButton\n *hasPermission=\"USER_PERMISSIONS.UPDATE\"\n [text]=\"true\"\n severity=\"danger\"\n size=\"small\"\n [disabled]=\"isRemoving()\"\n [fTooltip]=\"'shared.remove' | translate\"\n (click)=\"onRemove(user)\"\n >\n <ui-icon pButtonIcon name=\"trash\"></ui-icon>\n </button>\n </div>\n } @empty {\n <div class=\"text-center py-4 text-muted-color\">\n {{ 'administrative.permission.no.users' | translate }}\n </div>\n }\n </div>\n }\n\n <ng-template #footer>\n <button\n fButton\n severity=\"secondary\"\n [outlined]=\"true\"\n (click)=\"onClose()\"\n >\n <span pButtonLabel>{{ 'shared.close' | translate }}</span>\n </button>\n </ng-template>\n </f-dialog>\n `,\n})\nexport class BranchPermittedUsersDialogComponent {\n readonly USER_PERMISSIONS = USER_PERMISSIONS;\n\n private readonly permissionApi = inject(UserPermissionApiService);\n private readonly confirmationService = inject(ConfirmationService);\n private readonly messageService = inject(MessageService);\n private readonly translateAdapter = inject(TranslateService, {\n optional: true,\n });\n\n private t(key: string, params?: Record<string, unknown>): string {\n return this.translateAdapter?.translate(key, params) ?? key;\n }\n\n readonly visible = input.required<boolean>();\n readonly branch = input.required<IBranch | null>();\n readonly closed = output<void>();\n\n readonly isLoading = signal(false);\n readonly isRemoving = signal(false);\n readonly users = signal<IBranchPermittedUser[]>([]);\n\n constructor() {\n effect(() => {\n if (this.visible() && this.branch()) {\n this.loadUsers();\n }\n });\n }\n\n private async loadUsers(): Promise<void> {\n const branch = this.branch();\n if (!branch) return;\n\n this.isLoading.set(true);\n try {\n const response = await firstValueFrom(this.permissionApi.getBranchUsers(branch.id));\n this.users.set(response.data ?? []);\n } catch {\n // Error toast handled by global interceptor\n } finally {\n this.isLoading.set(false);\n }\n }\n\n onRemove(user: IBranchPermittedUser): void {\n const branch = this.branch();\n if (!branch) return;\n\n this.confirmationService.confirm({\n message: this.t('administrative.permission.remove.confirm', {\n name: user.userName,\n }),\n header: this.t('administrative.permission.remove'),\n icon: 'exclamation-triangle',\n acceptButtonStyleClass: 'p-button-danger',\n accept: async () => {\n this.isRemoving.set(true);\n try {\n const response = await firstValueFrom(\n this.permissionApi.revokeUserFromBranch(user.userId, branch.id),\n );\n\n if (response.success) {\n this.users.update((list) => list.filter((u) => u.id !== user.id));\n this.messageService.add({\n severity: 'success',\n summary: this.t('shared.success'),\n detail: response?.messageKey\n ? this.t(response.messageKey, response.messageVariables)\n : (response?.message ?? ''),\n });\n }\n } catch {\n // Error toast handled by global interceptor\n } finally {\n this.isRemoving.set(false);\n }\n },\n });\n }\n\n onClose(): void {\n this.closed.emit();\n }\n}\n","import { Component, effect, inject, input, output, signal } from '@angular/core';\nimport {\n ConfirmationService,\n DialogComponent,\n FButtonDirective,\n MessageService,\n ProgressSpinnerComponent,\n TooltipDirective,\n UiIconComponent,\n} from '@flusys/ng-ui';\nimport {\n HasPermissionDirective,\n TranslatePipe,\n TranslateService,\n USER_PERMISSIONS,\n} from '@flusys/ng-shared';\nimport { firstValueFrom } from 'rxjs';\nimport { ICompany } from '../interfaces/company.interface';\nimport { ICompanyPermittedUser } from '../interfaces/user-permission.interface';\nimport { UserPermissionApiService } from '../services/user-permission-api.service';\n\n/**\n * Read-only viewer for users permitted against a company, with a remove-only\n * action per user. Assigning new users stays on the user-centric permission\n * flow (`UserCompanyPermissionDialogComponent`) — this dialog intentionally\n * has no \"add\" affordance.\n */\n@Component({\n selector: 'lib-company-permitted-users-dialog',\n imports: [\n DialogComponent,\n FButtonDirective,\n ProgressSpinnerComponent,\n TooltipDirective,\n UiIconComponent,\n HasPermissionDirective,\n TranslatePipe,\n ],\n template: `\n <f-dialog\n [visible]=\"visible()\"\n [modal]=\"true\"\n [closable]=\"true\"\n [breakpoints]=\"{ '960px': '90vw', '640px': '95vw' }\"\n [style]=\"{ width: '50vw', maxWidth: '600px' }\"\n [header]=\"'administrative.permission.view.users' | translate\"\n (onHide)=\"onClose()\"\n >\n <div class=\"mb-4\">\n <p class=\"text-sm text-muted-color\">\n {{ 'administrative.company.title' | translate }}:\n <strong>{{ company()?.name }}</strong>\n </p>\n </div>\n\n @if (isLoading()) {\n <div class=\"flex justify-center items-center py-8\">\n <f-progressspinner />\n </div>\n } @else {\n <div class=\"flex flex-col gap-3\">\n @for (user of users(); track user.id) {\n <div\n class=\"flex items-center justify-between p-3 border border-surface rounded\"\n >\n <div>\n <div class=\"font-semibold\">{{ user.userName }}</div>\n <div class=\"text-sm text-muted-color\">{{ user.userEmail }}</div>\n </div>\n <button\n fButton\n *hasPermission=\"USER_PERMISSIONS.UPDATE\"\n [text]=\"true\"\n severity=\"danger\"\n size=\"small\"\n [disabled]=\"isRemoving()\"\n [fTooltip]=\"'shared.remove' | translate\"\n (click)=\"onRemove(user)\"\n >\n <ui-icon pButtonIcon name=\"trash\"></ui-icon>\n </button>\n </div>\n } @empty {\n <div class=\"text-center py-4 text-muted-color\">\n {{ 'administrative.permission.no.users' | translate }}\n </div>\n }\n </div>\n }\n\n <ng-template #footer>\n <button\n fButton\n severity=\"secondary\"\n [outlined]=\"true\"\n (click)=\"onClose()\"\n >\n <span pButtonLabel>{{ 'shared.close' | translate }}</span>\n </button>\n </ng-template>\n </f-dialog>\n `,\n})\nexport class CompanyPermittedUsersDialogComponent {\n readonly USER_PERMISSIONS = USER_PERMISSIONS;\n\n private readonly permissionApi = inject(UserPermissionApiService);\n private readonly confirmationService = inject(ConfirmationService);\n private readonly messageService = inject(MessageService);\n private readonly translateAdapter = inject(TranslateService, {\n optional: true,\n });\n\n private t(key: string, params?: Record<string, unknown>): string {\n return this.translateAdapter?.translate(key, params) ?? key;\n }\n\n readonly visible = input.required<boolean>();\n readonly company = input.required<ICompany | null>();\n readonly closed = output<void>();\n\n readonly isLoading = signal(false);\n readonly isRemoving = signal(false);\n readonly users = signal<ICompanyPermittedUser[]>([]);\n\n constructor() {\n effect(() => {\n if (this.visible() && this.company()) {\n this.loadUsers();\n }\n });\n }\n\n private async loadUsers(): Promise<void> {\n const company = this.company();\n if (!company) return;\n\n this.isLoading.set(true);\n try {\n const response = await firstValueFrom(this.permissionApi.getCompanyUsers(company.id));\n this.users.set(response.data ?? []);\n } catch {\n // Error toast handled by global interceptor\n } finally {\n this.isLoading.set(false);\n }\n }\n\n onRemove(user: ICompanyPermittedUser): void {\n const company = this.company();\n if (!company) return;\n\n this.confirmationService.confirm({\n message: this.t('administrative.permission.remove.confirm', {\n name: user.userName,\n }),\n header: this.t('administrative.permission.remove'),\n icon: 'exclamation-triangle',\n acceptButtonStyleClass: 'p-button-danger',\n accept: async () => {\n this.isRemoving.set(true);\n try {\n const response = await firstValueFrom(\n this.permissionApi.revokeUserFromCompany(user.userId, company.id),\n );\n\n if (response.success) {\n this.users.update((list) => list.filter((u) => u.id !== user.id));\n this.messageService.add({\n severity: 'success',\n summary: this.t('shared.success'),\n detail: response?.messageKey\n ? this.t(response.messageKey, response.messageVariables)\n : (response?.message ?? ''),\n });\n }\n } catch {\n // Error toast handled by global interceptor\n } finally {\n this.isRemoving.set(false);\n }\n },\n });\n }\n\n onClose(): void {\n this.closed.emit();\n }\n}\n","import {\n Component,\n DestroyRef,\n DOCUMENT,\n computed,\n inject,\n input,\n signal,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport {\n PlatformService,\n TranslatePipe,\n TranslateService,\n} from '@flusys/ng-shared';\nimport { FButtonDirective, MessageService } from '@flusys/ng-ui';\nimport { SocialProviderEnum } from '../enums/social-provider.enum';\nimport { ISocialProviderInfo } from '../interfaces/social-auth.interface';\nimport { SocialAuthApiService } from '../services/social-auth-api.service';\n\n@Component({\n selector: 'lib-social-login-buttons',\n imports: [FButtonDirective, TranslatePipe],\n template: `\n @if (providers().length) {\n <div class=\"mt-6\">\n <div class=\"flex items-center gap-3 mb-4\">\n <span class=\"flex-1 h-px bg-surface-200 dark:bg-surface-700\"></span>\n <span class=\"text-muted-color text-sm\">{{\n 'auth.social.continue.with' | translate\n }}</span>\n <span class=\"flex-1 h-px bg-surface-200 dark:bg-surface-700\"></span>\n </div>\n\n <div [class]=\"layoutClass()\">\n @for (info of providers(); track info.provider) {\n <button\n fButton\n type=\"button\"\n severity=\"secondary\"\n [outlined]=\"true\"\n [class]=\"showLabels() ? 'w-full' : 'shrink-0'\"\n [attr.aria-label]=\"\n showLabels()\n ? null\n : ('auth.social.provider.' + info.provider | translate)\n \"\n [attr.title]=\"\n showLabels()\n ? null\n : ('auth.social.provider.' + info.provider | translate)\n \"\n [disabled]=\"pendingProvider() !== null && pendingProvider() !== info.provider\"\n [loading]=\"pendingProvider() === info.provider\"\n (click)=\"onSelect(info.provider)\"\n >\n @if (pendingProvider() !== info.provider) {\n @switch (info.provider) {\n @case (providerEnum.GOOGLE) {\n <svg class=\"shrink-0\" width=\"18\" height=\"18\" viewBox=\"0 0 48 48\" aria-hidden=\"true\">\n <path fill=\"#EA4335\" d=\"M24 9.5c3.54 0 6.71 1.22 9.21 3.6l6.85-6.85C35.9 2.38 30.47 0 24 0 14.62 0 6.51 5.38 2.56 13.22l7.98 6.19C12.43 13.72 17.74 9.5 24 9.5z\" />\n <path fill=\"#4285F4\" d=\"M46.98 24.55c0-1.57-.15-3.09-.38-4.55H24v9.02h12.94c-.58 3-2.26 5.54-4.78 7.25l7.73 6c4.51-4.18 7.09-10.36 7.09-17.72z\" />\n <path fill=\"#FBBC05\" d=\"M10.53 28.59A14.5 14.5 0 0 1 9.77 24c0-1.6.29-3.14.76-4.59l-7.98-6.19A23.94 23.94 0 0 0 0 24c0 3.88.93 7.54 2.56 10.78l7.97-6.19z\" />\n <path fill=\"#34A853\" d=\"M24 48c6.48 0 11.93-2.13 15.89-5.81l-7.73-6c-2.15 1.45-4.92 2.3-8.16 2.3-6.26 0-11.57-4.22-13.47-9.91l-7.98 6.19C6.51 42.62 14.62 48 24 48z\" />\n </svg>\n }\n @case (providerEnum.FACEBOOK) {\n <svg class=\"shrink-0\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <path fill=\"#1877F2\" d=\"M24 12.07C24 5.4 18.63 0 12 0S0 5.4 0 12.07C0 18.1 4.39 23.1 10.13 24v-8.44H7.08v-3.49h3.05V9.41c0-3.02 1.79-4.69 4.53-4.69 1.31 0 2.69.24 2.69.24v2.96h-1.51c-1.49 0-1.96.93-1.96 1.88v2.25h3.33l-.53 3.49h-2.8V24C19.61 23.1 24 18.1 24 12.07z\" />\n </svg>\n }\n @case (providerEnum.LINKEDIN) {\n <svg class=\"shrink-0\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <path fill=\"#0A66C2\" d=\"M20.45 20.45h-3.56v-5.57c0-1.33-.03-3.04-1.85-3.04-1.86 0-2.14 1.45-2.14 2.94v5.67H9.35V9h3.41v1.56h.05a3.74 3.74 0 0 1 3.37-1.85c3.6 0 4.27 2.37 4.27 5.46v6.28zM5.34 7.43a2.06 2.06 0 1 1 0-4.13 2.06 2.06 0 0 1 0 4.13zM7.12 20.45H3.55V9h3.57v11.45zM22.22 0H1.77C.79 0 0 .78 0 1.73v20.54C0 23.22.79 24 1.77 24h20.45c.98 0 1.78-.78 1.78-1.73V1.73C24 .78 23.2 0 22.22 0z\" />\n </svg>\n }\n @case (providerEnum.MICROSOFT) {\n <svg class=\"shrink-0\" width=\"18\" height=\"18\" viewBox=\"0 0 23 23\" aria-hidden=\"true\">\n <path fill=\"#F25022\" d=\"M0 0h11v11H0z\" />\n <path fill=\"#7FBA00\" d=\"M12 0h11v11H12z\" />\n <path fill=\"#00A4EF\" d=\"M0 12h11v11H0z\" />\n <path fill=\"#FFB900\" d=\"M12 12h11v11H12z\" />\n </svg>\n }\n }\n }\n @if (showLabels()) {\n <span>{{\n 'auth.social.provider.' + info.provider | translate\n }}</span>\n }\n </button>\n }\n </div>\n </div>\n }\n `,\n})\nexport class SocialLoginButtonsComponent {\n private readonly destroyRef = inject(DestroyRef);\n private readonly socialApi = inject(SocialAuthApiService);\n private readonly messageService = inject(MessageService);\n private readonly platform = inject(PlatformService);\n private readonly document = inject(DOCUMENT);\n private readonly translateAdapter = inject(TranslateService, {\n optional: true,\n });\n\n readonly returnUrl = input<string>('');\n\n readonly providerEnum = SocialProviderEnum;\n\n private readonly _providers = signal<ISocialProviderInfo[]>([]);\n readonly providers = this._providers.asReadonly();\n\n private readonly _pendingProvider = signal<SocialProviderEnum | null>(null);\n readonly pendingProvider = this._pendingProvider.asReadonly();\n\n readonly showLabels = computed(() => this.providers().length <= 2);\n\n readonly layoutClass = computed(() => {\n switch (this.providers().length) {\n case 1:\n return 'grid grid-cols-1';\n case 2:\n return 'grid grid-cols-2 gap-3';\n default:\n return 'flex flex-wrap justify-center gap-3';\n }\n });\n\n constructor() {\n if (this.platform.isServer) return;\n\n this.socialApi\n .getProviders()\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe({\n next: (response) => this._providers.set(response.data ?? []),\n error: () => this._providers.set([]),\n });\n }\n\n onSelect(provider: SocialProviderEnum): void {\n this._pendingProvider.set(provider);\n this.socialApi.saveReturnUrl(this.returnUrl());\n\n this.socialApi\n .authorize(provider)\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe({\n next: (response) => {\n const url = response.data?.authorizationUrl;\n if (!url) {\n this._pendingProvider.set(null);\n return;\n }\n this.redirectTo(url);\n },\n error: (error) => {\n this._pendingProvider.set(null);\n const messageKey = error?.error?.messageKey;\n this.messageService.add({\n severity: 'error',\n summary: this.translate('auth.login.title'),\n detail: messageKey\n ? this.translate(messageKey, { provider })\n : error?.error?.message,\n });\n },\n });\n }\n\n protected redirectTo(url: string): void {\n this.document.location.assign(url);\n }\n\n private translate(\n key: string,\n vars?: Record<string, string | number>,\n ): string {\n return this.translateAdapter?.translate(key, vars) ?? key;\n }\n}\n","import {\n CheckboxComponent,\n DialogComponent,\n FButtonDirective,\n MessageService,\n ProgressSpinnerComponent,\n SelectComponent,\n UiIconComponent,\n} from '@flusys/ng-ui';\nimport {\n Component,\n computed,\n inject,\n input,\n output,\n resource,\n signal,\n} from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport {\n flattenBranchTree,\n getBranchPath,\n TranslatePipe,\n TranslateService,\n} from '@flusys/ng-shared';\nimport { firstValueFrom } from 'rxjs';\nimport { IBranch } from '../interfaces/branch.interface';\nimport { IUser } from '../interfaces/user.interface';\nimport { BranchApiService } from '../services/branch-api.service';\nimport { UserPermissionApiService } from '../services/user-permission-api.service';\n\ninterface BranchWithAssignment extends IBranch {\n isAssigned: boolean;\n}\n\n@Component({\n selector: 'lib-user-branch-permission-dialog',\n imports: [\n FormsModule,\n CheckboxComponent,\n DialogComponent,\n FButtonDirective,\n ProgressSpinnerComponent,\n SelectComponent,\n TranslatePipe,\n UiIconComponent,\n ],\n template: `\n <f-dialog\n [visible]=\"visible()\"\n [modal]=\"true\"\n [closable]=\"true\"\n [breakpoints]=\"{ '960px': '90vw', '640px': '95vw' }\"\n [style]=\"{ width: '50vw', maxWidth: '600px' }\"\n [header]=\"'administrative.permission.manage.branch' | translate\"\n (onHide)=\"onClose()\"\n >\n <div class=\"mb-4\">\n <p class=\"text-sm text-muted-color mb-3\">\n {{ 'administrative.permission.user' | translate }}:\n <strong>{{ user()?.name }}</strong> ({{ user()?.email }})\n </p>\n <div class=\"flex items-center gap-2\">\n <label class=\"text-sm font-medium min-w-[70px]\"\n >{{ 'shared.company' | translate }}:</label\n >\n <f-select\n [options]=\"companiesResource.value() ?? []\"\n [ngModel]=\"selectedCompanyId()\"\n (ngModelChange)=\"selectedCompanyId.set($event)\"\n optionLabel=\"name\"\n optionValue=\"id\"\n [placeholder]=\"'administrative.company.select' | translate\"\n styleClass=\"w-full\"\n [disabled]=\"isInitialLoading() || isSaving()\"\n />\n </div>\n </div>\n\n @if (isInitialLoading()) {\n <div class=\"flex justify-center items-center py-8\">\n <f-progressspinner />\n </div>\n } @else {\n <div class=\"flex flex-col gap-3\">\n @for (row of branchRows(); track row.branch.id) {\n @let branch = row.branch;\n <div\n class=\"flex items-center p-3 border border-surface rounded\"\n [style.margin-inline-start.rem]=\"row.depth * 1.5\"\n >\n @if (row.depth > 0) {\n <ui-icon\n name=\"corner-down-right\"\n class=\"text-muted-color me-2\"\n aria-hidden=\"true\"\n ></ui-icon>\n }\n <f-checkbox\n [ngModel]=\"branch.isAssigned\"\n [binary]=\"true\"\n [inputId]=\"'branch-' + branch.id\"\n [disabled]=\"isSaving()\"\n (onChange)=\"onBranchToggle(branch, $event.checked)\"\n />\n <label\n [for]=\"'branch-' + branch.id\"\n class=\"ml-3 flex-1 cursor-pointer\"\n >\n <div class=\"font-semibold\">{{ branch.name }}</div>\n @if (row.parentPath) {\n <span class=\"sr-only\" data-branch-path\n >{{ 'administrative.branch.parent' | translate }}:\n {{ row.parentPath }}</span\n >\n }\n <div class=\"text-sm text-muted-color\">{{ branch.slug }}</div>\n </label>\n </div>\n } @empty {\n <div class=\"text-center py-4 text-muted-color\">\n @if ((companiesResource.value() ?? []).length === 0) {\n {{ 'administrative.permission.no.company' | translate }}<br />\n <span class=\"text-xs\">{{\n 'administrative.permission.assign.company.first' | translate\n }}</span>\n } @else if (!selectedCompanyId()) {\n {{\n 'administrative.permission.select.company.for.branches'\n | translate\n }}\n } @else {\n {{ 'administrative.branch.no.branches' | translate }}\n }\n </div>\n }\n </div>\n }\n\n <ng-template #footer>\n <button\n fButton\n severity=\"secondary\"\n [outlined]=\"true\"\n (click)=\"onClose()\"\n [disabled]=\"isSaving()\"\n >\n <span pButtonLabel>{{ 'shared.close' | translate }}</span>\n </button>\n </ng-template>\n </f-dialog>\n `,\n})\nexport class UserBranchPermissionDialogComponent {\n private readonly branchApi = inject(BranchApiService);\n private readonly permissionApi = inject(UserPermissionApiService);\n private readonly messageService = inject(MessageService);\n private readonly translateAdapter = inject(TranslateService, {\n optional: true,\n });\n\n private t(key: string, params?: Record<string, unknown>): string {\n return this.translateAdapter?.translate(key, params) ?? key;\n }\n\n readonly visible = input.required<boolean>();\n readonly user = input.required<IUser | null>();\n readonly closed = output<void>();\n readonly permissionsChanged = output<void>();\n\n readonly isSaving = signal(false);\n readonly selectedCompanyId = signal<string | null>(null);\n\n readonly companiesResource = resource({\n params: () => {\n const user = this.user();\n if (!this.visible() || !user) return undefined;\n return { userId: user.id };\n },\n loader: async ({ params }) => {\n const response = await firstValueFrom(\n this.permissionApi.getUserCompanies(params!.userId),\n );\n this.selectedCompanyId.set(null);\n return (response.data ?? []).map((p) => ({\n id: p.companyId,\n name: p.companyName,\n }));\n },\n });\n\n readonly branchesResource = resource({\n params: () => {\n const user = this.user();\n const companyId = this.selectedCompanyId();\n if (!user || !companyId) return undefined;\n return { userId: user.id, companyId };\n },\n loader: async ({ params }) => {\n const [branchesResponse, assignedResponse] = await Promise.all([\n this.branchApi.getAll({\n pagination: { currentPage: 0, pageSize: 1000 },\n filter: { companyId: params!.companyId },\n select: [],\n sort: {},\n }),\n firstValueFrom(this.permissionApi.getUserBranches(params!.userId, params!.companyId)),\n ]);\n\n const assignedIds = new Set((assignedResponse.data ?? []).map((p) => p.branchId));\n\n return (branchesResponse.data ?? []).map((branch) => ({\n ...branch,\n isAssigned: assignedIds.has(branch.id),\n }));\n },\n });\n\n readonly branchRows = computed(() => {\n const branches = this.branchesResource.value() ?? [];\n return flattenBranchTree(branches).map((row) => ({\n ...row,\n parentPath: getBranchPath(branches, row.branch.parentId)\n .map((b) => b.name)\n .join(' / '),\n }));\n });\n\n readonly isInitialLoading = computed(\n () => this.branchesResource.isLoading() && !this.branchesResource.value(),\n );\n\n async onBranchToggle(\n branch: BranchWithAssignment,\n isAssigned: boolean,\n ): Promise<void> {\n const currentUser = this.user();\n if (!currentUser) return;\n\n this.isSaving.set(true);\n try {\n const response = await firstValueFrom(\n isAssigned\n ? this.permissionApi.assignUserToBranch(currentUser.id, branch.id)\n : this.permissionApi.revokeUserFromBranch(currentUser.id, branch.id),\n );\n if (response.success) {\n this.messageService.add({\n severity: 'success',\n summary: this.t('shared.success'),\n detail: response.messageKey\n ? this.t(response.messageKey, response.messageVariables)\n : (response.message ?? ''),\n });\n this.permissionsChanged.emit();\n this.branchesResource.reload();\n }\n } catch {\n } finally {\n this.isSaving.set(false);\n }\n }\n\n onClose(): void {\n this.closed.emit();\n }\n}\n","import {\n CheckboxComponent,\n DialogComponent,\n FButtonDirective,\n MessageService,\n ProgressSpinnerComponent,\n} from '@flusys/ng-ui';\nimport {\n Component,\n effect,\n inject,\n input,\n output,\n signal,\n} from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport {\n TranslatePipe,\n TranslateService,\n} from '@flusys/ng-shared';\nimport { firstValueFrom } from 'rxjs';\nimport { ICompany } from '../interfaces/company.interface';\nimport { IUser } from '../interfaces/user.interface';\nimport { CompanyApiService } from '../services/company-api.service';\nimport { UserPermissionApiService } from '../services/user-permission-api.service';\n\ninterface CompanyWithAssignment extends ICompany {\n isAssigned: boolean;\n}\n\n@Component({\n selector: 'lib-user-company-permission-dialog',\n imports: [\n FormsModule,\n CheckboxComponent,\n DialogComponent,\n FButtonDirective,\n ProgressSpinnerComponent,\n TranslatePipe,\n ],\n template: `\n <f-dialog\n [visible]=\"visible()\"\n [modal]=\"true\"\n [closable]=\"true\"\n [breakpoints]=\"{ '960px': '90vw', '640px': '95vw' }\"\n [style]=\"{ width: '50vw', maxWidth: '600px' }\"\n [header]=\"'administrative.permission.manage.company' | translate\"\n (onHide)=\"onClose()\"\n >\n <div class=\"mb-4\">\n <p class=\"text-sm text-muted-color\">\n {{ 'administrative.permission.user' | translate }}:\n <strong>{{ user()?.name }}</strong> ({{ user()?.email }})\n </p>\n </div>\n\n @if (isLoading()) {\n <div class=\"flex justify-center items-center py-8\">\n <f-progressspinner />\n </div>\n } @else {\n <div class=\"flex flex-col gap-3\">\n @for (company of companies(); track company.id) {\n <div class=\"flex items-center p-3 border border-surface rounded\">\n <f-checkbox\n [ngModel]=\"company.isAssigned\"\n [binary]=\"true\"\n [inputId]=\"'company-' + company.id\"\n [disabled]=\"isSaving()\"\n (onChange)=\"onCompanyToggle(company, $event.checked)\"\n />\n <label\n [for]=\"'company-' + company.id\"\n class=\"ml-3 flex-1 cursor-pointer\"\n >\n <div class=\"font-semibold\">{{ company.name }}</div>\n <div class=\"text-sm text-muted-color\">{{ company.slug }}</div>\n </label>\n </div>\n } @empty {\n <div class=\"text-center py-4 text-muted-color\">\n {{ 'administrative.company.no.companies' | translate }}\n </div>\n }\n </div>\n }\n\n <ng-template #footer>\n <button\n fButton\n severity=\"secondary\"\n [outlined]=\"true\"\n (click)=\"onClose()\"\n [disabled]=\"isSaving()\"\n >\n <span pButtonLabel>{{ 'shared.close' | translate }}</span>\n </button>\n </ng-template>\n </f-dialog>\n `,\n})\nexport class UserCompanyPermissionDialogComponent {\n private readonly companyApi = inject(CompanyApiService);\n private readonly permissionApi = inject(UserPermissionApiService);\n private readonly messageService = inject(MessageService);\n private readonly translateAdapter = inject(TranslateService, {\n optional: true,\n });\n\n private t(key: string, params?: Record<string, unknown>): string {\n return this.translateAdapter?.translate(key, params) ?? key;\n }\n\n readonly visible = input.required<boolean>();\n readonly user = input.required<IUser | null>();\n readonly closed = output<void>();\n readonly permissionsChanged = output<void>();\n\n readonly isLoading = signal(false);\n readonly isSaving = signal(false);\n readonly companies = signal<CompanyWithAssignment[]>([]);\n\n private assignedCompanyIds = new Set<string>();\n\n constructor() {\n effect(() => {\n if (this.visible() && this.user()) {\n this.loadData();\n }\n });\n }\n\n private async loadData(): Promise<void> {\n const currentUser = this.user();\n if (!currentUser) return;\n\n this.isLoading.set(true);\n try {\n const companiesResponse = await this.companyApi.getAll({\n pagination: { currentPage: 0, pageSize: 1000 },\n filter: {},\n select: [],\n sort: {},\n });\n\n const assignedResponse = await firstValueFrom(\n this.permissionApi.getUserCompanies(currentUser.id),\n );\n\n this.assignedCompanyIds.clear();\n if (assignedResponse.data) {\n assignedResponse.data.forEach((permission) => {\n this.assignedCompanyIds.add(permission.companyId);\n });\n }\n\n const companiesWithStatus: CompanyWithAssignment[] = (\n companiesResponse.data || []\n ).map((company) => ({\n ...company,\n isAssigned: this.assignedCompanyIds.has(company.id),\n }));\n\n this.companies.set(companiesWithStatus);\n } catch {\n } finally {\n this.isLoading.set(false);\n }\n }\n\n async onCompanyToggle(\n company: CompanyWithAssignment,\n isAssigned: boolean,\n ): Promise<void> {\n const currentUser = this.user();\n if (!currentUser) return;\n\n this.isSaving.set(true);\n try {\n const response = isAssigned\n ? await firstValueFrom(\n this.permissionApi.assignUserToCompany(currentUser.id, company.id),\n )\n : await firstValueFrom(\n this.permissionApi.revokeUserFromCompany(currentUser.id, company.id),\n );\n\n if (response.success) {\n if (isAssigned) this.assignedCompanyIds.add(company.id);\n else this.assignedCompanyIds.delete(company.id);\n\n this.companies.update((list) =>\n list.map((c) => (c.id === company.id ? { ...c, isAssigned } : c)),\n );\n\n this.messageService.add({\n severity: 'success',\n summary: this.t('shared.success'),\n detail: response?.messageKey\n ? this.t(response.messageKey, response.messageVariables)\n : (response?.message ?? ''),\n });\n this.permissionsChanged.emit();\n }\n } catch {\n // Signal was never optimistically updated, so the checkbox already\n // reflects the pre-toggle state once change detection re-runs below.\n } finally {\n this.isSaving.set(false);\n }\n }\n\n onClose(): void {\n this.closed.emit();\n }\n}\n"],"mappings":";;;;;;;;;;;;;;AAAA,IAAY;CAAZ,SAAY,oBAAkB;CAC5B,mBAAA,YAAA;CACA,mBAAA,cAAA;CACA,mBAAA,cAAA;CACA,mBAAA,eAAA;AACF,EAAA,CALY,uBAAA,qBAAkB,CAAA,EAAA;AAO9B,MAAa,mBAAmB;CAC9B,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;AACX;AC2HV,SAAgB,4BAA4B,UAAsB;CAChE,OAAO,CAAC,CAAC,SAAS,QAAQ,+BAA+B,SAAS,QAAQ,SAAS,KAAK,8BAA8B;AACxH;AAEA,SAAgB,2BAA2B,UAAsB;CAC/D,OAAO,CAAC,CAAC,SAAS,QAAQ,uBAAuB,SAAS,QAAQ,SAAS,KAAK,sBAAsB;AACxG;AAEA,SAAgB,gBAAgB,UAAsB;CACpD,OAAO,CAAC,CAAC,SAAS,QAAQ,iBAAiB,SAAS;AACtD;AC5HA,IAAa,iBAAb,MAAa,eAAc;CACR,YAAY,OAAO,UAAU;CAC7B,OAAO,OAAO,UAAU;CACxB;CAEjB,cAAA;EACE,KAAK,UAAU,cAAc,KAAK,WAAW,MAAM;CACrD;CAEA,MAAM,MAAmB;EACvB,OAAO,KAAK,KAAK,KAAmB,GAAG,KAAK,QAAO,SAAU,IAAI;CACnE;CAEA,SAAS,MAA0B;EACjC,OAAO,KAAK,KAAK,KAA4B,GAAG,KAAK,QAAO,YAAa,IAAI;CAC/E;CAEA,OAAO,MAAoB;EACzB,OAAO,KAAK,KAAK,KAAqB,GAAG,KAAK,QAAO,UAAW,IAAI;CACtE;CAEA,cAAc,MAA2B;EACvC,OAAO,KAAK,KAAK,KAAqB,GAAG,KAAK,QAAO,kBAAmB,IAAI;CAC9E;CAEA,eAAY;EACV,OAAO,KAAK,KAAK,KAAsC,GAAG,KAAK,QAAO,oBAAqB,CAAA,CAAE;CAC/F;CAEA,mBAAmB,WAAiB;EAClC,OAAO,KAAK,KAAK,KAA8C,GAAG,KAAK,QAAO,2BAA4B,EAAE,UAAS,CAAE;CACzH;CAEA,UAAO;EACL,OAAO,KAAK,KAAK,KAA4B,GAAG,KAAK,QAAO,WAAY,CAAA,CAAE;CAC5E;CAEA,KAAE;EACA,OAAO,KAAK,KAAK,KAAkB,GAAG,KAAK,QAAO,MAAO,CAAA,CAAE;CAC7D;CAEA,SAAM;EACJ,OAAO,KAAK,KAAK,KAAuB,GAAG,KAAK,QAAO,UAAW,CAAA,CAAE;CACtE;CAEA,eAAe,MAA4B;EACzC,OAAO,KAAK,KAAK,KAAuB,GAAG,KAAK,QAAO,mBAAoB,IAAI;CACjF;CAEA,eAAe,OAAa;EAC1B,OAAO,KAAK,KAAK,KAAuB,GAAG,KAAK,QAAO,mBAAoB,EAAE,MAAK,CAAE;CACtF;CAEA,cAAc,OAAe,aAAmB;EAC9C,OAAO,KAAK,KAAK,KAAuB,GAAG,KAAK,QAAO,kBAAmB;GAAE;GAAO;EAAW,CAAE;CAClG;CAEA,mBAAmB,OAAa;EAC9B,OAAO,KAAK,KAAK,KAAuB,GAAG,KAAK,QAAO,uBAAwB,EAAE,MAAK,CAAE;CAC1F;CAEA,YAAY,OAAa;EACvB,OAAO,KAAK,KAAK,KAA+C,GAAG,KAAK,QAAO,gBAAiB,EAAE,MAAK,CAAE;CAC3G;CA/DW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAc,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAd,OAAA,QAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;CAAc,CAAA;;AAAd,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAc,YAAA,CAAA,EAD1B,MAAA,QAAA,CAAA;;;ACCD,MAAM,UAAU;CACd,cAAc;CACd,YAAY;CACZ,WAAW;AACH;AAEV,MAAM,sBAAsB;AAO5B,IAAa,mBAAb,MAAa,iBAAgB;CAEV,YAAY,OAAO,UAAU;CAC7B,SAAS,OAAO,MAAM;CACtB,WAAW,OAAO,eAAe;CACjC,sBAAsB,OAAO,0BAA0B;CAGvD,QAAQ,OAAyB,MAAK,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CACtC,eAAe,OAAe,IAAG,GAAA,YAAA,CAAA,EAAA,WAAA,eAAA,CAAA,+BAAA,CAAA,CAAA;CACjC,kBAAkB,OAAsB,MAAK,GAAA,YAAA,CAAA,EAAA,WAAA,kBAAA,CAAA,+BAAA,CAAA,CAAA;CAC7C,WAAW,OAA4B,MAAK,GAAA,YAAA,CAAA,EAAA,WAAA,WAAA,CAAA,+BAAA,CAAA,CAAA;CAC5C,UAAU,OAA2B,MAAK,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CAElD,OAAO,KAAK,MAAM,WAAU;CAC5B,cAAc,KAAK,aAAa,WAAU;CAC1C,iBAAiB,KAAK,gBAAgB,WAAU;CAChD,UAAU,KAAK,SAAS,WAAU;CAClC,SAAS,KAAK,QAAQ,WAAU;CAGxB,sBAAsB,OAAsB,MAAK,GAAA,YAAA,CAAA,EAAA,WAAA,sBAAA,CAAA,+BAAA,CAAA,CAAA;CACjD,sBAAsB,OAA+B,CAAA,GAAG,GAAA,YAAA,CAAA,EAAA,WAAA,sBAAA,CAAA,+BAAA,CAAA,CAAA;CAEhE,qBAAqB,KAAK,oBAAoB,WAAU;CACxD,qBAAqB,KAAK,oBAAoB,WAAU;CAGxD,kBAAkB,eACnB,CAAC,CAAC,KAAK,aAAY,KAAM,CAAC,CAAC,KAAK,MAAK,GAC5C,GAAA,YAAA,CAAA,EAAA,WAAA,kBAAA,CAAA,+BAAA,CAAA,CAAA;CACQ,2BAA2B,eAC5B,CAAC,CAAC,KAAK,oBAAmB,KAAM,KAAK,oBAAmB,CAAE,CAAC,SAAS,GAC3E,GAAA,YAAA,CAAA,EAAA,WAAA,2BAAA,CAAA,+BAAA,CAAA,CAAA;CACQ,WAAW,eAAe,KAAK,MAAK,CAAE,EAAE,QAAQ,QAAO,GAAA,YAAA,CAAA,EAAA,WAAA,WAAA,CAAA,+BAAA,CAAA,CAAA;CACvD,cAAc,eAAe,KAAK,SAAQ,CAAE,EAAE,QAAQ,IAAG,GAAA,YAAA,CAAA,EAAA,WAAA,cAAA,CAAA,+BAAA,CAAA,CAAA;CACzD,aAAa,eAAe,KAAK,QAAO,CAAE,EAAE,QAAQ,IAAG,GAAA,YAAA,CAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;CAMvD,iBAAiB,eAAc;EACtC,MAAM,YAAY,KAAK,gBAAe;EACtC,IAAI,CAAC,WAAW,OAAO;EAEvB,OAAO,KAAK,IAAG,KAAM,YAAY;CACnC,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,iBAAA,CAAA,+BAAA,CAAA,CAAA;CAGO,WAAW,eACZ,KAAK,UAAU,YAAY,YAAY,MAC9C,GAAA,YAAA,CAAA,EAAA,WAAA,WAAA,CAAA,+BAAA,CAAA,CAAA;CAED,cAAA;EAEE,aAAY;GACV,MAAM,YAAY,KAAK,gBAAe;GACtC,YACI,KAAK,MAAM,QAAQ,cAAc,UAAU,SAAQ,CAAE,IACrD,KAAK,OAAO,QAAQ,YAAY;EACtC,CAAC;EAGD,aAAY;GACV,MAAM,YAAY,KAAK,SAAQ,CAAE,EAAE;GACnC,MAAM,WAAW,KAAK,QAAO,CAAE,EAAE;GACjC,YACI,KAAK,MAAM,QAAQ,YAAY,SAAS,IACxC,KAAK,OAAO,QAAQ,UAAU;GAClC,WACI,KAAK,MAAM,QAAQ,WAAW,QAAQ,IACtC,KAAK,OAAO,QAAQ,SAAS;EACnC,CAAC;EAGD,aAAY;GACV,MAAM,OAAO,KAAK,MAAK;GACvB,MAAM,OAAO,MAAM,MAAM,KAAI,KAAM,MAAM;GACzC,IAAI,MAAM,KAAK,MAAM,qBAAqB,IAAI;EAChD,CAAC;EAGD,KAAK,gBAAe;CACtB;CAMA,cAAc,MAAgB;EAC5B,KAAK,aAAa,IAAI,KAAK,WAAW;EACtC,KAAK,MAAM,IAAI,KAAK,IAAI;EACxB,KAAK,SAAS,IAAI,KAAK,WAAW,IAAI;EACtC,KAAK,QAAQ,IAAI,KAAK,UAAU,IAAI;EACpC,MAAM,SAAS,KAAK,kBAAkB,KAAK,WAAW;EACtD,KAAK,gBAAgB,IAAI,MAAM;EAC/B,KAAK,oBAAmB;CAC1B;CAEA,kBAAkB,MAA2B;EAC3C,KAAK,oBAAoB,IAAI,KAAK,SAAS;EAC3C,KAAK,oBAAoB,IAAI,KAAK,SAAS;EAC3C,KAAK,MAAM,IAAI,KAAK,IAAI;CAC1B;CAEA,sBAAmB;EACjB,KAAK,oBAAoB,IAAI,IAAI;EACjC,KAAK,oBAAoB,IAAI,CAAA,CAAE;CACjC;CAEA,aAAU;EACR,KAAK,MAAM,IAAI,IAAI;EACnB,KAAK,aAAa,IAAI,EAAE;EACxB,KAAK,gBAAgB,IAAI,IAAI;EAC7B,KAAK,SAAS,IAAI,IAAI;EACtB,KAAK,QAAQ,IAAI,IAAI;EACrB,KAAK,oBAAmB;EACxB,OAAO,OAAO,OAAO,CAAC,CAAC,SAAS,QAAQ,KAAK,OAAO,GAAG,CAAC;EACxD,KAAK,oBAAoB,iBAAgB;CAC3C;CAMA,QAAQ,MAAsB;EAC5B,KAAK,MAAM,IAAI,IAAI;CACrB;CAEA,eAAe,OAAa;EAC1B,KAAK,aAAa,IAAI,KAAK;EAE3B,MAAM,SAAS,KAAK,kBAAkB,KAAK;EAC3C,KAAK,gBAAgB,IAAI,MAAM;CACjC;CAEA,WAAW,SAA4B;EACrC,KAAK,SAAS,IAAI,OAAO;CAC3B;CAEA,UAAU,QAA0B;EAClC,KAAK,QAAQ,IAAI,MAAM;CACzB;CAMA,gBAAgB,WAAkB;EAChC,KAAK,OAAO,SACV,CAAC,aAAa,GACd,YAAY,EAAE,aAAa,EAAE,UAAS,EAAE,IAAK,CAAA,CAAE;CAEnD;CAEA,mBAAmB,WAAkB;EAEnC,MAAM,UAAU,KAAK,iBAAiB,SAAS,IAAI,YAAY;EAC/D,KAAK,OAAO,cAAc,OAAO;CACnC;CAGQ,iBAAiB,KAAuB;EAC9C,IAAI,CAAC,KAAK,OAAO;EAEjB,OAAO,IAAI,WAAW,GAAG,KAAK,CAAC,IAAI,SAAS,KAAK,KAAK,CAAC,IAAI,WAAW,IAAI;CAC5E;CAGA,qBAAkB;EAChB,OAAO,KAAK,IAAI,QAAQ,UAAU;CACpC;CAEA,oBAAiB;EACf,OAAO,KAAK,IAAI,QAAQ,SAAS;CACnC;CAEA,mBAAgB;EACd,OAAO,KAAK,IAAI,mBAAmB;CACrC;CAGQ,kBAAe;EACrB,IAAI,KAAK,SAAS,UAAU;EAE5B,MAAM,YAAY,KAAK,IAAI,QAAQ,YAAY;EAC/C,IAAI,WACF,KAAK,gBAAgB,IAAI,SAAS,WAAW,EAAE,CAAC;CAEpD;CAMQ,kBAAkB,OAAa;EACrC,IAAI;GACF,IAAI,CAAC,OAAO,OAAO;GACnB,MAAM,UAAU,MAAM,MAAM,GAAG,CAAC,CAAC;GACjC,IAAI,CAAC,SAAS,OAAO;GAErB,MAAM,SAAS,QAAQ,QAAQ,MAAM,GAAG,CAAC,CAAC,QAAQ,MAAM,GAAG;GAC3D,MAAM,SAAS,SAAS,IAAI,QAAQ,IAAK,OAAO,SAAS,KAAM,CAAC;GAChE,MAAM,UAAU,KAAK,MAAM,KAAK,MAAM,CAAC;GACvC,OAAO,QAAQ,MAAM,QAAQ,MAAM,MAAO;EAC5C,QAAQ;GACN,OAAO;EACT;CACF;CAEQ,MAAM,KAAa,OAAa;EACtC,IAAI,CAAC,KAAK,SAAS,UAAU,aAAa,QAAQ,KAAK,KAAK;CAC9D;CAEQ,IAAI,KAAW;EACrB,OAAO,CAAC,KAAK,SAAS,WAAW,aAAa,QAAQ,GAAG,IAAI;CAC/D;CAEQ,OAAO,KAAW;EACxB,IAAI,CAAC,KAAK,SAAS,UAAU,aAAa,WAAW,GAAG;CAC1D;CA7NW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAgB,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAhB,OAAA,QAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;CAAgB,CAAA;;AAAhB,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAgB,YAAA,CAAA,EAD5B,MAAA,QAAA,CAAA;;;AChBD,IAAa,kBAAb,MAAa,gBAAe;CACT,YAAY,OAAO,gBAAgB;CACnC,UAAU,OAAO,cAAc;CAC/B,YAAY,OAAO,UAAU;CAE7B,eAAe,OAAO,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,eAAA,CAAA,+BAAA,CAAA,CAAA;CACpC,cAAc,KAAK,aAAa,WAAU;CAE3C,uBAAmD;CAE3D,aAAU;EACR,IAAI,KAAK,UAAU,gBAAe,KAAM,KAAK,UAAU,KAAI,GAAI;GAC7D,KAAK,aAAa,IAAI,IAAI;GAC1B,OAAO,GAAG,IAAI;EAChB;EAEA,IAAI,KAAK,UAAU,yBAAwB,GAAI;GAC7C,KAAK,aAAa,IAAI,IAAI;GAC1B,OAAO,GAAG,KAAK;EACjB;EAEA,IAAI,KAAK,aAAY,GACnB,OAAO,GAAG,KAAK,UAAU,gBAAe,CAAE;EAG5C,IAAI,KAAK,sBACP,OAAO,KAAK;EAGd,KAAK,uBAAuB,KAAK,QAAQ,QAAO,CAAE,CAAC,KACjD,QAAQ,GAAI,GACZ,WAAW,oBAAmB;GAC5B,MAAM,cAAc,gBAAgB,MAAM;GAC1C,IAAI,CAAC,aAAa,OAAO,GAAG,KAAK;GACjC,KAAK,UAAU,eAAe,WAAW;GACzC,OAAO,KAAK,QAAQ,GAAE,CAAE,CAAC,KACvB,KAAK,eAAc;IACjB,MAAM,SAAS,WAAW;IAC1B,IAAI,CAAC,QAAQ,OAAO;IACpB,MAAM,EAAE,MAAM,SAAS,WAAW;IAElC,KAAK,UAAU,QAAQ,IAAI;IAE3B,IAAI,KAAK,UAAU,sBAAsB;KACvC,KAAK,UAAU,WAAW,WAAW,IAAI;KACzC,KAAK,UAAU,UAAU,UAAU,IAAI;IACzC;IAEA,OAAO;GACT,CAAC,CAAC;EAEN,CAAC,GAED,UAAS;GACP,KAAK,aAAa,IAAI,IAAI;EAC5B,CAAC,GAED,YAAY,QAAO;GACjB,KAAK,aAAa,IAAI,IAAI;GAE1B,MAAM,WAAmB,KAAK,OAAO,cAAc;GAYnD,qBAFuB,IARM,IAAI;IAC/B;IACA;IACA;IACA;IACA;GACD,CAEsB,EAAA,CAAiB,IAAI,QAExC,KAAkB,KAAK,UAAU,sBAAsB;IACzD,KAAK,UAAU,QAAQ,IAAI;IAC3B,KAAK,UAAU,WAAW,IAAI;IAC9B,KAAK,UAAU,UAAU,IAAI;GAC/B,OACE,KAAK,UAAU,WAAU;GAG3B,OAAO,GAAG,KAAK;EACjB,CAAC,GAED,YAAY;GAAE,YAAY;GAAG,UAAU;EAAI,CAAE,GAE7C,eAAc;GACZ,KAAK,uBAAuB;EAC9B,CAAC,CAAC;EAGJ,OAAO,KAAK;CACd;CA3FW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAe,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAf,OAAA,QAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;CAAe,CAAA;;AAAf,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAe,YAAA,CAAA,EAD3B,MAAA,QAAA,CAAA;;ACHD,IAAa,mBAAb,MAAa,yBAAyB,mBAGrC;CACC,cAAA;EACE,MAAM,UAAU,gBAAgB;CAClC;CAEA,eAAe,WAAmB,SAAS,IAAE;EAC3C,KAAK,UAAU,QAAQ,EAAE,QAAQ,EAAE,UAAS,EAAE,CAAE;CAClD;CAVW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAgB,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAhB,OAAA,QAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;CAAgB,CAAA;;AAAhB,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAgB,YAAA,CAAA,EAD5B,MAAA,QAAA,CAAA;;;ACCD,IAAa,oBAAb,MAAa,0BAA0B,mBAGtC;CACC,cAAA;EACE,MAAM,WAAW,gBAAgB;CACnC;CANW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAiB,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAjB,OAAA,QAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;CAAiB,CAAA;;AAAjB,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAiB,YAAA,CAAA,EAD7B,MAAA,QAAA,CAAA;;;ACND,MAAa,iBAAiB;CAC5B,OAAO;CACP,QAAQ;CACR,SAAS;CACT,UAAU;CACV,IAAI;CACJ,QAAQ;CACR,gBAAgB;CAChB,iBAAiB;CACjB,cAAc;CACd,iBAAiB;CACjB,gBAAgB;CAChB,qBAAqB;CACrB,iBAAiB;AACT;AAGV,SAAgB,WAAW,KAAa,UAAgB;CACtD,OAAO,IAAI,SAAS,QAAQ;AAC9B;ACVA,MAAa,wBAAwB;AAGrC,IAAa,uBAAb,MAAa,qBAAoB;CACd,YAAY,OAAO,UAAU;CAC7B,OAAO,OAAO,UAAU;CACxB,WAAW,OAAO,eAAe;CACjC,UAAU,cAAc,KAAK,WAAW,MAAM;CAE/D,IAAI,cAAW;EACb,IAAI,KAAK,SAAS,UAAU,OAAO;EACnC,OAAO,GAAG,OAAO,SAAS,SAAS,eAAe;CACpD;CAGA,cAAc,WAAiB;EAC7B,IAAI,KAAK,SAAS,UAAU;EAC5B,IAAI,WAAW,eAAe,QAAQ,uBAAuB,SAAS;OACjE,eAAe,WAAW,qBAAqB;CACtD;CAGA,mBAAgB;EACd,IAAI,KAAK,SAAS,UAAU,OAAO;EACnC,MAAM,YAAY,eAAe,QAAA,0BAA6B,KAAK;EACnE,eAAe,WAAW,qBAAqB;EAC/C,OAAO;CACT;CAEA,eAAY;EACV,OAAO,KAAK,KAAK,KACf,GAAG,KAAK,QAAO,oBACf,EAAE,aAAa,KAAK,YAAW,CAAE;CAErC;CAEA,UACE,UAA4B;EAE5B,OAAO,KAAK,KAAK,KACf,GAAG,KAAK,QAAO,oBACf;GAAE;GAAU,aAAa,KAAK;EAAW,CAAE;CAE/C;CAEA,SAAS,SAA+B;EACtC,OAAO,KAAK,KAAK,KACf,GAAG,KAAK,QAAO,mBACf,OAAO;CAEX;CA/CW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAoB,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAApB,OAAA,QAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;CAAoB,CAAA;;AAApB,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAoB,YAAA,CAAA,EADhC,MAAA,QAAA,CAAA;;ACRD,IAAa,6BAAb,MAAa,mCAAmC,mBAG/C;CACC,cAAA;EACE,MAAM,iBAAiB,MAAM;CAC/B;CANW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAA0B,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAA1B,OAAA,QAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;CAA0B,CAAA;;AAA1B,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAA0B,YAAA,CAAA,EADtC,MAAA,QAAA,CAAA;;;ACCD,IAAa,2BAAb,MAAa,yBAAwB;CAClB,gBAAgB,OAAO,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,gBAAA,CAAA,+BAAA,CAAA,CAAA;CACrC,eAAe,KAAK,cAAc,WAAU;CAEpC,uBAAuB,IAAI,gBAA+B,IAAI;CACtE,uBAAuB,KAAK,qBAAqB,aAAY;CAEtE,eAAY;EACV,KAAK,cAAc,IAAI,IAAI;EAC3B,KAAK,qBAAqB,KAAK,IAAI;CACrC;CAEA,gBAAgB,UAAgB;EAC9B,KAAK,cAAc,IAAI,KAAK;EAC5B,KAAK,qBAAqB,KAAK,QAAQ;CACzC;CAEA,cAAW;EACT,KAAK,cAAc,IAAI,KAAK;CAC9B;CAnBW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAwB,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAxB,OAAA,QAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;CAAwB,CAAA;;AAAxB,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAwB,YAAA,CAAA,EADpC,MAAA,QAAA,CAAA;;ACsBD,MAAa,yBAAyB,IAAI,eACxC,wBAAwB;AAS1B,MAAa,6BACX,IAAI,eACF,4BAA4B;AAuChC,MAAa,8BACX,IAAI,eACF,6BAA6B;AAkCjC,MAAa,2BACX,IAAI,eAA2C,0BAA0B;AAqB3E,MAAa,wBACX,IAAI,eAA6C,uBAAuB;AAyC1E,MAAa,yBACX,IAAI,eAA0C,wBAAwB;AAQxE,MAAa,0BACX,IAAI,eAA8C,yBAAyB;AAsC7E,MAAa,2BACX,IAAI,eAA2C,0BAA0B;AAmB3E,MAAa,0BACX,IAAI,eAAsC,yBAAyB;AAErE,MAAM,gCAAgC;AAEtC,MAAa,8BAA8B;CACzC,WAAW;CACX,WAAW;CACX,kBAAkB;CAClB,kBAAkB;CAClB,gBAAgB;CAChB,qBAAqB;AACuB;AAE9C,SAAgB,0BACd,QAAyC;CAEzC,MAAM,YAAY,OAAO,YACvB,OAAO,QAAQ,UAAU,CAAA,CAAE,CAAC,CAAC,QAAQ,GAAG,WAAW,UAAU,MAAS,CAAC;CAEzE,OAAO;EAAE,GAAG;EAA6B,GAAG;CAAS;AACvD;AAEA,SAAgB,iBACd,UACA,SAAoC,6BAA2B;CAE/D,MAAM,QAAQ,0BAA0B,MAAM;CAC9C,MAAM,QAAQ,QAAwB,MAAM,cAAc,MAAM,WAAW;CAE3E,IAAI,SAAS,UAAU,MAAM,aAAa,IACxC,OAAO,KAAK,qCAAqC;CAEnD,IAAI,MAAM,aAAa,SAAS,SAAS,MAAM,WAC7C,OAAO,KAAK,qCAAqC;CAGnD,IAAI,MAAM,SACR,OAAO,MAAM,QAAQ,KAAK,QAAQ,IAAI,OAAO,KAAK,kCAAkC;CAEtF,IAAI,MAAM,oBAAoB,CAAC,QAAQ,KAAK,QAAQ,GAClD,OAAO,KAAK,4CAA4C;CAE1D,IAAI,MAAM,oBAAoB,CAAC,QAAQ,KAAK,QAAQ,GAClD,OAAO,KAAK,4CAA4C;CAE1D,IAAI,MAAM,kBAAkB,CAAC,KAAK,KAAK,QAAQ,GAC7C,OAAO,KAAK,yCAAyC;CAEvD,IAAI,MAAM,uBAAuB,CAAC,8BAA8B,KAAK,QAAQ,GAC3E,OAAO,KAAK,0CAA0C;CAGxD,OAAO;AACT;AAEA,SAAgB,cACd,OACA,QAA+B;CAG/B,KADgB,QAAQ,WAAW,6BAC/B,CAAQ,KAAK,KAAK,GAAG,OAAO;CAChC,OAAO,QAAQ,cAAc,QAAQ,WAAW;AAClD;AC9SA,IAAa,wBAAb,MAAa,sBAAqB;CACf,SAAS,OAAO,wBAAwB,EAAE,UAAU,KAAI,CAAE;CAC1D,mBAAmB,OAAO,kBAAkB,EAAE,UAAU,KAAI,CAAE;CAE9D,QAAQ,0BAA0B,KAAK,QAAQ,QAAQ;CAC/D,YAAY,KAAK,MAAM,aAAa,4BAA4B;CACxD,YAAY,KAAK,MAAM,aAAa,4BAA4B;CAEjF,SAAS,UAAgB;EACvB,IAAI,CAAC,UAAU,OAAO;EACtB,MAAM,MAAM,iBAAiB,UAAU,KAAK,KAAK;EACjD,IAAI,CAAC,KAAK,OAAO;EACjB,MAAM,SAAS;GAAE,KAAK,KAAK;GAAW,KAAK,KAAK;GAAW,GAAG,KAAK,MAAM;EAAY;EACrF,OAAO,KAAK,kBAAkB,UAAU,KAAK,MAAM,KAAK;CAC1D;CAdW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAqB,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAArB,OAAA,QAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;CAAqB,CAAA;;AAArB,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAqB,YAAA,CAAA,EADjC,MAAA,QAAA,CAAA;;ACJD,IAAa,qBAAb,MAAa,mBAAkB;CACZ,SAAS,OAAO,wBAAwB,EAAE,UAAU,KAAI,CAAE,CAAC,EAAE;CAC7D,mBAAmB,OAAO,kBAAkB,EAAE,UAAU,KAAI,CAAE;CAE/E,SAAS,OAAa;EACpB,IAAI,CAAC,OAAO,OAAO;EACnB,MAAM,MAAM,cAAc,OAAO,KAAK,MAAM;EAC5C,IAAI,CAAC,KAAK,OAAO;EACjB,OAAO,KAAK,kBAAkB,UAAU,KAAK,KAAK,QAAQ,YAAY,KAAK;CAC7E;CATW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAkB,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAlB,OAAA,QAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;CAAkB,CAAA;;AAAlB,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAkB,YAAA,CAAA,EAD9B,MAAA,QAAA,CAAA;;ACgBD,IAAa,iBAAb,MAAa,uBAAuB,mBAGnC;CACC,cAAA;EACE,MAAM,SAAS,gBAAgB;CACjC;CAEA,cAAc,MAAwB;EACpC,OAAO,KAAK,KAAK,KACf,GAAG,KAAK,QAAO,WACf,IAAI;CAER;CAEA,OACE,QACA,SAAS,IAAE;EAEX,MAAM,SAAS,SAAS,EAAE,GAAG,OAAM,IAAK;EACxC,OAAO,KAAK,KAAK,KACf,GAAG,KAAK,QAAO,UACf,QACA,SAAS,EAAE,OAAM,IAAK,MAAS;CAEnC;CAzBW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAc,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAd,OAAA,QAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;CAAc,CAAA;;AAAd,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAc,YAAA,CAAA,EAD1B,MAAA,QAAA,CAAA;;;ACCD,IAAa,2BAAb,MAAa,yBAAwB;CAClB,YAAY,OAAmB,UAAU;CACzC,OAAO,OAAO,UAAU;CACxB,UAAU,GAAG,cAAc,KAAK,WAAW,gBAAgB,EAAC;CAG7E,oBAAoB,MAA+B;EACjD,OAAO,KAAK,KAAK,KAAuB,GAAG,KAAK,QAAO,uBAAwB,IAAI;CACrF;CAEA,oBAAoB,QAAgB,WAAiB;EACnD,OAAO,KAAK,oBAAoB;GAAE;GAAQ,OAAO,CAAC;IAAE,UAAU;IAAW,OAAO;GAAI,CAAE;EAAC,CAAE;CAC3F;CAEA,sBAAsB,QAAgB,WAAiB;EACrD,OAAO,KAAK,oBAAoB;GAAE;GAAQ,OAAO,CAAC;IAAE,UAAU;IAAW,OAAO;GAAK,CAAE;EAAC,CAAE;CAC5F;CAEA,iBAAiB,QAAc;EAC7B,OAAO,KAAK,KAAK,KAAgD,GAAG,KAAK,QAAO,oBAAqB,EAAE,OAAM,CAAE;CACjH;CAGA,mBAAmB,MAA8B;EAC/C,OAAO,KAAK,KAAK,KAAuB,GAAG,KAAK,QAAO,sBAAuB,IAAI;CACpF;CAEA,mBAAmB,QAAgB,UAAgB;EACjD,OAAO,KAAK,mBAAmB;GAAE;GAAQ,OAAO,CAAC;IAAE,UAAU;IAAU,OAAO;GAAI,CAAE;EAAC,CAAE;CACzF;CAEA,qBAAqB,QAAgB,UAAgB;EACnD,OAAO,KAAK,mBAAmB;GAAE;GAAQ,OAAO,CAAC;IAAE,UAAU;IAAU,OAAO;GAAK,CAAE;EAAC,CAAE;CAC1F;CAEA,gBAAgB,QAAgB,WAAkB;EAChD,OAAO,KAAK,KAAK,KAA+C,GAAG,KAAK,QAAO,mBAAoB;GACjG;GACA,GAAI,aAAa,EAAE,UAAS;EAC7B,CAAA;CACH;CAIA,gBAAgB,WAAiB;EAC/B,OAAO,KAAK,KAAK,KAA+C,GAAG,KAAK,QAAO,qBAAsB,EACnG,UACD,CAAA;CACH;CAEA,eAAe,UAAgB;EAC7B,OAAO,KAAK,KAAK,KAA8C,GAAG,KAAK,QAAO,oBAAqB,EACjG,SACD,CAAA;CACH;CAtDW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAwB,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAxB,OAAA,QAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;CAAwB,CAAA;;AAAxB,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAwB,YAAA,CAAA,EADpC,MAAA,QAAA,CAAA;;ACVD,SAAS,iBAAiB,KAAY;CACpC,IAAI,OAAO,QAAQ,YAAY,CAAC,KAAK,OAAO;CAC5C,OAAO,IAAI,WAAW,GAAG,KAAK,CAAC,IAAI,SAAS,KAAK,KAAK,CAAC,IAAI,WAAW,IAAI;AAC5E;AAGA,MAAa,aAA4B,QAAQ,UAAS;CACxD,MAAM,YAAY,OAAO,gBAAgB;CACzC,MAAM,SAAS,OAAO,MAAM;CAC5B,MAAM,YAAY,OAAO,UAAU;CAEnC,IAAI,CAAC,UAAU,gBAAe,GAC5B,OAAO,OAAO,cAAc,CAAC,eAAe,KAAK,GAAG,EAAE,aAAa,EAAE,WAAW,MAAM,IAAG,EAAE,CAAE;CAG/F,IAAI,UAAU,sBACZ;MAAI,UAAU,yBAAwB,KAAM,CAAC,UAAU,QAAO,GAC5D,OAAO,OAAO,cAAc,CAAC,eAAe,KAAK,GAAG,EAAE,aAAa,EAAE,WAAW,MAAM,IAAG,EAAE,CAAE;CAC/F;CAGF,OAAO;AACT;AAGA,MAAa,cAA6B,UAA4D;CACpG,MAAM,YAAY,OAAO,gBAAgB;CACzC,MAAM,WAAW,OAAO,eAAe;CACvC,MAAM,SAAS,OAAO,MAAM;CAC5B,MAAM,YAAY,OAAO,UAAU;CAEnC,MAAM,yBAA2C;EAC/C,IAAI,UAAU,yBAAwB,GAAI,OAAO;EAEjD,IAAI,UAAU,gBAAe,GAAI;GAC/B,IAAI,UAAU,wBAAwB,CAAC,UAAU,QAAO,GAAI,OAAO;GACnE,MAAM,YAAY,MAAM,YAAY;GACpC,OAAO,OAAO,cAAc,CAAC,iBAAiB,SAAS,IAAI,YAAY,GAAG,CAAC;EAC7E;EAEA,OAAO;CACT;CAEA,IAAI,SAAS,YAAW,GAAI,OAAO,iBAAgB;CAEnD,OAAO,SAAS,WAAU,CAAE,CAAC,KAC3B,YAAU,iBAAgB,CAAE,GAC5B,mBAAiB,GAAG,IAAI,CAAC,CAAC;AAE9B;AAGA,MAAa,4BAA0C;CACrD,MAAM,SAAS,OAAO,MAAM;CAG5B,IAAI,CAFc,OAAO,UAEpB,CAAA,CAAU,sBAAsB,OAAO,OAAO,cAAc,CAAC,GAAG,CAAC;CACtE,OAAO;AACT;AAGA,MAAa,0BAAwC;CACnD,MAAM,SAAS,OAAO,MAAM;CAG5B,IAAI,CAFc,OAAO,UAEpB,CAAA,CAAU,SAAS,OAAO,SAAS,OAAO,OAAO,cAAc,CAAC,eAAe,KAAK,CAAC;CAC1F,OAAO;AACT;AAGA,MAAa,2BAAyC;CACpD,MAAM,SAAS,OAAO,MAAM;CAG5B,IAFkB,OAAO,UAErB,CAAA,CAAU,iBAAiB,OAAO,OAAO,OAAO,cAAc,CAAC,eAAe,KAAK,CAAC;CACxF,OAAO;AACT;AC5EA,MAAM,mBAAmB;CACvB,eAAe;CACf,eAAe;CACf,eAAe;CACf,eAAe;CACf,eAAe;CACf,eAAe;CACf,eAAe;CACf,eAAe;AACP;AAKV,SAAgB,gBACd,KACA,MAAmB;CAEnB,MAAM,YAAY,OAAO,gBAAgB;CACzC,MAAM,gBAAgB,OAAO,aAAa;CAC1C,MAAM,YAAY,OAAO,UAAU;CAEnC,MAAM,UAAkC,CAAA;CAGxC,IAAI,UAAU,YAAY,SAAS;EACjC,MAAM,WAAW,UAAU,SAAQ;EACnC,IAAI,UACF,QAAQ,UAAU,YAAY,gBAAgB;CAElD;CAGA,MAAM,QAAQ,UAAU,YAAW;CACnC,IAAI,OACF,QAAQ,mBAAmB,UAAU;CAMvC,IAFyB,iBAAiB,MAAM,OAAO,WAAW,IAAI,KAAK,EAAE,CAEzE,GAAkB;EACpB,QAAQ,YAAY,cAAc,IAAG;EACrC,OAAO,KAAK,IAAI,MAAM;GAAE,iBAAiB;GAAM,YAAY;EAAO,CAAE,CAAC;CACvE;CAEA,IAAI,OAAO,KAAK,OAAO,CAAC,CAAC,SAAS,GAChC,OAAO,KAAK,IAAI,MAAM,EAAE,YAAY,QAAO,CAAE,CAAC;CAGhD,OAAO,KAAK,GAAG;AACjB;ACpCA,SAAgB,wBACd,KACA,MAAmB;CAEnB,MAAM,YAAY,OAAO,gBAAgB;CACzC,MAAM,UAAU,OAAO,cAAc;CACrC,MAAM,iBAAiB,OAAO,cAAc;CAC5C,MAAM,aAAa,OAAO,WAAW;CACrC,MAAM,YAAY,kBAAkB,UAAU;CAC9C,MAAM,eAAe,OAAO,wBAAwB;CACpD,MAAM,mBAAmB,OAAO,kBAAkB,EAAE,UAAU,KAAI,CAAE;CACpE,MAAM,KAAK,QAAgB,kBAAkB,UAAU,GAAG,KAAK;CAG/D,MAAM,mBAAmB,WAAW,IAAI,KAAK,eAAe,OAAO;CACnE,MAAM,iBAAiB,WAAW,IAAI,KAAK,eAAe,KAAK;CAC/D,MAAM,kBAAkB,WAAW,IAAI,KAAK,eAAe,MAAM;CACjE,MAAM,oBAAoB,WAAW,IAAI,KAAK,eAAe,QAAQ;CACrE,MAAM,0BAA0B,WAC9B,IAAI,KACJ,eAAe,eAAe;CAIhC,IACE,oBACA,kBACA,mBACA,qBACA,yBAEA,OAAO,KAAK,GAAG;CAIjB,IAAI,UAAU,eAAc,KAAM,UAAU,eAAc,MAAO,MAE/D,OAAO,mBACL,KACA,MACA,WACA,SACA,gBACA,WACA,cACA,CAAC;CAKL,OAAO,KAAK,GAAG,CAAC,CAAC,KACf,YAAY,UAA4B;EAEtC,IAAI,MAAM,WAAW,KACnB,OAAO,iBAAiB,KAAK;EAI/B,OAAO,mBACL,KACA,MACA,WACA,SACA,gBACA,WACA,cACA,CAAC;CAEL,CAAC,CAAC;AAEN;AAEA,SAAS,mBACP,KACA,MACA,WACA,SACA,gBACA,WACA,cACA,GAA0B;CAE1B,IAAI,aAAa,aAAY,GAC3B,OAAO,aAAa,qBAAqB,KACvC,QAAQ,UAAU,UAAU,IAAI,GAChC,KAAK,CAAC,GACN,WAAW,UACT,KAAK,IAAI,MAAM,EAAE,YAAY,EAAE,eAAe,UAAU,QAAO,EAAE,CAAE,CAAC,CAAC,CACtE;CAIL,aAAa,aAAY;CAEzB,OAAO,QAAQ,QAAO,CAAE,CAAC,KACvB,WAAW,aAAY;EACrB,MAAM,WAAW,SAAS,KAAM;EAChC,UAAU,eAAe,QAAQ;EACjC,aAAa,gBAAgB,QAAQ;EACrC,OAAO,KACL,IAAI,MAAM,EAAE,YAAY,EAAE,eAAe,UAAU,WAAU,EAAE,CAAE,CAAC;CAEtE,CAAC,GACD,YAAY,iBAAgB;EAC1B,aAAa,YAAW;EACxB,OAAO,qBACL,WACA,gBACA,WACA,cACA,CAAC;CAEL,CAAC,CAAC;AAEN;AAEA,SAAS,qBACP,WACA,gBACA,WACA,OACA,GAA0B;CAE1B,IAAI,WAAW;EACb,MAAM,YAAY,OAAO,OAAO;EAChC,eAAe,IAAI;GACjB,UAAU;GACV,SAAS,EAAE,4BAA4B;GACvC,QAAQ,EAAE,SAAS;EACpB,CAAA;CACH;CACA,UAAU,WAAU;CACpB,UAAU,gBAAe;CAEzB,OAAO,iBAAiB,KAAK;AAC/B;AC/JA,MAAa,gBAAwC;CAEnD,sBAAsB;CACtB,iCACE;CACF,kCAAkC;CAClC,iCAAiC;CACjC,kCAAkC;CAClC,uBAAuB;CACvB,yBAAyB;CACzB,wBAAwB;CACxB,wBAAwB;CACxB,mBAAmB;CACnB,uBAAuB;CACvB,+BAA+B;CAC/B,8BAA8B;CAC9B,iCACE;CACF,0CAA0C;CAC1C,gCAAgC;CAChC,wCAAwC;CACxC,yCAAyC;CACzC,kCAAkC;CAClC,+BAA+B;CAC/B,wBAAwB;CACxB,6BAA6B;CAC7B,0BAA0B;CAC1B,yBAAyB;CACzB,oCACE;CACF,4BAA4B;CAC5B,yBAAyB;CACzB,yBAAyB;CACzB,6BAA6B;CAC7B,0BAA0B;CAC1B,wBAAwB;CACxB,8BAA8B;CAC9B,8BAA8B;CAC9B,uCAAuC;CACvC,mCAAmC;CACnC,qCAAqC;CACrC,kCACE;CAGF,2BAA2B;CAC3B,8BAA8B;CAC9B,oCAAoC;CACpC,oCAAoC;CACpC,kCAAkC;CAClC,qCAAqC;CAGrC,uBAAuB;CACvB,4BAA4B;CAC5B,oBAAoB;CACpB,2BAA2B;CAC3B,uBAAuB;CACvB,4BAA4B;CAC5B,8BAA8B;CAC9B,wBAAwB;CACxB,uBAAuB;CACvB,wBAAwB;CACxB,kBAAkB;CAClB,+BAA+B;CAC/B,+BAA+B;CAC/B,iCAAiC;CACjC,qCACE;CACF,uCAAuC;CACvC,mCACE;CACF,6BAA6B;CAC7B,6BAA6B;CAC7B,8BAA8B;CAC9B,uBAAuB;CAGvB,0BAA0B;CAC1B,+BAA+B;CAC/B,uBAAuB;CACvB,8BAA8B;CAC9B,iCAAiC;CACjC,0BAA0B;CAC1B,+BAA+B;CAC/B,2BAA2B;CAC3B,0BAA0B;CAC1B,2BAA2B;CAC3B,qCAAqC;CAGrC,yBAAyB;CACzB,8BAA8B;CAC9B,sBAAsB;CACtB,6BAA6B;CAC7B,gCAAgC;CAChC,yBAAyB;CACzB,8BAA8B;CAC9B,0BAA0B;CAC1B,yBAAyB;CACzB,0BAA0B;CAC1B,oCAAoC;CACpC,yBAAyB;CACzB,0BAA0B;CAG1B,wCACE;CACF,uCAAuC;CACvC,iCACE;CACF,oCAAoC;CACpC,6BAA6B;CAK7B,sBAAsB;CACtB,2BAA2B;CAC3B,kCAAkC;CAClC,oBAAoB;CACpB,0BAA0B;CAC1B,uBAAuB;CACvB,6BAA6B;CAC7B,0BAA0B;CAC1B,wBAAwB;CACxB,sBAAsB;CACtB,yBAAyB;CACzB,sBAAsB;CACtB,mCAAmC;CACnC,sBAAsB;CACtB,8BAA8B;CAC9B,6BAA6B;CAC7B,qCACE;CACF,oCAAoC;CACpC,2BAA2B;CAC3B,mCAAmC;CACnC,iCAAiC;CACjC,uCACE;CACF,kCAAkC;CAClC,qCAAqC;CACrC,uCAAuC;CACvC,oCAAoC;CACpC,8CACE;CACF,8CACE;CACF,2CACE;CACF,4CACE;CACF,oCAAoC;CACpC,mCAAmC;CACnC,oBAAoB;CACpB,wBAAwB;CAGxB,8BAA8B;CAC9B,iCACE;CACF,wCAAwC;CACxC,0CAA0C;CAC1C,oCAAoC;CACpC,sCACE;CACF,sCAAsC;CACtC,kCAAkC;CAGlC,gCAAgC;CAChC,0BAA0B;CAC1B,iCAAiC;CACjC,2BAA2B;CAC3B,kCAAkC;CAClC,oBAAoB;CACpB,0BAA0B;CAC1B,kCAAkC;CAClC,8CAA8C;CAC9C,wCAAwC;CACxC,iCAAiC;CACjC,sCAAsC;CACtC,wCAAwC;CACxC,oCAAoC;CACpC,8BAA8B;CAC9B,uCAAuC;CACvC,0CAA0C;CAC1C,oCAAoC;CACpC,6BAA6B;CAC7B,sCAAsC;CACtC,yCAAyC;CACzC,8BAA8B;CAC9B,0CAA0C;CAC1C,sBAAsB;CACtB,4BAA4B;CAC5B,sCAAsC;CACtC,mCAAmC;CACnC,6CAA6C;CAG7C,+BAA+B;CAC/B,iCACE;CACF,6BAA6B;CAC7B,qCACE;CACF,4BAA4B;CAC5B,kCACE;CACF,kCAAkC;CAClC,kCAAkC;CAClC,qCACE;CACF,4BAA4B;CAC5B,0BAA0B;CAG1B,6BAA6B;CAC7B,gCAAgC;CAChC,oCAAoC;CACpC,gDAAgD;CAChD,wCAAwC;CACxC,oDACE;CACF,sCAAsC;CACtC,+BAA+B;CAC/B,uCACE;CACF,oCAAoC;CACpC,4CACE;CACF,wCAAwC;CAKxC,iBAAiB;CACjB,oBAAoB;CACpB,+BACE;CACF,sBAAsB;CACtB,4BAA4B;CAC5B,uBAAuB;CACvB,6BAA6B;CAC7B,2BAA2B;CAC3B,2BAA2B;CAC3B,4BAA4B;CAC5B,oBAAoB;CACpB,4BAA4B;CAC5B,wCAAwC;CACxC,wBAAwB;CACxB,4BAA4B;CAC5B,wCAAwC;CACxC,2BAA2B;CAC3B,0BAA0B;CAC1B,wBAAwB;CACxB,yBAAyB;CACzB,iCAAiC;CACjC,6BAA6B;CAC7B,uBAAuB;CACvB,+BAA+B;CAK/B,4CAA4C;CAC5C,kCAAkC;CAClC,uCAAuC;CAGvC,2CAA2C;CAC3C,iCAAiC;CACjC,wCACE;CACF,kDACE;CACF,yDACE;CACF,qCAAqC;CAGrC,wBAAwB;CACxB,2BAA2B;CAC3B,6BAA6B;CAC7B,gCAAgC;CAChC,+BAA+B;CAG/B,6BAA6B;CAC7B,8BAA8B;CAC9B,8BAA8B;CAC9B,0CAA0C;CAC1C,8BAA8B;CAC9B,0CAA0C;CAC1C,gCAAgC;CAChC,uCAAuC;CACvC,8BAA8B;CAC9B,oCAAoC;CACpC,8BAA8B;CAC9B,oCAAoC;CACpC,gCAAgC;CAChC,sCAAsC;CACtC,uCAAuC;CAGvC,6BAA6B;CAC7B,mCAAmC;CACnC,sDACE;CACF,8CAA8C;CAC9C,sCAAsC;CAGtC,+BAA+B;CAC/B,8BAA8B;CAC9B,+BAA+B;CAC/B,2CAA2C;CAC3C,+BAA+B;CAC/B,2CAA2C;CAC3C,kCAAkC;CAClC,8CAA8C;CAC9C,wCAAwC;CAGxC,8BAA8B;CAC9B,uCAAuC;CACvC,uCAAuC;CAGvC,wCAAwC;CACxC,sCAAsC;CACtC,oCAAoC;CACpC,4CACE;CAGF,4BAA4B;CAC5B,2BAA2B;CAC3B,4BAA4B;CAC5B,wCAAwC;CACxC,gCAAgC;CAChC,yCAAyC;CACzC,4CAA4C;CAC5C,sCAAsC;CACtC,sCACE;CAGF,2BAA2B;CAC3B,iDAAiD;CACjD,gDAAgD;CAChD,gCAAgC;CAChC,+BAA+B;CAC/B,oCAAoC;CAGpC,iCAAiC;CACjC,iCAAiC;CACjC,6BAA6B;CAC7B,iCAAiC;CACjC,uCACE;CACF,6BACE;CACF,qCACE;CACF,+BAA+B;CAC/B,kCACE;CACF,kCACE;CACF,gCACE;CACF,8BAA8B;CAC9B,kCACE;CACF,+BACE;CAGF,6BAA6B;CAC7B,+BAA+B;CAC/B,iCAAiC;CACjC,iCAAiC;CACjC,kCAAkC;CAGlC,0BAA0B;CAC1B,sBAAsB;CAGtB,6CACE;CACF,sCACE;CACF,uBAAuB;CACvB,0BACE;CACF,8BAA8B;CAC9B,2BAA2B;CAC3B,+BAA+B;CAC/B,yCAAyC;CACzC,2BAA2B;CAC3B,mCAAmC;CACnC,wBAAwB;CACxB,oCAAoC;CACpC,8BAA8B;CAC9B,sCAAsC;CACtC,wCAAwC;CACxC,wCAAwC;CACxC,yCAAyC;AAC1C;AChYD,SAAS,kCAA+B;CACtC,MAAM,sBAAsB,OAAO,0BAA0B;CAC7D,MAAM,wBAAwB,wBAAwB,OAAO,UAAU,CAAC;CAExE,IAAI,oBAAoB,cAAc,iBAAiB,IAAI,GACzD,OAAO;CAGT,IACE,yBACA,oBAAoB,cAAc,oBAAoB,IAAI,GAE1D,OAAO;CAGT,IACE,yBACA,oBAAoB,cAAc,mBAAmB,IAAI,GAEzD,OAAO;CAGT,IAAI,oBAAoB,cAAc,+BAA+B,IAAI,GACvE,OAAO;CAGT,OAAO;AACT;AAQA,MAAa,cAAsB,CACjC;CACE,MAAM;CACN,SAAS,EACP,cAAc,yBAAyB;EACrC,SAAS,CAAC,QAAQ,QAAQ;EAC1B,kBAAkB;GAAE,GAAG;GAAe,GAAG;EAAe;CACzD,CAAA,EACF;CACD,UAAU;EACR;GACE,MAAM;GACN,qBACE,OAAO,qDAAsC,CAAC,MAC3C,MAAM,EAAE,kBAAkB;GAE/B,aAAa,CAAC,UAAU;EACzB;EACD;GACE,MAAM;GACN,qBACE,OAAO,wDAA4C,CAAC,MACjD,MAAM,EAAE,qBAAqB;GAElC,aAAa,CAAC,oBAAoB,UAAU;EAC7C;EACD;GACE,MAAM;GACN,qBACE,OAAO,+DAA0D,CAAC,MAC/D,MAAM,EAAE,2BAA2B;GAExC,aAAa,CAAC,mBAAmB,UAAU;EAC5C;EACD;GACE,MAAM;GACN,qBACE,OAAO,8DAAwD,CAAC,MAC7D,MAAM,EAAE,0BAA0B;GAEvC,aAAa,CAAC,mBAAmB,UAAU;EAC5C;EACD;GACE,MAAM;GACN,qBACE,OAAO,+DAA0D,CAAC,MAC/D,MAAM,EAAE,2BAA2B;EAEzC;EACD;GACE,MAAM;GACN,qBACE,OAAO,4DAAoD,CAAC,MACzD,MAAM,EAAE,wBAAwB;GAErC,aAAa,CAAC,iBAAiB;EAChC;EACD;GACE,MAAM;GACN,YAAY;GACZ,WAAW;EACZ;CACF;AACF,CACF;AAOD,MAAa,wBAAgC,CAC3C;CACE,MAAM;CACN,aAAa,CAAC,SAAS;CACvB,SAAS,EACP,cAAc,yBAAyB;EACrC,SAAS,CAAC,QAAQ,gBAAgB;EAClC,kBAAkB;GAAE,GAAG;GAAe,GAAG;EAAe;CACzD,CAAA,EACF;CACD,qBACE,OAAO,8DAAwD,CAAC,MAC7D,MAAM,EAAE,2BAA2B;CAExC,UAAU;EAER;GACE,MAAM;GACN,aAAa,CAAC,gBAAgB,iBAAiB,IAAI,CAAC;GACpD,UAAU;IACR;KACE,MAAM;KACN,qBACE,OAAO,oDAAqC,CAAC,MAC1C,MAAM,EAAE,iBAAiB;IAE/B;IACD;KACE,MAAM;KACN,qBACE,OAAO,oDAAqC,CAAC,MAC1C,MAAM,EAAE,iBAAiB;IAE/B;IACD;KACE,MAAM;KACN,qBACE,OAAO,oDAAqC,CAAC,MAC1C,MAAM,EAAE,iBAAiB;IAE/B;GACF;EACF;EAED;GACE,MAAM;GACN,aAAa,CACX,qBACA,gBAAgB,oBAAoB,IAAI,CACzC;GACD,UAAU;IACR;KACE,MAAM;KACN,qBACE,OAAO,uDAA0C,CAAC,MAC/C,MAAM,EAAE,oBAAoB;IAElC;IACD;KACE,MAAM;KACN,qBACE,OAAO,uDAA0C,CAAC,MAC/C,MAAM,EAAE,oBAAoB;IAElC;IACD;KACE,MAAM;KACN,qBACE,OAAO,uDAA0C,CAAC,MAC/C,MAAM,EAAE,oBAAoB;IAElC;GACF;EACF;EAED;GACE,MAAM;GACN,aAAa,CACX,qBACA,gBAAgB,mBAAmB,IAAI,CACxC;GACD,UAAU;IACR;KACE,MAAM;KACN,qBACE,OAAO,sDAAwC,CAAC,MAC7C,MAAM,EAAE,mBAAmB;IAEjC;IACD;KACE,MAAM;KACN,qBACE,OAAO,sDAAwC,CAAC,MAC7C,MAAM,EAAE,mBAAmB;IAEjC;IACD;KACE,MAAM;KACN,qBACE,OAAO,sDAAwC,CAAC,MAC7C,MAAM,EAAE,mBAAmB;IAEjC;GACF;EACF;EAED;GACE,MAAM;GACN,aAAa,CAAC,gBAAgB,+BAA+B,IAAI,CAAC;GAClE,qBACE,OAAO,6DAAsD,CAAC,MAC3D,MAAM,EAAE,yBAAyB;EAEvC;EAED;GACE,MAAM;GACN,kBAAkB,gCAA+B;GACjD,WAAW;EACZ;CACF;AACF,CACF;AAMD,MAAa,iBAAyB,CACpC;CACE,MAAM;CACN,aAAa,CAAC,SAAS;CACvB,SAAS,EACP,cAAc,yBAAyB;EACrC,SAAS,CAAC,QAAQ,SAAS;EAC3B,kBAAkB;GAAE,GAAG;GAAe,GAAG;EAAe;CACzD,CAAA,EACF;CACD,qBACE,OAAO,uDAA0C,CAAC,MAC/C,MAAM,EAAE,oBAAoB;AAElC,CACF;ACtPD,IAAa,yBAAb,MAAa,uBAAsB;CAChB,YAAY,OAAO,gBAAgB;CAE3C,qBAAkD,eAAc;EACvE,MAAM,UAAU,KAAK,UAAU,QAAO;EACtC,IAAI,SACF,OAAO;GACL,IAAI,QAAQ;GACZ,MAAM,QAAQ;GACd,MAAM,QAAQ,QAAQ;GACtB,SAAS,QAAQ,UAAU;EAC5B;EAEH,OAAO;CACT,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,qBAAA,CAAA,+BAAA,CAAA,CAAA;CAEO,oBAAgD,eAAc;EACrE,MAAM,SAAS,KAAK,UAAU,OAAM;EACpC,IAAI,QACF,OAAO;GACL,IAAI,OAAO;GACX,MAAM,OAAO;GACb,MAAM,OAAO,QAAQ;GACrB,SAAS,OAAO,UAAU;EAC3B;EAEH,OAAO;CACT,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,oBAAA,CAAA,+BAAA,CAAA,CAAA;CAEO,gBAAgD,eAAc;EACrE,MAAM,OAAO,KAAK,UAAU,KAAI;EAChC,IAAI,MACF,OAAO;GACL,IAAI,KAAK;GACT,MAAM,KAAK,QAAQ,KAAK,UAAU,SAAQ;GAC1C,OAAO,KAAK;EACb;EAEH,OAAO;CACT,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,gBAAA,CAAA,+BAAA,CAAA,CAAA;CAvCS,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAsB,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAtB,OAAA,QAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;CAAsB,CAAA;;AAAtB,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAsB,YAAA,CAAA,EADlC,MAAA,QAAA,CAAA;;AAgDD,IAAa,uBAAb,MAAa,qBAAoB;CACd,UAAU,OAAO,cAAc;CAC/B,YAAY,OAAO,gBAAgB;CACnC,SAAS,OAAO,MAAM;CAEvC,SAAM;EACJ,OAAO,KAAK,QAAQ,OAAM,CAAE,CAAC,KAC3B,YAAS;GACP,KAAK,UAAU,WAAU;EAC3B,CAAC,CAAC;CAEN;CAEA,cAAc,SAAiB;EAC7B,IAAI,SAAS;GACX,MAAM,aAAa,KAAK,OAAO;GAC/B,KAAK,UAAU,gBAAgB,UAAU;EAC3C,OACE,KAAK,UAAU,gBAAe;CAElC;CAEA,cAAc,WAAmB,UAAgB;EAC/C,OAAO,KAAK,QAAQ,cAAc;GAAE;GAAW;EAAQ,CAAE,CAAC,CAAC,KACzD,YAAS;GACP,OAAO,SAAS,OAAM;EACxB,CAAC,CAAC;CAEN;CAEA,iBAAc;EACZ,OAAO,KAAK,QAAQ,aAAY,CAAE,CAAC,KACjC,OAAK,cACF,SAAS,QAAQ,CAAA,EAAA,CAAI,KAAK,aAAa;GACtC,IAAI,QAAQ;GACZ,MAAM,QAAQ;GACd,MAAM,QAAQ,QAAQ;GACtB,SAAS,QAAQ,UAAU;EAC5B,EAAC,CAAC,CACJ;CAEL;CAEA,qBAAqB,WAAiB;EACpC,OAAO,KAAK,QAAQ,mBAAmB,SAAS,CAAC,CAAC,KAChD,OAAK,cACF,SAAS,QAAQ,CAAA,EAAA,CAAI,KAAK,YAAY;GACrC,IAAI,OAAO;GACX,MAAM,OAAO;GACb,MAAM,OAAO,QAAQ;GACrB,SAAS,OAAO,UAAU;GAC1B,UAAU,OAAO,YAAY;GAC7B,QAAQ,OAAO,UAAU;GACzB,iBAAiB,OAAO;EACzB,EAAC,CAAC,CACJ;CAEL;CAzDW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAoB,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAApB,OAAA,QAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;CAAoB,CAAA;;AAApB,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAoB,YAAA,CAAA,EADhC,MAAA,QAAA,CAAA;;AC1CD,SAAS,oBAAiB;CACxB,OAAO;EACL,SAAS;EACT,SAAS;EACT,MAAM,CAAA;EACN,MAAM;GAAE,OAAO;GAAG,MAAM;GAAG,UAAU;GAAG,OAAO;EAAC;CACjD;AACH;AAEA,SAAS,gBACP,UACA,QAAkC;CAElC,OAAO;EACL,SAAS,SAAS;EAClB,SAAS,SAAS;EAClB,YAAY,SAAS;EACrB,kBAAkB,SAAS;EAC3B,OAAO,SAAS,QAAQ,CAAA,EAAA,CAAI,IAAI,MAAM;EACtC,MAAM,SAAS;CAChB;AACH;AAOA,IAAa,0BAAb,MAAa,wBAAuB;CACjB,UAAU,OAAO,cAAc;CAEhD,SAAS,QAMR;EACC,MAAM,EAAE,QAAQ,MAAM,UAAU,UAAU,GAAG,iBAAiB,UAAU,CAAA;EAExE,MAAM,YAAY;GAChB,YAAY;IACV,aAAa,QAAQ;IACrB,UAAU,YAAY;GACvB;GACD,QAAQ;IACN,GAAI,aAAa,UAAa,EAAE,SAAQ;IAGxC,GAAG,OAAO,YACR,OAAO,QAAQ,YAAY,CAAC,CAAC,QAC1B,CAAC,GAAG,OAAO,MAAM,UAAa,MAAM,IAAI,CAC1C;GAEJ;GACD,MAAM,EAAE,MAAM,MAAc;EAC7B;EAED,OAAO,KAAK,QAAQ,OAAO,WAAW,UAAU,EAAE,CAAC,CAAC,KAClD,KAAK,aACH,gBAAgB,WAAW,UAAU;GACnC,IAAI,KAAK;GACT,MAAM,KAAK,QAAQ,KAAK;GACxB,OAAO,KAAK;EACb,EAAC,CAAC,CACJ;CAEL;CAEA,cAAc,KAAa;EACzB,IAAI,IAAI,WAAW,GACjB,OAAO,KAAK,QAAQ,QAAQ,kBAAiB,CAAkB,CAAC;EAGlE,OAAO,KAAK,KAAK,QAAQ,UAAU,KAAK;GAAC;GAAM;GAAQ;EAAO,CAAC,CAAC,CAAC,CAAC,KAChE,KAAK,aACH,gBAAgB,WAAW,UAAU;GACnC,IAAI,KAAK;GACT,MAAM,KAAK,QAAQ,KAAK;GACxB,OAAO,KAAK;EACb,EAAC,CAAC,CACJ;CAEL;CAvDW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAuB,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAvB,OAAA,QAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAuB,cAAA;CAAA,CAAA;;AAAvB,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAuB,YAAA,CAAA;EADnC,MAAA;EAAQ,MAAA,CAAA,EAAE,cAAc,MAAK,CAAE;;;AAgEhC,IAAa,gCAAb,MAAa,8BAA6B;CACvB,aAAa,OAAO,iBAAiB;CACrC,YAAY,OAAO,gBAAgB;CAEpD,aAAa,QAIZ;EACC,MAAM,YAAY;GAChB,YAAY;IACV,aAAa,QAAQ,QAAQ;IAC7B,UAAU,QAAQ,YAAY;GAC/B;GACD,MAAM,EAAE,MAAM,MAAc;EAC7B;EAED,OAAO,KAAK,KAAK,WAAW,OAAO,WAAW,QAAQ,UAAU,EAAE,CAAC,CAAC,CAAC,KACnE,KAAK,aACH,gBAAgB,WAAW,aAAa;GACtC,IAAI,QAAQ;GACZ,MAAM,QAAQ;GACd,MAAM,QAAQ;EACf,EAAC,CAAC,CACJ;CAEL;CAEA,kBAAkB,KAAa;EAC7B,IAAI,IAAI,WAAW,GACjB,OAAO,KAAK,QAAQ,QAAQ,kBAAiB,CAAqB,CAAC;EAGrE,OAAO,KAAK,KAAK,WAAW,UAAU,KAAK;GAAC;GAAM;GAAQ;EAAM,CAAC,CAAC,CAAC,CAAC,KAClE,KAAK,aACH,gBAAgB,WAAW,aAAa;GACtC,IAAI,QAAQ;GACZ,MAAM,QAAQ;GACd,MAAM,QAAQ;EACf,EAAC,CAAC,CACJ;CAEL;CAEA,iBAAiB,KAAa;EAC5B,IAAI,IAAI,WAAW,GACjB,OAAO,KAAK,QAAQ,QAAQ,kBAAiB,CAAoB,CAAC;EAGpE,OAAO,KAAK,KAAK,UAAU,UAAU,KAAK,CAAC,MAAM,MAAM,CAAC,CAAC,CAAC,CAAC,KACzD,KAAK,aACH,gBAAgB,WAAW,YAAY;GAAE,IAAI,OAAO;GAAI,MAAM,OAAO;EAAI,EAAG,CAAC,CAC9E;CAEL;CAtDW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAA6B,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAA7B,OAAA,QAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAA6B,cAAA;CAAA,CAAA;;AAA7B,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAA6B,YAAA,CAAA;EADzC,MAAA;EAAQ,MAAA,CAAA,EAAE,cAAc,MAAK,CAAE;;;AA+DhC,IAAa,oCAAb,MAAa,kCAAiC;CAC3B,oBAAoB,OAAO,wBAAwB;CAEpE,yBACE,QACA,WAAkB;EAElB,OAAO,KAAK,kBAAkB,gBAAgB,QAAQ,SAAS;CACjE;CAEA,0BAA0B,QAAc;EACtC,OAAO,KAAK,kBAAkB,iBAAiB,MAAM,CAAC,CAAC,KACrD,KAAK,cAAc;GACjB,GAAG;GACH,OAAO,SAAS,QAAQ,CAAA,EAAA,CAAI,KAAK,OAAO;IAAE,IAAI,EAAE;IAAW,MAAM,EAAE;GAAW,EAAG;EAClF,EAAC,CAAC;CAEP;CAjBW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAiC,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAjC,OAAA,QAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAiC,cAAA;CAAA,CAAA;;AAAjC,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAiC,YAAA,CAAA;EAD7C,MAAA;EAAQ,MAAA,CAAA,EAAE,cAAc,MAAK,CAAE;;;AA0BhC,IAAa,2BAAb,MAAa,yBAAwB;CAClB,YAAY,OAAO,gBAAgB;CACnC,WAAW,OAAO,eAAe;CAElD,IAAI,kBAAe;EACjB,OAAO,KAAK,UAAU;CACxB;CAEA,aAAU;EACR,OAAO,KAAK,SAAS,WAAU,CAAE,CAAC,KAAK,UAAU,MAAS,CAAC;CAC7D;CAVW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAwB,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAxB,OAAA,QAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAwB,cAAA;CAAA,CAAA;;AAAxB,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAwB,YAAA,CAAA;EADpC,MAAA;EAAQ,MAAA,CAAA,EAAE,cAAc,MAAK,CAAE;;;AC/MhC,SAAgB,+BAA4B;CAC1C,OAAO,CACL;EAAE,SAAS;EAAmB,UAAU;CAAsB,GAC9D;EAAE,SAAS;EAAiB,UAAU;CAAoB,CAC3D;AACH;ACAA,SAAgB,uBAAoB;CAClC,OAAO;EACL;GAAE,SAAS;GAAe,UAAU;EAAuB;EAC3D;GAAE,SAAS;GAAsB,UAAU;EAA6B;EACxE;GAAE,SAAS;GAA0B,UAAU;EAAiC;EAChF;GAAE,SAAS;GAAqB,UAAU;EAAwB;CACnE;AACH;ACsFA,IAAa,sCAAb,MAAa,oCAAmC;CACrC,mBAAmB;CAEX,gBAAgB,OAAO,wBAAwB;CAC/C,sBAAsB,OAAO,mBAAmB;CAChD,iBAAiB,OAAO,cAAc;CACtC,mBAAmB,OAAO,kBAAkB,EAC3D,UAAU,KACX,CAAA;CAEO,EAAE,KAAa,QAAgC;EACrD,OAAO,KAAK,kBAAkB,UAAU,KAAK,MAAM,KAAK;CAC1D;CAES,UAAU,MAAM,SAAmB,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CACnC,SAAS,MAAM,SAA0B,GAAA,YAAA,CAAA,EAAA,WAAA,SAAA,CAAA,+BAAA,CAAA,CAAA;CACzC,SAAS,OAAM;CAEf,YAAY,OAAO,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,YAAA,CAAA,+BAAA,CAAA,CAAA;CACzB,aAAa,OAAO,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;CAC1B,QAAQ,OAA+B,CAAA,GAAG,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CAEnD,cAAA;EACE,aAAY;GACV,IAAI,KAAK,QAAO,KAAM,KAAK,OAAM,GAC/B,KAAK,UAAS;EAElB,CAAC;CACH;CAEQ,MAAM,YAAS;EACrB,MAAM,SAAS,KAAK,OAAM;EAC1B,IAAI,CAAC,QAAQ;EAEb,KAAK,UAAU,IAAI,IAAI;EACvB,IAAI;GACF,MAAM,WAAW,MAAM,eAAe,KAAK,cAAc,eAAe,OAAO,EAAE,CAAC;GAClF,KAAK,MAAM,IAAI,SAAS,QAAQ,CAAA,CAAE;EACpC,QAAQ,CAER,UAAU;GACR,KAAK,UAAU,IAAI,KAAK;EAC1B;CACF;CAEA,SAAS,MAA0B;EACjC,MAAM,SAAS,KAAK,OAAM;EAC1B,IAAI,CAAC,QAAQ;EAEb,KAAK,oBAAoB,QAAQ;GAC/B,SAAS,KAAK,EAAE,4CAA4C,EAC1D,MAAM,KAAK,SACZ,CAAA;GACD,QAAQ,KAAK,EAAE,kCAAkC;GACjD,MAAM;GACN,wBAAwB;GACxB,QAAQ,YAAW;IACjB,KAAK,WAAW,IAAI,IAAI;IACxB,IAAI;KACF,MAAM,WAAW,MAAM,eACrB,KAAK,cAAc,qBAAqB,KAAK,QAAQ,OAAO,EAAE,CAAC;KAGjE,IAAI,SAAS,SAAS;MACpB,KAAK,MAAM,QAAQ,SAAS,KAAK,QAAQ,MAAM,EAAE,OAAO,KAAK,EAAE,CAAC;MAChE,KAAK,eAAe,IAAI;OACtB,UAAU;OACV,SAAS,KAAK,EAAE,gBAAgB;OAChC,QAAQ,UAAU,aACd,KAAK,EAAE,SAAS,YAAY,SAAS,gBAAgB,IACpD,UAAU,WAAW;MAC3B,CAAA;KACH;IACF,QAAQ,CAER,UAAU;KACR,KAAK,WAAW,IAAI,KAAK;IAC3B;GACF;EACD,CAAA;CACH;CAEA,UAAO;EACL,KAAK,OAAO,KAAI;CAClB;CApFW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAmC,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAnC,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAmC,cAAA;EAAA,UAAA;EAAA,QAAA;GAAA,SAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,QAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;EAAA;EAAA,SAAA,EAAA,QAAA,SAAA;EAAA,UAAA;EAAA,UAjEpC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+DT,UAAA;EAAA,cAAA;GAAA;IAAA,MAAA;IAAA,MAvEC;IAAe,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;IAAA,SAAA;KAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MACf;IAAgB,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAChB;IAAwB,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MACxB;IAAgB,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAChB;IAAe,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MACf;IAAsB,UAAA;IAAA,QAAA,CAAA,eAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MACtB;IAAa,MAAA;GAAA;EAAA;CAAA,CAAA;;AAmEJ,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAmC,YAAA,CAAA;EA5E/C,MAAA;EAAU,MAAA,CAAA;GACT,UAAU;GACV,SAAS;IACP;IACA;IACA;IACA;IACA;IACA;IACA;GACD;GACD,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgEX,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;ACCD,IAAa,uCAAb,MAAa,qCAAoC;CACtC,mBAAmB;CAEX,gBAAgB,OAAO,wBAAwB;CAC/C,sBAAsB,OAAO,mBAAmB;CAChD,iBAAiB,OAAO,cAAc;CACtC,mBAAmB,OAAO,kBAAkB,EAC3D,UAAU,KACX,CAAA;CAEO,EAAE,KAAa,QAAgC;EACrD,OAAO,KAAK,kBAAkB,UAAU,KAAK,MAAM,KAAK;CAC1D;CAES,UAAU,MAAM,SAAmB,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CACnC,UAAU,MAAM,SAA2B,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CAC3C,SAAS,OAAM;CAEf,YAAY,OAAO,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,YAAA,CAAA,+BAAA,CAAA,CAAA;CACzB,aAAa,OAAO,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;CAC1B,QAAQ,OAAgC,CAAA,GAAG,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CAEpD,cAAA;EACE,aAAY;GACV,IAAI,KAAK,QAAO,KAAM,KAAK,QAAO,GAChC,KAAK,UAAS;EAElB,CAAC;CACH;CAEQ,MAAM,YAAS;EACrB,MAAM,UAAU,KAAK,QAAO;EAC5B,IAAI,CAAC,SAAS;EAEd,KAAK,UAAU,IAAI,IAAI;EACvB,IAAI;GACF,MAAM,WAAW,MAAM,eAAe,KAAK,cAAc,gBAAgB,QAAQ,EAAE,CAAC;GACpF,KAAK,MAAM,IAAI,SAAS,QAAQ,CAAA,CAAE;EACpC,QAAQ,CAER,UAAU;GACR,KAAK,UAAU,IAAI,KAAK;EAC1B;CACF;CAEA,SAAS,MAA2B;EAClC,MAAM,UAAU,KAAK,QAAO;EAC5B,IAAI,CAAC,SAAS;EAEd,KAAK,oBAAoB,QAAQ;GAC/B,SAAS,KAAK,EAAE,4CAA4C,EAC1D,MAAM,KAAK,SACZ,CAAA;GACD,QAAQ,KAAK,EAAE,kCAAkC;GACjD,MAAM;GACN,wBAAwB;GACxB,QAAQ,YAAW;IACjB,KAAK,WAAW,IAAI,IAAI;IACxB,IAAI;KACF,MAAM,WAAW,MAAM,eACrB,KAAK,cAAc,sBAAsB,KAAK,QAAQ,QAAQ,EAAE,CAAC;KAGnE,IAAI,SAAS,SAAS;MACpB,KAAK,MAAM,QAAQ,SAAS,KAAK,QAAQ,MAAM,EAAE,OAAO,KAAK,EAAE,CAAC;MAChE,KAAK,eAAe,IAAI;OACtB,UAAU;OACV,SAAS,KAAK,EAAE,gBAAgB;OAChC,QAAQ,UAAU,aACd,KAAK,EAAE,SAAS,YAAY,SAAS,gBAAgB,IACpD,UAAU,WAAW;MAC3B,CAAA;KACH;IACF,QAAQ,CAER,UAAU;KACR,KAAK,WAAW,IAAI,KAAK;IAC3B;GACF;EACD,CAAA;CACH;CAEA,UAAO;EACL,KAAK,OAAO,KAAI;CAClB;CApFW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAoC,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAApC,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAoC,cAAA;EAAA,UAAA;EAAA,QAAA;GAAA,SAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,SAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;EAAA;EAAA,SAAA,EAAA,QAAA,SAAA;EAAA,UAAA;EAAA,UAjErC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+DT,UAAA;EAAA,cAAA;GAAA;IAAA,MAAA;IAAA,MAvEC;IAAe,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;IAAA,SAAA;KAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MACf;IAAgB,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAChB;IAAwB,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MACxB;IAAgB,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAChB;IAAe,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MACf;IAAsB,UAAA;IAAA,QAAA,CAAA,eAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MACtB;IAAa,MAAA;GAAA;EAAA;CAAA,CAAA;;AAmEJ,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAoC,YAAA,CAAA;EA5EhD,MAAA;EAAU,MAAA,CAAA;GACT,UAAU;GACV,SAAS;IACP;IACA;IACA;IACA;IACA;IACA;IACA;GACD;GACD,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgEX,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;ACJD,IAAa,8BAAb,MAAa,4BAA2B;CACrB,aAAa,OAAO,UAAU;CAC9B,YAAY,OAAO,oBAAoB;CACvC,iBAAiB,OAAO,cAAc;CACtC,WAAW,OAAO,eAAe;CACjC,WAAW,OAAO,QAAQ;CAC1B,mBAAmB,OAAO,kBAAkB,EAC3D,UAAU,KACX,CAAA;CAEQ,YAAY,MAAc,IAAG,GAAA,YAAA,CAAA,EAAA,WAAA,YAAA,CAAA,+BAAA,CAAA,CAAA;CAE7B,eAAe;CAEP,aAAa,OAA8B,CAAA,GAAG,GAAA,YAAA,CAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;CACtD,YAAY,KAAK,WAAW,WAAU;CAE9B,mBAAmB,OAAkC,MAAK,GAAA,YAAA,CAAA,EAAA,WAAA,mBAAA,CAAA,+BAAA,CAAA,CAAA;CAClE,kBAAkB,KAAK,iBAAiB,WAAU;CAElD,aAAa,eAAe,KAAK,UAAS,CAAE,CAAC,UAAU,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;CAEzD,cAAc,eAAc;EACnC,QAAQ,KAAK,UAAS,CAAE,CAAC,QAAzB;GACE,KAAK,GACH,OAAO;GACT,KAAK,GACH,OAAO;GACT,SACE,OAAO;EACX;CACF,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,cAAA,CAAA,+BAAA,CAAA,CAAA;CAEF,cAAA;EACE,IAAI,KAAK,SAAS,UAAU;EAE5B,KAAK,UACF,aAAY,CAAE,CACd,KAAK,mBAAmB,KAAK,UAAU,CAAC,CAAC,CACzC,UAAU;GACT,OAAO,aAAa,KAAK,WAAW,IAAI,SAAS,QAAQ,CAAA,CAAE;GAC3D,aAAa,KAAK,WAAW,IAAI,CAAA,CAAE;EACpC,CAAA;CACL;CAEA,SAAS,UAA4B;EACnC,KAAK,iBAAiB,IAAI,QAAQ;EAClC,KAAK,UAAU,cAAc,KAAK,UAAS,CAAE;EAE7C,KAAK,UACF,UAAU,QAAQ,CAAC,CACnB,KAAK,mBAAmB,KAAK,UAAU,CAAC,CAAC,CACzC,UAAU;GACT,OAAO,aAAY;IACjB,MAAM,MAAM,SAAS,MAAM;IAC3B,IAAI,CAAC,KAAK;KACR,KAAK,iBAAiB,IAAI,IAAI;KAC9B;IACF;IACA,KAAK,WAAW,GAAG;GACrB;GACA,QAAQ,UAAS;IACf,KAAK,iBAAiB,IAAI,IAAI;IAC9B,MAAM,aAAa,OAAO,OAAO;IACjC,KAAK,eAAe,IAAI;KACtB,UAAU;KACV,SAAS,KAAK,UAAU,kBAAkB;KAC1C,QAAQ,aACJ,KAAK,UAAU,YAAY,EAAE,SAAQ,CAAE,IACvC,OAAO,OAAO;IACnB,CAAA;GACH;EACD,CAAA;CACL;CAEU,WAAW,KAAW;EAC9B,KAAK,SAAS,SAAS,OAAO,GAAG;CACnC;CAEQ,UACN,KACA,MAAsC;EAEtC,OAAO,KAAK,kBAAkB,UAAU,KAAK,IAAI,KAAK;CACxD;CApFW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAA2B,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAA3B,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAA2B,cAAA;EAAA,UAAA;EAAA,QAAA,EAAA,WAAA;GAAA,mBAAA;GAAA,YAAA;GAAA,UAAA;GAAA,YAAA;GAAA,mBAAA;EAAA,EAAA;EAAA,UAAA;EAAA,UA3E5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyET,UAAA;EAAA,cAAA,CAAA;GAAA,MAAA;GAAA,MA1ES;GAAgB,UAAA;GAAA,QAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;GAAA;EAAA,GAAA;GAAA,MAAA;GAAA,MAAE;GAAa,MAAA;EAAA,CAAA;CAAA,CAAA;;AA4E9B,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAA2B,YAAA,CAAA;EA9EvC,MAAA;EAAU,MAAA,CAAA;GACT,UAAU;GACV,SAAS,CAAC,kBAAkB,aAAa;GACzC,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA0EX,CAAA;;;;;;;;;;;;ACwDD,IAAa,sCAAb,MAAa,oCAAmC;CAC7B,YAAY,OAAO,gBAAgB;CACnC,gBAAgB,OAAO,wBAAwB;CAC/C,iBAAiB,OAAO,cAAc;CACtC,mBAAmB,OAAO,kBAAkB,EAC3D,UAAU,KACX,CAAA;CAEO,EAAE,KAAa,QAAgC;EACrD,OAAO,KAAK,kBAAkB,UAAU,KAAK,MAAM,KAAK;CAC1D;CAES,UAAU,MAAM,SAAmB,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CACnC,OAAO,MAAM,SAAwB,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CACrC,SAAS,OAAM;CACf,qBAAqB,OAAM;CAE3B,WAAW,OAAO,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,WAAA,CAAA,+BAAA,CAAA,CAAA;CACxB,oBAAoB,OAAsB,MAAK,GAAA,YAAA,CAAA,EAAA,WAAA,oBAAA,CAAA,+BAAA,CAAA,CAAA;CAE/C,oBAAoB,SAAQ;EAAA,GAAA,YAAA,EAAA,WAAA,oBAAA,+BAAA,CAAA;EACnC,cAAa;GACX,MAAM,OAAO,KAAK,KAAI;GACtB,IAAI,CAAC,KAAK,QAAO,KAAM,CAAC,MAAM,OAAO;GACrC,OAAO,EAAE,QAAQ,KAAK,GAAE;EAC1B;EACA,QAAQ,OAAO,EAAE,aAAY;GAC3B,MAAM,WAAW,MAAM,eACrB,KAAK,cAAc,iBAAiB,OAAQ,MAAM,CAAC;GAErD,KAAK,kBAAkB,IAAI,IAAI;GAC/B,QAAQ,SAAS,QAAQ,CAAA,EAAA,CAAI,KAAK,OAAO;IACvC,IAAI,EAAE;IACN,MAAM,EAAE;GACT,EAAC;EACJ;CAAC,CAAA;CAGM,mBAAmB,SAAQ;EAAA,GAAA,YAAA,EAAA,WAAA,mBAAA,+BAAA,CAAA;EAClC,cAAa;GACX,MAAM,OAAO,KAAK,KAAI;GACtB,MAAM,YAAY,KAAK,kBAAiB;GACxC,IAAI,CAAC,QAAQ,CAAC,WAAW,OAAO;GAChC,OAAO;IAAE,QAAQ,KAAK;IAAI;GAAS;EACrC;EACA,QAAQ,OAAO,EAAE,aAAY;GAC3B,MAAM,CAAC,kBAAkB,oBAAoB,MAAM,QAAQ,IAAI,CAC7D,KAAK,UAAU,OAAO;IACpB,YAAY;KAAE,aAAa;KAAG,UAAU;IAAI;IAC5C,QAAQ,EAAE,WAAW,OAAQ,UAAS;IACtC,QAAQ,CAAA;IACR,MAAM,CAAA;GACP,CAAA,GACD,eAAe,KAAK,cAAc,gBAAgB,OAAQ,QAAQ,OAAQ,SAAS,CAAC,CACrF,CAAA;GAED,MAAM,cAAc,IAAI,KAAK,iBAAiB,QAAQ,CAAA,EAAA,CAAI,KAAK,MAAM,EAAE,QAAQ,CAAC;GAEhF,QAAQ,iBAAiB,QAAQ,CAAA,EAAA,CAAI,KAAK,YAAY;IACpD,GAAG;IACH,YAAY,YAAY,IAAI,OAAO,EAAE;GACtC,EAAC;EACJ;CAAC,CAAA;CAGM,aAAa,eAAc;EAClC,MAAM,WAAW,KAAK,iBAAiB,MAAK,KAAM,CAAA;EAClD,OAAO,kBAAkB,QAAQ,CAAC,CAAC,KAAK,SAAS;GAC/C,GAAG;GACH,YAAY,cAAc,UAAU,IAAI,OAAO,QAAQ,CAAC,CACrD,KAAK,MAAM,EAAE,IAAI,CAAC,CAClB,KAAK,KAAK;EACd,EAAC;CACJ,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;CAEO,mBAAmB,eACpB,KAAK,iBAAiB,UAAS,KAAM,CAAC,KAAK,iBAAiB,MAAK,GACxE,GAAA,YAAA,CAAA,EAAA,WAAA,mBAAA,CAAA,+BAAA,CAAA,CAAA;CAED,MAAM,eACJ,QACA,YAAmB;EAEnB,MAAM,cAAc,KAAK,KAAI;EAC7B,IAAI,CAAC,aAAa;EAElB,KAAK,SAAS,IAAI,IAAI;EACtB,IAAI;GACF,MAAM,WAAW,MAAM,eACrB,aACI,KAAK,cAAc,mBAAmB,YAAY,IAAI,OAAO,EAAE,IAC/D,KAAK,cAAc,qBAAqB,YAAY,IAAI,OAAO,EAAE,CAAC;GAExE,IAAI,SAAS,SAAS;IACpB,KAAK,eAAe,IAAI;KACtB,UAAU;KACV,SAAS,KAAK,EAAE,gBAAgB;KAChC,QAAQ,SAAS,aACb,KAAK,EAAE,SAAS,YAAY,SAAS,gBAAgB,IACpD,SAAS,WAAW;IAC1B,CAAA;IACD,KAAK,mBAAmB,KAAI;IAC5B,KAAK,iBAAiB,OAAM;GAC9B;EACF,QAAQ,CACR,UAAU;GACR,KAAK,SAAS,IAAI,KAAK;EACzB;CACF;CAEA,UAAO;EACL,KAAK,OAAO,KAAI;CAClB;CAhHW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAmC,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAnC,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAmC,cAAA;EAAA,UAAA;EAAA,QAAA;GAAA,SAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,MAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;EAAA;EAAA,SAAA;GAAA,QAAA;GAAA,oBAAA;EAAA;EAAA,UAAA;EAAA,UA1GpC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwGT,UAAA;EAAA,cAAA;GAAA;IAAA,MAAA;IAAA,MAjHC;GAAW;GAAA;IAAA,MAAA;IAAA,MAAA,GAAA;IAAA,UAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAA,GAAA;IAAA,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;IAAA;IAAA,SAAA,CAAA,eAAA;IAAA,UAAA,CAAA,SAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MACX;IAAiB,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;IAAA,SAAA;KAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MACjB;IAAe,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;IAAA,SAAA;KAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MACf;IAAgB,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAChB;IAAwB,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MACxB;IAAe,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;IAAA,SAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAEf;IAAe,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MADf;IAAa,MAAA;GAAA;EAAA;CAAA,CAAA;;AA6GJ,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAmC,YAAA,CAAA;EAtH/C,MAAA;EAAU,MAAA,CAAA;GACT,UAAU;GACV,SAAS;IACP;IACA;IACA;IACA;IACA;IACA;IACA;IACA;GACD;GACD,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyGX,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AClDD,IAAa,uCAAb,MAAa,qCAAoC;CAC9B,aAAa,OAAO,iBAAiB;CACrC,gBAAgB,OAAO,wBAAwB;CAC/C,iBAAiB,OAAO,cAAc;CACtC,mBAAmB,OAAO,kBAAkB,EAC3D,UAAU,KACX,CAAA;CAEO,EAAE,KAAa,QAAgC;EACrD,OAAO,KAAK,kBAAkB,UAAU,KAAK,MAAM,KAAK;CAC1D;CAES,UAAU,MAAM,SAAmB,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CACnC,OAAO,MAAM,SAAwB,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CACrC,SAAS,OAAM;CACf,qBAAqB,OAAM;CAE3B,YAAY,OAAO,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,YAAA,CAAA,+BAAA,CAAA,CAAA;CACzB,WAAW,OAAO,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,WAAA,CAAA,+BAAA,CAAA,CAAA;CACxB,YAAY,OAAgC,CAAA,GAAG,GAAA,YAAA,CAAA,EAAA,WAAA,YAAA,CAAA,+BAAA,CAAA,CAAA;CAEhD,qCAAqB,IAAI,IAAG;CAEpC,cAAA;EACE,aAAY;GACV,IAAI,KAAK,QAAO,KAAM,KAAK,KAAI,GAC7B,KAAK,SAAQ;EAEjB,CAAC;CACH;CAEQ,MAAM,WAAQ;EACpB,MAAM,cAAc,KAAK,KAAI;EAC7B,IAAI,CAAC,aAAa;EAElB,KAAK,UAAU,IAAI,IAAI;EACvB,IAAI;GACF,MAAM,oBAAoB,MAAM,KAAK,WAAW,OAAO;IACrD,YAAY;KAAE,aAAa;KAAG,UAAU;IAAI;IAC5C,QAAQ,CAAA;IACR,QAAQ,CAAA;IACR,MAAM,CAAA;GACP,CAAA;GAED,MAAM,mBAAmB,MAAM,eAC7B,KAAK,cAAc,iBAAiB,YAAY,EAAE,CAAC;GAGrD,KAAK,mBAAmB,MAAK;GAC7B,IAAI,iBAAiB,MACnB,iBAAiB,KAAK,SAAS,eAAc;IAC3C,KAAK,mBAAmB,IAAI,WAAW,SAAS;GAClD,CAAC;GAGH,MAAM,uBACJ,kBAAkB,QAAQ,CAAA,EAAA,CAC1B,KAAK,aAAa;IAClB,GAAG;IACH,YAAY,KAAK,mBAAmB,IAAI,QAAQ,EAAE;GACnD,EAAC;GAEF,KAAK,UAAU,IAAI,mBAAmB;EACxC,QAAQ,CACR,UAAU;GACR,KAAK,UAAU,IAAI,KAAK;EAC1B;CACF;CAEA,MAAM,gBACJ,SACA,YAAmB;EAEnB,MAAM,cAAc,KAAK,KAAI;EAC7B,IAAI,CAAC,aAAa;EAElB,KAAK,SAAS,IAAI,IAAI;EACtB,IAAI;GACF,MAAM,WAAW,aACb,MAAM,eACJ,KAAK,cAAc,oBAAoB,YAAY,IAAI,QAAQ,EAAE,CAAC,IAEpE,MAAM,eACJ,KAAK,cAAc,sBAAsB,YAAY,IAAI,QAAQ,EAAE,CAAC;GAG1E,IAAI,SAAS,SAAS;IACpB,IAAI,YAAY,KAAK,mBAAmB,IAAI,QAAQ,EAAE;SACjD,KAAK,mBAAmB,OAAO,QAAQ,EAAE;IAE9C,KAAK,UAAU,QAAQ,SACrB,KAAK,KAAK,MAAO,EAAE,OAAO,QAAQ,KAAK;KAAE,GAAG;KAAG;IAAU,IAAK,CAAE,CAAC;IAGnE,KAAK,eAAe,IAAI;KACtB,UAAU;KACV,SAAS,KAAK,EAAE,gBAAgB;KAChC,QAAQ,UAAU,aACd,KAAK,EAAE,SAAS,YAAY,SAAS,gBAAgB,IACpD,UAAU,WAAW;IAC3B,CAAA;IACD,KAAK,mBAAmB,KAAI;GAC9B;EACF,QAAQ,CAGR,UAAU;GACR,KAAK,SAAS,IAAI,KAAK;EACzB;CACF;CAEA,UAAO;EACL,KAAK,OAAO,KAAI;CAClB;CAjHW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAoC,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAApC,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAoC,cAAA;EAAA,UAAA;EAAA,QAAA;GAAA,SAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,MAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;EAAA;EAAA,SAAA;GAAA,QAAA;GAAA,oBAAA;EAAA;EAAA,UAAA;EAAA,UA9DrC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4DT,UAAA;EAAA,cAAA;GAAA;IAAA,MAAA;IAAA,MAnEC;GAAW;GAAA;IAAA,MAAA;IAAA,MAAA,GAAA;IAAA,UAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAA,GAAA;IAAA,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;IAAA;IAAA,SAAA,CAAA,eAAA;IAAA,UAAA,CAAA,SAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MACX;IAAiB,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;IAAA,SAAA;KAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MACjB;IAAe,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;IAAA,SAAA;KAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MACf;IAAgB,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAChB;IAAwB,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MACxB;IAAa,MAAA;GAAA;EAAA;CAAA,CAAA;;AAgEJ,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAoC,YAAA,CAAA;EAxEhD,MAAA;EAAU,MAAA,CAAA;GACT,UAAU;GACV,SAAS;IACP;IACA;IACA;IACA;IACA;IACA;GACD;GACD,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6DX,CAAA"}
|
|
1
|
+
{"version":3,"file":"flusys-ng-auth.mjs","names":[],"sources":["../../../projects/ng-auth/enums/social-provider.enum.ts","../../../projects/ng-auth/interfaces/auth.interface.ts","../../../projects/ng-auth/services/auth-api.service.ts","../../../projects/ng-auth/services/auth-state.service.ts","../../../projects/ng-auth/services/auth-init.service.ts","../../../projects/ng-auth/services/branch-api.service.ts","../../../projects/ng-auth/services/company-api.service.ts","../../../projects/ng-auth/constants/auth-endpoints.const.ts","../../../projects/ng-auth/services/social-auth-api.service.ts","../../../projects/ng-auth/services/social-auth-config-api.service.ts","../../../projects/ng-auth/services/token-refresh-state.service.ts","../../../projects/ng-auth/providers/auth-extension.providers.ts","../../../projects/ng-auth/services/password-policy.service.ts","../../../projects/ng-auth/services/email-policy.service.ts","../../../projects/ng-auth/services/user-api.service.ts","../../../projects/ng-auth/services/user-permission-api.service.ts","../../../projects/ng-auth/guards/auth.guard.ts","../../../projects/ng-auth/interceptors/auth.interceptor.ts","../../../projects/ng-auth/interceptors/token-refresh.interceptor.ts","../../../projects/ng-auth/constants/messages.ts","../../../projects/ng-auth/routes/auth.routes.ts","../../../projects/ng-auth/adapters/auth-layout-providers.adapter.ts","../../../projects/ng-auth/adapters/auth-shared-providers.adapter.ts","../../../projects/ng-auth/providers/auth-layout.providers.ts","../../../projects/ng-auth/providers/auth-providers.ts","../../../projects/ng-auth/components/branch-permitted-users-dialog.component.ts","../../../projects/ng-auth/components/company-permitted-users-dialog.component.ts","../../../projects/ng-auth/components/social-login-buttons.component.ts","../../../projects/ng-auth/components/user-branch-permission-dialog.component.ts","../../../projects/ng-auth/components/user-company-permission-dialog.component.ts"],"sourcesContent":["export enum SocialProviderEnum {\n GOOGLE = 'google',\n FACEBOOK = 'facebook',\n LINKEDIN = 'linkedin',\n MICROSOFT = 'microsoft',\n}\n\nexport const SOCIAL_PROVIDERS = [\n SocialProviderEnum.GOOGLE,\n SocialProviderEnum.FACEBOOK,\n SocialProviderEnum.LINKEDIN,\n SocialProviderEnum.MICROSOFT,\n] as const;\n","import { ISingleResponse } from '@flusys/ng-shared';\n\nexport interface ILoginRequest {\n email: string;\n password: string;\n rememberMe?: boolean;\n}\n\nexport interface IRegistrationRequest {\n name: string;\n email: string;\n password: string;\n phone?: string;\n companySlug?: string;\n branchSlug?: string;\n newCompanyName?: string;\n newCompanyPhone?: string;\n newCompanyAddress?: string;\n additionalFields?: Record<string, unknown>;\n}\n\nexport interface ISelectRequest {\n sessionId: string;\n companyId: string;\n branchId: string;\n rememberMe?: boolean;\n}\n\nexport interface ISwitchCompanyRequest {\n companyId: string;\n branchId: string;\n}\n\nexport interface IChangePasswordRequest {\n currentPassword: string;\n newPassword: string;\n}\n\nexport interface IUserInfo {\n id: string;\n email: string;\n name?: string;\n phone?: string | null;\n profilePictureId?: string | null;\n companyId?: string;\n branchId?: string;\n companyLogoId?: string;\n branchLogoId?: string;\n}\n\nexport interface ICompanyInfo {\n id: string;\n name: string;\n slug?: string;\n logoId?: string | null;\n}\n\nexport interface IBranchInfo {\n id: string;\n name: string;\n slug?: string;\n logoId?: string | null;\n}\n\nexport interface IBranchSelectionInfo {\n id: string;\n name: string;\n slug: string;\n logoId?: string | null;\n parentId?: string | null;\n serial?: number | null;\n displayParentId?: string | null;\n}\n\nexport interface ICompanyWithBranches {\n id: string;\n name: string;\n slug: string;\n logoId?: string | null;\n branches: IBranchSelectionInfo[];\n}\n\n// ─── Data-level interfaces (what's inside `data`) ─────────────────────────────\n\nexport interface ILoginData {\n accessToken: string;\n refreshToken?: string;\n user: IUserInfo;\n company?: ICompanyInfo;\n branch?: IBranchInfo;\n}\n\nexport interface IMeData {\n user: IUserInfo;\n company?: ICompanyInfo;\n branch?: IBranchInfo;\n}\n\nexport interface IRegistrationData {\n accessToken?: string;\n refreshToken?: string;\n user: IUserInfo;\n company?: ICompanyInfo;\n branch?: IBranchInfo;\n requiresEmailVerification?: boolean;\n}\n\nexport interface ICompanySelectionData {\n requiresSelection: true;\n sessionId: string;\n expiresAt: Date | string;\n user: IUserInfo;\n companies: ICompanyWithBranches[];\n}\n\nexport interface IEmailVerificationData {\n requiresEmailVerification: true;\n email: string;\n}\n\n// ─── API response type aliases (FLUSYS envelope via ISingleResponse) ──────────\n\nexport type ILoginResponse = ISingleResponse<ILoginData>;\nexport type IMeResponse = ISingleResponse<IMeData>;\nexport type IRegistrationResponse = ISingleResponse<IRegistrationData>;\nexport type ICompanySelectionResponse = ISingleResponse<ICompanySelectionData>;\nexport type ILoginRequiresEmailVerification = ISingleResponse<IEmailVerificationData>;\nexport type IRefreshTokenResponse = ISingleResponse<{ accessToken: string }>;\n\n// ─── Union type for login endpoint response ────────────────────────────────────\n\nexport type AuthResponse = ISingleResponse<ILoginData | ICompanySelectionData | IEmailVerificationData>;\n\n// ─── Type guards ───────────────────────────────────────────────────────────────\n\nexport function isEmailVerificationRequired(response: AuthResponse): response is ILoginRequiresEmailVerification {\n return !!response.data && 'requiresEmailVerification' in response.data && response.data.requiresEmailVerification === true;\n}\n\nexport function isCompanySelectionResponse(response: AuthResponse): response is ICompanySelectionResponse {\n return !!response.data && 'requiresSelection' in response.data && response.data.requiresSelection === true;\n}\n\nexport function isLoginResponse(response: AuthResponse): response is ILoginResponse {\n return !!response.data && 'accessToken' in response.data;\n}\n","import { HttpClient } from '@angular/common/http';\nimport { inject, Service } from '@angular/core';\nimport { APP_CONFIG, getServiceUrl } from '@flusys/ng-core';\nimport { IMessageResponse, ISingleResponse } from '@flusys/ng-shared';\nimport { Observable } from 'rxjs';\nimport {\n AuthResponse,\n IBranchSelectionInfo,\n IChangePasswordRequest,\n ICompanyInfo,\n ILoginRequest,\n IMeResponse,\n IRefreshTokenResponse,\n IRegistrationRequest,\n IRegistrationResponse,\n ISelectRequest,\n ILoginResponse,\n ISwitchCompanyRequest,\n} from '../interfaces/auth.interface';\n\n@Service()\nexport class AuthApiService {\n private readonly appConfig = inject(APP_CONFIG);\n private readonly http = inject(HttpClient);\n private readonly baseUrl: string;\n\n constructor() {\n this.baseUrl = getServiceUrl(this.appConfig, 'auth');\n }\n\n login(data: ILoginRequest): Observable<AuthResponse> {\n return this.http.post<AuthResponse>(`${this.baseUrl}/login`, data);\n }\n\n register(data: IRegistrationRequest): Observable<IRegistrationResponse> {\n return this.http.post<IRegistrationResponse>(`${this.baseUrl}/register`, data);\n }\n\n select(data: ISelectRequest): Observable<ILoginResponse> {\n return this.http.post<ILoginResponse>(`${this.baseUrl}/select`, data);\n }\n\n switchCompany(data: ISwitchCompanyRequest): Observable<ILoginResponse> {\n return this.http.post<ILoginResponse>(`${this.baseUrl}/switch-company`, data);\n }\n\n getCompanies(): Observable<ISingleResponse<ICompanyInfo[]>> {\n return this.http.post<ISingleResponse<ICompanyInfo[]>>(`${this.baseUrl}/get-my-companies`, {});\n }\n\n getCompanyBranches(companyId: string): Observable<ISingleResponse<IBranchSelectionInfo[]>> {\n return this.http.post<ISingleResponse<IBranchSelectionInfo[]>>(`${this.baseUrl}/get-my-company-branches`, { companyId });\n }\n\n refresh(): Observable<IRefreshTokenResponse> {\n return this.http.post<IRefreshTokenResponse>(`${this.baseUrl}/refresh`, {});\n }\n\n me(): Observable<IMeResponse> {\n return this.http.post<IMeResponse>(`${this.baseUrl}/me`, {});\n }\n\n logout(): Observable<IMessageResponse> {\n return this.http.post<IMessageResponse>(`${this.baseUrl}/logout`, {});\n }\n\n changePassword(data: IChangePasswordRequest): Observable<IMessageResponse> {\n return this.http.post<IMessageResponse>(`${this.baseUrl}/change-password`, data);\n }\n\n forgotPassword(email: string): Observable<IMessageResponse> {\n return this.http.post<IMessageResponse>(`${this.baseUrl}/forgot-password`, { email });\n }\n\n resetPassword(token: string, newPassword: string): Observable<IMessageResponse> {\n return this.http.post<IMessageResponse>(`${this.baseUrl}/reset-password`, { token, newPassword });\n }\n\n resendVerification(email: string): Observable<IMessageResponse> {\n return this.http.post<IMessageResponse>(`${this.baseUrl}/resend-verification`, { email });\n }\n\n verifyEmail(token: string): Observable<IMessageResponse | IRegistrationResponse> {\n return this.http.post<IMessageResponse | IRegistrationResponse>(`${this.baseUrl}/verify-email`, { token });\n }\n}\n","import { computed, effect, inject, signal, Service } from '@angular/core';\nimport { Router } from '@angular/router';\nimport { APP_CONFIG } from '@flusys/ng-core';\nimport {\n PermissionValidatorService,\n PlatformService,\n} from '@flusys/ng-shared';\nimport {\n IBranchInfo,\n ICompanyInfo,\n ICompanySelectionData,\n ICompanyWithBranches,\n ILoginData,\n IUserInfo,\n} from '../interfaces/auth.interface';\n\n/**\n * Storage keys (static constants)\n * NOTE: Access token is NOT stored - kept in memory only for security (XSS protection)\n * Only token expiry is stored to know when refresh is needed on page load\n */\nconst STORAGE = {\n TOKEN_EXPIRY: 'tokenExpiresAt', // Store expiry time, not the token itself\n COMPANY_ID: 'selectedCompanyId',\n BRANCH_ID: 'selectedBranchId',\n} as const;\n\nconst SAVED_USER_NAME_KEY = 'savedUserName';\n\n/**\n * Auth State Service\n * Minimal signal-based state management for authentication\n */\n@Service()\nexport class AuthStateService {\n // DI Injection\n private readonly appConfig = inject(APP_CONFIG);\n private readonly router = inject(Router);\n private readonly platform = inject(PlatformService);\n private readonly permissionValidator = inject(PermissionValidatorService);\n\n // Core State (private writable, public readonly)\n private readonly _user = signal<IUserInfo | null>(null);\n private readonly _accessToken = signal<string>(''); // Memory-only, not persisted\n private readonly _tokenExpiresAt = signal<number | null>(null); // Token expiry timestamp\n private readonly _company = signal<ICompanyInfo | null>(null);\n private readonly _branch = signal<IBranchInfo | null>(null);\n\n readonly user = this._user.asReadonly();\n readonly accessToken = this._accessToken.asReadonly();\n readonly tokenExpiresAt = this._tokenExpiresAt.asReadonly();\n readonly company = this._company.asReadonly();\n readonly branch = this._branch.asReadonly();\n\n // Company Selection State (temporary during login flow)\n private readonly _selectionSessionId = signal<string | null>(null);\n private readonly _availableCompanies = signal<ICompanyWithBranches[]>([]);\n\n readonly selectionSessionId = this._selectionSessionId.asReadonly();\n readonly availableCompanies = this._availableCompanies.asReadonly();\n\n // Computed States\n readonly isAuthenticated = computed(\n () => !!this._accessToken() && !!this._user(),\n );\n readonly requiresCompanySelection = computed(\n () => !!this._selectionSessionId() && this._availableCompanies().length > 0,\n );\n readonly userName = computed(() => this._user()?.name ?? 'User');\n readonly companyName = computed(() => this._company()?.name ?? '');\n readonly branchName = computed(() => this._branch()?.name ?? '');\n\n /**\n * Check if token is expired or will expire soon (within 30 seconds).\n * Used to proactively refresh token before requests fail.\n */\n readonly isTokenExpired = computed(() => {\n const expiresAt = this._tokenExpiresAt();\n if (!expiresAt) return true;\n // Consider expired 30 seconds before actual expiry\n return Date.now() >= expiresAt - 30000;\n });\n\n // Config-derived states\n readonly tenantId = computed(\n () => this.appConfig.multiTenant.tenantId ?? null,\n );\n\n constructor() {\n // Auto-persist token expiry (NOT the token itself - security)\n effect(() => {\n const expiresAt = this._tokenExpiresAt();\n expiresAt\n ? this.store(STORAGE.TOKEN_EXPIRY, expiresAt.toString())\n : this.remove(STORAGE.TOKEN_EXPIRY);\n });\n\n // Auto-persist company/branch IDs\n effect(() => {\n const companyId = this._company()?.id;\n const branchId = this._branch()?.id;\n companyId\n ? this.store(STORAGE.COMPANY_ID, companyId)\n : this.remove(STORAGE.COMPANY_ID);\n branchId\n ? this.store(STORAGE.BRANCH_ID, branchId)\n : this.remove(STORAGE.BRANCH_ID);\n });\n\n // Persist display name for the login page's \"welcome back\" greeting\n effect(() => {\n const user = this._user();\n const name = user?.name?.trim() || user?.email;\n if (name) this.store(SAVED_USER_NAME_KEY, name);\n });\n\n // Load initial state from storage (expiry only, not token)\n this.loadFromStorage();\n }\n\n // ==========================================================================\n // State Management\n // ==========================================================================\n\n setLoginState(data: ILoginData): void {\n this._accessToken.set(data.accessToken);\n this._user.set(data.user);\n this._company.set(data.company ?? null);\n this._branch.set(data.branch ?? null);\n const expiry = this.decodeTokenExpiry(data.accessToken);\n this._tokenExpiresAt.set(expiry);\n this.clearSelectionState();\n }\n\n setSelectionState(data: ICompanySelectionData): void {\n this._selectionSessionId.set(data.sessionId);\n this._availableCompanies.set(data.companies);\n this._user.set(data.user);\n }\n\n clearSelectionState(): void {\n this._selectionSessionId.set(null);\n this._availableCompanies.set([]);\n }\n\n resetState(): void {\n this._user.set(null);\n this._accessToken.set('');\n this._tokenExpiresAt.set(null);\n this._company.set(null);\n this._branch.set(null);\n this.clearSelectionState();\n Object.values(STORAGE).forEach((key) => this.remove(key));\n this.permissionValidator.clearPermissions();\n }\n\n // ==========================================================================\n // Individual Setters (for external use where needed)\n // ==========================================================================\n\n setUser(user: IUserInfo | null): void {\n this._user.set(user);\n }\n\n setAccessToken(token: string): void {\n this._accessToken.set(token);\n // Decode token to get expiry time\n const expiry = this.decodeTokenExpiry(token);\n this._tokenExpiresAt.set(expiry);\n }\n\n setCompany(company: ICompanyInfo | null): void {\n this._company.set(company);\n }\n\n setBranch(branch: IBranchInfo | null): void {\n this._branch.set(branch);\n }\n\n // ==========================================================================\n // Navigation Helpers\n // ==========================================================================\n\n navigateToLogin(returnUrl?: string): void {\n this.router.navigate(\n ['/auth/login'],\n returnUrl ? { queryParams: { returnUrl } } : {},\n );\n }\n\n navigateAfterLogin(returnUrl?: string): void {\n // Validate returnUrl to prevent open redirect attacks\n const safeUrl = this.isValidReturnUrl(returnUrl) ? returnUrl : '/';\n this.router.navigateByUrl(safeUrl);\n }\n\n /** Validates a return URL to prevent open redirect attacks */\n private isValidReturnUrl(url: string | undefined): url is string {\n if (!url) return false;\n // Must start with '/' and not contain protocol indicators\n return url.startsWith('/') && !url.includes('://') && !url.startsWith('//');\n }\n\n // Storage accessors (used by components)\n getStoredCompanyId(): string | null {\n return this.get(STORAGE.COMPANY_ID);\n }\n\n getStoredBranchId(): string | null {\n return this.get(STORAGE.BRANCH_ID);\n }\n\n getSavedUserName(): string | null {\n return this.get(SAVED_USER_NAME_KEY);\n }\n\n // Storage helpers\n private loadFromStorage(): void {\n if (this.platform.isServer) return;\n // Load token expiry (NOT the token - it's memory-only for security)\n const expiryStr = this.get(STORAGE.TOKEN_EXPIRY);\n if (expiryStr) {\n this._tokenExpiresAt.set(parseInt(expiryStr, 10));\n }\n }\n\n /**\n * Decode JWT expiry without verification (client-side only).\n * Returns expiry timestamp in milliseconds.\n */\n private decodeTokenExpiry(token: string): number | null {\n try {\n if (!token) return null;\n const payload = token.split('.')[1];\n if (!payload) return null;\n // Convert base64url to base64 and add padding\n const base64 = payload.replace(/-/g, '+').replace(/_/g, '/');\n const padded = base64 + '='.repeat((4 - (base64.length % 4)) % 4);\n const decoded = JSON.parse(atob(padded));\n return decoded.exp ? decoded.exp * 1000 : null; // Convert to milliseconds\n } catch {\n return null;\n }\n }\n\n private store(key: string, value: string): void {\n if (!this.platform.isServer) localStorage.setItem(key, value);\n }\n\n private get(key: string): string | null {\n return !this.platform.isServer ? localStorage.getItem(key) : null;\n }\n\n private remove(key: string): void {\n if (!this.platform.isServer) localStorage.removeItem(key);\n }\n}\n","import { inject, signal, Service } from '@angular/core';\nimport { APP_CONFIG } from '@flusys/ng-core';\nimport {\n catchError,\n finalize,\n map,\n Observable,\n of,\n shareReplay,\n switchMap,\n tap,\n timeout,\n} from 'rxjs';\nimport { AuthApiService } from './auth-api.service';\nimport { AuthStateService } from './auth-state.service';\n\n@Service()\nexport class AuthInitService {\n private readonly authState = inject(AuthStateService);\n private readonly authApi = inject(AuthApiService);\n private readonly appConfig = inject(APP_CONFIG);\n\n private readonly _initialized = signal(false);\n readonly initialized = this._initialized.asReadonly();\n\n private initializationCache$: Observable<boolean> | null = null;\n\n initialize(): Observable<boolean> {\n if (this.authState.isAuthenticated() && this.authState.user()) {\n this._initialized.set(true);\n return of(true);\n }\n\n if (this.authState.requiresCompanySelection()) {\n this._initialized.set(true);\n return of(false);\n }\n\n if (this._initialized()) {\n return of(this.authState.isAuthenticated());\n }\n\n if (this.initializationCache$) {\n return this.initializationCache$;\n }\n\n this.initializationCache$ = this.authApi.refresh().pipe(\n timeout(5000),\n switchMap((refreshResponse) => {\n const accessToken = refreshResponse.data?.accessToken;\n if (!accessToken) return of(false);\n this.authState.setAccessToken(accessToken);\n return this.authApi.me().pipe(\n map((meResponse) => {\n const meData = meResponse.data;\n if (!meData) return false;\n const { user, company, branch } = meData;\n\n this.authState.setUser(user);\n\n if (this.appConfig.enableCompanyFeature) {\n this.authState.setCompany(company ?? null);\n this.authState.setBranch(branch ?? null);\n }\n\n return true;\n }),\n );\n }),\n\n tap(() => {\n this._initialized.set(true);\n }),\n\n catchError((err) => {\n this._initialized.set(true);\n\n const errorKey: string = err?.error?.messageKey ?? '';\n\n const companyErrorKeys = new Set([\n 'auth.company.required',\n 'auth.company.not.found',\n 'auth.company.no.access',\n 'auth.branch.not.found',\n 'auth.branch.no.access',\n ]);\n\n const isCompanyError = companyErrorKeys.has(errorKey);\n\n if (isCompanyError && this.appConfig.enableCompanyFeature) {\n this.authState.setUser(null);\n this.authState.setCompany(null);\n this.authState.setBranch(null);\n } else {\n this.authState.resetState();\n }\n\n return of(false);\n }),\n\n shareReplay({ bufferSize: 1, refCount: true }),\n\n finalize(() => {\n this.initializationCache$ = null;\n }),\n );\n\n return this.initializationCache$;\n }\n}\n","import { Service } from '@angular/core';\nimport { ApiResourceService } from '@flusys/ng-shared';\nimport {\n IBranch,\n ICreateBranchRequest,\n IUpdateBranchRequest,\n} from '../interfaces/branch.interface';\n\n/**\n * Branch API Service\n * Signal-based service for branch CRUD operations\n */\n@Service()\nexport class BranchApiService extends ApiResourceService<\n ICreateBranchRequest | IUpdateBranchRequest,\n IBranch\n> {\n constructor() {\n super('branch', 'administration');\n }\n\n fetchByCompany(companyId: string, search = ''): void {\n this.fetchList(search, { filter: { companyId } });\n }\n}\n","import { Service } from '@angular/core';\nimport { ApiResourceService } from '@flusys/ng-shared';\nimport {\n ICompany,\n ICreateCompanyRequest,\n IUpdateCompanyRequest,\n} from '../interfaces/company.interface';\n\n/**\n * Company API Service\n * Signal-based service for company CRUD operations\n */\n@Service()\nexport class CompanyApiService extends ApiResourceService<\n ICreateCompanyRequest | IUpdateCompanyRequest,\n ICompany\n> {\n constructor() {\n super('company', 'administration');\n }\n}\n","/**\n * Authentication API Endpoints\n *\n * Centralized endpoint definitions to prevent inconsistencies across interceptors\n * and services. All auth-related endpoints should be referenced from here.\n */\nexport const AUTH_ENDPOINTS = {\n LOGIN: '/auth/login',\n LOGOUT: '/auth/logout',\n REFRESH: '/auth/refresh',\n REGISTER: '/auth/register',\n ME: '/auth/me',\n SELECT: '/auth/select',\n SWITCH_COMPANY: '/auth/switch-company',\n CHANGE_PASSWORD: '/auth/change-password',\n VERIFY_EMAIL: '/auth/verify-email',\n FORGOT_PASSWORD: '/auth/forgot-password',\n RESET_PASSWORD: '/auth/reset-password',\n RESEND_VERIFICATION: '/auth/resend-verification',\n SOCIAL_CALLBACK: '/auth/social/callback',\n} as const;\n\n/** Check if a URL matches a specific endpoint */\nexport function isEndpoint(url: string, endpoint: string): boolean {\n return url.includes(endpoint);\n}\n","import { HttpClient } from '@angular/common/http';\nimport { inject, Service } from '@angular/core';\nimport { APP_CONFIG, getServiceUrl } from '@flusys/ng-core';\nimport { ISingleResponse, PlatformService } from '@flusys/ng-shared';\nimport { Observable } from 'rxjs';\nimport { AUTH_ENDPOINTS } from '../constants/auth-endpoints.const';\nimport { SocialProviderEnum } from '../enums/social-provider.enum';\nimport { AuthResponse } from '../interfaces/auth.interface';\nimport {\n ISocialAuthorization,\n ISocialCallbackRequest,\n ISocialProviderInfo,\n} from '../interfaces/social-auth.interface';\n\n/** Round-trips the pre-login returnUrl through the OAuth redirect, which cannot carry it itself. */\nexport const SOCIAL_RETURN_URL_KEY = 'flusys_social_return_url';\n\n@Service()\nexport class SocialAuthApiService {\n private readonly appConfig = inject(APP_CONFIG);\n private readonly http = inject(HttpClient);\n private readonly platform = inject(PlatformService);\n private readonly baseUrl = getServiceUrl(this.appConfig, 'auth');\n\n get redirectUri(): string {\n if (this.platform.isServer) return '';\n return `${window.location.origin}${AUTH_ENDPOINTS.SOCIAL_CALLBACK}`;\n }\n\n /** Called before redirecting to the provider, so the callback page can resume where the user left off. */\n saveReturnUrl(returnUrl: string): void {\n if (this.platform.isServer) return;\n if (returnUrl) sessionStorage.setItem(SOCIAL_RETURN_URL_KEY, returnUrl);\n else sessionStorage.removeItem(SOCIAL_RETURN_URL_KEY);\n }\n\n /** Reads and clears the returnUrl saved by {@link saveReturnUrl}. */\n consumeReturnUrl(): string {\n if (this.platform.isServer) return '';\n const returnUrl = sessionStorage.getItem(SOCIAL_RETURN_URL_KEY) ?? '';\n sessionStorage.removeItem(SOCIAL_RETURN_URL_KEY);\n return returnUrl;\n }\n\n getProviders(): Observable<ISingleResponse<ISocialProviderInfo[]>> {\n return this.http.post<ISingleResponse<ISocialProviderInfo[]>>(\n `${this.baseUrl}/social/providers`,\n { redirectUri: this.redirectUri },\n );\n }\n\n authorize(\n provider: SocialProviderEnum,\n ): Observable<ISingleResponse<ISocialAuthorization>> {\n return this.http.post<ISingleResponse<ISocialAuthorization>>(\n `${this.baseUrl}/social/authorize`,\n { provider, redirectUri: this.redirectUri },\n );\n }\n\n callback(request: ISocialCallbackRequest): Observable<AuthResponse> {\n return this.http.post<AuthResponse>(\n `${this.baseUrl}/social/callback`,\n request,\n );\n }\n}\n","import { Service } from '@angular/core';\nimport { ApiResourceService } from '@flusys/ng-shared';\nimport {\n ICreateSocialAuthConfigDto,\n ISocialAuthConfig,\n IUpdateSocialAuthConfigDto,\n} from '../interfaces/social-auth.interface';\n\n@Service()\nexport class SocialAuthConfigApiService extends ApiResourceService<\n ICreateSocialAuthConfigDto | IUpdateSocialAuthConfigDto,\n ISocialAuthConfig\n> {\n constructor() {\n super('social-config', 'auth');\n }\n}\n","import { signal, Service } from '@angular/core';\nimport { BehaviorSubject, Subject } from 'rxjs';\n\n/**\n * Token Refresh State Service\n * Manages token refresh state for SSR-safe request queuing.\n * Uses BehaviorSubject for RxJS interop (multi-subscriber async coordination).\n */\n@Service()\nexport class TokenRefreshStateService {\n private readonly _isRefreshing = signal(false);\n readonly isRefreshing = this._isRefreshing.asReadonly();\n\n private readonly _refreshTokenSubject = new BehaviorSubject<string | null>(null);\n readonly refreshTokenSubject$ = this._refreshTokenSubject.asObservable();\n\n private readonly _refreshFailed = new Subject<unknown>();\n readonly refreshFailed$ = this._refreshFailed.asObservable();\n\n startRefresh(): void {\n this._isRefreshing.set(true);\n this._refreshTokenSubject.next(null);\n }\n\n completeRefresh(newToken: string): void {\n this._isRefreshing.set(false);\n this._refreshTokenSubject.next(newToken);\n }\n\n failRefresh(error?: unknown): void {\n this._isRefreshing.set(false);\n this._refreshFailed.next(error);\n }\n}\n","import { InjectionToken, Injector, TemplateRef, Type } from '@angular/core';\nimport { ILogicNode } from '@flusys/ng-shared';\nimport { Observable } from 'rxjs';\nimport { IUser } from '../interfaces/user.interface';\n\nexport interface IEmailValidationConfig {\n pattern?: RegExp;\n message?: string;\n messageKey?: string;\n messageParam?: Record<string, string | number>;\n}\n\nexport interface IPasswordValidationConfig {\n minLength?: number;\n maxLength?: number;\n requireUppercase?: boolean;\n requireLowercase?: boolean;\n requireNumbers?: boolean;\n requireSpecialChars?: boolean;\n pattern?: RegExp;\n message?: string;\n messageKey?: string;\n messageParam?: Record<string, string | number>;\n}\n\nexport interface IAuthValidationConfig {\n email?: IEmailValidationConfig;\n password?: IPasswordValidationConfig;\n}\n\nexport const AUTH_VALIDATION_CONFIG = new InjectionToken<IAuthValidationConfig>(\n 'AUTH_VALIDATION_CONFIG',\n);\n\nexport interface IRegistrationFieldTemplateContext {\n field: IRegistrationExtraField;\n value: unknown;\n updateValue: (value: unknown) => void;\n}\n\nexport const REGISTRATION_FIELD_CONTEXT =\n new InjectionToken<IRegistrationFieldTemplateContext>(\n 'REGISTRATION_FIELD_CONTEXT',\n );\n\nexport interface IRegistrationExtraField {\n key: string;\n label: string;\n labelKey?: string;\n type:\n | 'text'\n | 'number'\n | 'select'\n | 'checkbox'\n | 'textarea'\n | 'date'\n | 'template';\n placeholder?: string;\n placeholderKey?: string;\n required?: boolean;\n defaultValue?: unknown;\n options?: Array<{ label: string; labelKey?: string; value: unknown }>;\n pattern?: RegExp;\n validationMessage?: string;\n validationMessageKey?: string;\n validationMessageParam?: Record<string, string | number>;\n order?: number;\n containerClass?: string;\n template?: TemplateRef<IRegistrationFieldTemplateContext>;\n component?: Type<unknown>;\n injector?: Injector;\n}\n\nexport interface IRegistrationExtensionProvider {\n getExtraFields(): IRegistrationExtraField[];\n transformRegistrationData?(\n data: Record<string, unknown>,\n ): Record<string, unknown>;\n validateExtraFields?(data: Record<string, unknown>): string | null;\n}\n\nexport const AUTH_REGISTRATION_EXTENSION =\n new InjectionToken<IRegistrationExtensionProvider>(\n 'AUTH_REGISTRATION_EXTENSION',\n );\n\nexport interface IUserListExtraColumn {\n key: string;\n header: string;\n headerKey?: string;\n field?: string;\n template?: TemplateRef<{ $implicit: IUser }>;\n styleClass?: string;\n width?: string;\n sortable?: boolean;\n order?: number;\n}\n\nexport interface IUserListExtraAction {\n key: string;\n label: string;\n labelKey?: string;\n icon: string;\n severity?: 'info' | 'success' | 'warn' | 'danger' | 'secondary' | 'contrast';\n permission?: string;\n onClick: (user: IUser) => void;\n isVisible?: (user: IUser) => boolean;\n isDisabled?: (user: IUser) => boolean;\n order?: number;\n}\n\nexport interface IUserListExtensionProvider {\n getExtraColumns(): IUserListExtraColumn[];\n getExtraActions(): IUserListExtraAction[];\n enrichUserData?(users: IUser[]): Observable<IUser[]>;\n}\n\nexport const AUTH_USER_LIST_EXTENSION =\n new InjectionToken<IUserListExtensionProvider>('AUTH_USER_LIST_EXTENSION');\n\nexport interface IProfileExtraSection {\n key: string;\n title: string;\n titleKey?: string;\n icon?: string;\n order?: number;\n component?: Type<unknown>;\n template?: TemplateRef<{ user: IUser }>;\n collapsible?: boolean;\n collapsed?: boolean;\n editPermission?: string | ILogicNode;\n}\n\nexport interface IProfileFieldTemplateContext {\n field: IProfileExtraField;\n value: unknown;\n updateValue: (value: unknown) => void;\n}\n\nexport const PROFILE_FIELD_CONTEXT =\n new InjectionToken<IProfileFieldTemplateContext>('PROFILE_FIELD_CONTEXT');\n\nexport interface IProfileExtraField {\n key: string;\n label: string;\n labelKey?: string;\n type:\n | 'text'\n | 'number'\n | 'select'\n | 'checkbox'\n | 'textarea'\n | 'date'\n | 'template';\n placeholder?: string;\n placeholderKey?: string;\n editable?: boolean;\n required?: boolean;\n options?: Array<{ label: string; labelKey?: string; value: unknown }>;\n pattern?: RegExp;\n validationMessage?: string;\n validationMessageKey?: string;\n validationMessageParam?: Record<string, string | number>;\n order?: number;\n sectionKey?: string;\n template?: TemplateRef<IProfileFieldTemplateContext>;\n component?: Type<unknown>;\n injector?: Injector;\n}\n\nexport interface IProfileExtensionProvider {\n getExtraSections?(): IProfileExtraSection[];\n getExtraFields?(): IProfileExtraField[];\n getExtraFieldValues?(userId: string): Observable<Record<string, unknown>>;\n saveExtraFieldValues?(\n userId: string,\n data: Record<string, unknown>,\n ): Observable<void>;\n validateExtraFields?(data: Record<string, unknown>): string | null;\n}\n\nexport const AUTH_PROFILE_EXTENSION =\n new InjectionToken<IProfileExtensionProvider>('AUTH_PROFILE_EXTENSION');\n\nexport interface IUserFormFieldTemplateContext {\n field: IUserFormExtraField;\n value: unknown;\n updateValue: (value: unknown) => void;\n}\n\nexport const USER_FORM_FIELD_CONTEXT =\n new InjectionToken<IUserFormFieldTemplateContext>('USER_FORM_FIELD_CONTEXT');\n\nexport interface IUserFormExtraField {\n key: string;\n label: string;\n labelKey?: string;\n type:\n | 'text'\n | 'number'\n | 'select'\n | 'checkbox'\n | 'textarea'\n | 'date'\n | 'template';\n placeholder?: string;\n placeholderKey?: string;\n required?: boolean;\n options?: Array<{ label: string; labelKey?: string; value: unknown }>;\n pattern?: RegExp;\n validationMessage?: string;\n validationMessageKey?: string;\n validationMessageParam?: Record<string, string | number>;\n order?: number;\n template?: TemplateRef<IUserFormFieldTemplateContext>;\n component?: Type<unknown>;\n injector?: Injector;\n}\n\nexport interface IUserFormExtensionProvider {\n getExtraFields?(): IUserFormExtraField[];\n getExtraFieldValues?(userId: string): Observable<Record<string, unknown>>;\n saveExtraFieldValues?(\n userId: string,\n data: Record<string, unknown>,\n ): Observable<void>;\n validateExtraFields?(data: Record<string, unknown>): string | null;\n}\n\nexport const AUTH_USER_FORM_EXTENSION =\n new InjectionToken<IUserFormExtensionProvider>('AUTH_USER_FORM_EXTENSION');\n\nexport type UserDetailViewMode = 'dialog' | 'sidebar' | 'page';\n\nexport interface IUserDetailViewConfig {\n viewMode: UserDetailViewMode;\n allowEdit?: boolean;\n width?: string;\n component?: Type<unknown>;\n tabs?: Array<{\n key: string;\n label: string;\n labelKey?: string;\n icon?: string;\n component?: Type<unknown>;\n template?: TemplateRef<{ user: IUser }>;\n }>;\n}\n\nexport const AUTH_USER_DETAIL_CONFIG =\n new InjectionToken<IUserDetailViewConfig>('AUTH_USER_DETAIL_CONFIG');\n\nconst PASSWORD_SPECIAL_CHAR_PATTERN = /[!@#$%^&*()_+\\-=[\\]{};':\"\\\\|,.<>/?~`]/;\n\nexport const DEFAULT_PASSWORD_VALIDATION = {\n minLength: 8,\n maxLength: 128,\n requireUppercase: true,\n requireLowercase: true,\n requireNumbers: true,\n requireSpecialChars: true,\n} as const satisfies IPasswordValidationConfig;\n\nexport function resolvePasswordValidation(\n config?: IPasswordValidationConfig | null,\n): IPasswordValidationConfig {\n const overrides = Object.fromEntries(\n Object.entries(config ?? {}).filter(([, value]) => value !== undefined),\n );\n return { ...DEFAULT_PASSWORD_VALIDATION, ...overrides };\n}\n\nexport function validatePassword(\n password: string,\n config: IPasswordValidationConfig = DEFAULT_PASSWORD_VALIDATION,\n): string | null {\n const rules = resolvePasswordValidation(config);\n const fail = (key: string): string => rules.messageKey ?? rules.message ?? key;\n\n if (password.length < (rules.minLength ?? 0)) {\n return fail('auth.validation.password.min.length');\n }\n if (rules.maxLength && password.length > rules.maxLength) {\n return fail('auth.validation.password.max.length');\n }\n\n if (rules.pattern) {\n return rules.pattern.test(password) ? null : fail('auth.validation.password.pattern');\n }\n if (rules.requireUppercase && !/[A-Z]/.test(password)) {\n return fail('auth.validation.password.require.uppercase');\n }\n if (rules.requireLowercase && !/[a-z]/.test(password)) {\n return fail('auth.validation.password.require.lowercase');\n }\n if (rules.requireNumbers && !/\\d/.test(password)) {\n return fail('auth.validation.password.require.number');\n }\n if (rules.requireSpecialChars && !PASSWORD_SPECIAL_CHAR_PATTERN.test(password)) {\n return fail('auth.validation.password.require.special');\n }\n\n return null;\n}\n\nexport function validateEmail(\n email: string,\n config?: IEmailValidationConfig,\n): string | null {\n const pattern = config?.pattern ?? /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n if (pattern.test(email)) return null;\n return config?.messageKey ?? config?.message ?? 'shared.invalid.email';\n}\n","import { inject, Service } from '@angular/core';\nimport { TranslateService } from '@flusys/ng-shared';\nimport {\n AUTH_VALIDATION_CONFIG,\n DEFAULT_PASSWORD_VALIDATION,\n resolvePasswordValidation,\n validatePassword,\n} from '../providers/auth-extension.providers';\n\n@Service()\nexport class PasswordPolicyService {\n private readonly config = inject(AUTH_VALIDATION_CONFIG, { optional: true });\n private readonly translateAdapter = inject(TranslateService, { optional: true });\n\n private readonly rules = resolvePasswordValidation(this.config?.password);\n readonly minLength = this.rules.minLength ?? DEFAULT_PASSWORD_VALIDATION.minLength;\n private readonly maxLength = this.rules.maxLength ?? DEFAULT_PASSWORD_VALIDATION.maxLength;\n\n validate(password: string): string | null {\n if (!password) return null;\n const key = validatePassword(password, this.rules);\n if (!key) return null;\n const params = { min: this.minLength, max: this.maxLength, ...this.rules.messageParam };\n return this.translateAdapter?.translate(key, params) ?? key;\n }\n}\n","import { inject, Service } from '@angular/core';\nimport { TranslateService } from '@flusys/ng-shared';\nimport { AUTH_VALIDATION_CONFIG, validateEmail } from '../providers/auth-extension.providers';\n\n@Service()\nexport class EmailPolicyService {\n private readonly config = inject(AUTH_VALIDATION_CONFIG, { optional: true })?.email;\n private readonly translateAdapter = inject(TranslateService, { optional: true });\n\n validate(email: string): string | null {\n if (!email) return null;\n const key = validateEmail(email, this.config);\n if (!key) return null;\n return this.translateAdapter?.translate(key, this.config?.messageParam) ?? key;\n }\n}\n","import { Service } from '@angular/core';\nimport {\n ApiResourceService,\n IFilterData,\n IListResponse,\n ISingleResponse,\n IUserBasicInfo,\n} from '@flusys/ng-shared';\nimport { Observable } from 'rxjs';\nimport {\n ICreateUserRequest,\n IUpdateUserRequest,\n IUser,\n} from '../interfaces/user.interface';\n\n/**\n * User API Service\n * Signal-based service for user CRUD operations\n */\n@Service()\nexport class UserApiService extends ApiResourceService<\n ICreateUserRequest | IUpdateUserRequest,\n IUser\n> {\n constructor() {\n super('users', 'administration');\n }\n\n updateProfile(data: IUpdateUserRequest): Observable<ISingleResponse<IUser>> {\n return this.http.post<ISingleResponse<IUser>>(\n `${this.baseUrl}/profile`,\n data,\n );\n }\n\n lookup(\n filter: IFilterData,\n search = '',\n ): Observable<IListResponse<IUserBasicInfo>> {\n const params = search ? { q: search } : undefined;\n return this.http.post<IListResponse<IUserBasicInfo>>(\n `${this.baseUrl}/lookup`,\n filter,\n params ? { params } : undefined,\n );\n }\n}\n","import { HttpClient } from '@angular/common/http';\nimport { inject, Service } from '@angular/core';\nimport { APP_CONFIG, getServiceUrl, IAppConfig } from '@flusys/ng-core';\nimport { IMessageResponse, ISingleResponse } from '@flusys/ng-shared';\nimport { Observable } from 'rxjs';\nimport {\n IAssignUserBranchRequest,\n IAssignUserCompanyRequest,\n IBranchPermittedUser,\n ICompanyPermittedUser,\n IUserBranchPermission,\n IUserCompanyPermission,\n} from '../interfaces/user-permission.interface';\n\n/**\n * User Permission API Service\n * Handles user-company and user-branch permission assignments.\n * Endpoint: POST /administration/permissions/*\n */\n@Service()\nexport class UserPermissionApiService {\n private readonly appConfig = inject<IAppConfig>(APP_CONFIG);\n private readonly http = inject(HttpClient);\n private readonly baseUrl = `${getServiceUrl(this.appConfig, 'administration')}/permissions`;\n\n // Company Permissions\n assignUserCompanies(data: IAssignUserCompanyRequest): Observable<IMessageResponse> {\n return this.http.post<IMessageResponse>(`${this.baseUrl}/user-company/assign`, data);\n }\n\n assignUserToCompany(userId: string, companyId: string): Observable<IMessageResponse> {\n return this.assignUserCompanies({ userId, items: [{ targetId: companyId, isAdd: true }] });\n }\n\n revokeUserFromCompany(userId: string, companyId: string): Observable<IMessageResponse> {\n return this.assignUserCompanies({ userId, items: [{ targetId: companyId, isAdd: false }] });\n }\n\n getUserCompanies(userId: string): Observable<ISingleResponse<IUserCompanyPermission[]>> {\n return this.http.post<ISingleResponse<IUserCompanyPermission[]>>(`${this.baseUrl}/get-user-company`, { userId });\n }\n\n // Branch Permissions\n assignUserBranches(data: IAssignUserBranchRequest): Observable<IMessageResponse> {\n return this.http.post<IMessageResponse>(`${this.baseUrl}/user-branch/assign`, data);\n }\n\n assignUserToBranch(userId: string, branchId: string): Observable<IMessageResponse> {\n return this.assignUserBranches({ userId, items: [{ targetId: branchId, isAdd: true }] });\n }\n\n revokeUserFromBranch(userId: string, branchId: string): Observable<IMessageResponse> {\n return this.assignUserBranches({ userId, items: [{ targetId: branchId, isAdd: false }] });\n }\n\n getUserBranches(userId: string, companyId?: string): Observable<ISingleResponse<IUserBranchPermission[]>> {\n return this.http.post<ISingleResponse<IUserBranchPermission[]>>(`${this.baseUrl}/get-user-branch`, {\n userId,\n ...(companyId && { companyId }),\n });\n }\n\n // Reverse Lookups (target -> users)\n\n getCompanyUsers(companyId: string): Observable<ISingleResponse<ICompanyPermittedUser[]>> {\n return this.http.post<ISingleResponse<ICompanyPermittedUser[]>>(`${this.baseUrl}/get-company-users`, {\n companyId,\n });\n }\n\n getBranchUsers(branchId: string): Observable<ISingleResponse<IBranchPermittedUser[]>> {\n return this.http.post<ISingleResponse<IBranchPermittedUser[]>>(`${this.baseUrl}/get-branch-users`, {\n branchId,\n });\n }\n}\n","import { inject } from '@angular/core';\nimport { CanActivateFn, Router, UrlTree } from '@angular/router';\nimport { APP_CONFIG } from '@flusys/ng-core';\nimport { Observable, of } from 'rxjs';\nimport { catchError, map } from 'rxjs/operators';\nimport { AUTH_ENDPOINTS } from '../constants/auth-endpoints.const';\nimport { AuthInitService } from '../services/auth-init.service';\nimport { AuthStateService } from '../services/auth-state.service';\n\nfunction isValidReturnUrl(url: unknown): url is string {\n if (typeof url !== 'string' || !url) return false;\n return url.startsWith('/') && !url.includes('://') && !url.startsWith('//');\n}\n\n/** Protects routes requiring authentication */\nexport const authGuard: CanActivateFn = (_route, state) => {\n const authState = inject(AuthStateService);\n const router = inject(Router);\n const appConfig = inject(APP_CONFIG);\n\n if (!authState.isAuthenticated()) {\n return router.createUrlTree([AUTH_ENDPOINTS.LOGIN], { queryParams: { returnUrl: state.url } });\n }\n\n if (appConfig.enableCompanyFeature) {\n if (authState.requiresCompanySelection() || !authState.company()) {\n return router.createUrlTree([AUTH_ENDPOINTS.LOGIN], { queryParams: { returnUrl: state.url } });\n }\n }\n\n return true;\n};\n\n/** Protects auth routes from authenticated users, restores session first */\nexport const guestGuard: CanActivateFn = (route): boolean | UrlTree | Observable<boolean | UrlTree> => {\n const authState = inject(AuthStateService);\n const authInit = inject(AuthInitService);\n const router = inject(Router);\n const appConfig = inject(APP_CONFIG);\n\n const checkAndRedirect = (): boolean | UrlTree => {\n if (authState.requiresCompanySelection()) return true;\n\n if (authState.isAuthenticated()) {\n if (appConfig.enableCompanyFeature && !authState.company()) return true;\n const returnUrl = route.queryParams['returnUrl'];\n return isValidReturnUrl(returnUrl) ? router.parseUrl(returnUrl) : router.createUrlTree(['/']);\n }\n\n return true;\n };\n\n if (authInit.initialized()) return checkAndRedirect();\n\n return authInit.initialize().pipe(\n map(() => checkAndRedirect()),\n catchError(() => of(true)),\n );\n};\n\n/** Protects routes requiring company feature to be enabled */\nexport const companyFeatureGuard: CanActivateFn = () => {\n const router = inject(Router);\n const appConfig = inject(APP_CONFIG);\n\n if (!appConfig.enableCompanyFeature) return router.createUrlTree(['/']);\n return true;\n};\n\n/** Protects routes requiring email feature to be enabled */\nexport const emailFeatureGuard: CanActivateFn = () => {\n const router = inject(Router);\n const appConfig = inject(APP_CONFIG);\n\n if (!appConfig.services.email?.enabled) return router.createUrlTree([AUTH_ENDPOINTS.LOGIN]);\n return true;\n};\n\n/** Protects routes requiring sign-up feature to be enabled */\nexport const signUpFeatureGuard: CanActivateFn = () => {\n const router = inject(Router);\n const appConfig = inject(APP_CONFIG);\n\n if (appConfig.enableSignUp === false) return router.createUrlTree([AUTH_ENDPOINTS.LOGIN]);\n return true;\n};\n","import { HttpEvent, HttpHandlerFn, HttpRequest } from '@angular/common/http';\nimport { inject } from '@angular/core';\nimport { APP_CONFIG } from '@flusys/ng-core';\nimport { CookieService } from '@flusys/ng-shared';\nimport { Observable } from 'rxjs';\nimport { AUTH_ENDPOINTS, isEndpoint } from '../constants/auth-endpoints.const';\nimport { AuthStateService } from '../services/auth-state.service';\n\n/** Endpoints that need withCredentials for cookie handling */\nconst COOKIE_ENDPOINTS = [\n AUTH_ENDPOINTS.LOGIN,\n AUTH_ENDPOINTS.LOGOUT,\n AUTH_ENDPOINTS.REFRESH,\n AUTH_ENDPOINTS.REGISTER,\n AUTH_ENDPOINTS.SELECT,\n AUTH_ENDPOINTS.SWITCH_COMPANY,\n AUTH_ENDPOINTS.VERIFY_EMAIL,\n AUTH_ENDPOINTS.SOCIAL_CALLBACK,\n] as const;\n\n/**\n * Auth Interceptor - Adds auth headers and cookie credentials to requests\n */\nexport function authInterceptor(\n req: HttpRequest<unknown>,\n next: HttpHandlerFn,\n): Observable<HttpEvent<unknown>> {\n const authState = inject(AuthStateService);\n const cookieService = inject(CookieService);\n const appConfig = inject(APP_CONFIG);\n\n const headers: Record<string, string> = {};\n\n // Add tenant header if multi-tenant mode\n if (appConfig.multiTenant.enabled) {\n const tenantId = authState.tenantId();\n if (tenantId) {\n headers[appConfig.multiTenant.tenantHeader] = tenantId;\n }\n }\n\n // Add Bearer token if available\n const token = authState.accessToken();\n if (token) {\n headers['Authorization'] = `Bearer ${token}`;\n }\n\n // Check if this endpoint needs withCredentials for cookies\n const needsCredentials = COOKIE_ENDPOINTS.some((ep) => isEndpoint(req.url, ep));\n\n if (needsCredentials) {\n headers['cookie'] = cookieService.get();\n return next(req.clone({ withCredentials: true, setHeaders: headers }));\n }\n\n if (Object.keys(headers).length > 0) {\n return next(req.clone({ setHeaders: headers }));\n }\n\n return next(req);\n}\n","import { isPlatformBrowser } from '@angular/common';\nimport {\n HttpErrorResponse,\n HttpEvent,\n HttpHandlerFn,\n HttpRequest,\n} from '@angular/common/http';\nimport { inject, PLATFORM_ID } from '@angular/core';\nimport { TranslateService } from '@flusys/ng-shared';\nimport { MessageService } from '@flusys/ng-ui';\nimport {\n catchError,\n filter,\n map,\n Observable,\n race,\n switchMap,\n take,\n throwError,\n} from 'rxjs';\nimport { AUTH_ENDPOINTS, isEndpoint } from '../constants/auth-endpoints.const';\nimport { AuthApiService } from '../services/auth-api.service';\nimport { AuthStateService } from '../services/auth-state.service';\nimport { TokenRefreshStateService } from '../services/token-refresh-state.service';\n\n/** Token Refresh Interceptor - Proactive and reactive token refresh with request queuing */\nexport function tokenRefreshInterceptor(\n req: HttpRequest<unknown>,\n next: HttpHandlerFn,\n): Observable<HttpEvent<unknown>> {\n const authState = inject(AuthStateService);\n const authApi = inject(AuthApiService);\n const messageService = inject(MessageService);\n const platformId = inject(PLATFORM_ID);\n const isBrowser = isPlatformBrowser(platformId);\n const refreshState = inject(TokenRefreshStateService);\n const translateAdapter = inject(TranslateService, { optional: true });\n const t = (key: string) => translateAdapter?.translate(key) ?? key;\n\n // Skip refresh for these endpoints to prevent infinite loops\n const isRefreshRequest = isEndpoint(req.url, AUTH_ENDPOINTS.REFRESH);\n const isLoginRequest = isEndpoint(req.url, AUTH_ENDPOINTS.LOGIN);\n const isSelectRequest = isEndpoint(req.url, AUTH_ENDPOINTS.SELECT);\n const isRegisterRequest = isEndpoint(req.url, AUTH_ENDPOINTS.REGISTER);\n const isSocialCallbackRequest = isEndpoint(\n req.url,\n AUTH_ENDPOINTS.SOCIAL_CALLBACK,\n );\n\n // Don't intercept auth-related endpoints\n if (\n isRefreshRequest ||\n isLoginRequest ||\n isSelectRequest ||\n isRegisterRequest ||\n isSocialCallbackRequest\n ) {\n return next(req);\n }\n\n // PROACTIVE REFRESH: Check if token is expired or expiring soon\n if (authState.isTokenExpired() && authState.tokenExpiresAt() !== null) {\n // Token is expired/expiring - refresh proactively before request\n return handleTokenRefresh(\n req,\n next,\n authState,\n authApi,\n messageService,\n isBrowser,\n refreshState,\n t,\n );\n }\n\n // Token is valid - proceed with request, handle 401 reactively\n return next(req).pipe(\n catchError((error: HttpErrorResponse) => {\n // Only handle 401 errors\n if (error.status !== 401) {\n return throwError(() => error);\n }\n\n // Handle 401 by refreshing token\n return handleTokenRefresh(\n req,\n next,\n authState,\n authApi,\n messageService,\n isBrowser,\n refreshState,\n t,\n );\n }),\n );\n}\n\nfunction handleTokenRefresh(\n req: HttpRequest<unknown>,\n next: HttpHandlerFn,\n authState: AuthStateService,\n authApi: AuthApiService,\n messageService: MessageService,\n isBrowser: boolean,\n refreshState: TokenRefreshStateService,\n t: (key: string) => string,\n): Observable<HttpEvent<unknown>> {\n if (refreshState.isRefreshing()) {\n return race(\n refreshState.refreshTokenSubject$.pipe(\n filter((token): token is string => token !== null),\n take(1),\n ),\n refreshState.refreshFailed$.pipe(\n take(1),\n switchMap((error) => throwError(() => error)),\n ),\n ).pipe(\n switchMap((token) =>\n next(req.clone({ setHeaders: { Authorization: `Bearer ${token}` } })),\n ),\n );\n }\n\n refreshState.startRefresh();\n\n return authApi.refresh().pipe(\n map((response) => {\n const newToken = response.data?.accessToken;\n if (!newToken) throw new Error('auth.session.expired');\n return newToken;\n }),\n catchError((refreshError) => {\n refreshState.failRefresh(refreshError);\n return handleRefreshFailure(\n authState,\n messageService,\n isBrowser,\n refreshError,\n t,\n );\n }),\n switchMap((newToken) => {\n authState.setAccessToken(newToken);\n refreshState.completeRefresh(newToken);\n return next(\n req.clone({ setHeaders: { Authorization: `Bearer ${newToken}` } }),\n );\n }),\n );\n}\n\nfunction handleRefreshFailure(\n authState: AuthStateService,\n messageService: MessageService,\n isBrowser: boolean,\n error: HttpErrorResponse,\n t: (key: string) => string,\n): Observable<never> {\n if (isBrowser) {\n const detailKey = error?.error?.messageKey;\n messageService.add({\n severity: 'error',\n summary: t('auth.session.expired.title'),\n detail: t(detailKey || 'auth.session.expired'),\n });\n }\n authState.resetState();\n authState.navigateToLogin();\n\n return throwError(() => error);\n}\n","export const AUTH_MESSAGES: Record<string, string> = {\n // AUTH_MESSAGES (API keys)\n 'auth.login.success': 'Login successful',\n 'auth.login.requires.selection':\n 'Please select a company and branch to continue',\n 'auth.login.invalid.credentials': 'Invalid email or password',\n 'auth.login.email.not.verified': 'Please verify your email before logging in',\n 'auth.login.account.deactivated': 'Your account has been deactivated',\n 'auth.logout.success': 'Logged out successfully',\n 'auth.register.success': 'Account created successfully',\n 'auth.register.failed': 'Registration failed. Please try again.',\n 'auth.refresh.success': 'Token refreshed successfully',\n 'auth.me.success': 'User info retrieved successfully',\n 'auth.select.success': 'Company selected successfully',\n 'auth.switch.company.success': 'Company switched successfully',\n 'auth.register.email.exists': 'Email already exists',\n 'auth.register.account.deleted':\n 'This account has been permanently deleted. Please contact your system administrator.',\n 'auth.register.company.already.assigned': 'Company already assigned',\n 'auth.password.change.success': 'Password changed successfully',\n 'auth.password.change.invalid.current': 'Current password is incorrect',\n 'auth.password.change.current.required': 'Current password is required',\n 'auth.password.reset.email.sent': 'Password reset email sent',\n 'auth.password.reset.success': 'Password reset successfully',\n 'auth.token.too.large': 'Refresh token too large (≈{{size}} bytes)',\n 'auth.company.list.success': 'User companies retrieved successfully',\n 'auth.company.not.found': 'Company not found',\n 'auth.company.required': 'Company is required',\n 'auth.company.feature.not.enabled':\n 'This feature is not enabled for your company',\n 'auth.branch.list.success': 'Company branches retrieved successfully',\n 'auth.branch.no.access': 'No access to this branch',\n 'auth.branch.not.found': 'Branch not found',\n 'auth.email.not.configured': 'Email service is not configured',\n 'auth.email.send.failed': 'Failed to send email',\n 'auth.session.invalid': 'Invalid session. Please login again.',\n 'auth.session.not.available': 'Session not available',\n 'auth.profile.access.denied': 'Access to profile denied',\n 'auth.profile.sections.not.supported': 'Profile sections not supported',\n 'auth.logout.service.unavailable': 'Logout service unavailable',\n 'auth.password.reset.token.expired': 'Password reset token has expired',\n 'auth.password.reset.token.used':\n 'Password reset token has already been used',\n\n // EMAIL_VERIFICATION_MESSAGES (API keys)\n 'email.verification.sent': 'Verification email sent',\n 'email.verification.success': 'Email verified successfully',\n 'email.verification.token.invalid': 'Invalid verification token',\n 'email.verification.token.expired': 'Verification token has expired',\n 'email.verification.not.enabled': 'Email verification is not enabled',\n 'email.verification.resend.success': 'Verification email resent successfully',\n\n // User CRUD messages (API keys)\n 'user.create.success': 'User created successfully',\n 'user.create.many.success': '{{count}} users created successfully',\n 'user.get.success': 'User retrieved successfully',\n 'user.get.by.ids.success': 'Users retrieved successfully by Ids',\n 'user.update.success': 'User updated successfully',\n 'user.update.many.success': '{{count}} users updated successfully',\n 'user.get.by.filter.success': 'Users retrieved successfully by filter',\n 'user.get.all.success': 'Users retrieved successfully',\n 'user.delete.success': 'User deleted successfully',\n 'user.restore.success': 'User restored successfully',\n 'user.not.found': 'User not found',\n 'user.profile.update.success': 'Profile updated successfully',\n 'user.profile.extras.success': 'Profile extras retrieved successfully',\n 'user.profile.sections.success': 'Profile sections retrieved successfully',\n 'user.profile.section.data.success':\n 'Profile section data retrieved successfully',\n 'user.profile.section.update.success': 'Profile section updated successfully',\n 'user.profile.completion.success':\n 'Profile completion retrieved successfully',\n 'user.email.verify.success': 'Email verified successfully',\n 'user.phone.verify.success': 'Phone verified successfully',\n 'user.status.update.success': 'User status updated successfully',\n 'user.lookup.success': 'Users retrieved successfully',\n\n // Company CRUD messages (API keys)\n 'company.create.success': 'Company created successfully',\n 'company.create.many.success': '{{count}} companies created successfully',\n 'company.get.success': 'Company retrieved successfully',\n 'company.get.by.ids.success': 'Companies retrieved successfully by Ids',\n 'company.get.by.filter.success': 'Companies retrieved successfully by filter',\n 'company.update.success': 'Company updated successfully',\n 'company.update.many.success': '{{count}} companies updated successfully',\n 'company.get.all.success': 'Companies retrieved successfully',\n 'company.delete.success': 'Company deleted successfully',\n 'company.restore.success': 'Company restored successfully',\n 'company.readonly.delete.forbidden': 'Cannot delete readonly company(ies): {{names}}',\n\n // Branch CRUD messages (API keys)\n 'branch.create.success': 'Branch created successfully',\n 'branch.create.many.success': '{{count}} branches created successfully',\n 'branch.get.success': 'Branch retrieved successfully',\n 'branch.get.by.ids.success': 'Branches retrieved successfully by Ids',\n 'branch.get.by.filter.success': 'Branches retrieved successfully by filter',\n 'branch.update.success': 'Branch updated successfully',\n 'branch.update.many.success': '{{count}} branches updated successfully',\n 'branch.get.all.success': 'Branches retrieved successfully',\n 'branch.delete.success': 'Branch deleted successfully',\n 'branch.restore.success': 'Branch restored successfully',\n 'branch.readonly.delete.forbidden': 'Cannot delete readonly branch(es): {{names}}',\n 'branch.invalid.parent': 'Parent branch must belong to the same company',\n 'branch.circular.parent': 'A branch cannot be moved under itself or its descendants',\n\n // USER_PERMISSION_MESSAGES (API keys)\n 'user.permission.company.list.success':\n 'User companies retrieved successfully',\n 'user.permission.branch.list.success': 'User branches retrieved successfully',\n 'user.permission.batch.success':\n 'Processed {{added}} additions and {{removed}} removals',\n 'user.permission.already.assigned': 'User already assigned to this {{type}}',\n 'user.permission.not.found': '{{type}} permission not found',\n\n // === UI KEYS — AUTH DOMAIN (AUTH_ROUTES: login, register, forgot-password, reset-password, verify-email) ===\n\n // pages/login/login-page.component.ts\n 'auth.login.welcome': 'Welcome!',\n 'auth.login.welcome.back': 'Welcome back, {{name}}!',\n 'auth.login.sign.in.to.continue': 'Sign in to continue to your account',\n 'auth.email.label': 'Email Address',\n 'auth.email.placeholder': 'Enter email address',\n 'auth.password.label': 'Password',\n 'auth.password.placeholder': 'Enter your password',\n 'auth.field.remember.me': 'Remember me',\n 'auth.password.forgot': 'Forgot Password?',\n 'auth.login.sign.in': 'Sign In',\n 'auth.login.no.account': \"Don't have an account?\",\n 'auth.login.sign.up': 'Sign Up',\n 'auth.login.verify.email.message': 'Please verify your email !',\n 'auth.verify.resend': 'Resend Verification Email',\n 'auth.login.back.to.sign.in': 'Back to Sign In',\n 'auth.login.select.company': 'Select Company',\n 'auth.login.select.company.message':\n 'Please select a company and branch to continue',\n 'auth.login.select.company.option': 'Select a company',\n 'auth.login.branch.label': 'Branch',\n 'auth.login.select.branch.option': 'Select a branch',\n 'auth.login.remember.selection': 'Remember my selection',\n 'auth.validation.password.min.length':\n 'Password must be at least {{min}} characters',\n 'auth.validation.email.required': 'Email is required',\n 'auth.validation.password.required': 'Password is required',\n 'auth.validation.password.max.length': 'Password must be at most {{max}} characters',\n 'auth.validation.password.pattern': 'Password does not meet requirements',\n 'auth.validation.password.require.uppercase':\n 'Password must contain at least one uppercase letter',\n 'auth.validation.password.require.lowercase':\n 'Password must contain at least one lowercase letter',\n 'auth.validation.password.require.number':\n 'Password must contain at least one number',\n 'auth.validation.password.require.special':\n 'Password must contain at least one special character',\n 'auth.validation.company.required': 'Please select a company',\n 'auth.validation.branch.required': 'Please select a branch',\n 'auth.login.title': 'Login',\n 'auth.session.expired': 'Your session has expired. Please login again.',\n\n // pages/forgot-password/forgot-password-page.component.ts\n 'auth.forgot.password.title': 'Forgot Password',\n 'auth.forgot.password.subtitle':\n 'Enter your email address and we will send you a reset link.',\n 'auth.forgot.password.send.reset.link': 'Send Reset Link',\n 'auth.forgot.password.remember.password': 'Remember your password?',\n 'auth.forgot.password.check.email': 'Check Your Email',\n 'auth.forgot.password.email.sent.to':\n 'We sent a password reset link to {{email}}',\n 'auth.forgot.password.didnt.receive': \"Didn't receive the email?\",\n 'auth.forgot.password.try.again': 'Try Again',\n\n // pages/register/register-page.component.ts\n 'auth.register.create.account': 'Create Account',\n 'auth.register.subtitle': 'Fill in your details to create an account.',\n 'auth.register.signup.disabled': 'New account registration is currently disabled.',\n 'auth.register.full.name': 'Full Name',\n 'auth.register.name.placeholder': 'Enter your full name',\n 'auth.phone.label': 'Phone Number',\n 'auth.phone.placeholder': 'Enter phone number',\n 'auth.register.confirm.password': 'Confirm Password',\n 'auth.register.confirm.password.placeholder': 'Confirm your password',\n 'auth.register.passwords.do.not.match': 'Passwords do not match',\n 'auth.register.company.details': 'Company Details',\n 'auth.register.join.default.company': 'Join Default Company',\n 'auth.register.join.or.create.company': 'Join or Create Company',\n 'auth.register.create.new.company': 'Create New Company',\n 'auth.register.company.code': 'Company Code',\n 'auth.register.preconfigured.company': 'Pre-configured Company',\n 'auth.register.company.code.placeholder': 'Enter company code',\n 'auth.register.enter.company.code': 'Enter company code to join',\n 'auth.register.branch.code': 'Branch Code',\n 'auth.register.preconfigured.branch': 'Pre-configured Branch',\n 'auth.register.branch.code.placeholder': 'Enter branch code',\n 'auth.register.company.name': 'Company Name',\n 'auth.register.company.name.placeholder': 'Enter company name',\n 'auth.address.label': 'Address',\n 'auth.address.placeholder': 'Enter address',\n 'auth.register.already.have.account': 'Already have an account?',\n 'auth.validation.name.min.length': 'Name must be at least {{min}} characters',\n 'auth.validation.confirm.password.required': 'Please confirm your password',\n\n // pages/verify-email/verify-email-page.component.ts\n 'auth.verify.email.verifying': 'Verifying Email',\n 'auth.verify.email.please.wait':\n 'Please wait while we verify your email address...',\n 'auth.verify.email.success': 'Email Verified',\n 'auth.verify.email.success.message':\n 'Your email has been verified successfully. You can now login to your account.',\n 'auth.verify.email.failed': 'Verification Failed',\n 'auth.verify.email.invalid.link':\n 'This verification link is invalid or has expired.',\n 'auth.verify.email.resend.email': 'Resend Verification Email',\n 'auth.verify.email.resend.title': 'Resend Verification',\n 'auth.verify.email.resend.subtitle':\n 'Enter your email to receive a new verification link.',\n 'auth.verify.email.resend': 'Resend Email',\n 'auth.verify.email.sent': 'Verification email sent. Please check your inbox.',\n\n // pages/reset-password/reset-password-page.component.ts\n 'auth.reset.password.title': 'Reset Password',\n 'auth.reset.password.subtitle': 'Enter your new password below.',\n 'auth.reset.password.new.password': 'New Password',\n 'auth.reset.password.new.password.placeholder': 'Enter your new password',\n 'auth.reset.password.confirm.password': 'Confirm Password',\n 'auth.reset.password.confirm.password.placeholder':\n 'Confirm your new password',\n 'auth.reset.password.reset.password': 'Reset Password',\n 'auth.reset.password.success': 'Password Reset Successful',\n 'auth.reset.password.success.message':\n 'Your password has been reset successfully. You can now login with your new password.',\n 'auth.reset.password.invalid.link': 'Invalid Reset Link',\n 'auth.reset.password.invalid.link.message':\n 'This password reset link is invalid or has expired.',\n 'auth.reset.password.request.new.link': 'Request New Link',\n\n // === UI KEYS — PROFILE DOMAIN (PROFILE_ROUTES) ===\n\n // pages/profile/profile-page.component.ts\n 'profile.title': 'Profile',\n 'profile.subtitle': 'Manage your account settings and preferences.',\n 'profile.storage.not.enabled':\n 'Profile picture upload is not available. Storage service is not configured.',\n 'profile.name.label': 'Full Name',\n 'profile.name.placeholder': 'Enter your full name',\n 'profile.phone.label': 'Phone',\n 'profile.phone.placeholder': 'Enter phone number',\n 'profile.additional.info': 'Additional Information',\n 'profile.employment.info': 'Employment Information',\n 'profile.managed.by.admin': 'This field is managed by an administrator.',\n 'profile.security': 'Security',\n 'profile.current.password': 'Current Password',\n 'profile.current.password.placeholder': 'Enter current password',\n 'profile.new.password': 'New Password',\n 'profile.confirm.password': 'Confirm New Password',\n 'profile.confirm.password.placeholder': 'Confirm new password',\n 'profile.change.password': 'Change Password',\n 'profile.company.branch': 'Company & Branch',\n 'profile.branch.label': 'Branch',\n 'profile.actions.label': 'Direct Actions',\n 'profile.actions.none.assigned': 'No actions assigned',\n 'profile.permissions.label': 'My Permissions',\n 'profile.roles.label': 'Roles',\n 'profile.roles.none.assigned': 'No roles assigned',\n\n // === UI KEYS — ADMINISTRATIVE DOMAIN (ADMINISTRATION_ROUTES: users, company, branch) ===\n\n // components/user-company-permission-dialog.component.ts\n 'administrative.permission.manage.company': 'Manage Company Permissions',\n 'administrative.permission.user': 'User',\n 'administrative.company.no.companies': 'No companies found',\n\n // components/user-branch-permission-dialog.component.ts\n 'administrative.permission.manage.branch': 'Manage Branch Permissions',\n 'administrative.company.select': 'Select Company',\n 'administrative.permission.no.company':\n 'This user has no company permissions assigned.',\n 'administrative.permission.assign.company.first':\n 'Assign company permissions first before managing branch access.',\n 'administrative.permission.select.company.for.branches':\n 'Please select a company to view branches.',\n 'administrative.branch.no.branches': 'No branches found',\n\n // pages/administration/administration-page.component.ts\n 'administrative.title': 'Administration',\n 'administrative.subtitle': 'Manage users, companies, and branches',\n 'administrative.user.title': 'Users',\n 'administrative.company.title': 'Companies',\n 'administrative.branch.title': 'Branches',\n\n // pages/branch/branch-form.component.ts\n 'administrative.branch.new': 'New Branch',\n 'administrative.branch.edit': 'Edit Branch',\n 'administrative.branch.name': 'Branch Name',\n 'administrative.branch.name.placeholder': 'Enter branch name',\n 'administrative.branch.slug': 'Branch Slug',\n 'administrative.branch.slug.placeholder': 'Enter branch slug',\n 'administrative.branch.parent': 'Parent Branch',\n 'administrative.branch.select.parent': 'Select parent branch (optional)',\n 'administrative.email.label': 'Email',\n 'administrative.email.placeholder': 'Enter email address',\n 'administrative.phone.label': 'Phone',\n 'administrative.phone.placeholder': 'Enter phone number',\n 'administrative.address.label': 'Address',\n 'administrative.address.placeholder': 'Enter address',\n 'administrative.branch.slug.required': 'Branch slug is required',\n\n // pages/branch/branch-list.component.ts\n 'administrative.branch.add': 'Add Branch',\n 'administrative.branch.add.child': 'Add Sub-branch',\n 'administrative.branch.confirm.delete.with.children':\n 'Are you sure you want to delete \"{{name}}\"? Its {{count}} sub-branch(es) will also be deleted.',\n 'administrative.branch.select.company.first': 'Please select a company first',\n 'administrative.branch.delete.title': 'Delete Branch',\n\n // pages/company/company-form.component.ts\n 'administrative.company.edit': 'Edit Company',\n 'administrative.company.new': 'New Company',\n 'administrative.company.name': 'Company Name',\n 'administrative.company.name.placeholder': 'Enter company name',\n 'administrative.company.slug': 'Company Slug',\n 'administrative.company.slug.placeholder': 'Enter company slug',\n 'administrative.company.website': 'Website',\n 'administrative.company.website.placeholder': 'Enter website URL',\n 'administrative.company.slug.required': 'Company slug is required',\n\n // pages/company/company-list.component.ts\n 'administrative.company.add': 'Add Company',\n 'administrative.branch.view.branches': 'View Branches',\n 'administrative.company.delete.title': 'Delete Company',\n\n // components/company-permitted-users-dialog.component.ts, components/branch-permitted-users-dialog.component.ts\n 'administrative.permission.view.users': 'View Users',\n 'administrative.permission.no.users': 'No users found',\n 'administrative.permission.remove': 'Remove Access',\n 'administrative.permission.remove.confirm':\n 'Remove access for {{name}}?',\n\n // pages/users/user-form.component.ts\n 'administrative.user.edit': 'Edit User',\n 'administrative.user.new': 'New User',\n 'administrative.user.name': 'Name',\n 'administrative.user.name.placeholder': 'Enter full name',\n 'administrative.user.password': 'Password',\n 'administrative.user.password.optional': '(leave blank to keep current)',\n 'administrative.user.password.placeholder': 'Enter password',\n 'administrative.user.email.verified': 'Email Verified',\n 'administrative.user.auto.assign.to':\n 'New user will be automatically assigned to',\n\n // pages/users/user-list.component.ts\n 'administrative.user.add': 'Add User',\n 'administrative.permission.company.permissions': 'Company Permissions',\n 'administrative.permission.branch.permissions': 'Branch Permissions',\n 'administrative.user.no.users': 'No users found',\n 'administrative.user.details': 'User Details',\n 'administrative.user.delete.title': 'Delete User',\n\n // Social sign-in API keys\n 'auth.social.providers.success': 'Social providers retrieved successfully',\n 'auth.social.authorize.success': 'Authorization URL generated successfully',\n 'auth.social.login.success': 'Signed in successfully',\n 'auth.social.provider.disabled': 'Social sign-in with {{provider}} is not enabled',\n 'auth.social.provider.not.configured':\n 'Social sign-in with {{provider}} is missing its client credentials',\n 'auth.social.state.invalid':\n 'Social sign-in session is invalid or has expired',\n 'auth.social.redirect.uri.mismatch':\n 'Redirect URI does not match the one the sign-in started with',\n 'auth.social.exchange.failed': 'Social sign-in with {{provider}} failed',\n 'auth.social.profile.incomplete':\n '{{provider}} did not return an account identifier',\n 'auth.social.account.not.linked':\n 'No account is linked to this {{provider}} profile',\n 'auth.social.company.required':\n 'No account is linked to this {{provider}} profile. Please sign up manually and join or create a company first, then social sign-in will work.',\n 'auth.social.email.required': '{{provider}} did not share an email address',\n 'auth.social.email.not.verified':\n '{{provider}} has not verified this email address',\n 'auth.social.account.deleted':\n 'This account has been permanently deleted. Please contact your system administrator.',\n\n // components/social-login-buttons.component.ts\n 'auth.social.continue.with': 'or continue with',\n 'auth.social.provider.google': 'Google',\n 'auth.social.provider.facebook': 'Facebook',\n 'auth.social.provider.linkedin': 'LinkedIn',\n 'auth.social.provider.microsoft': 'Microsoft',\n\n // pages/social-callback/social-callback-page.component.ts\n 'auth.social.signing.in': 'Signing you in...',\n 'auth.social.failed': 'Social sign-in failed',\n\n // pages/social-config/social-config-page.component.ts (API keys)\n 'social.config.provider.already.configured':\n 'Social provider \"{{provider}}\" is already configured',\n 'social.config.credentials.required':\n 'Client ID and client secret are required for {{provider}}',\n 'social.config.title': 'Social Config',\n 'social.config.subtitle':\n 'Enable the providers users may sign in with, and hold their credentials',\n 'social.config.redirect.uri': 'Redirect URI',\n 'social.config.client.id': 'Client ID',\n 'social.config.client.secret': 'Client Secret',\n 'social.config.client.secret.unchanged': 'Unchanged - leave blank to keep the saved secret',\n 'social.config.tenant.id': 'Directory (tenant) ID',\n 'social.config.tenant.id.example': 'common',\n 'social.config.scopes': 'Scopes',\n 'social.config.scopes.placeholder': 'Leave blank to use the provider defaults',\n 'social.config.save.success': 'Social sign-in settings saved',\n 'social.config.provider.hint.google': 'Google Cloud console, OAuth 2.0 client ID',\n 'social.config.provider.hint.facebook': 'Meta for Developers, Facebook Login app',\n 'social.config.provider.hint.linkedin': 'LinkedIn developers, Sign In with LinkedIn',\n 'social.config.provider.hint.microsoft': 'Microsoft Entra ID, app registration',\n};\n","import { inject } from '@angular/core';\nimport { Routes } from '@angular/router';\nimport { APP_CONFIG, isCompanyFeatureEnabled } from '@flusys/ng-core';\nimport {\n BRANCH_PERMISSIONS,\n COMPANY_PERMISSIONS,\n PermissionValidatorService,\n permissionGuard,\n resolveTranslationModule,\n SHARED_MESSAGES,\n SOCIAL_AUTH_CONFIG_PERMISSIONS,\n USER_PERMISSIONS,\n} from '@flusys/ng-shared';\nimport { AUTH_MESSAGES } from '../constants/messages';\nimport {\n authGuard,\n companyFeatureGuard,\n emailFeatureGuard,\n guestGuard,\n signUpFeatureGuard,\n} from '../guards/auth.guard';\n\n/**\n * Resolves which administration tab the current user should land on when\n * navigating to the bare `/administration` route. Mirrors the tab\n * visibility order in AdministrationPageComponent.visibleTabs so the\n * redirect never points at a tab the user can't actually see.\n */\nfunction resolveAdministrationDefaultTab(): string {\n const permissionValidator = inject(PermissionValidatorService);\n const companyFeatureEnabled = isCompanyFeatureEnabled(inject(APP_CONFIG));\n\n if (permissionValidator.hasPermission(USER_PERMISSIONS.READ)) {\n return 'users';\n }\n\n if (\n companyFeatureEnabled &&\n permissionValidator.hasPermission(COMPANY_PERMISSIONS.READ)\n ) {\n return 'company';\n }\n\n if (\n companyFeatureEnabled &&\n permissionValidator.hasPermission(BRANCH_PERMISSIONS.READ)\n ) {\n return 'branch';\n }\n\n if (permissionValidator.hasPermission(SOCIAL_AUTH_CONFIG_PERMISSIONS.READ)) {\n return 'social-config';\n }\n\n return 'users';\n}\n\n/**\n * Auth Routes Configuration\n * Public routes for authentication (login, register, etc.)\n *\n * Note: Company selection is now handled within the login page as a multi-step flow.\n */\nexport const AUTH_ROUTES: Routes = [\n {\n path: '',\n resolve: {\n translations: resolveTranslationModule({\n modules: ['auth', 'shared'],\n fallbackMessages: { ...AUTH_MESSAGES, ...SHARED_MESSAGES },\n }),\n },\n children: [\n {\n path: 'login',\n loadComponent: () =>\n import('../pages/login/login-page.component').then(\n (m) => m.LoginPageComponent,\n ),\n canActivate: [guestGuard],\n },\n {\n path: 'register',\n loadComponent: () =>\n import('../pages/register/register-page.component').then(\n (m) => m.RegisterPageComponent,\n ),\n canActivate: [signUpFeatureGuard, guestGuard],\n },\n {\n path: 'forgot-password',\n loadComponent: () =>\n import('../pages/forgot-password/forgot-password-page.component').then(\n (m) => m.ForgotPasswordPageComponent,\n ),\n canActivate: [emailFeatureGuard, guestGuard],\n },\n {\n path: 'reset-password',\n loadComponent: () =>\n import('../pages/reset-password/reset-password-page.component').then(\n (m) => m.ResetPasswordPageComponent,\n ),\n canActivate: [emailFeatureGuard, guestGuard],\n },\n {\n path: 'social/callback',\n loadComponent: () =>\n import('../pages/social-callback/social-callback-page.component').then(\n (m) => m.SocialCallbackPageComponent,\n ),\n },\n {\n path: 'verify-email',\n loadComponent: () =>\n import('../pages/verify-email/verify-email-page.component').then(\n (m) => m.VerifyEmailPageComponent,\n ),\n canActivate: [emailFeatureGuard],\n },\n {\n path: '',\n redirectTo: 'login',\n pathMatch: 'full',\n },\n ],\n },\n];\n\n/**\n * Administration Routes Configuration\n * Protected routes for company, branch, user management and permissions\n * Uses tabbed interface - all under /administration with child routes\n */\nexport const ADMINISTRATION_ROUTES: Routes = [\n {\n path: '',\n canActivate: [authGuard],\n resolve: {\n translations: resolveTranslationModule({\n modules: ['auth', 'administrative'],\n fallbackMessages: { ...AUTH_MESSAGES, ...SHARED_MESSAGES },\n }),\n },\n loadComponent: () =>\n import('../pages/administration/administration-page.component').then(\n (m) => m.AdministrationPageComponent,\n ),\n children: [\n // Users tab\n {\n path: 'users',\n canActivate: [permissionGuard(USER_PERMISSIONS.READ)],\n children: [\n {\n path: '',\n loadComponent: () =>\n import('../pages/users/user-list.component').then(\n (m) => m.UserListComponent,\n ),\n },\n {\n path: 'new',\n loadComponent: () =>\n import('../pages/users/user-form.component').then(\n (m) => m.UserFormComponent,\n ),\n },\n {\n path: ':id',\n loadComponent: () =>\n import('../pages/users/user-form.component').then(\n (m) => m.UserFormComponent,\n ),\n },\n ],\n },\n // Company tab (requires company feature)\n {\n path: 'company',\n canActivate: [\n companyFeatureGuard,\n permissionGuard(COMPANY_PERMISSIONS.READ),\n ],\n children: [\n {\n path: '',\n loadComponent: () =>\n import('../pages/company/company-list.component').then(\n (m) => m.CompanyListComponent,\n ),\n },\n {\n path: 'new',\n loadComponent: () =>\n import('../pages/company/company-form.component').then(\n (m) => m.CompanyFormComponent,\n ),\n },\n {\n path: ':id',\n loadComponent: () =>\n import('../pages/company/company-form.component').then(\n (m) => m.CompanyFormComponent,\n ),\n },\n ],\n },\n // Branch tab (requires company feature)\n {\n path: 'branch',\n canActivate: [\n companyFeatureGuard,\n permissionGuard(BRANCH_PERMISSIONS.READ),\n ],\n children: [\n {\n path: '',\n loadComponent: () =>\n import('../pages/branch/branch-list.component').then(\n (m) => m.BranchListComponent,\n ),\n },\n {\n path: 'new',\n loadComponent: () =>\n import('../pages/branch/branch-form.component').then(\n (m) => m.BranchFormComponent,\n ),\n },\n {\n path: ':id',\n loadComponent: () =>\n import('../pages/branch/branch-form.component').then(\n (m) => m.BranchFormComponent,\n ),\n },\n ],\n },\n // Social sign-in provider credentials tab\n {\n path: 'social-config',\n canActivate: [permissionGuard(SOCIAL_AUTH_CONFIG_PERMISSIONS.READ)],\n loadComponent: () =>\n import('../pages/social-config/social-config-page.component').then(\n (m) => m.SocialConfigPageComponent,\n ),\n },\n // Default redirect to the first tab the user has permission to see\n {\n path: '',\n redirectTo: () => resolveAdministrationDefaultTab(),\n pathMatch: 'full',\n },\n ],\n },\n];\n\n/**\n * Profile Routes Configuration\n * Protected route for user profile management\n */\nexport const PROFILE_ROUTES: Routes = [\n {\n path: '',\n canActivate: [authGuard],\n resolve: {\n translations: resolveTranslationModule({\n modules: ['auth', 'profile'],\n fallbackMessages: { ...AUTH_MESSAGES, ...SHARED_MESSAGES },\n }),\n },\n loadComponent: () =>\n import('../pages/profile/profile-page.component').then(\n (m) => m.ProfilePageComponent,\n ),\n },\n];\n","import { computed, inject, Signal, Service } from '@angular/core';\nimport { Router } from '@angular/router';\nimport {\n IBranchInfo,\n ICompanyInfo,\n ILayoutAuthApi,\n ILayoutAuthState,\n IUserInfo as ILayoutUserInfo,\n} from '@flusys/ng-layout';\nimport { Observable } from 'rxjs';\nimport { map, tap } from 'rxjs/operators';\nimport { AuthApiService } from '../services/auth-api.service';\nimport { AuthStateService } from '../services/auth-state.service';\n\n/**\n * Auth Layout Provider Adapters\n *\n * Implements provider interfaces from ng-layout using ng-auth services.\n * Bridges auth state and API to layout components.\n *\n * @example\n * // In app.config.ts\n * import { provideAuthLayoutIntegration } from '@flusys/ng-auth';\n * providers: [...provideAuthLayoutIntegration()]\n */\n\n// =============================================================================\n// Layout State Adapter\n// =============================================================================\n\n@Service()\nexport class AuthLayoutStateAdapter implements ILayoutAuthState {\n private readonly authState = inject(AuthStateService);\n\n readonly currentCompanyInfo: Signal<ICompanyInfo | null> = computed(() => {\n const company = this.authState.company();\n if (company) {\n return {\n id: company.id,\n name: company.name,\n slug: company.slug ?? '',\n imageId: company.logoId ?? '',\n };\n }\n return null;\n });\n\n readonly currentBranchInfo: Signal<IBranchInfo | null> = computed(() => {\n const branch = this.authState.branch();\n if (branch) {\n return {\n id: branch.id,\n name: branch.name,\n slug: branch.slug ?? '',\n imageId: branch.logoId ?? undefined,\n };\n }\n return null;\n });\n\n readonly loginUserData: Signal<ILayoutUserInfo | null> = computed(() => {\n const user = this.authState.user();\n if (user) {\n return {\n id: user.id,\n name: user.name ?? this.authState.userName(),\n email: user.email,\n };\n }\n return null;\n });\n}\n\n// =============================================================================\n// Layout API Adapter\n// =============================================================================\n\n@Service()\nexport class AuthLayoutApiAdapter implements ILayoutAuthApi {\n private readonly authApi = inject(AuthApiService);\n private readonly authState = inject(AuthStateService);\n private readonly router = inject(Router);\n\n logOut(): Observable<unknown> {\n return this.authApi.logout().pipe(\n tap({\n next: () => this.authState.resetState(),\n error: () => {\n this.authState.resetState();\n this.authState.navigateToLogin();\n },\n }),\n );\n }\n\n navigateLogin(withUrl?: boolean): void {\n if (withUrl) {\n const currentUrl = this.router.url;\n this.authState.navigateToLogin(currentUrl);\n } else {\n this.authState.navigateToLogin();\n }\n }\n\n switchCompany(companyId: string, branchId: string): Observable<unknown> {\n return this.authApi.switchCompany({ companyId, branchId }).pipe(\n tap(() => {\n window.location.reload();\n }),\n );\n }\n\n getMyCompanies(): Observable<ICompanyInfo[]> {\n return this.authApi.getCompanies().pipe(\n map((response) =>\n (response.data || []).map((company) => ({\n id: company.id,\n name: company.name,\n slug: company.slug ?? '',\n imageId: company.logoId ?? '',\n })),\n ),\n );\n }\n\n getMyCompanyBranches(companyId: string): Observable<IBranchInfo[]> {\n return this.authApi.getCompanyBranches(companyId).pipe(\n map((response) =>\n (response.data || []).map((branch) => ({\n id: branch.id,\n name: branch.name,\n slug: branch.slug ?? '',\n imageId: branch.logoId ?? undefined,\n parentId: branch.parentId ?? null,\n serial: branch.serial ?? null,\n displayParentId: branch.displayParentId,\n })),\n ),\n );\n }\n}\n","import { inject, Signal, Service } from '@angular/core';\nimport {\n IAuthStateProvider,\n IBranchBasicInfo,\n ICompanyApiProvider,\n ICompanyBasicInfo,\n IListResponse,\n ISingleResponse,\n IUserBasicInfo,\n IUserBranchPermission,\n IUserCompanyInfo,\n IUserPermissionProvider,\n IUserProvider,\n} from '@flusys/ng-shared';\nimport { from, map, Observable } from 'rxjs';\nimport { AuthInitService } from '../services/auth-init.service';\nimport { AuthStateService } from '../services/auth-state.service';\nimport { BranchApiService } from '../services/branch-api.service';\nimport { CompanyApiService } from '../services/company-api.service';\nimport { UserApiService } from '../services/user-api.service';\nimport { UserPermissionApiService } from '../services/user-permission-api.service';\n\n/**\n * Auth Shared Provider Adapters\n *\n * Implements provider interfaces from ng-shared using ng-auth services.\n * Allows IAM, Storage, and Form-Builder packages to access auth data\n * without depending on ng-auth directly.\n *\n * @example\n * // In app.config.ts\n * import { provideAuthProviders } from '@flusys/ng-auth';\n * providers: [...provideAuthProviders()]\n */\n\nfunction emptyListResponse<T>(): IListResponse<T> {\n return {\n success: true,\n message: '',\n data: [],\n meta: { total: 0, page: 0, pageSize: 0, count: 0 },\n };\n}\n\nfunction mapListResponse<TSource, TTarget>(\n response: IListResponse<TSource>,\n mapper: (item: TSource) => TTarget,\n): IListResponse<TTarget> {\n return {\n success: response.success,\n message: response.message,\n messageKey: response.messageKey,\n messageVariables: response.messageVariables,\n data: (response.data ?? []).map(mapper),\n meta: response.meta,\n };\n}\n\n// =============================================================================\n// User Provider Adapter\n// =============================================================================\n\n@Service({ autoProvided: false })\nexport class AuthUserProviderAdapter implements IUserProvider {\n private readonly userApi = inject(UserApiService);\n\n getUsers(filter?: {\n page?: number;\n pageSize?: number;\n search?: string;\n isActive?: boolean;\n [key: string]: unknown;\n }): Observable<IListResponse<IUserBasicInfo>> {\n const { search, page, pageSize, isActive, ...extraFilters } = filter || {};\n\n const apiFilter = {\n pagination: {\n currentPage: page ?? 0,\n pageSize: pageSize ?? 50,\n },\n filter: {\n ...(isActive !== undefined && { isActive }),\n ...Object.fromEntries(\n Object.entries(extraFilters).filter(\n ([_, v]) => v !== undefined && v !== null,\n ),\n ),\n },\n sort: { name: 'ASC' as const },\n };\n\n return this.userApi.lookup(apiFilter, search ?? '').pipe(\n map((response) =>\n mapListResponse(response, (user) => ({\n id: user.id,\n name: user.name || user.email,\n email: user.email,\n })),\n ),\n );\n }\n\n getUsersByIds(ids: string[]): Observable<IListResponse<IUserBasicInfo>> {\n if (ids.length === 0) {\n return from(Promise.resolve(emptyListResponse<IUserBasicInfo>()));\n }\n\n return from(this.userApi.findByIds(ids, ['id', 'name', 'email'])).pipe(\n map((response) =>\n mapListResponse(response, (user) => ({\n id: user.id,\n name: user.name || user.email,\n email: user.email,\n })),\n ),\n );\n }\n}\n\n// =============================================================================\n// Company API Provider Adapter\n// =============================================================================\n\n@Service({ autoProvided: false })\nexport class AuthCompanyApiProviderAdapter implements ICompanyApiProvider {\n private readonly companyApi = inject(CompanyApiService);\n private readonly branchApi = inject(BranchApiService);\n\n getCompanies(filter?: {\n page?: number;\n pageSize?: number;\n search?: string;\n }): Observable<IListResponse<ICompanyBasicInfo>> {\n const apiFilter = {\n pagination: {\n currentPage: filter?.page ?? 0,\n pageSize: filter?.pageSize ?? 50,\n },\n sort: { name: 'ASC' as const },\n };\n\n return from(this.companyApi.getAll(apiFilter, filter?.search ?? '')).pipe(\n map((response) =>\n mapListResponse(response, (company) => ({\n id: company.id,\n name: company.name,\n slug: company.slug,\n })),\n ),\n );\n }\n\n getCompaniesByIds(ids: string[]): Observable<IListResponse<ICompanyBasicInfo>> {\n if (ids.length === 0) {\n return from(Promise.resolve(emptyListResponse<ICompanyBasicInfo>()));\n }\n\n return from(this.companyApi.findByIds(ids, ['id', 'name', 'slug'])).pipe(\n map((response) =>\n mapListResponse(response, (company) => ({\n id: company.id,\n name: company.name,\n slug: company.slug,\n })),\n ),\n );\n }\n\n getBranchesByIds(ids: string[]): Observable<IListResponse<IBranchBasicInfo>> {\n if (ids.length === 0) {\n return from(Promise.resolve(emptyListResponse<IBranchBasicInfo>()));\n }\n\n return from(this.branchApi.findByIds(ids, ['id', 'name'])).pipe(\n map((response) =>\n mapListResponse(response, (branch) => ({ id: branch.id, name: branch.name })),\n ),\n );\n }\n}\n\n// =============================================================================\n// User Permission Provider Adapter\n// =============================================================================\n\n@Service({ autoProvided: false })\nexport class AuthUserPermissionProviderAdapter implements IUserPermissionProvider {\n private readonly userPermissionApi = inject(UserPermissionApiService);\n\n getUserBranchPermissions(\n userId: string,\n companyId?: string,\n ): Observable<ISingleResponse<IUserBranchPermission[]>> {\n return this.userPermissionApi.getUserBranches(userId, companyId);\n }\n\n getUserCompanyPermissions(userId: string): Observable<ISingleResponse<IUserCompanyInfo[]>> {\n return this.userPermissionApi.getUserCompanies(userId).pipe(\n map((response) => ({\n ...response,\n data: (response.data ?? []).map((c) => ({ id: c.companyId, name: c.companyName })),\n })),\n );\n }\n}\n\n// =============================================================================\n// Auth State Provider Adapter\n// =============================================================================\n\n@Service({ autoProvided: false })\nexport class AuthStateProviderAdapter implements IAuthStateProvider {\n private readonly authState = inject(AuthStateService);\n private readonly authInit = inject(AuthInitService);\n\n get isAuthenticated(): Signal<boolean> {\n return this.authState.isAuthenticated;\n }\n\n initialize(): Observable<void> {\n return this.authInit.initialize().pipe(map(() => undefined));\n }\n}\n","import { Provider } from '@angular/core';\nimport { LAYOUT_AUTH_API, LAYOUT_AUTH_STATE } from '@flusys/ng-layout';\nimport { AuthLayoutApiAdapter, AuthLayoutStateAdapter } from '../adapters/auth-layout-providers.adapter';\n\n/** Provides auth integration for ng-layout */\nexport function provideAuthLayoutIntegration(): Provider[] {\n return [\n { provide: LAYOUT_AUTH_STATE, useClass: AuthLayoutStateAdapter },\n { provide: LAYOUT_AUTH_API, useClass: AuthLayoutApiAdapter },\n ];\n}\n","import { Provider } from '@angular/core';\nimport { AUTH_STATE_PROVIDER, COMPANY_API_PROVIDER, USER_PERMISSION_PROVIDER, USER_PROVIDER } from '@flusys/ng-shared';\nimport {\n AuthCompanyApiProviderAdapter,\n AuthStateProviderAdapter,\n AuthUserPermissionProviderAdapter,\n AuthUserProviderAdapter,\n} from '../adapters/auth-shared-providers.adapter';\n\n/** Provides auth implementations for ng-shared provider interfaces */\nexport function provideAuthProviders(): Provider[] {\n return [\n { provide: USER_PROVIDER, useClass: AuthUserProviderAdapter },\n { provide: COMPANY_API_PROVIDER, useClass: AuthCompanyApiProviderAdapter },\n { provide: USER_PERMISSION_PROVIDER, useClass: AuthUserPermissionProviderAdapter },\n { provide: AUTH_STATE_PROVIDER, useClass: AuthStateProviderAdapter },\n ];\n}\n","import { Component, effect, inject, input, output, signal } from '@angular/core';\nimport {\n ConfirmationService,\n DialogComponent,\n FButtonDirective,\n MessageService,\n ProgressSpinnerComponent,\n TooltipDirective,\n UiIconComponent,\n} from '@flusys/ng-ui';\nimport {\n HasPermissionDirective,\n TranslatePipe,\n TranslateService,\n USER_PERMISSIONS,\n} from '@flusys/ng-shared';\nimport { firstValueFrom } from 'rxjs';\nimport { IBranch } from '../interfaces/branch.interface';\nimport { IBranchPermittedUser } from '../interfaces/user-permission.interface';\nimport { UserPermissionApiService } from '../services/user-permission-api.service';\n\n/**\n * Read-only viewer for users permitted against a branch, with a remove-only\n * action per user. Assigning new users stays on the user-centric permission\n * flow (`UserBranchPermissionDialogComponent`) — this dialog intentionally\n * has no \"add\" affordance.\n */\n@Component({\n selector: 'lib-branch-permitted-users-dialog',\n imports: [\n DialogComponent,\n FButtonDirective,\n ProgressSpinnerComponent,\n TooltipDirective,\n UiIconComponent,\n HasPermissionDirective,\n TranslatePipe,\n ],\n template: `\n <f-dialog\n [visible]=\"visible()\"\n [modal]=\"true\"\n [closable]=\"true\"\n [breakpoints]=\"{ '960px': '90vw', '640px': '95vw' }\"\n [style]=\"{ width: '50vw', maxWidth: '600px' }\"\n [header]=\"'administrative.permission.view.users' | translate\"\n (onHide)=\"onClose()\"\n >\n <div class=\"mb-4\">\n <p class=\"text-sm text-muted-color\">\n {{ 'administrative.branch.title' | translate }}:\n <strong>{{ branch()?.name }}</strong>\n </p>\n </div>\n\n @if (isLoading()) {\n <div class=\"flex justify-center items-center py-8\">\n <f-progressspinner />\n </div>\n } @else {\n <div class=\"flex flex-col gap-3\">\n @for (user of users(); track user.id) {\n <div\n class=\"flex items-center justify-between p-3 border border-surface rounded\"\n >\n <div>\n <div class=\"font-semibold\">{{ user.userName }}</div>\n <div class=\"text-sm text-muted-color\">{{ user.userEmail }}</div>\n </div>\n <button\n fButton\n *hasPermission=\"USER_PERMISSIONS.UPDATE\"\n [text]=\"true\"\n severity=\"danger\"\n size=\"small\"\n [disabled]=\"isRemoving()\"\n [fTooltip]=\"'shared.remove' | translate\"\n (click)=\"onRemove(user)\"\n >\n <ui-icon pButtonIcon name=\"trash\"></ui-icon>\n </button>\n </div>\n } @empty {\n <div class=\"text-center py-4 text-muted-color\">\n {{ 'administrative.permission.no.users' | translate }}\n </div>\n }\n </div>\n }\n\n <ng-template #footer>\n <button\n fButton\n severity=\"secondary\"\n [outlined]=\"true\"\n (click)=\"onClose()\"\n >\n <span pButtonLabel>{{ 'shared.close' | translate }}</span>\n </button>\n </ng-template>\n </f-dialog>\n `,\n})\nexport class BranchPermittedUsersDialogComponent {\n readonly USER_PERMISSIONS = USER_PERMISSIONS;\n\n private readonly permissionApi = inject(UserPermissionApiService);\n private readonly confirmationService = inject(ConfirmationService);\n private readonly messageService = inject(MessageService);\n private readonly translateAdapter = inject(TranslateService, {\n optional: true,\n });\n\n private t(key: string, params?: Record<string, unknown>): string {\n return this.translateAdapter?.translate(key, params) ?? key;\n }\n\n readonly visible = input.required<boolean>();\n readonly branch = input.required<IBranch | null>();\n readonly closed = output<void>();\n\n readonly isLoading = signal(false);\n readonly isRemoving = signal(false);\n readonly users = signal<IBranchPermittedUser[]>([]);\n\n constructor() {\n effect(() => {\n if (this.visible() && this.branch()) {\n this.loadUsers();\n }\n });\n }\n\n private async loadUsers(): Promise<void> {\n const branch = this.branch();\n if (!branch) return;\n\n this.isLoading.set(true);\n try {\n const response = await firstValueFrom(this.permissionApi.getBranchUsers(branch.id));\n if (this.branch()?.id !== branch.id) return;\n this.users.set(response.data ?? []);\n } catch {\n // Error toast handled by global interceptor\n } finally {\n this.isLoading.set(false);\n }\n }\n\n onRemove(user: IBranchPermittedUser): void {\n const branch = this.branch();\n if (!branch) return;\n\n this.confirmationService.confirm({\n message: this.t('administrative.permission.remove.confirm', {\n name: user.userName,\n }),\n header: this.t('administrative.permission.remove'),\n icon: 'exclamation-triangle',\n acceptButtonStyleClass: 'p-button-danger',\n accept: async () => {\n this.isRemoving.set(true);\n try {\n const response = await firstValueFrom(\n this.permissionApi.revokeUserFromBranch(user.userId, branch.id),\n );\n\n if (response.success) {\n this.users.update((list) => list.filter((u) => u.id !== user.id));\n this.messageService.add({\n severity: 'success',\n summary: this.t('shared.success'),\n detail: response?.messageKey\n ? this.t(response.messageKey, response.messageVariables)\n : (response?.message ?? ''),\n });\n }\n } catch {\n // Error toast handled by global interceptor\n } finally {\n this.isRemoving.set(false);\n }\n },\n });\n }\n\n onClose(): void {\n this.closed.emit();\n }\n}\n","import { Component, effect, inject, input, output, signal } from '@angular/core';\nimport {\n ConfirmationService,\n DialogComponent,\n FButtonDirective,\n MessageService,\n ProgressSpinnerComponent,\n TooltipDirective,\n UiIconComponent,\n} from '@flusys/ng-ui';\nimport {\n HasPermissionDirective,\n TranslatePipe,\n TranslateService,\n USER_PERMISSIONS,\n} from '@flusys/ng-shared';\nimport { firstValueFrom } from 'rxjs';\nimport { ICompany } from '../interfaces/company.interface';\nimport { ICompanyPermittedUser } from '../interfaces/user-permission.interface';\nimport { UserPermissionApiService } from '../services/user-permission-api.service';\n\n/**\n * Read-only viewer for users permitted against a company, with a remove-only\n * action per user. Assigning new users stays on the user-centric permission\n * flow (`UserCompanyPermissionDialogComponent`) — this dialog intentionally\n * has no \"add\" affordance.\n */\n@Component({\n selector: 'lib-company-permitted-users-dialog',\n imports: [\n DialogComponent,\n FButtonDirective,\n ProgressSpinnerComponent,\n TooltipDirective,\n UiIconComponent,\n HasPermissionDirective,\n TranslatePipe,\n ],\n template: `\n <f-dialog\n [visible]=\"visible()\"\n [modal]=\"true\"\n [closable]=\"true\"\n [breakpoints]=\"{ '960px': '90vw', '640px': '95vw' }\"\n [style]=\"{ width: '50vw', maxWidth: '600px' }\"\n [header]=\"'administrative.permission.view.users' | translate\"\n (onHide)=\"onClose()\"\n >\n <div class=\"mb-4\">\n <p class=\"text-sm text-muted-color\">\n {{ 'administrative.company.title' | translate }}:\n <strong>{{ company()?.name }}</strong>\n </p>\n </div>\n\n @if (isLoading()) {\n <div class=\"flex justify-center items-center py-8\">\n <f-progressspinner />\n </div>\n } @else {\n <div class=\"flex flex-col gap-3\">\n @for (user of users(); track user.id) {\n <div\n class=\"flex items-center justify-between p-3 border border-surface rounded\"\n >\n <div>\n <div class=\"font-semibold\">{{ user.userName }}</div>\n <div class=\"text-sm text-muted-color\">{{ user.userEmail }}</div>\n </div>\n <button\n fButton\n *hasPermission=\"USER_PERMISSIONS.UPDATE\"\n [text]=\"true\"\n severity=\"danger\"\n size=\"small\"\n [disabled]=\"isRemoving()\"\n [fTooltip]=\"'shared.remove' | translate\"\n (click)=\"onRemove(user)\"\n >\n <ui-icon pButtonIcon name=\"trash\"></ui-icon>\n </button>\n </div>\n } @empty {\n <div class=\"text-center py-4 text-muted-color\">\n {{ 'administrative.permission.no.users' | translate }}\n </div>\n }\n </div>\n }\n\n <ng-template #footer>\n <button\n fButton\n severity=\"secondary\"\n [outlined]=\"true\"\n (click)=\"onClose()\"\n >\n <span pButtonLabel>{{ 'shared.close' | translate }}</span>\n </button>\n </ng-template>\n </f-dialog>\n `,\n})\nexport class CompanyPermittedUsersDialogComponent {\n readonly USER_PERMISSIONS = USER_PERMISSIONS;\n\n private readonly permissionApi = inject(UserPermissionApiService);\n private readonly confirmationService = inject(ConfirmationService);\n private readonly messageService = inject(MessageService);\n private readonly translateAdapter = inject(TranslateService, {\n optional: true,\n });\n\n private t(key: string, params?: Record<string, unknown>): string {\n return this.translateAdapter?.translate(key, params) ?? key;\n }\n\n readonly visible = input.required<boolean>();\n readonly company = input.required<ICompany | null>();\n readonly closed = output<void>();\n\n readonly isLoading = signal(false);\n readonly isRemoving = signal(false);\n readonly users = signal<ICompanyPermittedUser[]>([]);\n\n constructor() {\n effect(() => {\n if (this.visible() && this.company()) {\n this.loadUsers();\n }\n });\n }\n\n private async loadUsers(): Promise<void> {\n const company = this.company();\n if (!company) return;\n\n this.isLoading.set(true);\n try {\n const response = await firstValueFrom(this.permissionApi.getCompanyUsers(company.id));\n if (this.company()?.id !== company.id) return;\n this.users.set(response.data ?? []);\n } catch {\n // Error toast handled by global interceptor\n } finally {\n this.isLoading.set(false);\n }\n }\n\n onRemove(user: ICompanyPermittedUser): void {\n const company = this.company();\n if (!company) return;\n\n this.confirmationService.confirm({\n message: this.t('administrative.permission.remove.confirm', {\n name: user.userName,\n }),\n header: this.t('administrative.permission.remove'),\n icon: 'exclamation-triangle',\n acceptButtonStyleClass: 'p-button-danger',\n accept: async () => {\n this.isRemoving.set(true);\n try {\n const response = await firstValueFrom(\n this.permissionApi.revokeUserFromCompany(user.userId, company.id),\n );\n\n if (response.success) {\n this.users.update((list) => list.filter((u) => u.id !== user.id));\n this.messageService.add({\n severity: 'success',\n summary: this.t('shared.success'),\n detail: response?.messageKey\n ? this.t(response.messageKey, response.messageVariables)\n : (response?.message ?? ''),\n });\n }\n } catch {\n // Error toast handled by global interceptor\n } finally {\n this.isRemoving.set(false);\n }\n },\n });\n }\n\n onClose(): void {\n this.closed.emit();\n }\n}\n","import {\n Component,\n DestroyRef,\n DOCUMENT,\n computed,\n inject,\n input,\n signal,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport {\n PlatformService,\n TranslatePipe,\n TranslateService,\n} from '@flusys/ng-shared';\nimport { FButtonDirective, MessageService } from '@flusys/ng-ui';\nimport { SocialProviderEnum } from '../enums/social-provider.enum';\nimport { ISocialProviderInfo } from '../interfaces/social-auth.interface';\nimport { SocialAuthApiService } from '../services/social-auth-api.service';\n\n@Component({\n selector: 'lib-social-login-buttons',\n imports: [FButtonDirective, TranslatePipe],\n template: `\n @if (providers().length) {\n <div class=\"mt-6\">\n <div class=\"flex items-center gap-3 mb-4\">\n <span class=\"flex-1 h-px bg-surface-200 dark:bg-surface-700\"></span>\n <span class=\"text-muted-color text-sm\">{{\n 'auth.social.continue.with' | translate\n }}</span>\n <span class=\"flex-1 h-px bg-surface-200 dark:bg-surface-700\"></span>\n </div>\n\n <div [class]=\"layoutClass()\">\n @for (info of providers(); track info.provider) {\n <button\n fButton\n type=\"button\"\n severity=\"secondary\"\n [outlined]=\"true\"\n [class]=\"showLabels() ? 'w-full' : 'shrink-0'\"\n [attr.aria-label]=\"\n showLabels()\n ? null\n : ('auth.social.provider.' + info.provider | translate)\n \"\n [attr.title]=\"\n showLabels()\n ? null\n : ('auth.social.provider.' + info.provider | translate)\n \"\n [disabled]=\"pendingProvider() !== null && pendingProvider() !== info.provider\"\n [loading]=\"pendingProvider() === info.provider\"\n (click)=\"onSelect(info.provider)\"\n >\n @if (pendingProvider() !== info.provider) {\n @switch (info.provider) {\n @case (providerEnum.GOOGLE) {\n <svg class=\"shrink-0\" width=\"18\" height=\"18\" viewBox=\"0 0 48 48\" aria-hidden=\"true\">\n <path fill=\"#EA4335\" d=\"M24 9.5c3.54 0 6.71 1.22 9.21 3.6l6.85-6.85C35.9 2.38 30.47 0 24 0 14.62 0 6.51 5.38 2.56 13.22l7.98 6.19C12.43 13.72 17.74 9.5 24 9.5z\" />\n <path fill=\"#4285F4\" d=\"M46.98 24.55c0-1.57-.15-3.09-.38-4.55H24v9.02h12.94c-.58 3-2.26 5.54-4.78 7.25l7.73 6c4.51-4.18 7.09-10.36 7.09-17.72z\" />\n <path fill=\"#FBBC05\" d=\"M10.53 28.59A14.5 14.5 0 0 1 9.77 24c0-1.6.29-3.14.76-4.59l-7.98-6.19A23.94 23.94 0 0 0 0 24c0 3.88.93 7.54 2.56 10.78l7.97-6.19z\" />\n <path fill=\"#34A853\" d=\"M24 48c6.48 0 11.93-2.13 15.89-5.81l-7.73-6c-2.15 1.45-4.92 2.3-8.16 2.3-6.26 0-11.57-4.22-13.47-9.91l-7.98 6.19C6.51 42.62 14.62 48 24 48z\" />\n </svg>\n }\n @case (providerEnum.FACEBOOK) {\n <svg class=\"shrink-0\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <path fill=\"#1877F2\" d=\"M24 12.07C24 5.4 18.63 0 12 0S0 5.4 0 12.07C0 18.1 4.39 23.1 10.13 24v-8.44H7.08v-3.49h3.05V9.41c0-3.02 1.79-4.69 4.53-4.69 1.31 0 2.69.24 2.69.24v2.96h-1.51c-1.49 0-1.96.93-1.96 1.88v2.25h3.33l-.53 3.49h-2.8V24C19.61 23.1 24 18.1 24 12.07z\" />\n </svg>\n }\n @case (providerEnum.LINKEDIN) {\n <svg class=\"shrink-0\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <path fill=\"#0A66C2\" d=\"M20.45 20.45h-3.56v-5.57c0-1.33-.03-3.04-1.85-3.04-1.86 0-2.14 1.45-2.14 2.94v5.67H9.35V9h3.41v1.56h.05a3.74 3.74 0 0 1 3.37-1.85c3.6 0 4.27 2.37 4.27 5.46v6.28zM5.34 7.43a2.06 2.06 0 1 1 0-4.13 2.06 2.06 0 0 1 0 4.13zM7.12 20.45H3.55V9h3.57v11.45zM22.22 0H1.77C.79 0 0 .78 0 1.73v20.54C0 23.22.79 24 1.77 24h20.45c.98 0 1.78-.78 1.78-1.73V1.73C24 .78 23.2 0 22.22 0z\" />\n </svg>\n }\n @case (providerEnum.MICROSOFT) {\n <svg class=\"shrink-0\" width=\"18\" height=\"18\" viewBox=\"0 0 23 23\" aria-hidden=\"true\">\n <path fill=\"#F25022\" d=\"M0 0h11v11H0z\" />\n <path fill=\"#7FBA00\" d=\"M12 0h11v11H12z\" />\n <path fill=\"#00A4EF\" d=\"M0 12h11v11H0z\" />\n <path fill=\"#FFB900\" d=\"M12 12h11v11H12z\" />\n </svg>\n }\n }\n }\n @if (showLabels()) {\n <span>{{\n 'auth.social.provider.' + info.provider | translate\n }}</span>\n }\n </button>\n }\n </div>\n </div>\n }\n `,\n})\nexport class SocialLoginButtonsComponent {\n private readonly destroyRef = inject(DestroyRef);\n private readonly socialApi = inject(SocialAuthApiService);\n private readonly messageService = inject(MessageService);\n private readonly platform = inject(PlatformService);\n private readonly document = inject(DOCUMENT);\n private readonly translateAdapter = inject(TranslateService, {\n optional: true,\n });\n\n readonly returnUrl = input<string>('');\n\n readonly providerEnum = SocialProviderEnum;\n\n private readonly _providers = signal<ISocialProviderInfo[]>([]);\n readonly providers = this._providers.asReadonly();\n\n private readonly _pendingProvider = signal<SocialProviderEnum | null>(null);\n readonly pendingProvider = this._pendingProvider.asReadonly();\n\n readonly showLabels = computed(() => this.providers().length <= 2);\n\n readonly layoutClass = computed(() => {\n switch (this.providers().length) {\n case 1:\n return 'grid grid-cols-1';\n case 2:\n return 'grid grid-cols-2 gap-3';\n default:\n return 'flex flex-wrap justify-center gap-3';\n }\n });\n\n constructor() {\n if (this.platform.isServer) return;\n\n this.socialApi\n .getProviders()\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe({\n next: (response) => this._providers.set(response.data ?? []),\n error: () => this._providers.set([]),\n });\n }\n\n onSelect(provider: SocialProviderEnum): void {\n this._pendingProvider.set(provider);\n this.socialApi.saveReturnUrl(this.returnUrl());\n\n this.socialApi\n .authorize(provider)\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe({\n next: (response) => {\n const url = response.data?.authorizationUrl;\n if (!url) {\n this._pendingProvider.set(null);\n return;\n }\n this.redirectTo(url);\n },\n error: (error) => {\n this._pendingProvider.set(null);\n const messageKey = error?.error?.messageKey;\n this.messageService.add({\n severity: 'error',\n summary: this.translate('auth.login.title'),\n detail: messageKey\n ? this.translate(messageKey, { provider })\n : error?.error?.message,\n });\n },\n });\n }\n\n protected redirectTo(url: string): void {\n this.document.location.assign(url);\n }\n\n private translate(\n key: string,\n vars?: Record<string, string | number>,\n ): string {\n return this.translateAdapter?.translate(key, vars) ?? key;\n }\n}\n","import {\n CheckboxComponent,\n DialogComponent,\n FButtonDirective,\n MessageService,\n ProgressSpinnerComponent,\n SelectComponent,\n UiIconComponent,\n} from '@flusys/ng-ui';\nimport {\n Component,\n computed,\n inject,\n input,\n output,\n resource,\n signal,\n} from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport {\n flattenBranchTree,\n getBranchPath,\n TranslatePipe,\n TranslateService,\n} from '@flusys/ng-shared';\nimport { firstValueFrom } from 'rxjs';\nimport { IBranch } from '../interfaces/branch.interface';\nimport { IUser } from '../interfaces/user.interface';\nimport { BranchApiService } from '../services/branch-api.service';\nimport { UserPermissionApiService } from '../services/user-permission-api.service';\n\ninterface BranchWithAssignment extends IBranch {\n isAssigned: boolean;\n}\n\n@Component({\n selector: 'lib-user-branch-permission-dialog',\n imports: [\n FormsModule,\n CheckboxComponent,\n DialogComponent,\n FButtonDirective,\n ProgressSpinnerComponent,\n SelectComponent,\n TranslatePipe,\n UiIconComponent,\n ],\n template: `\n <f-dialog\n [visible]=\"visible()\"\n [modal]=\"true\"\n [closable]=\"true\"\n [breakpoints]=\"{ '960px': '90vw', '640px': '95vw' }\"\n [style]=\"{ width: '50vw', maxWidth: '600px' }\"\n [header]=\"'administrative.permission.manage.branch' | translate\"\n (onHide)=\"onClose()\"\n >\n <div class=\"mb-4\">\n <p class=\"text-sm text-muted-color mb-3\">\n {{ 'administrative.permission.user' | translate }}:\n <strong>{{ user()?.name }}</strong> ({{ user()?.email }})\n </p>\n <div class=\"flex items-center gap-2\">\n <label class=\"text-sm font-medium min-w-[70px]\"\n >{{ 'shared.company' | translate }}:</label\n >\n <f-select\n [options]=\"companiesResource.value() ?? []\"\n [ngModel]=\"selectedCompanyId()\"\n (ngModelChange)=\"selectedCompanyId.set($event)\"\n optionLabel=\"name\"\n optionValue=\"id\"\n [placeholder]=\"'administrative.company.select' | translate\"\n styleClass=\"w-full\"\n [disabled]=\"isInitialLoading() || isSaving()\"\n />\n </div>\n </div>\n\n @if (isInitialLoading()) {\n <div class=\"flex justify-center items-center py-8\">\n <f-progressspinner />\n </div>\n } @else {\n <div class=\"flex flex-col gap-3\">\n @for (row of branchRows(); track row.branch.id) {\n @let branch = row.branch;\n <div\n class=\"flex items-center p-3 border border-surface rounded\"\n [style.margin-inline-start.rem]=\"row.depth * 1.5\"\n >\n @if (row.depth > 0) {\n <ui-icon\n name=\"corner-down-right\"\n class=\"text-muted-color me-2\"\n aria-hidden=\"true\"\n ></ui-icon>\n }\n <f-checkbox\n [ngModel]=\"branch.isAssigned\"\n [binary]=\"true\"\n [inputId]=\"'branch-' + branch.id\"\n [disabled]=\"isSaving()\"\n (onChange)=\"onBranchToggle(branch, $event.checked)\"\n />\n <label\n [for]=\"'branch-' + branch.id\"\n class=\"ml-3 flex-1 cursor-pointer\"\n >\n <div class=\"font-semibold\">{{ branch.name }}</div>\n @if (row.parentPath) {\n <span class=\"sr-only\" data-branch-path\n >{{ 'administrative.branch.parent' | translate }}:\n {{ row.parentPath }}</span\n >\n }\n <div class=\"text-sm text-muted-color\">{{ branch.slug }}</div>\n </label>\n </div>\n } @empty {\n <div class=\"text-center py-4 text-muted-color\">\n @if ((companiesResource.value() ?? []).length === 0) {\n {{ 'administrative.permission.no.company' | translate }}<br />\n <span class=\"text-xs\">{{\n 'administrative.permission.assign.company.first' | translate\n }}</span>\n } @else if (!selectedCompanyId()) {\n {{\n 'administrative.permission.select.company.for.branches'\n | translate\n }}\n } @else {\n {{ 'administrative.branch.no.branches' | translate }}\n }\n </div>\n }\n </div>\n }\n\n <ng-template #footer>\n <button\n fButton\n severity=\"secondary\"\n [outlined]=\"true\"\n (click)=\"onClose()\"\n [disabled]=\"isSaving()\"\n >\n <span pButtonLabel>{{ 'shared.close' | translate }}</span>\n </button>\n </ng-template>\n </f-dialog>\n `,\n})\nexport class UserBranchPermissionDialogComponent {\n private readonly branchApi = inject(BranchApiService);\n private readonly permissionApi = inject(UserPermissionApiService);\n private readonly messageService = inject(MessageService);\n private readonly translateAdapter = inject(TranslateService, {\n optional: true,\n });\n\n private t(key: string, params?: Record<string, unknown>): string {\n return this.translateAdapter?.translate(key, params) ?? key;\n }\n\n readonly visible = input.required<boolean>();\n readonly user = input.required<IUser | null>();\n readonly closed = output<void>();\n readonly permissionsChanged = output<void>();\n\n readonly isSaving = signal(false);\n readonly selectedCompanyId = signal<string | null>(null);\n\n readonly companiesResource = resource({\n params: () => {\n const user = this.user();\n if (!this.visible() || !user) return undefined;\n return { userId: user.id };\n },\n loader: async ({ params }) => {\n const response = await firstValueFrom(\n this.permissionApi.getUserCompanies(params!.userId),\n );\n this.selectedCompanyId.set(null);\n return (response.data ?? []).map((p) => ({\n id: p.companyId,\n name: p.companyName,\n }));\n },\n });\n\n readonly branchesResource = resource({\n params: () => {\n const user = this.user();\n const companyId = this.selectedCompanyId();\n if (!user || !companyId) return undefined;\n return { userId: user.id, companyId };\n },\n loader: async ({ params }) => {\n const [branchesResponse, assignedResponse] = await Promise.all([\n this.branchApi.getAll({\n pagination: { currentPage: 0, pageSize: 1000 },\n filter: { companyId: params!.companyId },\n select: [],\n sort: {},\n }),\n firstValueFrom(this.permissionApi.getUserBranches(params!.userId, params!.companyId)),\n ]);\n\n const assignedIds = new Set((assignedResponse.data ?? []).map((p) => p.branchId));\n\n return (branchesResponse.data ?? []).map((branch) => ({\n ...branch,\n isAssigned: assignedIds.has(branch.id),\n }));\n },\n });\n\n readonly branchRows = computed(() => {\n const branches = this.branchesResource.value() ?? [];\n return flattenBranchTree(branches).map((row) => ({\n ...row,\n parentPath: getBranchPath(branches, row.branch.parentId)\n .map((b) => b.name)\n .join(' / '),\n }));\n });\n\n readonly isInitialLoading = computed(\n () => this.branchesResource.isLoading() && !this.branchesResource.value(),\n );\n\n async onBranchToggle(\n branch: BranchWithAssignment,\n isAssigned: boolean,\n ): Promise<void> {\n const currentUser = this.user();\n if (!currentUser) return;\n\n this.isSaving.set(true);\n try {\n const response = await firstValueFrom(\n isAssigned\n ? this.permissionApi.assignUserToBranch(currentUser.id, branch.id)\n : this.permissionApi.revokeUserFromBranch(currentUser.id, branch.id),\n );\n if (response.success) {\n this.messageService.add({\n severity: 'success',\n summary: this.t('shared.success'),\n detail: response.messageKey\n ? this.t(response.messageKey, response.messageVariables)\n : (response.message ?? ''),\n });\n this.permissionsChanged.emit();\n this.branchesResource.reload();\n }\n } catch {\n } finally {\n this.isSaving.set(false);\n }\n }\n\n onClose(): void {\n this.closed.emit();\n }\n}\n","import {\n CheckboxComponent,\n DialogComponent,\n FButtonDirective,\n MessageService,\n ProgressSpinnerComponent,\n} from '@flusys/ng-ui';\nimport {\n Component,\n effect,\n inject,\n input,\n output,\n signal,\n} from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport {\n TranslatePipe,\n TranslateService,\n} from '@flusys/ng-shared';\nimport { firstValueFrom } from 'rxjs';\nimport { ICompany } from '../interfaces/company.interface';\nimport { IUser } from '../interfaces/user.interface';\nimport { CompanyApiService } from '../services/company-api.service';\nimport { UserPermissionApiService } from '../services/user-permission-api.service';\n\ninterface CompanyWithAssignment extends ICompany {\n isAssigned: boolean;\n}\n\n@Component({\n selector: 'lib-user-company-permission-dialog',\n imports: [\n FormsModule,\n CheckboxComponent,\n DialogComponent,\n FButtonDirective,\n ProgressSpinnerComponent,\n TranslatePipe,\n ],\n template: `\n <f-dialog\n [visible]=\"visible()\"\n [modal]=\"true\"\n [closable]=\"true\"\n [breakpoints]=\"{ '960px': '90vw', '640px': '95vw' }\"\n [style]=\"{ width: '50vw', maxWidth: '600px' }\"\n [header]=\"'administrative.permission.manage.company' | translate\"\n (onHide)=\"onClose()\"\n >\n <div class=\"mb-4\">\n <p class=\"text-sm text-muted-color\">\n {{ 'administrative.permission.user' | translate }}:\n <strong>{{ user()?.name }}</strong> ({{ user()?.email }})\n </p>\n </div>\n\n @if (isLoading()) {\n <div class=\"flex justify-center items-center py-8\">\n <f-progressspinner />\n </div>\n } @else {\n <div class=\"flex flex-col gap-3\">\n @for (company of companies(); track company.id) {\n <div class=\"flex items-center p-3 border border-surface rounded\">\n <f-checkbox\n [ngModel]=\"company.isAssigned\"\n [binary]=\"true\"\n [inputId]=\"'company-' + company.id\"\n [disabled]=\"isSaving()\"\n (onChange)=\"onCompanyToggle(company, $event.checked)\"\n />\n <label\n [for]=\"'company-' + company.id\"\n class=\"ml-3 flex-1 cursor-pointer\"\n >\n <div class=\"font-semibold\">{{ company.name }}</div>\n <div class=\"text-sm text-muted-color\">{{ company.slug }}</div>\n </label>\n </div>\n } @empty {\n <div class=\"text-center py-4 text-muted-color\">\n {{ 'administrative.company.no.companies' | translate }}\n </div>\n }\n </div>\n }\n\n <ng-template #footer>\n <button\n fButton\n severity=\"secondary\"\n [outlined]=\"true\"\n (click)=\"onClose()\"\n [disabled]=\"isSaving()\"\n >\n <span pButtonLabel>{{ 'shared.close' | translate }}</span>\n </button>\n </ng-template>\n </f-dialog>\n `,\n})\nexport class UserCompanyPermissionDialogComponent {\n private readonly companyApi = inject(CompanyApiService);\n private readonly permissionApi = inject(UserPermissionApiService);\n private readonly messageService = inject(MessageService);\n private readonly translateAdapter = inject(TranslateService, {\n optional: true,\n });\n\n private t(key: string, params?: Record<string, unknown>): string {\n return this.translateAdapter?.translate(key, params) ?? key;\n }\n\n readonly visible = input.required<boolean>();\n readonly user = input.required<IUser | null>();\n readonly closed = output<void>();\n readonly permissionsChanged = output<void>();\n\n readonly isLoading = signal(false);\n readonly isSaving = signal(false);\n readonly companies = signal<CompanyWithAssignment[]>([]);\n\n private assignedCompanyIds = new Set<string>();\n\n constructor() {\n effect(() => {\n if (this.visible() && this.user()) {\n this.loadData();\n }\n });\n }\n\n private async loadData(): Promise<void> {\n const currentUser = this.user();\n if (!currentUser) return;\n\n this.isLoading.set(true);\n try {\n const companiesResponse = await this.companyApi.getAll({\n pagination: { currentPage: 0, pageSize: 1000 },\n filter: {},\n select: [],\n sort: {},\n });\n\n const assignedResponse = await firstValueFrom(\n this.permissionApi.getUserCompanies(currentUser.id),\n );\n if (this.user()?.id !== currentUser.id) return;\n\n this.assignedCompanyIds.clear();\n if (assignedResponse.data) {\n assignedResponse.data.forEach((permission) => {\n this.assignedCompanyIds.add(permission.companyId);\n });\n }\n\n const companiesWithStatus: CompanyWithAssignment[] = (\n companiesResponse.data || []\n ).map((company) => ({\n ...company,\n isAssigned: this.assignedCompanyIds.has(company.id),\n }));\n\n this.companies.set(companiesWithStatus);\n } catch {\n } finally {\n this.isLoading.set(false);\n }\n }\n\n async onCompanyToggle(\n company: CompanyWithAssignment,\n isAssigned: boolean,\n ): Promise<void> {\n const currentUser = this.user();\n if (!currentUser) return;\n\n this.isSaving.set(true);\n try {\n const response = isAssigned\n ? await firstValueFrom(\n this.permissionApi.assignUserToCompany(currentUser.id, company.id),\n )\n : await firstValueFrom(\n this.permissionApi.revokeUserFromCompany(currentUser.id, company.id),\n );\n\n if (response.success) {\n if (isAssigned) this.assignedCompanyIds.add(company.id);\n else this.assignedCompanyIds.delete(company.id);\n\n this.companies.update((list) =>\n list.map((c) => (c.id === company.id ? { ...c, isAssigned } : c)),\n );\n\n this.messageService.add({\n severity: 'success',\n summary: this.t('shared.success'),\n detail: response?.messageKey\n ? this.t(response.messageKey, response.messageVariables)\n : (response?.message ?? ''),\n });\n this.permissionsChanged.emit();\n }\n } catch {\n } finally {\n this.isSaving.set(false);\n }\n }\n\n onClose(): void {\n this.closed.emit();\n }\n}\n"],"mappings":"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"}
|