U+202F (narrow no-break space) is missing from DejaVu Sans in some DomPDF versions on prod, rendering as '?'. U+00A0 is in Latin-1 Supplement and guaranteed present in all DejaVu Sans builds. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
260 lines
13 KiB
PHP
260 lines
13 KiB
PHP
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<title>Devis {{ $devis->number }}</title>
|
|
<style>
|
|
@page { margin: 0; size: A4; }
|
|
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
|
|
body {
|
|
font-family: 'DejaVu Sans', sans-serif;
|
|
color: #334155;
|
|
font-size: 8.5pt;
|
|
line-height: 1.5;
|
|
background: #ffffff;
|
|
}
|
|
|
|
/* ─── PAGE WRAPPER ─────────────────────────────────── */
|
|
.page { padding: 32px 40px; }
|
|
|
|
/* ─── SECTION SPACER ────────────────────────────────── */
|
|
.section-gap { height: 22px; }
|
|
.section-gap-sm { height: 12px; }
|
|
|
|
/* ─── HEADER ────────────────────────────────────────── */
|
|
.header-table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
border-bottom: 1px solid #e2e8f0;
|
|
}
|
|
.header-table td { border: none; vertical-align: middle; padding: 0 0 14px 0; }
|
|
.header-logo { height: 70px; width: auto; vertical-align: middle; margin-right: 14px; }
|
|
.header-entity-name {
|
|
font-size: 13pt;
|
|
font-weight: bold;
|
|
color: #0f172a;
|
|
letter-spacing: -0.5px;
|
|
display: block;
|
|
margin-bottom: 5px;
|
|
}
|
|
.deco-squares { margin-top: 3px; }
|
|
.deco-sq { display: inline-block; width: 13px; height: 11px; margin-right: 3px; }
|
|
.header-right {
|
|
text-align: right;
|
|
font-size: 7.5pt;
|
|
color: #64748b;
|
|
line-height: 1.65;
|
|
font-weight: 600;
|
|
}
|
|
.header-right .entity-sub { font-weight: 800; color: #1e293b; display: block; margin-bottom: 2px; }
|
|
|
|
/* ─── INFO CARDS ────────────────────────────────────── */
|
|
.cards-table { width: 100%; border-collapse: collapse; }
|
|
.cards-table td { border: none; padding: 0; vertical-align: top; }
|
|
.card { border: 2px solid #0f172a; border-radius: 24px; padding: 20px 24px; }
|
|
.card-title {
|
|
font-size: 9pt;
|
|
font-weight: bold;
|
|
text-transform: uppercase;
|
|
color: #0f172a;
|
|
letter-spacing: -0.3px;
|
|
margin-bottom: 10px;
|
|
}
|
|
.card-body { font-size: 8pt; color: #334155; line-height: 1.7; }
|
|
.card-label { font-weight: bold; color: #0f172a; }
|
|
.card-dest-name { font-weight: bold; color: #0f172a; font-size: 9pt; display: block; margin-bottom: 3px; }
|
|
.card-dest-type { font-weight: 700; color: #64748b; font-size: 7.5pt; display: block; margin-bottom: 7px; }
|
|
.card-referent-sep { border-top: 1px solid #e2e8f0; margin-top: 7px; padding-top: 7px; }
|
|
|
|
/* ─── ITEMS TABLE ───────────────────────────────────── */
|
|
.items-table { width: 100%; border-collapse: collapse; }
|
|
.items-table thead tr { background-color: #f1f5f9; }
|
|
.items-table th {
|
|
font-size: 7.5pt;
|
|
font-weight: bold;
|
|
text-transform: uppercase;
|
|
color: #0f172a;
|
|
letter-spacing: 0.4px;
|
|
padding: 10px 20px;
|
|
text-align: left;
|
|
border: none;
|
|
}
|
|
.items-table td {
|
|
padding: 13px 20px;
|
|
border-bottom: 2px dotted #cbd5e1;
|
|
vertical-align: middle;
|
|
border-top: none; border-left: none; border-right: none;
|
|
}
|
|
.item-designation { font-weight: bold; color: #0f172a; font-size: 9pt; margin-bottom: 2px; }
|
|
.item-type { font-weight: bold; color: #94a3b8; font-size: 7pt; text-transform: uppercase; letter-spacing: 0.4px; }
|
|
.col-price { text-align: right; font-size: 8.5pt; }
|
|
.col-qty { text-align: center; font-weight: bold; color: #0f172a; font-size: 8.5pt; }
|
|
.col-total { text-align: right; font-weight: bold; color: #0f172a; font-size: 9pt; }
|
|
|
|
/* ─── TOTAUX ────────────────────────────────────────── */
|
|
.sig-label {
|
|
font-size: 7pt;
|
|
font-weight: bold;
|
|
text-transform: uppercase;
|
|
color: #94a3b8;
|
|
letter-spacing: 0.4px;
|
|
display: block;
|
|
margin-bottom: 22px;
|
|
}
|
|
.sig-line { border-bottom: 1px dashed #94a3b8; width: 200px; height: 8px; margin-bottom: 5px; }
|
|
.sig-note { font-size: 6.5pt; color: #94a3b8; font-style: italic; }
|
|
|
|
/* ─── FOOTER ────────────────────────────────────────── */
|
|
.footer-table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
border-top: 1px solid #e2e8f0;
|
|
margin-top: 20px;
|
|
}
|
|
.footer-table td { border: none; padding: 0; vertical-align: top; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="page">
|
|
|
|
{{-- ─── HEADER ─────────────────────────────────────────── --}}
|
|
<table class="header-table">
|
|
<tbody>
|
|
<tr>
|
|
<td style="width: 60%;">
|
|
<table style="border-collapse: collapse; width: 100%;"><tbody><tr>
|
|
<td style="border: none; padding: 0; vertical-align: middle; width: 1%;">
|
|
@if(file_exists(public_path('logo.png')))
|
|
<img src="data:image/png;base64,{{ base64_encode(file_get_contents(public_path('logo.png'))) }}"
|
|
class="header-logo" alt="Logo">
|
|
@endif
|
|
</td>
|
|
<td style="border: none; padding: 0; vertical-align: middle; padding-left: 20px;">
|
|
<span class="header-entity-name">{{ $settings->entity_name ?? "Direction des Systèmes d'Information" }}</span>
|
|
<div class="deco-squares">
|
|
<span class="deco-sq" style="background-color:#047857;"></span>
|
|
<span class="deco-sq" style="background-color:#14b8a6;"></span>
|
|
<span class="deco-sq" style="background-color:#f59e0b;"></span>
|
|
<span class="deco-sq" style="background-color:#f43f5e;"></span>
|
|
<span class="deco-sq" style="background-color:#f472b6;"></span>
|
|
</div>
|
|
</td>
|
|
</tr></tbody></table>
|
|
</td>
|
|
<td style="width: 40%; text-align: right;" class="header-right">
|
|
<span class="entity-sub">{{ $settings->entity_sub ?? "Communauté d'Agglomération Béziers Méditerranée" }}</span>
|
|
@if(!empty($settings->telephone))<span>Téléphone : {{ $settings->telephone }}</span><br>@endif
|
|
@if(!empty($settings->email))<span>E-mail : {{ $settings->email }}</span><br>@endif
|
|
@if(!empty($settings->adresse))<span>Adresse : {{ $settings->adresse }}</span>@endif
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
<div class="section-gap"></div>
|
|
|
|
{{-- ─── INFO CARDS ──────────────────────────────────────── --}}
|
|
<table class="cards-table">
|
|
<tbody><tr>
|
|
<td style="width: 48%;">
|
|
<div class="card">
|
|
<div class="card-title">DEVIS N° : {{ $devis->number }}</div>
|
|
<div class="card-body">
|
|
<span class="card-label">DATE :</span> {{ \Carbon\Carbon::parse($devis->date_devis)->format('d/m/Y') }}<br>
|
|
<span class="card-label">OBJET :</span> {{ $devis->title }}
|
|
@if(!empty($devis->notes))
|
|
<br><span class="card-label">CONDITIONS :</span> {{ $devis->notes }}
|
|
@endif
|
|
</div>
|
|
</div>
|
|
</td>
|
|
<td style="width: 4%;"></td>
|
|
<td style="width: 48%;">
|
|
<div class="card">
|
|
<div class="card-title">DESTINATAIRE :</div>
|
|
<div class="card-body">
|
|
<span class="card-dest-name">{{ $devis->destinataire_nom }}</span>
|
|
<span class="card-dest-type">
|
|
{{ $devis->destinataire_type === 'commune' ? 'Commune / Collectivité' : 'Service Interne' }}
|
|
</span>
|
|
@if(!empty($devis->referent))
|
|
<div class="card-referent-sep">
|
|
<span class="card-label">À L'ATTENTION DE :</span> {{ $devis->referent }}
|
|
</div>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
</td>
|
|
</tr></tbody>
|
|
</table>
|
|
|
|
<div class="section-gap"></div>
|
|
|
|
{{-- ─── TABLEAU LIGNES ──────────────────────────────────── --}}
|
|
<table class="items-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Description :</th>
|
|
<th style="text-align: right;">Prix Unitaire :</th>
|
|
<th style="text-align: center;">Quantité :</th>
|
|
<th style="text-align: right;">Total :</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@foreach($devis->items as $item)
|
|
<tr>
|
|
<td>
|
|
<div class="item-designation">{{ $item['designation'] ?? '' }}</div>
|
|
<div class="item-type">{{ $item['type'] ?? '' }}</div>
|
|
</td>
|
|
<td class="col-price">{{ number_format($item['prix_unitaire'] ?? 0, 2, ',', "\xc2\xa0") }} €</td>
|
|
<td class="col-qty">{{ $item['quantite'] ?? 0 }}</td>
|
|
<td class="col-total">{{ number_format(($item['quantite'] ?? 0) * ($item['prix_unitaire'] ?? 0), 2, ',', "\xc2\xa0") }} €</td>
|
|
</tr>
|
|
@endforeach
|
|
</tbody>
|
|
</table>
|
|
|
|
<div class="section-gap-sm"></div>
|
|
|
|
{{-- ─── TOTAUX ───────────────────────────────────────────── --}}
|
|
<table style="width: 100%; border-collapse: collapse;">
|
|
<tbody><tr>
|
|
<td style="border: none; padding: 0;"></td>
|
|
<td style="border: none; padding: 0; width: 280px; text-align: right;">
|
|
<table style="width: 100%; border-collapse: collapse;">
|
|
<tbody>
|
|
<tr>
|
|
<td style="border: none; padding: 4px 0; font-weight: bold; font-size: 8.5pt; color: #0f172a; text-align: left;">TOTAL HT :</td>
|
|
<td style="border: none; padding: 4px 0; font-weight: bold; font-size: 8.5pt; color: #0f172a; text-align: right;">{{ number_format($devis->total_ht, 2, ',', "\xc2\xa0") }} €</td>
|
|
</tr>
|
|
<tr>
|
|
<td style="border: none; padding: 4px 0; font-weight: bold; font-size: 8.5pt; color: #0f172a; text-align: left;">TVA ({{ $devis->tva_rate }}%) :</td>
|
|
<td style="border: none; padding: 4px 0; font-weight: bold; font-size: 8.5pt; color: #0f172a; text-align: right;">{{ number_format($devis->total_ttc - $devis->total_ht, 2, ',', "\xc2\xa0") }} €</td>
|
|
</tr>
|
|
<tr>
|
|
<td style="border: none; border-top: 2px solid #0f172a; padding: 9px 0 4px 0; font-weight: bold; font-size: 10.5pt; color: #0f172a; text-align: left;">TOTAL TTC :</td>
|
|
<td style="border: none; border-top: 2px solid #0f172a; padding: 9px 0 4px 0; font-weight: 800; font-size: 10.5pt; color: #0284c7; text-align: right;">{{ number_format($devis->total_ttc, 2, ',', "\xc2\xa0") }} €</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</td>
|
|
</tr></tbody>
|
|
</table>
|
|
|
|
{{-- ─── FOOTER : SIGNATURE DESTINATAIRE ────────────────── --}}
|
|
<table class="footer-table">
|
|
<tbody><tr>
|
|
<td style="vertical-align: top; padding-top: 22px;">
|
|
<span class="sig-label">Pour le Destinataire (Bon pour accord)</span>
|
|
<div class="sig-line"></div>
|
|
<span class="sig-note">Nom, Date et Signature</span>
|
|
</td>
|
|
</tr></tbody>
|
|
</table>
|
|
|
|
</div>
|
|
</body>
|
|
</html>
|