From 38523a809eb826aeac12199be27325a1c38c31bd Mon Sep 17 00:00:00 2001 From: horacioskrp Date: Sun, 6 Sep 2026 00:16:15 +0000 Subject: [PATCH 01/11] =?UTF-8?q?feat(stats):=20recouvrement=20par=20class?= =?UTF-8?q?e=20filtrable=20et=20d=C3=A9taill=C3=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit La section « Recouvrement par classe » (onglet Finances) n'était qu'un tableau. Elle devient une vue riche et filtrable : - filtre par cycle (Maternelle / Primaire / Collège / Lycée) et tri (par montant ou par taux, les classes en retard d'abord), côté client ; - graphe « facturé : encaissé / reste à recouvrer » (barres empilées, montants) ; - graphe « taux de recouvrement » coloré par palier (≥80 / 60–79 / <60 %) avec une ligne de moyenne de l'école ; - tableau de détail (facturé, encaissé, reste, taux) suivant le filtre. Le backend enrichit financeStats.by_class du cycle et du reste à recouvrer, ordonné par niveau. L'export PDF/xlsx reste compatible (accès par clé). --- app/Services/StatisticsService.php | 15 ++-- resources/js/pages/Statistiques/Index.tsx | 103 ++++++++++++++++++---- 2 files changed, 98 insertions(+), 20 deletions(-) diff --git a/app/Services/StatisticsService.php b/app/Services/StatisticsService.php index 681de02..0977bd7 100644 --- a/app/Services/StatisticsService.php +++ b/app/Services/StatisticsService.php @@ -188,19 +188,24 @@ public function financeStats(array $filters): array $billed = (float) ($stats->billed ?? 0); $collected = (float) ($stats->collected ?? 0); - // Recouvrement par classe + // Recouvrement par classe (avec cycle + reste, pour filtre et charts détaillés) $byClass = (clone $inv) ->join('classes', 'enrollments.class_id', '=', 'classes.id') - ->selectRaw('classes.name AS name, + ->leftJoin('classroom_types', 'classroom_types.id', '=', 'classes.classroom_type_id') + ->selectRaw('classes.name AS name, classroom_types.name AS cycle, COALESCE(SUM(invoices.total), 0) AS billed, - COALESCE(SUM(invoices.amount_paid), 0) AS collected') - ->groupBy('classes.name') - ->orderByDesc('billed') + COALESCE(SUM(invoices.amount_paid), 0) AS collected, + COALESCE(SUM(invoices.amount_remaining), 0) AS remaining') + ->groupBy('classes.name', 'classroom_types.name', 'classes.expected_age') + ->orderByRaw('classes.expected_age NULLS LAST') + ->orderBy('classes.name') ->get() ->map(fn ($r) => [ 'name' => $r->name, + 'cycle' => $this->cycleLabel($r->cycle), 'billed' => (float) $r->billed, 'collected' => (float) $r->collected, + 'remaining' => (float) $r->remaining, 'rate' => $r->billed > 0 ? round($r->collected / $r->billed * 100, 1) : 0.0, ]); diff --git a/resources/js/pages/Statistiques/Index.tsx b/resources/js/pages/Statistiques/Index.tsx index 3d34d6d..271affe 100644 --- a/resources/js/pages/Statistiques/Index.tsx +++ b/resources/js/pages/Statistiques/Index.tsx @@ -3,7 +3,7 @@ import { BarChart3, Download, FileSpreadsheet, GraduationCap, Layers, MapPin, Pi import { useState } from 'react'; import { Area, AreaChart, Bar, BarChart, CartesianGrid, Cell, LabelList, Legend, Line, LineChart, Pie, PieChart, - ResponsiveContainer, Tooltip as RTooltip, Treemap, XAxis, YAxis, + ReferenceLine, ResponsiveContainer, Tooltip as RTooltip, Treemap, XAxis, YAxis, } from 'recharts'; import { Button } from '@/components/ui/button'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; @@ -34,7 +34,7 @@ interface Enrollment { interface Finance { billed: number; collected: number; remaining: number; recovery_rate: number; total_invoices: number; paid_count: number; partial_count: number; unpaid_count: number; - by_class: { name: string; billed: number; collected: number; rate: number }[]; + by_class: { name: string; cycle: string; billed: number; collected: number; remaining: number; rate: number }[]; by_method: { method: string; total: number; count: number }[]; monthly: { month: string; total: number }[]; } @@ -223,6 +223,19 @@ export default function StatisticsIndex({ filters, academicYears, classes, enrol const agePyramid = enrollment.age_distribution.map((d) => ({ age: d.age, male: -d.male, female: d.female })); const ageAxisMax = Math.max(1, ...enrollment.age_distribution.map((d) => Math.max(d.male, d.female))); + /* ---- Finances : recouvrement par classe, filtrable par cycle. ---- */ + const finCycles = [...new Set(finance.by_class.map((c) => c.cycle))]; + const [finCycle, setFinCycle] = useState('Tous'); + const [finSort, setFinSort] = useState<'facture' | 'taux'>('facture'); + const finClasses = (() => { + const f = finance.by_class.filter((c) => finCycle === 'Tous' || c.cycle === finCycle); + // Tri par taux = les classes en retard d'abord (croissant) ; par montant = les plus grosses d'abord. + return finSort === 'taux' ? [...f].sort((a, b) => a.rate - b.rate) : [...f].sort((a, b) => b.billed - a.billed); + })(); + // Couleur du taux par palier (statut, toujours accompagné du chiffre). + const rateColor = (r: number) => (r >= 80 ? '#16a34a' : r >= 60 ? '#d97706' : '#dc2626'); + const finChartHeight = Math.max(220, finClasses.length * 24 + 28); + /* ---- Comparaisons : l'année active est en cours, ses taux de fin d'année (redoublement, abandon, admission) ne sont pas encore décidés. On les met à null pour que les courbes s'arrêtent au lieu de plonger à zéro. ---- */ @@ -472,20 +485,80 @@ export default function StatisticsIndex({ filters, academicYears, classes, enrol - }> -
- - - - {finance.by_class.map((c) => ( - - - - - ))} -
ClasseFacturéEncaisséTaux
{c.name}{money(c.billed)}{money(c.collected)}{c.rate}%
+ {/* Recouvrement par classe — filtrable, plusieurs situations */} +
+
+ Recouvrement par classe + {['Tous', ...finCycles].map((c) => ( + + ))} +
+ Tri + {(['facture', 'taux'] as const).map((s) => ( + + ))} +
- + +
+ }> + + + + (Number(v) >= 1000 ? `${Math.round(Number(v) / 1000)}k` : String(v))} /> + + [money(Number(v)), n]} /> + + + + + + + }> + + + + `${v}%`} /> + + [`${v}%`, 'Taux']} /> + + + {finClasses.map((c) => )} + `${v}%`} style={{ fontSize: 10, fill: theme.tick }} /> + + + +
+ ≥ 80 % + 60–79 % + < 60 % +
+
+
+ + }> +
+ + + + {finClasses.map((c) => ( + + + + + + + ))} +
ClasseFacturéEncaisséResteTaux
{c.name}{money(c.billed)}{money(c.collected)}{money(c.remaining)}{c.rate}%
+
+
+
)} From 209a8ada164bc53e5e850c309c4f2c4334893439 Mon Sep 17 00:00:00 2001 From: horacioskrp Date: Sun, 6 Sep 2026 00:22:53 +0000 Subject: [PATCH 02/11] fix(stats): logo trop grand dans l'export PDF des statistiques MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit L'export PDF injecte l'en-tête ministériel (avec logo) via headerHtml(), mais le gabarit statistics/report.blade.php n'embarquait pas les styles `.mh-*` — dont le plafond de taille du logo. Résultat : logo à sa taille naturelle qui écrase l'en-tête, alors que le bulletin et le bulletin de paie, eux, incluent bien ce CSS. Le contrôleur passe désormais headerCss() au gabarit, qui l'inclut. --- app/Http/Controllers/Statistics/StatisticsController.php | 1 + resources/views/statistics/report.blade.php | 3 +++ 2 files changed, 4 insertions(+) diff --git a/app/Http/Controllers/Statistics/StatisticsController.php b/app/Http/Controllers/Statistics/StatisticsController.php index 77ae02f..5c5908e 100644 --- a/app/Http/Controllers/Statistics/StatisticsController.php +++ b/app/Http/Controllers/Statistics/StatisticsController.php @@ -62,6 +62,7 @@ public function export(Request $request, string $section, string $format) $html = view('statistics.report', [ 'header' => $renderer->headerHtml($school, $vars), + 'headerCss' => $renderer->headerCss(), 'section' => $section, 'data' => $data, 'year' => optional(AcademicYear::find($filters['academic_year_id']))->year, diff --git a/resources/views/statistics/report.blade.php b/resources/views/statistics/report.blade.php index 322dba8..406fe59 100644 --- a/resources/views/statistics/report.blade.php +++ b/resources/views/statistics/report.blade.php @@ -19,6 +19,9 @@ th { background: #f1f5f9; font-size: 10px; text-transform: uppercase; } td.n, th.n { text-align: right; } .kpis td { font-weight: bold; } + {{-- Styles de l'en-tête ministériel (dont le plafond de taille du logo) : sans eux + le logo s'affiche à sa taille naturelle et écrase l'en-tête. --}} + {!! $headerCss !!} From dfb51c72162902e451e70f9e2c0876356da25525 Mon Sep 17 00:00:00 2001 From: horacioskrp Date: Sun, 6 Sep 2026 00:34:29 +0000 Subject: [PATCH 03/11] =?UTF-8?q?refactor(documents):=20en-t=C3=AAte=20min?= =?UTF-8?q?ist=C3=A9rielle=20en=20source=20unique=20(headerCss)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le baseCss des documents officiels (certificats, attestations) redéfinissait sa propre en-tête — logo à 100px, école 17px, marge 32px — divergente de celle du bulletin (logo 68px). baseCss() compose désormais headerCss() et ne garde que le corps et la signature : tous les documents partagent exactement l'en-tête du bulletin. Source unique, plus aucune divergence possible. --- app/Services/DocumentRenderer.php | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/app/Services/DocumentRenderer.php b/app/Services/DocumentRenderer.php index 784ad72..4d5d708 100644 --- a/app/Services/DocumentRenderer.php +++ b/app/Services/DocumentRenderer.php @@ -370,8 +370,10 @@ protected function renderSignature(DocumentTemplate $template, array $variables) } /** - * CSS de l'en-tête officiel (ministériel + logo), réutilisable par des - * documents qui n'embarquent pas tout le baseCss (ex. bulletin de paie). + * CSS de l'en-tête officiel (ministériel + logo). **Source unique** : tous les + * documents (bulletin, bulletin de paie, export statistiques, certificats et + * attestations) partagent exactement cette en-tête. Ne pas redéfinir les + * règles `.mh-*` ou `.doc-mheader` ailleurs — {@see baseCss()} la compose. */ public function headerCss(): string { @@ -393,22 +395,12 @@ public function headerCss(): string protected function baseCss(): string { - return <<headerCss() . << Date: Sun, 6 Sep 2026 00:36:49 +0000 Subject: [PATCH 04/11] =?UTF-8?q?refactor(exports):=20en-t=C3=AAte=20du=20?= =?UTF-8?q?bulletin=20sur=20la=20liste=20des=20=C3=A9l=C3=A8ves?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le roster avait sa propre en-tête centrée (terme/devise/nom, sans logo). Il utilise désormais l'en-tête ministérielle unifiée (headerHtml + headerCss), identique au bulletin. --- app/Http/Controllers/Eleves/RosterController.php | 16 ++++++++++------ resources/views/exports/roster.blade.php | 9 +++------ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/app/Http/Controllers/Eleves/RosterController.php b/app/Http/Controllers/Eleves/RosterController.php index c3c4069..59171e4 100644 --- a/app/Http/Controllers/Eleves/RosterController.php +++ b/app/Http/Controllers/Eleves/RosterController.php @@ -8,6 +8,7 @@ use App\Models\Classroom; use App\Models\Enrollment; use App\Models\School; +use App\Services\DocumentRenderer; use Barryvdh\DomPDF\Facade\Pdf; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; @@ -112,14 +113,17 @@ public function export(Request $request) ->sortBy(fn ($e) => $e->student?->lastname) ->values(); - $school = School::where('active', true)->first() ?? School::query()->first(); + $school = School::where('active', true)->first() ?? School::query()->first(); + $renderer = app(DocumentRenderer::class); $pdf = Pdf::loadView('exports.roster', [ - 'school' => $school, - 'classroom' => $classroom, - 'year' => $year, - 'students' => $students, - 'statuses' => Enrollment::ACADEMIC_STATUSES, + 'school' => $school, + 'headerHtml' => $school ? $renderer->headerHtml($school, $renderer->resolveVariables($school)) : '', + 'headerCss' => $renderer->headerCss(), + 'classroom' => $classroom, + 'year' => $year, + 'students' => $students, + 'statuses' => Enrollment::ACADEMIC_STATUSES, ])->setPaper('a4', 'portrait'); return $pdf->stream('effectifs-' . Str::slug($classroom->name . '-' . $year->year) . '.pdf'); diff --git a/resources/views/exports/roster.blade.php b/resources/views/exports/roster.blade.php index 9f68c0f..7caf187 100644 --- a/resources/views/exports/roster.blade.php +++ b/resources/views/exports/roster.blade.php @@ -30,18 +30,15 @@ .footer { margin-top: 16px; font-size: 9px; color: #888; display: flex; justify-content: space-between; } .sign { margin-top: 36px; text-align: right; font-size: 11px; } + {{-- En-tête ministérielle unifiée (identique au bulletin). --}} + {!! $headerCss !!} + {!! $headerHtml !!}
- @if($school) -
{{ $school->terme ?? 'République Togolaise' }}
- @if($school->devise)
{{ $school->devise }}
@endif -
{{ $school->name }}
- @endif
LISTE DES ÉLÈVES
Classe : {{ $classroom->name }} ({{ $classroom->code }}) — Année : {{ $year->year }}
-
From 874274997423bd72454fb7314b2d8c359893ba61 Mon Sep 17 00:00:00 2001 From: horacioskrp Date: Sun, 6 Sep 2026 00:38:16 +0000 Subject: [PATCH 05/11] =?UTF-8?q?refactor(exports):=20en-t=C3=AAte=20du=20?= =?UTF-8?q?bulletin=20sur=20l'emploi=20du=20temps?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit L'export emploi du temps (paysage) utilise désormais l'en-tête ministérielle unifiée au lieu de son en-tête centrée maison. --- app/Http/Controllers/Eleves/TimetableController.php | 5 +++++ resources/views/exports/timetable.blade.php | 8 +++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/app/Http/Controllers/Eleves/TimetableController.php b/app/Http/Controllers/Eleves/TimetableController.php index a19f763..a23f849 100644 --- a/app/Http/Controllers/Eleves/TimetableController.php +++ b/app/Http/Controllers/Eleves/TimetableController.php @@ -6,6 +6,7 @@ use App\Models\AcademicYear; use App\Models\Classroom; use App\Models\School; +use App\Services\DocumentRenderer; use App\Models\Subject; use App\Models\TimetableSlot; use App\Models\User; @@ -84,8 +85,12 @@ public function export(Request $request, string $classId) $grid[$range][$slot->day_of_week] = $slot; } + $renderer = app(DocumentRenderer::class); + $pdf = Pdf::loadView('exports.timetable', [ 'school' => $school, + 'headerHtml' => $school ? $renderer->headerHtml($school, $renderer->resolveVariables($school)) : '', + 'headerCss' => $renderer->headerCss(), 'classroom' => $classroom, 'days' => TimetableSlot::DAYS, 'timeRanges' => $timeRanges, diff --git a/resources/views/exports/timetable.blade.php b/resources/views/exports/timetable.blade.php index 01431aa..9540ff7 100644 --- a/resources/views/exports/timetable.blade.php +++ b/resources/views/exports/timetable.blade.php @@ -23,15 +23,13 @@ .slot-meta { font-size: 9px; color: #555; } .empty { color: #ccc; text-align: center; } .footer { margin-top: 12px; font-size: 9px; color: #888; text-align: right; } + {{-- En-tête ministérielle unifiée (identique au bulletin). --}} + {!! $headerCss !!} + {!! $headerHtml !!}
- @if($school) -
{{ $school->terme ?? 'République Togolaise' }}
- @if($school->devise)
{{ $school->devise }}
@endif -
{{ $school->name }}
- @endif
EMPLOI DU TEMPS
Classe : {{ $classroom->name }}
From fb94f51fe27bfc8f7aede2bb7ea8f5bbea382ffa Mon Sep 17 00:00:00 2001 From: horacioskrp Date: Sun, 6 Sep 2026 00:40:00 +0000 Subject: [PATCH 06/11] =?UTF-8?q?refactor(exports):=20en-t=C3=AAte=20du=20?= =?UTF-8?q?bulletin=20sur=20le=20planning=20des=20examens?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le planning (page d'impression HTML) affichait un simple nom d'école stylisé. Il reçoit désormais l'en-tête ministérielle unifiée (logo compris), comme les autres documents. --- app/Http/Controllers/Examens/EvaluationController.php | 6 +++++- resources/views/exports/planning.blade.php | 6 ++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/app/Http/Controllers/Examens/EvaluationController.php b/app/Http/Controllers/Examens/EvaluationController.php index 5e6fb48..b7faa1c 100644 --- a/app/Http/Controllers/Examens/EvaluationController.php +++ b/app/Http/Controllers/Examens/EvaluationController.php @@ -220,7 +220,11 @@ public function exportPlanning(Request $request, string $classroomId): \Illumina $school = School::where('active', true)->first(); - $html = view('exports.planning', compact('classroom', 'evaluations', 'school', 'activeYear'))->render(); + $renderer = app(\App\Services\DocumentRenderer::class); + $headerHtml = $school ? $renderer->headerHtml($school, $renderer->resolveVariables($school)) : ''; + $headerCss = $renderer->headerCss(); + + $html = view('exports.planning', compact('classroom', 'evaluations', 'school', 'activeYear', 'headerHtml', 'headerCss'))->render(); return response($html)->header('Content-Type', 'text/html'); } diff --git a/resources/views/exports/planning.blade.php b/resources/views/exports/planning.blade.php index 36a6aac..a2c3409 100644 --- a/resources/views/exports/planning.blade.php +++ b/resources/views/exports/planning.blade.php @@ -42,14 +42,16 @@ body { padding: 16px; } @page { margin: 1cm; size: A4 landscape; } } + /* En-tête ministérielle unifiée (identique au bulletin). */ + {!! $headerCss !!} -
-
{{ $school?->name ?? 'Établissement scolaire' }}
+{!! $headerHtml !!} +
Planning des examens
Classe : {{ $classroom->name }} ({{ $classroom->code }}) From 8fa62a4f74768756644a65199a7b115cd6269873 Mon Sep 17 00:00:00 2001 From: horacioskrp Date: Sun, 6 Sep 2026 00:42:34 +0000 Subject: [PATCH 07/11] =?UTF-8?q?fix(stats):=20en-t=C3=AAte=20unifi=C3=A9e?= =?UTF-8?q?=20(logo=20plafonn=C3=A9)=20sur=20l'export=20PDF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Http/Controllers/Statistics/StatisticsController.php | 1 + resources/views/statistics/report.blade.php | 2 ++ 2 files changed, 3 insertions(+) diff --git a/app/Http/Controllers/Statistics/StatisticsController.php b/app/Http/Controllers/Statistics/StatisticsController.php index 77ae02f..5c5908e 100644 --- a/app/Http/Controllers/Statistics/StatisticsController.php +++ b/app/Http/Controllers/Statistics/StatisticsController.php @@ -62,6 +62,7 @@ public function export(Request $request, string $section, string $format) $html = view('statistics.report', [ 'header' => $renderer->headerHtml($school, $vars), + 'headerCss' => $renderer->headerCss(), 'section' => $section, 'data' => $data, 'year' => optional(AcademicYear::find($filters['academic_year_id']))->year, diff --git a/resources/views/statistics/report.blade.php b/resources/views/statistics/report.blade.php index 322dba8..511181c 100644 --- a/resources/views/statistics/report.blade.php +++ b/resources/views/statistics/report.blade.php @@ -19,6 +19,8 @@ th { background: #f1f5f9; font-size: 10px; text-transform: uppercase; } td.n, th.n { text-align: right; } .kpis td { font-weight: bold; } + {{-- En-tête ministérielle unifiée (dont le plafond de taille du logo). --}} + {!! $headerCss !!} From 533005920bfe6ee609b72eecbff6dab7058193d2 Mon Sep 17 00:00:00 2001 From: horacioskrp Date: Sun, 6 Sep 2026 01:02:13 +0000 Subject: [PATCH 08/11] =?UTF-8?q?feat(parametres):=20page=20=C2=AB=20?= =?UTF-8?q?=C3=80=20propos=20=C2=BB=20sous=20Sauvegardes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ajoute une entrée « À propos » dans le menu Paramètres, juste sous Sauvegardes, accessible à tout utilisateur connecté (sans permission dédiée). La page présente l'application : version (lue dans package.json, donc alignée sur la release), description, liens (documentation, site, code source, journal des versions), modules couverts, éditeur et licence (GNU GPL v3), informations techniques (Laravel, PHP, environnement) et accès au support. --- .../Parametres/AboutController.php | 33 ++++ resources/js/helpers/route.ts | 1 + resources/js/pages/Parametres/About.tsx | 153 ++++++++++++++++++ resources/js/types/menu.ts | 3 +- routes/web.php | 3 + 5 files changed, 192 insertions(+), 1 deletion(-) create mode 100644 app/Http/Controllers/Parametres/AboutController.php create mode 100644 resources/js/pages/Parametres/About.tsx diff --git a/app/Http/Controllers/Parametres/AboutController.php b/app/Http/Controllers/Parametres/AboutController.php new file mode 100644 index 0000000..e159361 --- /dev/null +++ b/app/Http/Controllers/Parametres/AboutController.php @@ -0,0 +1,33 @@ +version ?? '—'; + } + + return Inertia::render('Parametres/About', [ + 'app' => [ + 'name' => config('app.name', 'Dalibi'), + 'version' => $version, + 'laravel' => app()->version(), + 'php' => PHP_VERSION, + 'environment' => app()->environment(), + ], + 'school' => School::query()->value('name'), + ]); + } +} diff --git a/resources/js/helpers/route.ts b/resources/js/helpers/route.ts index 203abf5..f8feae6 100644 --- a/resources/js/helpers/route.ts +++ b/resources/js/helpers/route.ts @@ -157,6 +157,7 @@ export function route(name: string, params?: any): string { 'backups.restore': '/settings/backups/restore', 'backups.download': `/settings/backups/${params}/download`, 'backups.destroy': `/settings/backups/${params}`, + 'about.index': '/settings/about', 'fee-structures.index': '/fee-structures', 'fee-structures.replicate': '/fee-structures/replicate', diff --git a/resources/js/pages/Parametres/About.tsx b/resources/js/pages/Parametres/About.tsx new file mode 100644 index 0000000..e52f1f4 --- /dev/null +++ b/resources/js/pages/Parametres/About.tsx @@ -0,0 +1,153 @@ +import { Head } from '@inertiajs/react'; +import { + BadgeCheck, BookOpen, CalendarRange, ClipboardList, DatabaseBackup, ExternalLink, + FileBadge, GraduationCap, Info, Scale, Server, Wallet, Globe, FileCode2, ScrollText, Users, Heart, +} from 'lucide-react'; +import AppLayout from '@/layouts/app-layout'; + +interface Props { + app: { name: string; version: string; laravel: string; php: string; environment: string }; + school: string | null; +} + +const GITHUB = 'https://github.com/wearedalibi/dalibi'; +const SITE = 'https://dalibi.wearekarfi.dev'; + +/** Modules couverts par l'application (résumé). */ +const MODULES: { icon: React.ElementType; title: string; desc: string }[] = [ + { icon: Users, title: 'Élèves & inscriptions', desc: 'Dossiers complets, inscriptions, passage de classe, bourses.' }, + { icon: FileBadge, title: 'Notes & bulletins', desc: 'Saisie, moyennes paramétrables, bulletins PDF, réclamations.' }, + { icon: ClipboardList, title: 'Présences', desc: 'Appel par séance, statistiques d’assiduité, permissions d’absence.' }, + { icon: GraduationCap, title: 'Examens officiels', desc: 'CEPD, BEPC, BAC : inscriptions, planning, résultats.' }, + { icon: Wallet, title: 'Finances & recouvrement', desc: 'Frais, factures, paiements (dont Mobile Money), reçus.' }, + { icon: BadgeCheck, title: 'Personnel & paie', desc: 'Fiches employés, cycles de paie, bulletins (CNSS, ITS).' }, + { icon: CalendarRange, title: 'Emploi du temps & calendrier', desc: 'Grilles par classe, calendrier de l’établissement.' }, + { icon: DatabaseBackup, title: 'Sauvegardes & statistiques', desc: 'Sauvegardes planifiées, tableaux de bord et exports.' }, +]; + +const LINKS: { icon: React.ElementType; title: string; href: string; sub: string }[] = [ + { icon: BookOpen, title: 'Documentation', href: `${SITE}/documentation`, sub: 'Guide de A à Z' }, + { icon: Globe, title: 'Site web', href: SITE, sub: 'Présentation & fonctionnalités' }, + { icon: FileCode2, title: 'Code source', href: GITHUB, sub: 'Dépôt GitHub' }, + { icon: ScrollText, title: 'Journal des versions', href: `${GITHUB}/blob/main/CHANGELOG.md`, sub: 'Historique des évolutions' }, +]; + +function Card({ children }: { children: React.ReactNode }) { + return
{children}
; +} + +export default function About({ app, school }: Readonly) { + const brand = app.name ? app.name.charAt(0).toUpperCase() + app.name.slice(1) : 'Dalibi'; + + return ( + + +
+ + {/* En-tête */} +
+
+
+ +
+
+
+

{brand}

+ + v{app.version} + +
+

+ Système de gestion scolaire — de l’inscription de l’élève au bulletin, en passant par l’écolage et la paie. + Pensé pour les établissements togolais 🇹🇬. +

+
+
+
+ + {/* Liens utiles */} +
+ {LINKS.map((l) => { + const Icon = l.icon; + return ( + +
+ + +
+

{l.title}

+

{l.sub}

+
+ ); + })} +
+ + {/* Ce que fait l'application */} + +

Ce que couvre l’application

+
+ {MODULES.map((m) => { + const Icon = m.icon; + return ( +
+
+
+

{m.title}

+

{m.desc}

+
+
+ ); + })} +
+
+ +
+ {/* Éditeur & licence */} + +

Éditeur & licence

+
+
+
Édité par
+
Kudayah Sassou Horacio Herve
+
+
+
Licence
+
GNU GPL v3 — logiciel libre
+
+
+
Droits
+
© {new Date().getFullYear()} {brand}
+
+
+

+ Vous pouvez utiliser, étudier, modifier et redistribuer ce logiciel selon les termes de la GPL v3. +

+
+ + {/* Informations techniques */} + +

Informations techniques

+
+
Version de l’application
v{app.version}
+
Laravel
{app.laravel}
+
PHP
{app.php}
+
Environnement
{app.environment}
+ {school &&
Établissement
{school}
} +
+
+
+ + {/* Support */} + +

Besoin d’aide ?

+

+ Consultez d’abord la documentation. + Pour signaler un problème ou proposer une amélioration, ouvrez un ticket sur le dépôt GitHub. +

+
+
+
+ ); +} diff --git a/resources/js/types/menu.ts b/resources/js/types/menu.ts index 2fb1af5..c3fa992 100644 --- a/resources/js/types/menu.ts +++ b/resources/js/types/menu.ts @@ -1,4 +1,4 @@ -import { BookOpen, Calendar, Clock, ClipboardList, GraduationCap, LayoutGrid, Layers, Settings, Tag, Users, Shield, Lock, Wallet, Percent, DollarSign, UserCircle, TrendingUp, ArrowLeftRight, PieChart, FileText, ListChecks, NotebookPen, SlidersHorizontal, AlertCircle, CalendarRange, UserCheck, BarChart3, ShieldCheck, HardDrive, FileBadge, ScanLine, DatabaseBackup, Archive, Globe, TrendingDown, Briefcase, Receipt, Coins } from 'lucide-react'; +import { BookOpen, Calendar, Clock, ClipboardList, GraduationCap, LayoutGrid, Layers, Settings, Tag, Users, Shield, Lock, Wallet, Percent, DollarSign, UserCircle, TrendingUp, ArrowLeftRight, PieChart, FileText, ListChecks, NotebookPen, SlidersHorizontal, AlertCircle, CalendarRange, UserCheck, BarChart3, ShieldCheck, HardDrive, FileBadge, ScanLine, DatabaseBackup, Archive, Globe, TrendingDown, Briefcase, Receipt, Coins, Info } from 'lucide-react'; import { route } from '@/helpers/route'; import type { NavItem } from '@/types'; @@ -134,6 +134,7 @@ export const mainNavItems: NavItem[] = [ { title: 'Fichiers & Stockage', href: route('file-storage.index'), icon: HardDrive, permission: 'manage_file_storage' }, { title: 'Modèles de documents', href: route('document-templates.index'), icon: FileBadge, permission: 'view_documents' }, { title: 'Sauvegardes', href: route('backups.index'), icon: DatabaseBackup, permission: 'view_backups' }, + { title: 'À propos', href: route('about.index'), icon: Info }, ], }, { diff --git a/routes/web.php b/routes/web.php index 6e44bdc..e9cb8d6 100644 --- a/routes/web.php +++ b/routes/web.php @@ -395,6 +395,9 @@ Route::post('settings/backups/{backup}/verify', [\App\Http\Controllers\Parametres\BackupController::class, 'verify'])->middleware('can:view_backups')->name('backups.verify'); Route::delete('settings/backups/{backup}', [\App\Http\Controllers\Parametres\BackupController::class, 'destroy'])->middleware('can:delete_backups')->name('backups.destroy'); + // À propos (informations sur l'application) — accessible à tout utilisateur connecté + Route::get('settings/about', [\App\Http\Controllers\Parametres\AboutController::class, 'index'])->name('about.index'); + // Passage de classe / réinscription en masse Route::get('promotion', [PromotionController::class, 'index'])->middleware('can:execute_promotion')->name('promotion.index'); Route::post('promotion', [PromotionController::class, 'store'])->middleware('can:execute_promotion')->name('promotion.store'); From 1117a58a32cb8bc0abf0e1a6f1c5306a75ce0b3d Mon Sep 17 00:00:00 2001 From: horacioskrp Date: Sun, 6 Sep 2026 01:37:11 +0000 Subject: [PATCH 09/11] =?UTF-8?q?feat(parametres):=20vrai=20logo=20Dalibi?= =?UTF-8?q?=20dans=20l'en-t=C3=AAte=20=C2=AB=20=C3=80=20propos=20=C2=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remplace l'icône générique et le nom en texte par le logo officiel horizontal (mark + mot-symbole). Version colorée sur fond clair, version blanche en mode sombre. Les SVG (issus de /svgs) sont copiés dans public/svgs pour être servis. --- public/svgs/dalibi-blanc.svg | 24 +++++++++++++++++++ public/svgs/dalibi.svg | 28 ++++++++++++++++++++++ resources/js/pages/Parametres/About.tsx | 31 +++++++++++-------------- 3 files changed, 65 insertions(+), 18 deletions(-) create mode 100644 public/svgs/dalibi-blanc.svg create mode 100644 public/svgs/dalibi.svg diff --git a/public/svgs/dalibi-blanc.svg b/public/svgs/dalibi-blanc.svg new file mode 100644 index 0000000..fca1aaa --- /dev/null +++ b/public/svgs/dalibi-blanc.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/svgs/dalibi.svg b/public/svgs/dalibi.svg new file mode 100644 index 0000000..483bdef --- /dev/null +++ b/public/svgs/dalibi.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/js/pages/Parametres/About.tsx b/resources/js/pages/Parametres/About.tsx index e52f1f4..a272e34 100644 --- a/resources/js/pages/Parametres/About.tsx +++ b/resources/js/pages/Parametres/About.tsx @@ -44,26 +44,21 @@ export default function About({ app, school }: Readonly) {
- {/* En-tête */} + {/* En-tête : logo officiel Dalibi (version blanche en mode sombre) + version */}
-
-
- -
-
-
-

{brand}

- - v{app.version} - -
-

- Système de gestion scolaire — de l’inscription de l’élève au bulletin, en passant par l’écolage et la paie. - Pensé pour les établissements togolais 🇹🇬. -

-
+
+

{brand}

+ {brand} + {brand} + + v{app.version} +
+

+ Système de gestion scolaire — de l’inscription de l’élève au bulletin, en passant par l’écolage et la paie. + Pensé pour les établissements togolais 🇹🇬. +

{/* Liens utiles */} From 470bc011b4b7030a71518de9d780c4cfae479127 Mon Sep 17 00:00:00 2001 From: horacioskrp Date: Sun, 6 Sep 2026 01:47:39 +0000 Subject: [PATCH 10/11] =?UTF-8?q?refactor(parametres):=20retirer=20=C2=AB?= =?UTF-8?q?=20=C3=89tablissement=20=C2=BB=20des=20infos=20techniques=20(?= =?UTF-8?q?=C3=80=20propos)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ligne retirée de la section Informations techniques ; la donnée school n'étant plus affichée, elle n'est plus transmise par le contrôleur. --- app/Http/Controllers/Parametres/AboutController.php | 2 -- resources/js/pages/Parametres/About.tsx | 4 +--- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/app/Http/Controllers/Parametres/AboutController.php b/app/Http/Controllers/Parametres/AboutController.php index e159361..2716578 100644 --- a/app/Http/Controllers/Parametres/AboutController.php +++ b/app/Http/Controllers/Parametres/AboutController.php @@ -3,7 +3,6 @@ namespace App\Http\Controllers\Parametres; use App\Http\Controllers\Controller; -use App\Models\School; use Illuminate\Support\Facades\File; use Inertia\Inertia; use Inertia\Response; @@ -27,7 +26,6 @@ public function index(): Response 'php' => PHP_VERSION, 'environment' => app()->environment(), ], - 'school' => School::query()->value('name'), ]); } } diff --git a/resources/js/pages/Parametres/About.tsx b/resources/js/pages/Parametres/About.tsx index a272e34..a91101f 100644 --- a/resources/js/pages/Parametres/About.tsx +++ b/resources/js/pages/Parametres/About.tsx @@ -7,7 +7,6 @@ import AppLayout from '@/layouts/app-layout'; interface Props { app: { name: string; version: string; laravel: string; php: string; environment: string }; - school: string | null; } const GITHUB = 'https://github.com/wearedalibi/dalibi'; @@ -36,7 +35,7 @@ function Card({ children }: { children: React.ReactNode }) { return
{children}
; } -export default function About({ app, school }: Readonly) { +export default function About({ app }: Readonly) { const brand = app.name ? app.name.charAt(0).toUpperCase() + app.name.slice(1) : 'Dalibi'; return ( @@ -129,7 +128,6 @@ export default function About({ app, school }: Readonly) {
Laravel
{app.laravel}
PHP
{app.php}
Environnement
{app.environment}
- {school &&
Établissement
{school}
}
From 65ed3c4f8dcf188b04869348a06f090acdd75115 Mon Sep 17 00:00:00 2001 From: horacioskrp Date: Sun, 6 Sep 2026 02:13:30 +0000 Subject: [PATCH 11/11] chore(release): v1.0.0 (relance) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Consolide les en-têtes de documents unifiées, l'amélioration du recouvrement par classe et la page « À propos ». Le versionnage repart à 1.0.0 : cette version est considérée comme la première stable, l'historique de versions est réécrit en une seule entrée. --- CHANGELOG.md | 179 +++++++++++++-------------------------------------- package.json | 2 +- 2 files changed, 44 insertions(+), 137 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f7c9fb8..fe5a8b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,142 +4,49 @@ Toutes les évolutions notables de **Dalibi** sont consignées ici. Le format suit [Keep a Changelog](https://keepachangelog.com/fr/1.1.0/) et le versionnage respecte [SemVer](https://semver.org/lang/fr/). -## [1.2.0] — 2026-09-03 +## [1.0.0] — 2026-09-06 -Refonte du module **Statistiques** : chaque onglet gagne des graphiques plus lisibles, -accessibles (palette validée en vision déficiente, mode sombre), interactifs et, là où -c'est pertinent, ventilés par sexe et filtrables. - -### Ajouté -- **Comparaisons** : cartes de variation vs année précédente, séparation en deux lectures - claires — *Performance* (réussite, recouvrement) et *Déperdition* (redoublement, - abandon) — l'année en cours n'étant pas tracée pour les taux de fin d'année encore - indécis. Le jeu de démonstration sème deux années passées pour donner de vraies tendances. -- **Géographie** : treemap hiérarchique région → préfecture, une teinte par région - (nuancée selon l'effectif) et une légende ; KPI de concentration (couverture, part du - Grand Lomé, régions, préfectures). -- **Réussite & examens** : examens officiels (CEPD, BEPC, BAC) avec résultats - admis / échoué / absent et taux d'admission ; **répartition des mentions** enfin - alimentée (quatre paliers). -- **Effectifs & parité** : **pyramide des âges** divergente garçons / filles, **origine - géographique** (top villes) ventilée par sexe, et **filtre par cycle** (Maternelle / - Primaire / Collège / Lycée) avec tri sur le graphe des classes. -- **Statistiques élèves** (module Élèves) refondue : vrais graphiques thémés, mode sombre, - donut de parité, histogramme d'âge, effectifs par classe filtrables et empilés par sexe, - KPI d'âge moyen et de sur-âge. -- Âge attendu par classe renseigné, ce qui active le calcul du **sur-âge** (retard scolaire). - -### Corrigé -- **Répartition des mentions vide** : les libellés (« Très bien », « Assez bien »…) sont - désormais normalisés avant d'être agrégés sur les quatre paliers standard. -- **Lisibilité de la géographie** : couleurs par région (les faibles effectifs, en teinte - unique quasi blanche, étaient invisibles) et libellés du treemap en graisse normale. - -## [1.1.0] — 2026-09-03 - -### Ajouté -- **Jeu de démonstration complet** (`DemoSeeder`) : une année scolaire vivante sur toutes - les classes actives (au moins 20 élèves par classe), avec dossiers d'élèves complets, - programme et affectations des enseignants, évaluations notées et moyennes par matière, - bulletins figés, facturation et paiements, présences, emploi du temps, calendrier, - cycles de paie et dossiers courants (justificatifs, réclamations, primes, documents). - Noms, prénoms et villes réels du Togo (divisions administratives officielles), - recrutement pondéré autour de Lomé. Seeder idempotent, déterministe, et interdit en - production. Lancement : `php artisan db:seed --class=DemoSeeder`. - -### Corrigé -- **Bulletin — colonne Composition toujours vide** : la colonne de source « composition » - était résolue sur une clé absente du bulletin figé (la valeur y est stockée sous - « compo »). La colonne restait vide **même quand la note existait**, quelle que soit la - période ou le barème. Correctif d'affichage : aucun bulletin à régénérer. -- **Bulletin — logo de l'en-tête surdimensionné** : les styles de l'en-tête ministériel - (dont le plafond de taille du logo) n'étaient pas embarqués dans le CSS du bulletin ; le - logo s'affichait à sa taille naturelle et écrasait l'en-tête. -- **Types d'évaluation — catégorie de la « Composition »** : lorsqu'elle avait dérivé vers - « contrôle continu », la composition était diluée dans la note de classe et la - pondération Classe/Compo du barème était ignorée. Rejouer `ReferenceDataSeeder` corrige - la donnée, puis régénérer les bulletins concernés. - -### Modifié -- **Bulletin — la colonne « Classe »** (contrôle continu) s'intitule désormais « Devoir » - par défaut. Seul l'affichage change : la colonne agrège toujours interro + devoir et - alimente la moyenne. Un libellé déjà personnalisé par une école n'est pas écrasé. - -## [1.0.1] — 2026-09-02 - -### Corrigé -- **Couleur des catégories dans les graphiques** : la couleur suivait la *position* - dans le tableau et non la catégorie. Lorsqu'une catégorie vide était filtrée, les - suivantes changeaient de couleur — les filles pouvaient hériter du bleu des garçons, - « Très bien » perdre son vert. - -### Accessibilité -- **Palette revue et validée** (bande de luminosité, chroma, séparation en vision - déficiente, contraste) dans les modes clair *et* sombre. L'ancien couple bleu/violet - était indistinguable en deutéranopie. -- **Légendes ajoutées** aux camemberts qui n'en avaient pas : l'identité ne repose plus - sur la seule couleur. -- Les répartitions à plus de trois catégories (modes de paiement, régions) passent en - **barres étiquetées** ; les mentions, données ordonnées, en **rampe séquentielle**. -- **Mode sombre** : couleurs d'axes et de grille désormais adaptées au thème, au lieu de - valeurs claires codées en dur (la grille était quasi invisible sur fond sombre). -- L'animation d'entrée des camemberts est retirée : elle laissait le graphique **vide** - lorsque les images d'animation sont ralenties (onglet en arrière-plan, économie - d'énergie, `prefers-reduced-motion`). -## [1.0.0] — 2026-09-02 - -Première version stable. Dalibi couvre le cycle complet de gestion d'un établissement -scolaire, de l'inscription de l'élève au bulletin, en passant par l'écolage et la paie. +Première version stable de **Dalibi**, système de gestion scolaire pensé pour les +établissements togolais 🇹🇬 — de l'inscription de l'élève au bulletin, en passant par +l'écolage, la paie et le pilotage. ### Scolarité -- **Élèves & inscriptions** : dossiers complets (état civil, parents, fiche médicale, pièces - justificatives sur disque privé), import CSV en masse, inscriptions rattachées à l'année - académique, effectifs et listes de classe, passage de classe en fin d'année, bourses. -- **Notes & bulletins** : saisie par matière et évaluation, calcul des moyennes paramétrable - (trimestre ou semestre **par type de classe**), bulletins PDF fidèles avec modèle et - en-tête configurables, réclamations de notes. -- **Examens** : modèles d'évaluation réutilisables, déploiement par classe, planning - imprimable, examens officiels (CEPD, BEPC, BAC). -- **Présences** : appel par classe et par séance, statistiques d'assiduité, demandes de - permission d'absence avec cycle de révision. -- **Emploi du temps** : grille hebdomadaire par classe, export PDF. - -### Gestion -- **Comptabilité & écolage** : structures de frais, encaissements, reçus vérifiables par - code-barres, situation par classe, dépenses, caisses multiples (dont Mobile Money). -- **Personnel & Paie** : fiches employés, grilles salariales et rubriques, cycles de paie - mensuels avec bulletins PDF, CNSS et ITS calculés automatiquement, décaissement écrit - en comptabilité. -- **Archives & documents** : modèles de documents avec en-tête glisser-déposer et filigrane, - archivage avec tags et corbeille, fichiers sur disque privé. -- **Statistiques** : indicateurs alignés sur la carte scolaire (MEPSTA), exports PDF et Excel. - -### Portail parents & élèves -- API REST (`/api/v1`) authentifiée par token, spécifiée en OpenAPI 3.1. -- Isolation stricte : un tuteur n'accède qu'à ses enfants, un élève qu'à ses propres données. -- Activable par établissement, accès délivré compte par compte. - -### Sécurité -- Contrôle d'accès **piloté par les permissions** (~145), avec **une permission par verbe** : - un droit de lecture ne permet jamais de créer, modifier ou supprimer. -- **Cloisonnement enseignant** : notes et appels limités aux classes affectées. -- **Intégrité financière** : gardes anti trop-perçu et transitions du cycle de paie évaluées - sous verrou ; une inscription portant des paiements ne peut pas être supprimée. -- Protection des comptes à privilèges, 2FA, journal d'audit, fichiers sensibles hors du - dossier public. -- Données de démonstration **interdites en production**. - -### Exploitation -- **Sauvegardes** conçues pour la durée : écriture en flux, compression gzip, `pg_dump` natif, - archives d'année scolaire verrouillées, empreinte SHA-256, sauvegarde optionnelle des médias, - restauration sélective par table. -- Déploiement **Docker** (app / worker / scheduler), observabilité optionnelle (logs JSON, - Sentry/GlitchTip). -- Intégration continue : tests, build et vérification des types à chaque contribution. - -### Socle technique -Laravel 12 (PHP 8.3+), React 19 + TypeScript via Inertia.js, Tailwind CSS 4, PostgreSQL, -identifiants UUID. **502 tests** automatisés. - -[1.0.1]: https://github.com/wearedalibi/dalibi/releases/tag/v1.0.1 -[1.0.0]: https://github.com/wearedalibi/dalibi/releases/tag/v1.0.0 +- **Élèves & inscriptions** : dossiers complets (état civil, parents, fiche médicale, + pièces justificatives sur disque privé), import CSV, inscriptions rattachées à l'année + académique, effectifs et listes de classe, passage de classe, bourses. +- **Notes & bulletins** : saisie par matière et évaluation, calcul des moyennes + paramétrable (trimestre ou semestre par type de classe), mentions, bulletins PDF + fidèles avec modèle et en-tête configurables, réclamations de notes. +- **Examens** : modèles d'évaluation réutilisables, planning imprimable, examens officiels + (CEPD, BEPC, BAC) avec inscriptions et résultats. +- **Présences** : appel par séance, statistiques d'assiduité, permissions d'absence avec + cycle de révision. +- **Emploi du temps & calendrier** : grille hebdomadaire par classe, calendrier scolaire. + +### Finances & paie +- **Écolage** : structures de frais, factures, paiements (espèces, Mobile Money, virement, + chèque), reçus vérifiables, recouvrement par classe. +- **Comptabilité** : caisses, journal des transactions, dépenses, situation par classe. +- **Personnel & paie** : fiches employés, grilles et rubriques, cycles de paie et bulletins + (retenues légales CNSS et ITS). + +### Statistiques +- Tableaux de bord par thème : **effectifs & parité** (pyramide des âges par sexe, origine + géographique par sexe, filtre par cycle), **finances & recouvrement** (par classe, + filtrable et détaillé), **réussite & examens**, **encadrement**, **assiduité**, + **comparaisons** pluriannuelles et **géographie** (treemap région → préfecture). +- Graphiques accessibles : palette validée en vision déficiente, mode sombre, légendes, + survols ; exports PDF et Excel. + +### Documents & système +- **En-tête unique** : bulletins, bulletins de paie, certificats, attestations, listes, + emplois du temps, planning et exports statistiques partagent la même en-tête officielle. +- **Sauvegardes** : à la demande ou planifiées, base + médias, restauration sûre, + archives annuelles verrouillées. +- **Sécurité** : rôles et permissions (RBAC), authentification à deux facteurs, + changement de mot de passe imposé aux comptes de démonstration, journal d'audit. +- **Portail** : accès parents/élèves, API du portail. +- **Paramètres** : configuration complète de l'établissement, stockage local ou S3, et + une page **À propos** (version, licence, informations techniques). + +Dalibi est un logiciel libre publié sous licence **GNU GPL v3**. diff --git a/package.json b/package.json index 5e01440..27a7f8a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "$schema": "https://www.schemastore.org/package.json", "private": true, - "version": "1.2.0", + "version": "1.0.0", "type": "module", "scripts": { "build": "vite build",