- Add activeClients and inactiveClients to AdminStatistics type - Add pie chart showing client status (active/inactive) - Add detailed stats rows for active/inactive clients 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
248 lines
4.7 KiB
TypeScript
248 lines
4.7 KiB
TypeScript
// User Types
|
|
export interface User {
|
|
id: string;
|
|
email: string;
|
|
firstName: string;
|
|
lastName: string;
|
|
phone?: string;
|
|
address?: string;
|
|
city?: string;
|
|
postalCode?: string;
|
|
gender?: 'MALE' | 'FEMALE' | 'OTHER' | 'NOT_SPECIFIED';
|
|
dateOfBirth?: string;
|
|
role: 'CLIENT' | 'EMPLOYEE' | 'ADMIN';
|
|
isVerified: boolean;
|
|
isActive: boolean;
|
|
createdAt: string;
|
|
updatedAt?: string;
|
|
// Ticket statistics (populated in getUserById)
|
|
ticketsCount?: number;
|
|
pendingTickets?: number;
|
|
claimedTickets?: number;
|
|
}
|
|
|
|
// Auth Types
|
|
export interface LoginCredentials {
|
|
email: string;
|
|
password: string;
|
|
}
|
|
|
|
export interface RegisterData {
|
|
email: string;
|
|
password: string;
|
|
confirmPassword: string;
|
|
firstName: string;
|
|
lastName: string;
|
|
phone?: string;
|
|
captchaToken?: string;
|
|
}
|
|
|
|
export interface AuthResponse {
|
|
user: User;
|
|
token: string;
|
|
}
|
|
|
|
// Ticket Types
|
|
export type TicketStatus = 'PENDING' | 'REJECTED' | 'CLAIMED';
|
|
|
|
export interface Ticket {
|
|
id: string;
|
|
code: string;
|
|
userId?: string;
|
|
prizeId?: string;
|
|
status: TicketStatus;
|
|
playedAt?: string;
|
|
claimedAt?: string;
|
|
validatedAt?: string;
|
|
validatedBy?: string;
|
|
rejectionReason?: string;
|
|
createdAt?: string;
|
|
updatedAt?: string;
|
|
prize?: Prize;
|
|
user?: User;
|
|
}
|
|
|
|
// Prize Types
|
|
export type PrizeType =
|
|
| 'INFUSEUR'
|
|
| 'THE_SIGNATURE'
|
|
| 'COFFRET_DECOUVERTE'
|
|
| 'COFFRET_PRESTIGE'
|
|
| 'THE_GRATUIT'
|
|
| 'GRAND_PRIZE'
|
|
| 'PHYSICAL'
|
|
| 'DISCOUNT';
|
|
|
|
export interface Prize {
|
|
id: string;
|
|
name: string;
|
|
type: PrizeType;
|
|
description: string;
|
|
value: string;
|
|
probability: number;
|
|
stock: number; // Stock restant
|
|
initialStock?: number; // Stock initial (généré)
|
|
ticketsUsed?: number; // Nombre de tickets utilisés
|
|
isActive: boolean;
|
|
imageUrl?: string;
|
|
createdAt: string;
|
|
updatedAt?: string;
|
|
}
|
|
|
|
export interface CreatePrizeData {
|
|
name: string;
|
|
type: PrizeType;
|
|
description: string;
|
|
value: string;
|
|
probability: number;
|
|
stock: number;
|
|
}
|
|
|
|
export interface UpdatePrizeData {
|
|
name?: string;
|
|
description?: string;
|
|
value?: string;
|
|
probability?: number;
|
|
stock?: number;
|
|
isActive?: boolean;
|
|
}
|
|
|
|
// Game Types
|
|
export interface PlayGameRequest {
|
|
ticketCode: string;
|
|
}
|
|
|
|
export interface PlayGameResponse {
|
|
success: boolean;
|
|
ticket: Ticket;
|
|
prize: Prize;
|
|
message: string;
|
|
}
|
|
|
|
// Statistics Types
|
|
export interface GameStatistics {
|
|
totalTickets: number;
|
|
claimedTickets: number;
|
|
pendingTickets: number;
|
|
rejectedTickets: number;
|
|
prizeDistribution: {
|
|
[key in PrizeType]: number;
|
|
};
|
|
totalParticipants: number;
|
|
claimRate: number;
|
|
}
|
|
|
|
// API Response Types
|
|
export interface ApiResponse<T> {
|
|
success: boolean;
|
|
data?: T;
|
|
message?: string;
|
|
error?: string;
|
|
}
|
|
|
|
export interface PaginatedResponse<T> {
|
|
data: T[];
|
|
total: number;
|
|
page: number;
|
|
limit: number;
|
|
totalPages: number;
|
|
stats?: {
|
|
pending: number;
|
|
claimed: number;
|
|
rejected: number;
|
|
};
|
|
}
|
|
|
|
// Form Validation Types
|
|
export interface ValidationError {
|
|
field: string;
|
|
message: string;
|
|
}
|
|
|
|
// Navigation Types
|
|
export interface NavItem {
|
|
label: string;
|
|
href: string;
|
|
icon?: string;
|
|
roles?: User['role'][];
|
|
}
|
|
|
|
// Admin Types
|
|
export interface CreateEmployeeData {
|
|
email: string;
|
|
password: string;
|
|
firstName: string;
|
|
lastName: string;
|
|
}
|
|
|
|
export interface UpdateUserData {
|
|
role?: 'CLIENT' | 'EMPLOYEE' | 'ADMIN';
|
|
isVerified?: boolean;
|
|
isActive?: boolean;
|
|
firstName?: string;
|
|
lastName?: string;
|
|
}
|
|
|
|
export interface AdminStatistics {
|
|
users: {
|
|
total: number;
|
|
clients: number;
|
|
activeClients: number;
|
|
inactiveClients: number;
|
|
employees: number;
|
|
admins: number;
|
|
verifiedEmails: number;
|
|
};
|
|
tickets: {
|
|
total: number;
|
|
distributed: number; // Tickets fournis/distribués
|
|
used: number; // Tickets utilisés en temps réel
|
|
pending: number;
|
|
rejected: number;
|
|
claimed: number;
|
|
};
|
|
prizes: {
|
|
total: number;
|
|
active: number;
|
|
totalStock: number;
|
|
distributed: number;
|
|
byCategory?: PrizeDistribution[]; // Répartition des lots par catégorie
|
|
};
|
|
demographics?: DemographicStatistics; // Statistiques démographiques
|
|
}
|
|
|
|
// Répartition des lots par catégorie
|
|
export interface PrizeDistribution {
|
|
prizeId: string;
|
|
prizeName: string;
|
|
prizeType: PrizeType;
|
|
count: number;
|
|
percentage: number;
|
|
}
|
|
|
|
// Statistiques démographiques des participants
|
|
export interface DemographicStatistics {
|
|
gender?: {
|
|
male: number;
|
|
female: number;
|
|
other: number;
|
|
notSpecified: number;
|
|
};
|
|
ageRanges?: {
|
|
range: string; // ex: "18-25", "26-35", etc.
|
|
count: number;
|
|
percentage: number;
|
|
}[];
|
|
locations?: {
|
|
city: string;
|
|
postalCode?: string;
|
|
count: number;
|
|
percentage: number;
|
|
}[];
|
|
topCities?: {
|
|
city: string;
|
|
count: number;
|
|
percentage: number;
|
|
}[];
|
|
}
|