574 lines
13 KiB
TypeScript
574 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
|
|
|
|
// 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;
|
|
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_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;
|
|
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;
|
|
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;
|
|
}
|