feat(absences) : avancement module absences + suppression du portail client
Deux lots regroupés sur la branche feat/absence-management. Suppression complète du portail client : - retire ROLE_CLIENT (security.yaml) ; User::getRoles() ajoute toujours ROLE_USER - supprime l'entité ClientTicket (+ repo, states, relations), User.client et User.allowedProjects, NotificationService, ProjectAllowedExtension, le bloc ROLE_CLIENT de MailAccessChecker - front : pages /portal, layout portal, composants client-ticket/, AdminClientTicketTab, services/dto/i18n/docs associés - fixtures : retire les users client-liot / client-acme - migration Version20260522110000 (drop client_ticket, user_allowed_projects, colonnes liées ; task_document.task_id -> NOT NULL) - tests : retire les cas obsolètes testant le blocage des clients sur le mail Module gestion des absences (WIP) : - entités / migrations (Version20260521160000, Version20260522090000) - pages absences.vue / team-absences.vue, composants frontend/components/absence/ - services front, AccrueLeaveCommand, PublicHolidayController Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
93
frontend/composables/useAbsenceHelpers.ts
Normal file
93
frontend/composables/useAbsenceHelpers.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
import type { AbsenceRequest, AbsenceStatus, AbsenceType, HalfDay } from '~/services/dto/absence'
|
||||
|
||||
export type BadgeVariant = 'neutral' | 'info' | 'success' | 'warning' | 'danger'
|
||||
|
||||
const STATUS_VARIANTS: Record<AbsenceStatus, BadgeVariant> = {
|
||||
pending: 'warning',
|
||||
approved: 'success',
|
||||
rejected: 'danger',
|
||||
cancelled: 'neutral',
|
||||
}
|
||||
|
||||
const STATUS_ICONS: Record<AbsenceStatus, string> = {
|
||||
pending: 'mdi:clock-outline',
|
||||
approved: 'mdi:check-circle-outline',
|
||||
rejected: 'mdi:close-circle-outline',
|
||||
cancelled: 'mdi:cancel',
|
||||
}
|
||||
|
||||
// Colours used for the calendar bars, keyed by absence type.
|
||||
const TYPE_COLORS: Record<AbsenceType, string> = {
|
||||
cp: '#4A90D9',
|
||||
mariage_pacs: '#E91E63',
|
||||
conge_parental: '#9C27B0',
|
||||
deces: '#607D8B',
|
||||
maladie: '#C62828',
|
||||
}
|
||||
|
||||
export function useAbsenceHelpers() {
|
||||
const { t } = useI18n()
|
||||
|
||||
function statusLabel(status: AbsenceStatus): string {
|
||||
return t(`absences.status.${status}`)
|
||||
}
|
||||
|
||||
function statusVariant(status: AbsenceStatus): BadgeVariant {
|
||||
return STATUS_VARIANTS[status] ?? 'neutral'
|
||||
}
|
||||
|
||||
function statusIcon(status: AbsenceStatus): string {
|
||||
return STATUS_ICONS[status] ?? 'mdi:help-circle-outline'
|
||||
}
|
||||
|
||||
function typeLabel(type: AbsenceType): string {
|
||||
return t(`absences.types.${type}`)
|
||||
}
|
||||
|
||||
function typeColor(type: AbsenceType): string {
|
||||
return TYPE_COLORS[type] ?? '#9CA3AF'
|
||||
}
|
||||
|
||||
function halfDayLabel(half: HalfDay): string {
|
||||
return t(`absences.halfDay.${half}`)
|
||||
}
|
||||
|
||||
function formatDate(iso: string | null): string {
|
||||
if (!iso) return ''
|
||||
const d = new Date(iso)
|
||||
if (isNaN(d.getTime())) return ''
|
||||
const day = String(d.getDate()).padStart(2, '0')
|
||||
const month = String(d.getMonth() + 1).padStart(2, '0')
|
||||
return `${day}/${month}/${d.getFullYear()}`
|
||||
}
|
||||
|
||||
/** Human-readable period with half-day annotations. */
|
||||
function formatRange(req: Pick<AbsenceRequest, 'startDate' | 'endDate' | 'startHalfDay' | 'endHalfDay'>): string {
|
||||
const start = formatDate(req.startDate)
|
||||
const end = formatDate(req.endDate)
|
||||
const startSuffix = req.startHalfDay ? ` (${halfDayLabel(req.startHalfDay)})` : ''
|
||||
const endSuffix = req.endHalfDay ? ` (${halfDayLabel(req.endHalfDay)})` : ''
|
||||
if (start === end) {
|
||||
return `${start}${startSuffix}`
|
||||
}
|
||||
return `${start}${startSuffix} → ${end}${endSuffix}`
|
||||
}
|
||||
|
||||
function formatDays(days: number): string {
|
||||
const rounded = Math.round(days * 2) / 2
|
||||
const unit = rounded > 1 ? t('absences.daysPlural') : t('absences.daySingular')
|
||||
return `${rounded} ${unit}`
|
||||
}
|
||||
|
||||
return {
|
||||
statusLabel,
|
||||
statusVariant,
|
||||
statusIcon,
|
||||
typeLabel,
|
||||
typeColor,
|
||||
halfDayLabel,
|
||||
formatDate,
|
||||
formatRange,
|
||||
formatDays,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user