From a443ec389bf07f3702169e5f1b3fb5addb080bb6 Mon Sep 17 00:00:00 2001 From: perco Date: Mon, 11 May 2026 16:33:49 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20garage=20=E2=80=94=20photos=20(limite=20?= =?UTF-8?q?20MB),=20entretiens=20globaux,=20pi=C3=A8ces=20group=C3=A9es=20?= =?UTF-8?q?par=20v=C3=A9hicule?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Dockerfile + docker/php.ini : upload_max_filesize 2M → 20M - garage.php : onglet Entretiens dans sous-nav + page #page-maintenances-all - garage.js : loadAllMaintenances() (entretiens groupés par véhicule) - garage.js : loadParts() redesigné — pièces groupées par véhicule - garage.js : navigate() gère 'maintenances-all' - DB : vehicle_id des pièces mis à jour via maintenance Co-Authored-By: Claude Sonnet 4.6 --- Dockerfile | 1 + docker/php.ini | 3 ++ garage.php | 15 +++++- modules/garage/assets/garage.js | 89 +++++++++++++++++++++++++++------ 4 files changed, 92 insertions(+), 16 deletions(-) create mode 100644 docker/php.ini diff --git a/Dockerfile b/Dockerfile index e83523c..e1975dc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,3 +11,4 @@ COPY . /var/www/html/ RUN chown -R www-data:www-data /var/www/html COPY docker/apache.conf /etc/apache2/sites-available/000-default.conf +COPY docker/php.ini /usr/local/etc/php/conf.d/uploads.ini diff --git a/docker/php.ini b/docker/php.ini new file mode 100644 index 0000000..81297f7 --- /dev/null +++ b/docker/php.ini @@ -0,0 +1,3 @@ +upload_max_filesize = 20M +post_max_size = 25M +memory_limit = 256M diff --git a/garage.php b/garage.php index 92e79a2..0700ef8 100644 --- a/garage.php +++ b/garage.php @@ -14,11 +14,24 @@ require __DIR__ . '/header.php'; +
+
+
+
+

🔧

+

0 · Total : --

+
+
+
+
+
+
diff --git a/modules/garage/assets/garage.js b/modules/garage/assets/garage.js index 4564e8c..12a5494 100644 --- a/modules/garage/assets/garage.js +++ b/modules/garage/assets/garage.js @@ -26,6 +26,7 @@ function navigate(page,params={}){ else if(page==='vehicles')loadVehicles(); else if(page==='vehicle')loadVehicleDetail(params.id); else if(page==='parts')loadParts(); + else if(page==='maintenances-all')loadAllMaintenances(); } // API @@ -204,21 +205,37 @@ async function loadParts(){ $('#all-parts-total').textContent=fmtPrice(total); $('#all-parts-count').textContent=list.length; if(!list.length){el.innerHTML='
\ud83d\udd29

Aucune pi\u00e8ce

';return;} - el.innerHTML='
'+ - list.map(p=>''+ - ''+ - ''+ - ''+ - ''+ - ''+ - ''+ - ''+ - ''+ - ''+ - ''+ - ''+ - '').join('')+ - '
PhotoNomV\u00e9hiculeMarqueR\u00e9f\u00e9renceCat\u00e9goriePrix unit.Qt\u00e9TotalEntretien
'+(p.photo?'':'--')+''+p.name+''+(p.vehicle_name?''+p.vehicle_name+'':'--')+''+(p.brand||'--')+''+(p.reference||'--')+''+p.category+''+fmtPrice(p.price)+''+p.quantity+' '+p.unit+''+fmtPrice(parseFloat(p.price||0)*parseInt(p.quantity||1))+''+(p.maintenance_type?p.maintenance_type+' ('+fmtDate(p.maintenance_date)+')':'--')+'
'; + // Grouper par v\u00e9hicule + const byVehicle={}; + list.forEach(p=>{ + const key=p.vehicle_name||'Sans v\u00e9hicule'; + if(!byVehicle[key])byVehicle[key]=[]; + byVehicle[key].push(p); + }); + let html=''; + for(const[vname,parts] of Object.entries(byVehicle)){ + const vtotal=parts.reduce((s,p)=>s+parseFloat(p.price||0)*parseInt(p.quantity||1),0); + html+='
'+ + '
'+ + '

\ud83d\ude97 '+escHtml(vname)+'

'+ + ''+parts.length+' pi\u00e8ces \u00b7 '+fmtPrice(vtotal)+''+ + '
'+ + '
'+ + parts.map(p=>''+ + ''+ + ''+ + ''+ + ''+ + ''+ + ''+ + ''+ + ''+ + ''+ + ''+ + '').join('')+ + '
PhotoNomMarqueR\u00e9f\u00e9renceCat\u00e9goriePrix unit.Qt\u00e9TotalEntretien
'+(p.photo?'':'--')+''+escHtml(p.name)+''+(p.brand||'--')+''+(p.reference||'--')+''+p.category+''+fmtPrice(p.price)+''+p.quantity+' '+p.unit+''+fmtPrice(parseFloat(p.price||0)*parseInt(p.quantity||1))+''+(p.maintenance_type?p.maintenance_type+' ('+fmtDate(p.maintenance_date)+')':'--')+'
'; + } + el.innerHTML=html; }catch(e){toast(e.message,'error');} } @@ -361,6 +378,48 @@ function previewPhoto(inputId,previewId){ reader.readAsDataURL(file); } +// ALL MAINTENANCES +async function loadAllMaintenances(){ + try{ + // Récupérer tous les véhicules puis leurs maintenances + const vehicles=await api('vehicles'); + const el=$('#all-maintenances-list'); + if(!vehicles.length){el.innerHTML='
🔧

Aucun véhicule

';return;} + let totalAll=0, countAll=0; + let html=''; + for(const v of vehicles){ + const mlist=await api('maintenances',undefined,null,'&vehicle_id='+v.id); + if(!mlist.length)continue; + const total=mlist.reduce((s,m)=>s+parseFloat(m.cost||0)+parseFloat(m.parts_cost||0),0); + totalAll+=total; countAll+=mlist.length; + html+='
'+ + '
'+ + '

🚗 '+v.name+'

'+ + (v.license_plate?''+v.license_plate+'':'')+ + ''+mlist.length+' entretiens · '+fmtPrice(total)+''+ + '
'+ + '
'+ + mlist.map(m=>''+ + ''+ + ''+ + ''+ + ''+ + ''+ + ''+ + ''+ + ''+ + ''+ + '').join('')+ + '
DateTypeDescriptionKmCoût M.O.PiècesTotalMécanicien
'+fmtDate(m.date)+''+m.type+''+escHtml(m.description||'--')+''+(m.km?fmt(m.km)+' km':'--')+''+fmtPrice(m.cost)+''+(m.parts_count>0?m.parts_count+' ('+fmtPrice(m.parts_cost)+')':'--')+''+fmtPrice(parseFloat(m.cost||0)+parseFloat(m.parts_cost||0))+''+(m.mechanic||'--')+'
'; + } + $('#all-maint-count').textContent=countAll; + $('#all-maint-total').textContent=fmtPrice(totalAll); + el.innerHTML=html||'
🔧

Aucun entretien

'; + }catch(e){console.error(e);} +} + +function escHtml(s){const d=document.createElement('div');d.textContent=s;return d.innerHTML;} + // INIT document.addEventListener('DOMContentLoaded',()=>{ $$('.nav-link').forEach(n=>n.addEventListener('click',()=>navigate(n.dataset.page)));