monacousa-portal/utils/types.ts

582 lines
13 KiB
TypeScript

// 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<T = any> {
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
portal_group?: 'user' | 'board' | 'admin'; // Portal access level group
// 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: {
members: string;
events: string;
rsvps: string;
[tableName: string]: string;
}; // e.g., { "members": "m2sri3jqfqutiy5", "events": "evt123abc", "rsvps": "rsvp456def" }
}
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<string, string[]>;
groups?: string[];
realmRoles?: string[];
clientRoles?: Record<string, string[]>;
createdTimestamp?: number;
requiredActions?: string[];
}
export interface KeycloakRoleRepresentation {
id?: string;
name?: string;
description?: string;
composite?: boolean;
clientRole?: boolean;
containerId?: string;
attributes?: Record<string, string[]>;
}
export interface KeycloakGroupRepresentation {
id?: string;
name?: string;
path?: string;
attributes?: Record<string, string[]>;
realmRoles?: string[];
clientRoles?: Record<string, string[]>;
subGroups?: KeycloakGroupRepresentation[];
}
export interface UserSessionRepresentation {
id?: string;
username?: string;
userId?: string;
ipAddress?: string;
start?: number;
lastAccess?: number;
clients?: Record<string, string>;
}
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<string, string[]>;
attributes?: Record<string, string[]>;
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<string, string>;
}
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<string, string[]>;
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;
event_id?: string; // Custom event identifier (e.g., "evt_1723555200_abc123")
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
guests_permitted?: string; // 'true' or 'false' as string
max_guests_permitted?: string; // Maximum guests per person
visibility: 'public' | 'board-only' | 'admin-only';
status: 'active' | 'cancelled' | 'completed' | 'draft';
creator: string; // member_id who created event
created_time: string; // Updated to match database schema
updated_time: string; // Updated to match database schema
// Computed fields
current_attendees?: string; // Changed to string to match database
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;
extra_guests?: string; // Number of additional guests as string
created_time: string; // Updated to match database schema
updated_time: string; // Updated to match database schema
// 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;
guests_permitted?: string;
max_guests_permitted?: string;
visibility: string;
status?: string;
}
export interface EventRSVPRequest {
event_id: string;
member_id: string;
rsvp_status: 'confirmed' | 'declined' | 'pending' | 'waitlist';
rsvp_notes?: string;
extra_guests?: string; // Number of additional guests as 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;
}