Files
maria_uslugi/public/praticien/factures_details.php
T
2026-03-05 10:25:39 +01:00

389 lines
11 KiB
PHP

<?php
require_once __DIR__ . '/../includes/init_praticien.php';
$paiement_id = intval($_GET['id'] ?? 0);
$stmt = $pdo->prepare("
SELECT p.*, a.nom AS formule
FROM paiement p
JOIN abonnement a ON p.abonnement_id = a.id
WHERE p.id = ? AND p.praticien_id = ?
");
$stmt->execute([$paiement_id, $_SESSION['reference_id']]);
$paiement = $stmt->fetch();
if (!$paiement) {
die(htmlspecialchars($translations['facture_introuvable']));
}
$methodeMap = [
'cb' => $translations['methode_carte'] ?? 'CB',
'virement' => $translations['methode_virement'] ?? 'Virement',
'paypal' => $translations['methode_paypal'] ?? 'PayPal',
'stripe' => $translations['methode_stripe'] ?? 'Stripe',
];
$statutMap = [
'paye' => $translations['statut_paye'] ?? 'Payé',
'payé' => $translations['statut_paye'] ?? 'Payé',
'succeeded' => $translations['statut_paye'] ?? 'Payé',
'pending' => $translations['statut_en_attente'] ?? 'En attente',
'en_attente' => $translations['statut_en_attente'] ?? 'En attente',
'failed' => $translations['statut_echoue'] ?? 'Échoué',
'echoue' => $translations['statut_echoue'] ?? 'Échoué',
'échoué' => $translations['statut_echoue'] ?? 'Échoué',
'refunded' => $translations['statut_rembourse'] ?? 'Remboursé',
'rembourse' => $translations['statut_rembourse'] ?? 'Remboursé',
'remboursé' => $translations['statut_rembourse'] ?? 'Remboursé',
];
$methode = strtolower($paiement['methode'] ?? '');
$translationKey = 'methode_' . $methode;
$libMethode = $translations[$translationKey] ?? ucfirst($methode);
$libStatut = $statutMap[strtolower($paiement['statut'] ?? '')] ?? ($paiement['statut'] ?? '');
$numero = str_pad((string)$paiement['id'], 6, '0', STR_PAD_LEFT);
$datePaiement = !empty($paiement['date_paiement']) ? date('d/m/Y', strtotime($paiement['date_paiement'])) : '';
$montant = number_format((float)$paiement['montant'], 2, ',', ' ') . ' €';
$formuleKey = trim((string)($paiement['formule'] ?? ''));
$formuleTxt = $formuleKey !== '' ? ($translations[$formuleKey] ?? $formuleKey) : '';
$statutLower = strtolower((string)($paiement['statut'] ?? ''));
$badgeClass =
in_array($statutLower, ['paye','payé','succeeded'], true) ? 'badge--paid' :
(in_array($statutLower, ['pending','en_attente'], true) ? 'badge--pending' :
(in_array($statutLower, ['failed','echoue','échoué'], true) ? 'badge--failed' :
(in_array($statutLower, ['refunded','rembourse','remboursé'], true) ? 'badge--refunded' : 'badge--neutral')));
?>
<!doctype html>
<html lang="<?= htmlspecialchars($_SESSION['lang'] ?? 'fr') ?>">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title><?= htmlspecialchars($translations['titre_facture']) ?> #<?= htmlspecialchars($numero) ?></title>
<style>
:root{
--brand:#38378B; /* même vibe que la capture */
--bg:#f3f4f6; /* gris clair */
--card:#ffffff;
--text:#111827;
--muted:#6b7280;
--line:#d9dde6;
--shadow:0 14px 40px rgba(17,24,39,.10);
--radius:18px;
--paid:#16a34a;
--pending:#f59e0b;
--failed:#dc2626;
--refunded:#2563eb;
--neutral:#6b7280;
--btn:#e53935; /* rouge bouton comme capture */
--btnHover:#cf2f2b;
}
*{box-sizing:border-box}
body{
margin:0;
font-family: system-ui, -apple-system, Segoe UI, Roboto, Arial, "Noto Sans", sans-serif;
color:var(--text);
background:var(--bg);
}
.wrap{
max-width: 980px;
margin: 0 auto;
padding: 28px 18px 40px;
}
/* Carte principale */
.card{
background:var(--card);
border-radius: var(--radius);
box-shadow: var(--shadow);
overflow:hidden; /* pour arrondi de la bande top */
border: 1px solid rgba(17,24,39,.06);
}
/* Bande violette top */
.topbar{
background: var(--brand);
height: 90px;
position: relative;
}
.brand{
position:absolute;
left: 28px;
bottom: 22px;
display:flex;
align-items:center;
gap: 14px;
}
.brand__logo{
height: 46px;
width:auto;
display:block;
filter: drop-shadow(0 2px 0 rgba(0,0,0,.08));
}
/* Contenu */
.content{
padding: 34px 34px 18px;
}
.title{
margin:0 0 14px;
font-size: 28px;
font-weight: 800;
letter-spacing: .2px;
}
.subtitle{
margin:0 0 24px;
color:var(--muted);
font-size: 16px;
line-height: 1.5;
}
/* Ligne en-tête reçu */
.meta{
display:flex;
flex-wrap:wrap;
align-items:flex-start;
justify-content:space-between;
gap: 14px;
margin: 6px 0 18px;
}
.receipt-id{
display:flex;
flex-direction:column;
gap: 6px;
}
.receipt-id .k{
color:var(--muted);
font-size: 13px;
}
.receipt-id .v{
font-size: 18px;
font-weight: 800;
letter-spacing: .6px;
}
.badge{
display:inline-flex;
align-items:center;
gap: 8px;
padding: 10px 14px;
border-radius: 999px;
font-weight: 700;
font-size: 14px;
border: 1px solid rgba(17,24,39,.10);
background: #fff;
white-space:nowrap;
}
.dot{
width:10px; height:10px; border-radius:999px;
background: var(--neutral);
}
.badge--paid .dot{background:var(--paid)}
.badge--pending .dot{background:var(--pending)}
.badge--failed .dot{background:var(--failed)}
.badge--refunded .dot{background:var(--refunded)}
.badge--neutral .dot{background:var(--neutral)}
/* Bloc infos encadré (comme capture) */
.box{
border:1px solid var(--line);
border-radius: 14px;
overflow:hidden;
margin: 18px 0 24px;
}
.row{
display:grid;
grid-template-columns: 260px 1fr;
gap: 0;
padding: 16px 18px;
border-top: 1px solid var(--line);
}
.row:first-child{border-top:none}
.label{
color:var(--muted);
font-size: 16px;
padding-right: 18px;
border-right: 1px solid var(--line);
display:flex;
align-items:center;
min-height: 28px;
}
.value{
font-size: 18px;
font-weight: 700;
padding-left: 18px;
display:flex;
align-items:center;
min-height: 28px;
word-break: break-word;
}
/* Total */
.total{
display:flex;
align-items:center;
justify-content:space-between;
gap: 14px;
padding: 18px 18px;
border-top: 1px solid var(--line);
background: rgba(56,55,139,.04);
}
.total .k{ color:var(--muted); font-weight:700; }
.total .v{ font-size: 22px; font-weight: 900; }
/* Bouton */
.actions{
display:flex;
justify-content:center;
padding: 6px 0 18px;
}
.btn{
border:0;
background: var(--btn);
color:#fff;
font-weight: 800;
padding: 16px 26px;
border-radius: 999px;
cursor:pointer;
font-size: 16px;
box-shadow: 0 10px 22px rgba(229,57,53,.22);
transition: transform .05s ease, background .15s ease;
}
.btn:hover{ background: var(--btnHover); }
.btn:active{ transform: translateY(1px); }
/* Footer carte */
.card-footer{
padding: 16px 34px 28px;
color: var(--muted);
font-size: 14px;
border-top: 1px solid rgba(17,24,39,.06);
}
/* Footer page (comme capture) */
.page-footer{
text-align:center;
color:#9ca3af;
padding: 18px 6px 0;
font-size: 14px;
}
/* Mobile */
@media (max-width: 720px){
.topbar{height: 90px}
.brand{left: 18px; bottom: 18px}
.content{padding: 26px 18px 12px}
.card-footer{padding: 14px 18px 22px}
.row{grid-template-columns: 1fr; padding: 14px 14px}
.label{border-right:none; padding-right:0; margin-bottom:6px}
.value{padding-left:0}
.title{font-size:24px}
}
/* Impression */
@media print{
body{background:#fff}
.wrap{padding:0; max-width:100%}
.card{box-shadow:none; border:1px solid #e5e7eb}
.page-footer{display:none}
.btn{display:none}
.topbar{height: 90px}
}
</style>
</head>
<body>
<div class="wrap">
<div class="card">
<div class="topbar">
<div class="brand">
<img class="brand__logo" src="/public/uploads/img/logo_mail.png" alt="Logo">
</div>
</div>
<div class="content">
<h1 class="title">
<?= htmlspecialchars($translations['titre_facture']) ?>
</h1>
<p class="subtitle">
<?= htmlspecialchars($translations['facture_prefix'] ?? 'Reçu') ?>
#<?= htmlspecialchars($numero) ?> —
<?= htmlspecialchars($translations['facture_date'] ?? 'Date') ?> : <?= htmlspecialchars($datePaiement) ?>
</p>
<div class="meta">
<div class="receipt-id">
<div class="k"><?= htmlspecialchars($translations['facture_prefix'] ?? 'Reçu') ?></div>
<div class="v">#<?= htmlspecialchars($numero) ?></div>
</div>
<div class="badge <?= $badgeClass ?>">
<span class="dot"></span>
<span><?= htmlspecialchars($libStatut) ?></span>
</div>
</div>
<div class="box">
<div class="row">
<div class="label"><?= htmlspecialchars($translations['facture_date']) ?></div>
<div class="value"><?= htmlspecialchars($datePaiement) ?></div>
</div>
<div class="row">
<div class="label"><?= htmlspecialchars($translations['facture_formule']) ?></div>
<div class="value"><?= htmlspecialchars($formuleTxt) ?></div>
</div>
<div class="row">
<div class="label"><?= htmlspecialchars($translations['facture_methode']) ?></div>
<div class="value"><?= htmlspecialchars($libMethode) ?></div>
</div>
<div class="row">
<div class="label"><?= htmlspecialchars($translations['facture_statut']) ?></div>
<div class="value"><?= htmlspecialchars($libStatut) ?></div>
</div>
<div class="total">
<div class="k"><?= htmlspecialchars($translations['facture_montant']) ?></div>
<div class="v"><?= htmlspecialchars($montant) ?></div>
</div>
</div>
<div class="actions">
<button class="btn" onclick="window.print()">
<?= htmlspecialchars($translations['btn_imprimer_facture']) ?>
</button>
</div>
</div>
<div class="card-footer">
<div>
<?= htmlspecialchars($translations['facture_note'] ?? 'Merci pour votre paiement. Conservez ce reçu pour vos archives.') ?>
</div>
</div>
</div>
<div class="page-footer">
© <?= date('Y') ?> УСЛУГИ.ФР — <?= htmlspecialchars($translations['merci'] ?? 'Спасибо.') ?>
</div>
</div>
</body>
</html>