// utils/types.ts export interface User { id: string; email: string; name: string; firstName?: string; lastName?: string; username?: string; tier: 'user' | 'board' | 'admin'; groups: string[]; } export interface AuthState { authenticated: boolean; user: User | null; groups: string[]; } export interface ApiResponse { success: boolean; data?: T; error?: string; message?: string; } export interface FileUpload { fieldName: string; fileName: string; originalName: string; size: number; contentType: string; } export interface DatabaseRecord { id: string; created_at: string; updated_at: string; [key: string]: any; } export interface HealthCheck { status: 'healthy' | 'degraded' | 'unhealthy'; timestamp: string; checks: { server: string; database: string; storage: string; auth: string; }; } export interface TokenResponse { access_token: string; refresh_token: string; id_token: string; token_type: string; expires_in: number; } export interface UserInfo { sub: string; email: string; given_name?: string; family_name?: string; name?: string; preferred_username?: string; groups?: string[]; tier?: string; } export interface SessionData { user: User; tokens: { accessToken: string; refreshToken: string; expiresAt: number; }; rememberMe?: boolean; createdAt: number; lastActivity: number; } export interface KeycloakConfig { issuer: string; clientId: string; clientSecret: string; callbackUrl: string; } export interface KeycloakAdminConfig { issuer: string; clientId: string; clientSecret: string; } export interface NocoDBConfig { url: string; token: string; baseId: string; } export interface MinIOConfig { endPoint: string; port: number; useSSL: boolean; accessKey: string; secretKey: string; bucketName: string; } // Member Management Types export enum MembershipStatus { Active = 'Active', Inactive = 'Inactive', Pending = 'Pending', Expired = 'Expired' } export interface Member { Id: string; member_id?: string; // MUSA-{unique number} - Member identification number first_name: string; last_name: string; email: string; phone: string; current_year_dues_paid: string; // "true" or "false" nationality: string; // "FR,MC,US" for multiple nationalities date_of_birth: string; membership_date_paid: string; payment_due_date: string; membership_status: string; address: string; member_since: string; keycloak_id?: string; // New field for linking to Keycloak user registration_date?: string; // New field for tracking registration date // Computed fields (added by processing) FullName?: string; FormattedPhone?: string; NationalityArray?: string[]; // Parsed from comma-separated string } // Admin-only NocoDB Configuration export interface NocoDBSettings { url: string; apiKey: string; baseId: string; tables: { [tableName: string]: string }; // e.g., { "members": "m2sri3jqfqutiy5", "events": "evt123abc", ... } } export interface MemberResponse { list: Member[]; PageInfo: { pageSize: number; totalRows: number; isFirstPage: boolean; isLastPage: boolean; page: number; }; } export interface MemberFilters { searchTerm?: string; nationality?: string; membershipStatus?: MembershipStatus; duesPaid?: boolean; memberSince?: string; } // Registration System Types export interface RegistrationFormData { first_name: string; last_name: string; email: string; phone: string; date_of_birth: string; address: string; nationality: string; recaptcha_token: string; } export interface RecaptchaConfig { siteKey: string; secretKey: string; } export interface RegistrationConfig { membershipFee: number; iban: string; accountHolder: string; } export interface SMTPConfig { host: string; port: number; secure: boolean; username: string; password: string; fromAddress: string; fromName: string; } // Enhanced Keycloak Admin API Types export interface KeycloakUserRepresentation { id?: string; username?: string; enabled?: boolean; firstName?: string; lastName?: string; email?: string; emailVerified?: boolean; attributes?: Record; groups?: string[]; realmRoles?: string[]; clientRoles?: Record; createdTimestamp?: number; requiredActions?: string[]; } export interface KeycloakRoleRepresentation { id?: string; name?: string; description?: string; composite?: boolean; clientRole?: boolean; containerId?: string; attributes?: Record; } export interface KeycloakGroupRepresentation { id?: string; name?: string; path?: string; attributes?: Record; realmRoles?: string[]; clientRoles?: Record; subGroups?: KeycloakGroupRepresentation[]; } export interface UserSessionRepresentation { id?: string; username?: string; userId?: string; ipAddress?: string; start?: number; lastAccess?: number; clients?: Record; } export interface EmailWorkflowData { emailType: 'DUES_REMINDER' | 'MEMBERSHIP_RENEWAL' | 'WELCOME' | 'ADMIN_NOTIFICATION' | 'VERIFICATION'; customData?: { dueAmount?: string; dueDate?: string; memberSince?: string; renewalDate?: string; welcomeMessage?: string; adminNote?: string; }; lifespan?: number; // Email validity in seconds redirectUri?: string; } export interface MembershipProfileData { membershipStatus?: string; duesStatus?: 'paid' | 'unpaid' | 'overdue'; memberSince?: string; nationality?: string; phone?: string; address?: string; registrationDate?: string; paymentDueDate?: string; lastLoginDate?: string; membershipTier?: 'user' | 'board' | 'admin'; nocodbMemberId?: string; } // Enhanced User interface with role support export interface EnhancedUser extends User { realmRoles?: string[]; clientRoles?: Record; attributes?: Record; sessions?: UserSessionRepresentation[]; memberProfile?: MembershipProfileData; } // Role management types export interface RoleAssignmentRequest { userId: string; roleName: string; roleType: 'realm' | 'client'; clientId?: string; } export interface RoleManagementResponse { success: boolean; assignedRoles?: string[]; removedRoles?: string[]; message?: string; } // Group management types export interface GroupCreationRequest { name: string; path: string; parentPath?: string; attributes?: Record; } export interface GroupAssignmentRequest { userId: string; groupId: string; groupPath: string; } // Session management types export interface SessionManagementRequest { userId: string; sessionId?: string; action: 'get' | 'logout' | 'logoutAll'; } export interface SessionAnalytics { totalSessions: number; activeSessions: number; uniqueUsers: number; sessionsToday: number; averageSessionDuration: number; topClientApplications: Array<{ clientId: string; sessionCount: number; }>; } // Enhanced authentication state with role support export interface EnhancedAuthState extends AuthState { realmRoles: string[]; clientRoles: Record; hasRole: (roleName: string) => boolean; isUser: boolean; isBoard: boolean; isAdmin: boolean; } // Member synchronization types export interface MemberKeycloakSync { memberId: string; keycloakUserId: string; syncDirection: 'nocodb-to-keycloak' | 'keycloak-to-nocodb' | 'bidirectional'; syncFields: string[]; lastSyncTimestamp: string; } export interface SyncResult { success: boolean; syncedFields: string[]; conflictFields?: string[]; errors?: string[]; timestamp: string; } // Admin dashboard types export interface AdminUserManagement { userId: string; email: string; firstName?: string; lastName?: string; enabled: boolean; emailVerified: boolean; realmRoles: string[]; groups: string[]; activeSessions: number; lastLogin?: string; memberProfile?: MembershipProfileData; } export interface AdminDashboardStats { totalUsers: number; activeUsers: number; newRegistrationsToday: number; totalSessions: number; membershipStats: { totalMembers: number; paidMembers: number; unpaidMembers: number; overdueMembers: number; }; roleDistribution: { [roleName: string]: number; }; } // Dues Management System Types export interface DuesMemberWithStatus extends Member { overdueDays?: number; overdueReason?: string; daysUntilDue?: number; nextDueDate?: string; } export interface DuesStatusResponse { success: boolean; data: { overdue: DuesMemberWithStatus[]; upcoming: DuesMemberWithStatus[]; autoUpdated: number; }; } export interface DuesOverdueCountResponse { success: boolean; data: { count: number; overdueMembers: DuesMemberWithStatus[]; }; } export interface DuesPaymentInfo { membershipFee: number; iban: string; accountHolder: string; paymentReference: string; daysRemaining: number; paymentMessage: string; } // Shared dues calculation utilities (used across components) export interface DuesCalculationUtils { isInGracePeriod: (member: Member) => boolean; isPaymentOverOneYear: (member: Member) => boolean; isDuesActuallyCurrent: (member: Member) => boolean; calculateOverdueDays: (member: Member) => number; calculateDaysUntilDue: (member: Member) => { daysUntilDue: number; nextDueDate: string } | null; } // Event Management System Types export interface Event { id: string; title: string; description: string; event_type: 'meeting' | 'social' | 'fundraiser' | 'workshop' | 'board-only'; start_datetime: string; end_datetime: string; location: string; is_recurring: string; // 'true' or 'false' as string recurrence_pattern?: string; // JSON string max_attendees?: string; // null/empty for unlimited is_paid: string; // 'true' or 'false' as string cost_members?: string; cost_non_members?: string; member_pricing_enabled: string; // 'true' or 'false' as string visibility: 'public' | 'board-only' | 'admin-only'; status: 'active' | 'cancelled' | 'completed' | 'draft'; creator: string; // member_id who created event created_at: string; updated_at: string; // Computed fields current_attendees?: number; user_rsvp?: EventRSVP; attendee_list?: EventRSVP[]; } export interface EventRSVP { id: string; event_id: string; member_id: string; rsvp_status: 'confirmed' | 'declined' | 'pending' | 'waitlist'; payment_status: 'not_required' | 'pending' | 'paid' | 'overdue'; payment_reference: string; // EVT-{member_id}-{date} attended: string; // 'true' or 'false' as string rsvp_notes?: string; created_at: string; updated_at: string; // Computed fields member_details?: Member; is_member_pricing?: string; // 'true' or 'false' } export interface EventsResponse { success: boolean; data: Event[]; total?: number; message?: string; } export interface EventCreateRequest { title: string; description: string; event_type: string; start_datetime: string; end_datetime: string; location: string; is_recurring?: string; recurrence_pattern?: string; max_attendees?: string; is_paid: string; cost_members?: string; cost_non_members?: string; member_pricing_enabled: string; visibility: string; status?: string; } export interface EventRSVPRequest { event_id: string; member_id: string; rsvp_status: 'confirmed' | 'declined' | 'pending'; rsvp_notes?: string; } export interface EventAttendanceRequest { event_id: string; member_id: string; attended: boolean; } // Calendar subscription types export interface CalendarSubscription { user_id: string; feed_url: string; include_rsvp_only?: boolean; created_at: string; } // Event configuration types export interface EventsConfig { eventsBaseId: string; eventsTableId: string; defaultEventTypes: string[]; maxEventsPerPage: number; cacheTimeout: number; } // FullCalendar integration types export interface FullCalendarEvent { id: string; title: string; start: string; end: string; backgroundColor?: string; borderColor?: string; textColor?: string; extendedProps: { description: string; location: string; event_type: string; is_paid: boolean; cost_members?: string; cost_non_members?: string; max_attendees?: number; current_attendees?: number; user_rsvp?: EventRSVP; visibility: string; creator: string; }; } export interface EventFilters { start_date?: string; end_date?: string; event_type?: string; visibility?: string; status?: string; user_role?: 'user' | 'board' | 'admin'; search?: string; }