@next-helpdesk/core
Version:
Une bibliothèque React/Next.js complète pour systèmes de support/ticketing avec Kanban, diagramme de Gantt et gestion des tickets
570 lines (540 loc) • 19.5 kB
TypeScript
import React, { ReactNode } from 'react';
import { z } from 'zod';
import { Control } from 'react-hook-form';
import { AvatarProps, ChipProps } from '@mui/material';
import { Task } from 'gantt-task-react';
type Priority = 'low' | 'medium' | 'high';
interface User {
id: string;
name: string;
email: string;
avatar?: string | ReactNode | null;
role: 'user' | 'admin' | 'agent';
}
interface Ticket {
id: string;
title: string;
description: string;
priority: Priority;
status: string;
category: string;
tags?: TagConfig[];
createdAt: Date;
updatedAt: Date;
author: Omit<User, 'role'>;
assignedTo?: Omit<User, 'role'>;
comments?: Comment[];
attachments?: Attachment[];
hoursSpent?: number;
startDate?: Date;
endDate?: Date;
}
interface Comment {
id: string;
content: string;
createdAt: Date;
author: Omit<User, 'role'>;
ticketId: string;
attachments?: Attachment[];
}
interface Attachment {
id: string;
filename: string;
url: string;
size: number;
type: string;
uploadedAt: Date;
uploadedBy: Omit<User, 'role'>;
}
type UserRole = "user" | "agent" | "admin";
interface StatusConfig {
value: string;
label: string;
color?: "primary" | "secondary" | "error" | "info" | "success" | "warning" | "default";
}
interface TagConfig {
id: string;
label: string;
color?: string;
}
interface CategoryConfig {
value: string;
label: string;
statuses: StatusConfig[];
defaultStatus?: string;
tags?: TagConfig[];
}
interface HelpdeskConfig {
categories: CategoryConfig[];
priorities: Array<{
value: Priority;
label: string;
color?: "primary" | "secondary" | "error" | "info" | "success" | "warning" | "default";
}>;
statuses?: StatusConfig[];
defaultPriority: Priority;
allowFileUpload?: boolean;
maxFileSize?: number;
allowedFileTypes?: string[];
enableNotifications?: boolean;
enableAutoAssign?: boolean;
}
interface HelpdeskContextType {
config: HelpdeskConfig;
userRole: UserRole;
currentUser: User;
users: User[];
isAdmin: boolean;
isAgent: boolean;
isUser: boolean;
updateConfig: (newConfig: Partial<HelpdeskConfig>) => void;
updateUserRole: (role: UserRole) => void;
setCurrentUser: (user: User) => void;
setUsers: (users: User[]) => void;
getStatusesForCategory: (category: string) => StatusConfig[];
getDefaultStatusForCategory: (category: string) => string | undefined;
getTagsForCategory: (category: string) => TagConfig[];
addTagToCategory: (category: string, tag: TagConfig, onTagAdded?: (category: string, tag: TagConfig) => Promise<TagConfig>) => Promise<TagConfig>;
removeTagFromCategory: (category: string, tagId: string, onTagRemoved?: (category: string, tagId: string) => Promise<void>) => Promise<void>;
}
interface HelpdeskProviderProps {
children: ReactNode;
config?: Partial<HelpdeskConfig>;
userRole?: UserRole;
currentUser: User;
users: User[];
onTagAdded?: (category: string, tag: TagConfig) => Promise<TagConfig>;
onTagRemoved?: (category: string, tagId: string) => Promise<void>;
}
declare const HelpdeskProvider: React.FC<HelpdeskProviderProps>;
declare const useHelpdesk: () => HelpdeskContextType;
interface HelpdeskAppProps {
config?: Partial<HelpdeskConfig>;
userRole?: UserRole;
currentUser: User;
users: User[];
}
declare const HelpdeskApp: React.FC<HelpdeskAppProps>;
declare const createTicketSchema: z.ZodObject<{
title: z.ZodString;
description: z.ZodString;
category: z.ZodString;
priority: z.ZodEnum<["low", "medium", "high"]>;
assignedTo: z.ZodOptional<z.ZodString>;
tags: z.ZodOptional<z.ZodArray<z.ZodObject<{
id: z.ZodString;
label: z.ZodString;
color: z.ZodOptional<z.ZodString>;
}, "strip", z.ZodTypeAny, {
id: string;
label: string;
color?: string | undefined;
}, {
id: string;
label: string;
color?: string | undefined;
}>, "many">>;
files: z.ZodEffects<z.ZodOptional<z.ZodAny>, any, any>;
}, "strip", z.ZodTypeAny, {
title: string;
description: string;
category: string;
priority: "low" | "medium" | "high";
assignedTo?: string | undefined;
tags?: {
id: string;
label: string;
color?: string | undefined;
}[] | undefined;
files?: any;
}, {
title: string;
description: string;
category: string;
priority: "low" | "medium" | "high";
assignedTo?: string | undefined;
tags?: {
id: string;
label: string;
color?: string | undefined;
}[] | undefined;
files?: any;
}>;
declare const updateTicketSchema: z.ZodObject<{
title: z.ZodString;
description: z.ZodString;
category: z.ZodString;
priority: z.ZodEnum<["low", "medium", "high"]>;
assignedTo: z.ZodOptional<z.ZodString>;
tags: z.ZodOptional<z.ZodArray<z.ZodObject<{
id: z.ZodString;
label: z.ZodString;
color: z.ZodOptional<z.ZodString>;
}, "strip", z.ZodTypeAny, {
id: string;
label: string;
color?: string | undefined;
}, {
id: string;
label: string;
color?: string | undefined;
}>, "many">>;
files: z.ZodEffects<z.ZodOptional<z.ZodAny>, any, any>;
} & {
status: z.ZodOptional<z.ZodString>;
hoursSpent: z.ZodOptional<z.ZodNumber>;
startDate: z.ZodOptional<z.ZodDate>;
endDate: z.ZodOptional<z.ZodDate>;
}, "strip", z.ZodTypeAny, {
title: string;
description: string;
category: string;
priority: "low" | "medium" | "high";
status?: string | undefined;
assignedTo?: string | undefined;
tags?: {
id: string;
label: string;
color?: string | undefined;
}[] | undefined;
files?: any;
hoursSpent?: number | undefined;
startDate?: Date | undefined;
endDate?: Date | undefined;
}, {
title: string;
description: string;
category: string;
priority: "low" | "medium" | "high";
status?: string | undefined;
assignedTo?: string | undefined;
tags?: {
id: string;
label: string;
color?: string | undefined;
}[] | undefined;
files?: any;
hoursSpent?: number | undefined;
startDate?: Date | undefined;
endDate?: Date | undefined;
}>;
type CreateTicketFormData = z.infer<typeof createTicketSchema>;
type UpdateTicketFormData = z.infer<typeof updateTicketSchema>;
interface TicketListProps {
tickets: Ticket[];
onViewTicket?: (ticket: Ticket) => void;
onEditTicket?: (ticket: Ticket) => void;
onDeleteTicket?: (ticket: Ticket) => void;
onUpdateTicket?: (ticketId: string, data: Partial<UpdateTicketFormData>) => Promise<void>;
onAddComment?: (ticketId: string, content: string, files?: File[]) => Promise<void>;
onCloseTicket?: (ticketId: string) => Promise<void>;
loading?: boolean;
title?: string;
}
declare const TicketList: React.FC<TicketListProps>;
interface TicketCardProps {
id: string;
title: string;
description: string;
priority: Priority;
status: string;
createdAt: Date;
author: User;
assignedTo?: User;
category: string;
currentUser: User;
onView?: () => void;
onEdit?: () => void;
onDelete?: () => void;
showActions?: boolean;
}
declare const TicketCard: React.FC<TicketCardProps>;
interface DashboardStats {
totalTickets: number;
openTickets: number;
resolvedTickets: number;
inProgressTickets: number;
}
interface DashboardProps {
stats: DashboardStats;
}
declare const Dashboard: React.FC<DashboardProps>;
interface CreateTicketFormProps {
open: boolean;
onClose: () => void;
onSubmit: (data: CreateTicketFormData) => Promise<void>;
loading?: boolean;
}
declare const CreateTicketForm: React.FC<CreateTicketFormProps>;
interface CreateTicketButtonProps {
onSubmit: (data: CreateTicketFormData) => Promise<void>;
loading?: boolean;
variant?: "button" | "fab";
buttonText?: string;
}
declare const CreateTicketButton: React.FC<CreateTicketButtonProps>;
interface TicketDetailDialogProps {
open: boolean;
onClose: () => void;
ticket: Ticket;
onUpdateTicket?: (ticketId: string, data: Partial<UpdateTicketFormData>) => Promise<void>;
onAddComment?: (ticketId: string, content: string, files?: File[]) => Promise<void>;
onCloseTicket?: (ticketId: string) => Promise<void>;
loading?: boolean;
mode?: "view" | "edit";
}
declare const TicketDetailDialog: React.FC<TicketDetailDialogProps>;
interface TicketChatProps {
comments?: Comment[];
currentUser: User;
onAddComment: (content: string, attachments?: File[]) => Promise<void>;
loading?: boolean;
}
declare const TicketChat: React.FC<TicketChatProps>;
interface UserSelectProps {
name: string;
control: Control<any>;
users: User[];
label?: string;
error?: boolean;
helperText?: string;
placeholder?: string;
}
declare const UserSelect: React.FC<UserSelectProps>;
interface UserAvatarProps extends Omit<AvatarProps, "src" | "alt"> {
user: Omit<User, "role">;
size?: number;
}
declare const UserAvatar: React.FC<UserAvatarProps>;
interface StatusSelectProps {
name: string;
control: Control<any>;
label?: string;
error?: boolean;
helperText?: string;
placeholder?: string;
size?: "small" | "medium";
fullWidth?: boolean;
disabled?: boolean;
sx?: any;
category?: string;
}
declare const StatusSelect: React.FC<StatusSelectProps>;
interface StatusChipProps extends Omit<ChipProps, "label"> {
status: string;
category?: string;
showValue?: boolean;
size?: "small" | "medium";
}
declare const StatusChip: React.FC<StatusChipProps>;
interface TagChipProps extends Omit<ChipProps, "label"> {
tag: TagConfig;
showValue?: boolean;
size?: "small" | "medium";
category?: string;
onDelete?: (tagValue: string) => void;
deletable?: boolean;
globalDelete?: boolean;
}
declare const TagChip: React.FC<TagChipProps>;
interface TagSelectProps {
category: string;
value: TagConfig[];
onChange: (tags: TagConfig[]) => void;
label?: string;
placeholder?: string;
error?: boolean;
helperText?: string;
disabled?: boolean;
deletable?: boolean;
onTagAdded?: (category: string, tag: TagConfig) => Promise<TagConfig>;
}
declare const TagSelect: React.FC<TagSelectProps>;
interface PrioritySelectProps {
name: string;
control: Control<any>;
label?: string;
error?: boolean;
helperText?: string;
placeholder?: string;
size?: "small" | "medium";
fullWidth?: boolean;
disabled?: boolean;
sx?: any;
}
declare const PrioritySelect: React.FC<PrioritySelectProps>;
interface PriorityChipProps extends Omit<ChipProps, "label" | "color"> {
priority: string;
showValue?: boolean;
size?: "small" | "medium";
}
declare const PriorityChip: React.FC<PriorityChipProps>;
interface TimeTrackingFieldsProps {
control: Control<any>;
errors?: any;
disabled?: boolean;
}
declare const TimeTrackingFields: React.FC<TimeTrackingFieldsProps>;
interface TicketGanttChartProps {
tickets?: Ticket[];
height?: number;
width?: number;
title?: string;
users?: User[];
onDateChange?: (task: Task, children: Task[]) => Promise<boolean | void>;
onExpanderClick?: (task: Task) => Promise<void>;
onUpdateTicket?: (ticketId: string, data: any) => Promise<void>;
onAddComment?: (ticketId: string, content: string, files?: File[]) => Promise<void>;
onCloseTicket?: (ticketId: string) => Promise<void>;
}
declare const TicketGanttChart: React.FC<TicketGanttChartProps>;
interface TicketKanbanProps {
tickets: Ticket[];
onUpdateTicket?: (ticketId: string, data: Partial<UpdateTicketFormData>) => Promise<void>;
onAddComment?: (ticketId: string, content: string, files?: File[]) => Promise<void>;
onCloseTicket?: (ticketId: string) => Promise<void>;
title?: string;
description?: string;
height?: number;
}
declare const TicketKanban: React.FC<TicketKanbanProps>;
/**
* Vérifie si un utilisateur peut modifier un ticket
* @param ticket - Le ticket à vérifier
* @param currentUser - L'utilisateur actuel
* @returns true si l'utilisateur peut modifier le ticket
*/
declare const canEditTicket: (ticket: Ticket, currentUser: User) => boolean;
/**
* Vérifie si un utilisateur peut supprimer un ticket
* @param currentUser - L'utilisateur actuel
* @returns true si l'utilisateur peut supprimer le ticket
*/
declare const canDeleteTicket: (currentUser: User) => boolean;
/**
* Vérifie si un utilisateur peut voir un ticket
* @param ticket - Le ticket à vérifier
* @param currentUser - L'utilisateur actuel
* @returns true si l'utilisateur peut voir le ticket
*/
declare const canViewTicket: (ticket: Ticket, currentUser: User) => boolean;
/**
* Filtre une liste de tickets selon les permissions de l'utilisateur
* @param tickets - La liste des tickets
* @param currentUser - L'utilisateur actuel
* @returns La liste filtrée des tickets
*/
declare const filterTicketsByPermission: (tickets: Ticket[], currentUser: User) => Ticket[];
/**
* Vérifie si un utilisateur peut voir tous les tickets
* @param currentUser - L'utilisateur actuel
* @returns true si l'utilisateur peut voir tous les tickets
*/
declare const canViewAllTickets: (currentUser: User) => boolean;
/**
* Vérifie si un utilisateur peut voir seulement ses propres tickets
* @param currentUser - L'utilisateur actuel
* @returns true si l'utilisateur peut voir seulement ses propres tickets
*/
declare const canViewOwnTickets: (currentUser: User) => boolean;
/**
* Utilitaires pour la manipulation de chaînes de caractères
*/
/**
* Capitalise le premier caractère d'une chaîne
* @param value - La chaîne à capitaliser
* @returns La chaîne avec le premier caractère en majuscule
*/
declare const capitalizeFirstChar: (value: string) => string;
/**
* Capitalise la première lettre de chaque mot dans une chaîne
* @param value - La chaîne à capitaliser
* @returns La chaîne avec chaque mot capitalisé
*/
declare const capitalizeWords: (value: string) => string;
/**
* Met en minuscules une chaîne avec capitalisation de la première lettre
* @param value - La chaîne à formater
* @returns La chaîne formatée (première lettre majuscule, reste en minuscules)
*/
declare const toTitleCase: (value: string) => string;
type StatusColor = "primary" | "secondary" | "error" | "info" | "success" | "warning" | "default";
/**
* Obtient la couleur d'un statut basé sur la configuration
* @param statusValue - La valeur du statut
* @param statuses - La liste des statuts de la configuration
* @returns La couleur du statut ou "default" si non trouvé
*/
declare const getStatusColor: (statusValue: string, statuses: StatusConfig[]) => StatusColor;
/**
* Obtient le label d'un statut basé sur la configuration
* @param statusValue - La valeur du statut
* @param statuses - La liste des statuts de la configuration
* @returns Le label du statut ou la valeur si non trouvé
*/
declare const getStatusLabel: (statusValue: string, statuses: StatusConfig[]) => string;
/**
* Vérifie si un statut existe dans la configuration
* @param statusValue - La valeur du statut
* @param statuses - La liste des statuts de la configuration
* @returns true si le statut existe, false sinon
*/
declare const isValidStatus: (statusValue: string, statuses: StatusConfig[]) => boolean;
/**
* Obtient les statuts disponibles pour une catégorie donnée
* @param category - La catégorie
* @param config - La configuration du helpdesk
* @returns La liste des statuts pour cette catégorie
*/
declare function getStatusesForCategory(category: string | undefined, config: HelpdeskConfig): StatusConfig[];
/**
* Obtient le statut par défaut pour une catégorie donnée
* @param category - La catégorie
* @param config - La configuration du helpdesk
* @returns Le statut par défaut ou undefined
*/
declare const getDefaultStatusForCategory: (category: string, config: HelpdeskConfig) => string | undefined;
type PriorityColor = "primary" | "secondary" | "error" | "info" | "success" | "warning" | "default";
/**
* Obtient la couleur d'une priorité basée sur la configuration
* @param priorityValue - La valeur de la priorité
* @param priorities - La liste des priorités de la configuration
* @returns La couleur de la priorité ou "default" si non trouvé
*/
declare const getPriorityColor: (priorityValue: string, priorities: HelpdeskConfig["priorities"]) => PriorityColor;
/**
* Obtient le label d'une priorité basé sur la configuration
* @param priorityValue - La valeur de la priorité
* @param priorities - La liste des priorités de la configuration
* @returns Le label de la priorité ou la valeur si non trouvé
*/
declare const getPriorityLabel: (priorityValue: string, priorities: HelpdeskConfig["priorities"]) => string;
/**
* Vérifie si une priorité existe dans la configuration
* @param priorityValue - La valeur de la priorité
* @param priorities - La liste des priorités de la configuration
* @returns true si la priorité existe, false sinon
*/
declare const isValidPriority: (priorityValue: string, priorities: HelpdeskConfig["priorities"]) => boolean;
/**
* Obtient le label d'une catégorie basé sur la configuration
* @param categoryValue - La valeur de la catégorie
* @param categories - La liste des catégories de la configuration
* @returns Le label de la catégorie ou la valeur si non trouvé
*/
declare const getCategoryLabel: (categoryValue: string, categories: HelpdeskConfig["categories"]) => string;
/**
* Vérifie si une catégorie existe dans la configuration
* @param categoryValue - La valeur de la catégorie
* @param categories - La liste des catégories de la configuration
* @returns true si la catégorie existe, false sinon
*/
declare const isValidCategory: (categoryValue: string, categories: HelpdeskConfig["categories"]) => boolean;
/**
* Obtient la configuration d'une catégorie
* @param categoryValue - La valeur de la catégorie
* @param categories - La liste des catégories de la configuration
* @returns La configuration de la catégorie ou undefined si non trouvé
*/
declare const getCategoryConfig: (categoryValue: string, categories: HelpdeskConfig["categories"]) => CategoryConfig | undefined;
export { type Attachment, type Comment, CreateTicketButton, CreateTicketForm, type CreateTicketFormData, Dashboard, HelpdeskApp, type HelpdeskConfig, HelpdeskProvider, type Priority, PriorityChip, PrioritySelect, StatusChip, StatusSelect, TagChip, TagSelect, type Ticket, TicketCard, TicketChat, TicketDetailDialog, TicketGanttChart, TicketKanban, TicketList, TimeTrackingFields, type UpdateTicketFormData, type User, UserAvatar, type UserRole, UserSelect, canDeleteTicket, canEditTicket, canViewAllTickets, canViewOwnTickets, canViewTicket, capitalizeFirstChar, capitalizeWords, createTicketSchema, filterTicketsByPermission, getCategoryConfig, getCategoryLabel, getDefaultStatusForCategory, getPriorityColor, getPriorityLabel, getStatusColor, getStatusLabel, getStatusesForCategory, isValidCategory, isValidPriority, isValidStatus, toTitleCase, updateTicketSchema, useHelpdesk };