menu compteGF et compteJFG full operationnel

This commit is contained in:
2026-07-02 15:03:26 +00:00
parent 236ae4ab8c
commit 33a23d0392
8 changed files with 1148 additions and 4 deletions
+257
View File
@@ -0,0 +1,257 @@
body.comptegf-page {
--comptegf-header-height: 76px;
--comptegf-titlebar-height: 80px;
--comptegf-form-height: 260px;
--comptegf-footer-height: 64px;
background: #070a12;
color: var(--text-primary);
}
.comptegf-page {
display: flex;
min-height: 100vh;
}
.comptegf-shell {
width: 100%;
padding: 1rem;
background: transparent;
}
.comptegf-container {
max-width: 1200px;
margin: 0 auto;
display: flex;
flex-direction: column;
gap: 1rem;
}
.comptegf-header {
display: flex;
justify-content: space-between;
align-items: center;
gap: 1rem;
}
.comptegf-title {
margin: 0;
font-size: 1.8rem;
color: var(--text-primary);
}
.comptegf-button {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0.75rem 1rem;
color: #fff;
background: var(--accent-color);
border-radius: 0.75rem;
text-decoration: none;
transition: background 0.2s ease;
}
.comptegf-button:hover {
background: #1d4ed8;
}
.comptegf-panel,
.comptegf-card {
background: rgba(12, 18, 34, 0.96);
border: 1px solid rgba(84, 138, 255, 0.18);
border-radius: 1rem;
box-shadow: 0 18px 40px rgba(0, 0, 0, 0.18);
padding: 1.25rem;
}
.comptegf-form-row {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 1rem;
align-items: flex-end;
}
.comptegf-form-row label {
display: flex;
flex-direction: column;
gap: 0.5rem;
color: #d3e1ff;
font-size: 0.95rem;
}
.comptegf-form-row input {
width: 100%;
min-height: 2.25rem;
padding: 0.65rem 0.85rem;
border: 1px solid rgba(96, 156, 255, 0.18);
border-radius: 0.75rem;
background: rgba(15, 22, 41, 0.98);
font-size: 0.97rem;
color: #edf2ff;
}
.comptegf-form-row input:focus {
border-color: rgba(89, 151, 255, 0.65);
outline: none;
box-shadow: 0 0 0 4px rgba(64, 126, 255, 0.14);
}
.comptegf-panel-footer {
display: flex;
flex-wrap: wrap;
gap: 0.75rem;
margin-top: 1rem;
}
.btn-action {
border: none;
cursor: pointer;
border-radius: 0.75rem;
padding: 0.6rem 1rem;
min-height: 38px;
font-weight: 600;
font-size: 0.95rem;
transition: transform 0.2s ease, background-color 0.2s ease, box-shadow 0.2s ease;
background-color: rgba(37, 99, 235, 0.16);
color: #edf2ff;
}
.btn-action:hover {
transform: translateY(-1px);
}
.btn-primary {
background-color: #2563eb;
color: white;
}
.btn-edit {
background-color: #2563eb;
color: white;
}
.btn-cancel {
background-color: rgba(255, 255, 255, 0.08);
color: #edf2ff;
border: 1px solid rgba(255, 255, 255, 0.12);
}
.table-container {
overflow: hidden;
}
.comptegf-table-wrapper {
overflow-x: auto;
}
.comptegf-table {
width: 100%;
border-collapse: collapse;
min-width: 800px;
}
.comptegf-table th,
.comptegf-table td {
padding: 0.75rem 0.85rem;
text-align: left;
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
.comptegf-table th {
background: rgba(255, 255, 255, 0.04);
color: var(--text-secondary);
font-size: 0.95rem;
text-align: center;
}
.comptegf-table tr.totals-row th,
.comptegf-table tr.totals-row td {
background: rgba(37, 99, 235, 0.12);
color: #edf2ff;
font-weight: 700;
}
.comptegf-table tr.totals-row th.totals-label {
text-align: left;
}
.comptegf-table td.numeric-cell {
text-align: right;
}
.comptegf-table .totals-value {
text-align: right;
}
.comptegf-table tbody td:nth-child(1) {
width: 17%;
}
.comptegf-table tbody td:nth-child(2) {
width: 50%;
}
.comptegf-table tbody td:nth-child(3),
.comptegf-table tbody td:nth-child(4),
.comptegf-table tbody td:nth-child(5) {
width: 11%;
}
.comptegf-table tr:hover {
background: rgba(255, 255, 255, 0.06);
}
.form-error {
margin-top: 1rem;
padding: 0.75rem 1rem;
border-radius: 0.75rem;
background: rgba(248, 113, 113, 0.12);
color: #f8c0c0;
border: 1px solid rgba(248, 113, 113, 0.24);
}
.action-notice {
padding: 1rem 1.25rem;
border-radius: 1rem;
margin-bottom: 1rem;
}
body.comptegf-page .form-error,
body.comptegf-page .action-notice {
background: rgba(255, 255, 255, 0.05);
border-color: rgba(255, 255, 255, 0.1);
color: var(--text-primary);
}
.action-success {
background: rgba(16, 185, 129, 0.14);
border: 1px solid rgba(16, 185, 129, 0.24);
color: #a7f3d0;
}
.action-error {
background: rgba(248, 113, 113, 0.14);
border: 1px solid rgba(248, 113, 113, 0.24);
color: #fecaca;
}
@media (max-width: 1024px) {
.comptegf-form-row {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (max-width: 640px) {
.comptegf-form-row {
grid-template-columns: 1fr;
}
.comptegf-header {
flex-direction: column;
align-items: stretch;
}
.comptegf-button {
width: 100%;
}
}
+258
View File
@@ -0,0 +1,258 @@
/* Duplicate of compteGF dark styles but for compteJFG */
body.comptejfg-page {
--comptegf-header-height: 76px;
--comptegf-titlebar-height: 80px;
--comptegf-form-height: 260px;
--comptegf-footer-height: 64px;
background: #070a12;
color: var(--text-primary);
}
.comptejfg-page {
display: flex;
min-height: 100vh;
}
.comptegf-shell {
width: 100%;
padding: 1rem;
background: transparent;
}
.comptegf-container {
max-width: 1200px;
margin: 0 auto;
display: flex;
flex-direction: column;
gap: 1rem;
}
.comptegf-header {
display: flex;
justify-content: space-between;
align-items: center;
gap: 1rem;
}
.comptegf-title {
margin: 0;
font-size: 1.8rem;
color: var(--text-primary);
}
.comptegf-button {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0.75rem 1rem;
color: #fff;
background: var(--accent-color);
border-radius: 0.75rem;
text-decoration: none;
transition: background 0.2s ease;
}
.comptegf-button:hover {
background: #1d4ed8;
}
.comptegf-panel,
.comptegf-card {
background: rgba(12, 18, 34, 0.96);
border: 1px solid rgba(84, 138, 255, 0.18);
border-radius: 1rem;
box-shadow: 0 18px 40px rgba(0, 0, 0, 0.18);
padding: 1.25rem;
}
.comptegf-form-row {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 1rem;
align-items: flex-end;
}
.comptegf-form-row label {
display: flex;
flex-direction: column;
gap: 0.5rem;
color: #d3e1ff;
font-size: 0.95rem;
}
.comptegf-form-row input {
width: 100%;
min-height: 2.25rem;
padding: 0.65rem 0.85rem;
border: 1px solid rgba(96, 156, 255, 0.18);
border-radius: 0.75rem;
background: rgba(15, 22, 41, 0.98);
font-size: 0.97rem;
color: #edf2ff;
}
.comptegf-form-row input:focus {
border-color: rgba(89, 151, 255, 0.65);
outline: none;
box-shadow: 0 0 0 4px rgba(64, 126, 255, 0.14);
}
.comptegf-panel-footer {
display: flex;
flex-wrap: wrap;
gap: 0.75rem;
margin-top: 1rem;
}
.btn-action {
border: none;
cursor: pointer;
border-radius: 0.75rem;
padding: 0.6rem 1rem;
min-height: 38px;
font-weight: 600;
font-size: 0.95rem;
transition: transform 0.2s ease, background-color 0.2s ease, box-shadow 0.2s ease;
background-color: rgba(37, 99, 235, 0.16);
color: #edf2ff;
}
.btn-action:hover {
transform: translateY(-1px);
}
.btn-primary {
background-color: #2563eb;
color: white;
}
.btn-edit {
background-color: #2563eb;
color: white;
}
.btn-cancel {
background-color: rgba(255, 255, 255, 0.08);
color: #edf2ff;
border: 1px solid rgba(255, 255, 255, 0.12);
}
.table-container {
overflow: hidden;
}
.comptegf-table-wrapper {
overflow-x: auto;
}
.comptegf-table {
width: 100%;
border-collapse: collapse;
min-width: 800px;
}
.comptegf-table th,
.comptegf-table td {
padding: 0.75rem 0.85rem;
text-align: left;
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
.comptegf-table th {
background: rgba(255, 255, 255, 0.04);
color: var(--text-secondary);
font-size: 0.95rem;
text-align: center;
}
.comptegf-table tr.totals-row th,
.comptegf-table tr.totals-row td {
background: rgba(37, 99, 235, 0.12);
color: #edf2ff;
font-weight: 700;
}
.comptegf-table tr.totals-row th.totals-label {
text-align: left;
}
.comptegf-table td.numeric-cell {
text-align: right;
}
.comptegf-table .totals-value {
text-align: right;
}
.comptegf-table tbody td:nth-child(1) {
width: 17%;
}
.comptegf-table tbody td:nth-child(2) {
width: 50%;
}
.comptegf-table tbody td:nth-child(3),
.comptegf-table tbody td:nth-child(4),
.comptegf-table tbody td:nth-child(5) {
width: 11%;
}
.comptegf-table tr:hover {
background: rgba(255, 255, 255, 0.06);
}
.form-error {
margin-top: 1rem;
padding: 0.75rem 1rem;
border-radius: 0.75rem;
background: rgba(248, 113, 113, 0.12);
color: #f8c0c0;
border: 1px solid rgba(248, 113, 113, 0.24);
}
.action-notice {
padding: 1rem 1.25rem;
border-radius: 1rem;
margin-bottom: 1rem;
}
body.comptejfg-page .form-error,
body.comptejfg-page .action-notice {
background: rgba(255, 255, 255, 0.05);
border-color: rgba(255, 255, 255, 0.1);
color: var(--text-primary);
}
.action-success {
background: rgba(16, 185, 129, 0.14);
border: 1px solid rgba(16, 185, 129, 0.24);
color: #a7f3d0;
}
.action-error {
background: rgba(248, 113, 113, 0.14);
border: 1px solid rgba(248, 113, 113, 0.24);
color: #fecaca;
}
@media (max-width: 1024px) {
.comptegf-form-row {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (max-width: 640px) {
.comptegf-form-row {
grid-template-columns: 1fr;
}
.comptegf-header {
flex-direction: column;
align-items: stretch;
}
.comptegf-button {
width: 100%;
}
}
+73
View File
@@ -0,0 +1,73 @@
document.addEventListener('DOMContentLoaded', () => {
const compteForm = document.getElementById('comptegf-form');
const compteIdInput = document.querySelector('input[name="comptegf_id"]');
const dateInput = document.getElementById('comptegf-date_operation');
const debitInput = document.getElementById('comptegf-debit');
const creditInput = document.getElementById('comptegf-credit');
const libelleInput = document.getElementById('comptegf-libelle');
const feedbackMessage = document.getElementById('comptegf-form-feedback');
const createButton = document.querySelector('.create-button');
const updateButton = document.querySelector('.update-button');
const cancelEditButton = document.querySelector('.cancel-edit-button');
const panel = document.querySelector('.comptegf-panel');
const editButtons = document.querySelectorAll('.edit-comptegf-button');
const setFeedback = (message) => {
if (!feedbackMessage) {
return;
}
feedbackMessage.textContent = message;
feedbackMessage.style.display = message ? 'block' : 'none';
};
const resetFormMode = () => {
if (!compteForm) {
return;
}
compteForm.reset();
compteIdInput.value = '';
createButton.removeAttribute('disabled');
createButton.hidden = false;
updateButton.hidden = true;
cancelEditButton.hidden = true;
dateInput.removeAttribute('readonly');
setFeedback('');
panel.classList.remove('edit-mode');
};
const setEditMode = (row) => {
const id = row.dataset.id || '';
const dateOperation = row.dataset.date_operation || '';
const debit = row.dataset.debit || '0.00';
const credit = row.dataset.credit || '0.00';
const libelle = row.dataset.libelle || '';
compteIdInput.value = id;
dateInput.value = dateOperation;
debitInput.value = debit;
creditInput.value = credit;
libelleInput.value = libelle;
createButton.setAttribute('disabled', 'disabled');
createButton.hidden = true;
updateButton.hidden = false;
cancelEditButton.hidden = false;
panel.classList.add('edit-mode');
setFeedback('Mode édition activé. Modifiez puis enregistrez.');
};
editButtons.forEach((button) => {
button.addEventListener('click', () => {
const row = button.closest('tr');
if (!row) {
return;
}
setEditMode(row);
libelleInput.focus();
});
});
cancelEditButton.addEventListener('click', resetFormMode);
resetFormMode();
});
+74
View File
@@ -0,0 +1,74 @@
document.addEventListener('DOMContentLoaded', () => {
const compteForm = document.getElementById('comptejfg-form');
const compteIdInput = document.querySelector('input[name="comptejfg_id"]');
const dateInput = document.getElementById('comptejfg-date_operation');
const debitInput = document.getElementById('comptejfg-debit');
const creditInput = document.getElementById('comptejfg-credit');
const libelleInput = document.getElementById('comptejfg-libelle');
const feedbackMessage = document.getElementById('comptejfg-form-feedback');
const createButton = document.querySelector('.create-button');
const updateButton = document.querySelector('.update-button');
const cancelEditButton = document.querySelector('.cancel-edit-button');
const panel = document.querySelector('.comptegf-panel');
const editButtons = document.querySelectorAll('.edit-comptejfg-button');
const setFeedback = (message) => {
if (!feedbackMessage) {
return;
}
feedbackMessage.textContent = message;
feedbackMessage.style.display = message ? 'block' : 'none';
};
const resetFormMode = () => {
if (!compteForm) {
return;
}
compteForm.reset();
compteIdInput.value = '';
createButton.removeAttribute('disabled');
createButton.hidden = false;
updateButton.hidden = true;
cancelEditButton.hidden = true;
dateInput.removeAttribute('readonly');
setFeedback('');
panel.classList.remove('edit-mode');
};
const setEditMode = (row) => {
const id = row.dataset.id || '';
const dateOperation = row.dataset.date_operation || '';
const debit = row.dataset.debit || '0.00';
const credit = row.dataset.credit || '0.00';
const libelle = row.dataset.libelle || '';
compteIdInput.value = id;
dateInput.value = dateOperation;
debitInput.value = debit;
creditInput.value = credit;
libelleInput.value = libelle;
createButton.setAttribute('disabled', 'disabled');
createButton.hidden = true;
updateButton.hidden = false;
cancelEditButton.hidden = false;
dateInput.setAttribute('readonly', 'readonly');
panel.classList.add('edit-mode');
setFeedback('Mode édition activé. Modifiez puis enregistrez.');
};
editButtons.forEach((button) => {
button.addEventListener('click', () => {
const row = button.closest('tr');
if (!row) {
return;
}
setEditMode(row);
libelleInput.focus();
});
});
cancelEditButton.addEventListener('click', resetFormMode);
resetFormMode();
});
+179
View File
@@ -0,0 +1,179 @@
<?php
declare(strict_types=1);
require_once __DIR__ . '/session.php';
require_once __DIR__ . '/db.php';
// Redirection si l'utilisateur n'est pas authentifié.
if (empty($_SESSION['user_id'])) {
header('Location: ../index.php');
exit;
}
$pageStylesheets = ['/css/compteGF.css'];
$bodyClass = 'comptegf-page';
$database = new App\Database\Database();
$compteGFManager = new App\Database\CompteGFManager($database);
$creationMessage = null;
$creationError = null;
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['comptegf_create'])) {
$newEntry = [
'date_operation' => trim($_POST['date_operation'] ?? ''),
'debit' => trim($_POST['debit'] ?? '0.00'),
'credit' => trim($_POST['credit'] ?? '0.00'),
'libelle' => trim($_POST['libelle'] ?? ''),
];
if ($newEntry['date_operation'] === '' || $newEntry['libelle'] === '') {
$creationError = 'Veuillez remplir la date et le libellé.';
} else {
if ($compteGFManager->createCompteGF($newEntry)) {
$creationMessage = 'Nouvelle écriture ajoutée avec succès.';
} else {
$creationError = 'Impossible dajouter l’écriture, veuillez réessayer.';
}
}
}
$updateMessage = null;
$updateError = null;
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['comptegf_update'], $_POST['comptegf_id'])) {
$entryId = (int) $_POST['comptegf_id'];
$updateData = [
'date_operation' => trim($_POST['date_operation'] ?? ''),
'debit' => trim($_POST['debit'] ?? '0.00'),
'credit' => trim($_POST['credit'] ?? '0.00'),
'libelle' => trim($_POST['libelle'] ?? ''),
];
if ($entryId <= 0 || $updateData['date_operation'] === '' || $updateData['libelle'] === '') {
$updateError = 'Tous les champs requis doivent être remplis pour mettre à jour cette écriture.';
} else {
if ($compteGFManager->updateCompteGF($entryId, $updateData)) {
$updateMessage = 'Écriture mise à jour avec succès.';
} else {
$updateError = 'Impossible de mettre à jour l’écriture. Vérifiez les données et réessayez.';
}
}
}
$entries = $compteGFManager->listCompteGF();
$totalCredit = 0.0;
$totalDebit = 0.0;
foreach ($entries as $entry) {
$totalCredit += (float) $entry['credit'];
$totalDebit += (float) $entry['debit'];
}
require_once __DIR__ . '/header.php';
?>
<section class="comptegf-shell">
<div class="comptegf-container">
<div class="comptegf-header">
<h1 class="comptegf-title">Compte GF</h1>
<a href="/php/menu.php" class="comptegf-button">Retour au menu</a>
</div>
<?php if ($creationMessage): ?>
<div class="comptegf-card action-notice action-success"><?= htmlspecialchars($creationMessage, ENT_QUOTES, 'UTF-8') ?></div>
<?php endif; ?>
<?php if ($creationError): ?>
<div class="comptegf-card action-notice action-error"><?= htmlspecialchars($creationError, ENT_QUOTES, 'UTF-8') ?></div>
<?php endif; ?>
<?php if ($updateMessage): ?>
<div class="comptegf-card action-notice action-success"><?= htmlspecialchars($updateMessage, ENT_QUOTES, 'UTF-8') ?></div>
<?php endif; ?>
<?php if ($updateError): ?>
<div class="comptegf-card action-notice action-error"><?= htmlspecialchars($updateError, ENT_QUOTES, 'UTF-8') ?></div>
<?php endif; ?>
<section class="comptegf-panel" id="formulaire-creation">
<form id="comptegf-form" method="post" action="" autocomplete="off">
<input type="hidden" name="comptegf_id" value="">
<div class="comptegf-form-row">
<label class="field-date_operation">
Date opération
<input id="comptegf-date_operation" type="date" name="date_operation" required>
</label>
<label class="field-libelle">
Libellé
<input id="comptegf-libelle" type="text" name="libelle" placeholder="Description" required>
</label>
<label class="field-credit">
Crédit
<input id="comptegf-credit" type="number" name="credit" step="0.01" min="0" value="0.00" required>
</label>
<label class="field-debit">
Débit
<input id="comptegf-debit" type="number" name="debit" step="0.01" min="0" value="0.00" required>
</label>
</div>
<div id="comptegf-form-feedback" class="form-error" aria-live="polite" style="display:none;"></div>
<div class="comptegf-panel-footer">
<button type="submit" name="comptegf_create" class="btn-action btn-primary create-button">Créer une écriture</button>
<button type="submit" name="comptegf_update" class="btn-action btn-primary update-button" hidden>Modifier l'écriture</button>
<button type="button" class="btn-action btn-cancel cancel-edit-button" hidden>Annuler</button>
</div>
</form>
</section>
<section class="comptegf-card table-container">
<div class="comptegf-table-wrapper">
<table class="comptegf-table">
<thead>
<tr class="totals-row">
<th colspan="2" class="totals-label">Totaux :</th>
<th class="numeric-cell totals-value"><?= htmlspecialchars(number_format($totalCredit, 2, ',', ' '), ENT_QUOTES, 'UTF-8') ?></th>
<th class="numeric-cell totals-value"><?= htmlspecialchars(number_format($totalDebit, 2, ',', ' '), ENT_QUOTES, 'UTF-8') ?></th>
<th class="numeric-cell totals-value"><?= htmlspecialchars(number_format($totalCredit - $totalDebit, 2, ',', ' '), ENT_QUOTES, 'UTF-8') ?></th>
</tr>
<tr>
<th>Date opération</th>
<th>Libellé</th>
<th>Crédit</th>
<th>Débit</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($entries as $entry): ?>
<?php
$formattedDate = $entry['date_operation'];
if (!empty($entry['date_operation'])) {
$dateTime = DateTime::createFromFormat('Y-m-d', $entry['date_operation']);
if ($dateTime !== false) {
$formattedDate = $dateTime->format('d/m/Y');
}
}
?>
<tr class="comptegf-row"
data-id="<?= htmlspecialchars((string) $entry['id'], ENT_QUOTES, 'UTF-8') ?>"
data-date_operation="<?= htmlspecialchars((string) $entry['date_operation'], ENT_QUOTES, 'UTF-8') ?>"
data-debit="<?= htmlspecialchars((string) $entry['debit'], ENT_QUOTES, 'UTF-8') ?>"
data-credit="<?= htmlspecialchars((string) $entry['credit'], ENT_QUOTES, 'UTF-8') ?>"
data-libelle="<?= htmlspecialchars((string) $entry['libelle'], ENT_QUOTES, 'UTF-8') ?>"
>
<td><?= htmlspecialchars((string) $formattedDate, ENT_QUOTES, 'UTF-8') ?></td>
<td><?= htmlspecialchars((string) $entry['libelle'], ENT_QUOTES, 'UTF-8') ?></td>
<td class="numeric-cell"><?= htmlspecialchars((string) $entry['credit'], ENT_QUOTES, 'UTF-8') ?></td>
<td class="numeric-cell"><?= htmlspecialchars((string) $entry['debit'], ENT_QUOTES, 'UTF-8') ?></td>
<td>
<button type="button" class="btn-action btn-edit edit-comptegf-button">Modifier</button>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</section>
</div>
</section>
<script src="/js/compteGF.js" defer></script>
<?php require_once __DIR__ . '/footer.php';
+179
View File
@@ -0,0 +1,179 @@
<?php
declare(strict_types=1);
require_once __DIR__ . '/session.php';
require_once __DIR__ . '/db.php';
// Redirection si l'utilisateur n'est pas authentifié.
if (empty($_SESSION['user_id'])) {
header('Location: ../index.php');
exit;
}
$pageStylesheets = ['/css/compteJFG.css'];
$bodyClass = 'comptejfg-page';
$database = new App\Database\Database();
$compteJFGManager = new App\Database\CompteJFGManager($database);
$creationMessage = null;
$creationError = null;
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['comptejfg_create'])) {
$newEntry = [
'date_operation' => trim($_POST['date_operation'] ?? ''),
'debit' => trim($_POST['debit'] ?? '0.00'),
'credit' => trim($_POST['credit'] ?? '0.00'),
'libelle' => trim($_POST['libelle'] ?? ''),
];
if ($newEntry['date_operation'] === '' || $newEntry['libelle'] === '') {
$creationError = 'Veuillez remplir la date et le libellé.';
} else {
if ($compteJFGManager->createCompteJFG($newEntry)) {
$creationMessage = 'Nouvelle écriture ajoutée avec succès.';
} else {
$creationError = 'Impossible dajouter l’écriture, veuillez réessayer.';
}
}
}
$updateMessage = null;
$updateError = null;
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['comptejfg_update'], $_POST['comptejfg_id'])) {
$entryId = (int) $_POST['comptejfg_id'];
$updateData = [
'date_operation' => trim($_POST['date_operation'] ?? ''),
'debit' => trim($_POST['debit'] ?? '0.00'),
'credit' => trim($_POST['credit'] ?? '0.00'),
'libelle' => trim($_POST['libelle'] ?? ''),
];
if ($entryId <= 0 || $updateData['date_operation'] === '' || $updateData['libelle'] === '') {
$updateError = 'Tous les champs requis doivent être remplis pour mettre à jour cette écriture.';
} else {
if ($compteJFGManager->updateCompteJFG($entryId, $updateData)) {
$updateMessage = 'Écriture mise à jour avec succès.';
} else {
$updateError = 'Impossible de mettre à jour l’écriture. Vérifiez les données et réessayez.';
}
}
}
$entries = $compteJFGManager->listCompteJFG();
$totalCredit = 0.0;
$totalDebit = 0.0;
foreach ($entries as $entry) {
$totalCredit += (float) $entry['credit'];
$totalDebit += (float) $entry['debit'];
}
require_once __DIR__ . '/header.php';
?>
<section class="comptegf-shell">
<div class="comptegf-container">
<div class="comptegf-header">
<h1 class="comptegf-title">Compte JFG</h1>
<a href="/php/menu.php" class="comptegf-button">Retour au menu</a>
</div>
<?php if ($creationMessage): ?>
<div class="comptegf-card action-notice action-success"><?= htmlspecialchars($creationMessage, ENT_QUOTES, 'UTF-8') ?></div>
<?php endif; ?>
<?php if ($creationError): ?>
<div class="comptegf-card action-notice action-error"><?= htmlspecialchars($creationError, ENT_QUOTES, 'UTF-8') ?></div>
<?php endif; ?>
<?php if ($updateMessage): ?>
<div class="comptegf-card action-notice action-success"><?= htmlspecialchars($updateMessage, ENT_QUOTES, 'UTF-8') ?></div>
<?php endif; ?>
<?php if ($updateError): ?>
<div class="comptegf-card action-notice action-error"><?= htmlspecialchars($updateError, ENT_QUOTES, 'UTF-8') ?></div>
<?php endif; ?>
<section class="comptegf-panel" id="formulaire-creation">
<form id="comptejfg-form" method="post" action="" autocomplete="off">
<input type="hidden" name="comptejfg_id" value="">
<div class="comptegf-form-row">
<label class="field-date_operation">
Date opération
<input id="comptejfg-date_operation" type="date" name="date_operation" required>
</label>
<label class="field-libelle">
Libellé
<input id="comptejfg-libelle" type="text" name="libelle" placeholder="Description" required>
</label>
<label class="field-credit">
Crédit
<input id="comptejfg-credit" type="number" name="credit" step="0.01" min="0" value="0.00" required>
</label>
<label class="field-debit">
Débit
<input id="comptejfg-debit" type="number" name="debit" step="0.01" min="0" value="0.00" required>
</label>
</div>
<div id="comptejfg-form-feedback" class="form-error" aria-live="polite" style="display:none;"></div>
<div class="comptegf-panel-footer">
<button type="submit" name="comptejfg_create" class="btn-action btn-primary create-button">Créer une écriture</button>
<button type="submit" name="comptejfg_update" class="btn-action btn-primary update-button" hidden>Modifier l'écriture</button>
<button type="button" class="btn-action btn-cancel cancel-edit-button" hidden>Annuler</button>
</div>
</form>
</section>
<section class="comptegf-card table-container">
<div class="comptegf-table-wrapper">
<table class="comptegf-table">
<thead>
<tr class="totals-row">
<th colspan="2" class="totals-label">Totaux :</th>
<th class="numeric-cell totals-value"><?= htmlspecialchars(number_format($totalCredit, 2, ',', ' '), ENT_QUOTES, 'UTF-8') ?></th>
<th class="numeric-cell totals-value"><?= htmlspecialchars(number_format($totalDebit, 2, ',', ' '), ENT_QUOTES, 'UTF-8') ?></th>
<th class="numeric-cell totals-value"><?= htmlspecialchars(number_format($totalCredit - $totalDebit, 2, ',', ' '), ENT_QUOTES, 'UTF-8') ?></th>
</tr>
<tr>
<th>Date opération</th>
<th>Libellé</th>
<th>Crédit</th>
<th>Débit</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($entries as $entry): ?>
<?php
$formattedDate = $entry['date_operation'];
if (!empty($entry['date_operation'])) {
$dateTime = DateTime::createFromFormat('Y-m-d', $entry['date_operation']);
if ($dateTime !== false) {
$formattedDate = $dateTime->format('d/m/Y');
}
}
?>
<tr class="comptegf-row"
data-id="<?= htmlspecialchars((string) $entry['id'], ENT_QUOTES, 'UTF-8') ?>"
data-date_operation="<?= htmlspecialchars((string) $entry['date_operation'], ENT_QUOTES, 'UTF-8') ?>"
data-debit="<?= htmlspecialchars((string) $entry['debit'], ENT_QUOTES, 'UTF-8') ?>"
data-credit="<?= htmlspecialchars((string) $entry['credit'], ENT_QUOTES, 'UTF-8') ?>"
data-libelle="<?= htmlspecialchars((string) $entry['libelle'], ENT_QUOTES, 'UTF-8') ?>"
>
<td><?= htmlspecialchars((string) $formattedDate, ENT_QUOTES, 'UTF-8') ?></td>
<td><?= htmlspecialchars((string) $entry['libelle'], ENT_QUOTES, 'UTF-8') ?></td>
<td class="numeric-cell"><?= htmlspecialchars((string) $entry['credit'], ENT_QUOTES, 'UTF-8') ?></td>
<td class="numeric-cell"><?= htmlspecialchars((string) $entry['debit'], ENT_QUOTES, 'UTF-8') ?></td>
<td>
<button type="button" class="btn-action btn-edit edit-comptejfg-button">Modifier</button>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</section>
</div>
</section>
<script src="/js/compteJFG.js" defer></script>
<?php require_once __DIR__ . '/footer.php';
+124
View File
@@ -71,6 +71,68 @@ class Database
}
}
/**
* Class CompteJFGManager
*
* Opérations CRUD sur la table `compteJFG`.
*/
class CompteJFGManager
{
private PDO $connection;
public function __construct(Database $database)
{
$this->connection = $database->getConnection();
}
public function listCompteJFG(): array
{
$statement = $this->connection->query(
'SELECT id, date_operation, debit, credit, libelle, updated_at
FROM compteJFG
ORDER BY date_operation DESC, id DESC'
);
return $statement->fetchAll();
}
public function createCompteJFG(array $data): bool
{
$statement = $this->connection->prepare(
'INSERT INTO compteJFG (date_operation, debit, credit, libelle, created_at, updated_at)
VALUES (:date_operation, :debit, :credit, :libelle, NOW(), NOW())'
);
$statement->bindValue(':date_operation', $data['date_operation'], PDO::PARAM_STR);
$statement->bindValue(':debit', $data['debit'], PDO::PARAM_STR);
$statement->bindValue(':credit', $data['credit'], PDO::PARAM_STR);
$statement->bindValue(':libelle', $data['libelle'], PDO::PARAM_STR);
return $statement->execute();
}
public function updateCompteJFG(int $id, array $data): bool
{
$statement = $this->connection->prepare(
'UPDATE compteJFG
SET date_operation = :date_operation,
debit = :debit,
credit = :credit,
libelle = :libelle,
updated_at = NOW()
WHERE id = :id'
);
$statement->bindValue(':date_operation', $data['date_operation'], PDO::PARAM_STR);
$statement->bindValue(':debit', $data['debit'], PDO::PARAM_STR);
$statement->bindValue(':credit', $data['credit'], PDO::PARAM_STR);
$statement->bindValue(':libelle', $data['libelle'], PDO::PARAM_STR);
$statement->bindValue(':id', $id, PDO::PARAM_INT);
return $statement->execute();
}
}
/**
* Class LoginManager
*
@@ -507,3 +569,65 @@ class ActionsManager
return $statement->execute();
}
}
/**
* Class CompteGFManager
*
* Opérations CRUD sur la table `compteGF`.
*/
class CompteGFManager
{
private PDO $connection;
public function __construct(Database $database)
{
$this->connection = $database->getConnection();
}
public function listCompteGF(): array
{
$statement = $this->connection->query(
'SELECT id, date_operation, debit, credit, libelle, updated_at
FROM compteGF
ORDER BY date_operation DESC, id DESC'
);
return $statement->fetchAll();
}
public function createCompteGF(array $data): bool
{
$statement = $this->connection->prepare(
'INSERT INTO compteGF (date_operation, debit, credit, libelle, created_at, updated_at)
VALUES (:date_operation, :debit, :credit, :libelle, NOW(), NOW())'
);
$statement->bindValue(':date_operation', $data['date_operation'], PDO::PARAM_STR);
$statement->bindValue(':debit', $data['debit'], PDO::PARAM_STR);
$statement->bindValue(':credit', $data['credit'], PDO::PARAM_STR);
$statement->bindValue(':libelle', $data['libelle'], PDO::PARAM_STR);
return $statement->execute();
}
public function updateCompteGF(int $id, array $data): bool
{
$statement = $this->connection->prepare(
'UPDATE compteGF
SET date_operation = :date_operation,
debit = :debit,
credit = :credit,
libelle = :libelle,
updated_at = NOW()
WHERE id = :id'
);
$statement->bindValue(':date_operation', $data['date_operation'], PDO::PARAM_STR);
$statement->bindValue(':debit', $data['debit'], PDO::PARAM_STR);
$statement->bindValue(':credit', $data['credit'], PDO::PARAM_STR);
$statement->bindValue(':libelle', $data['libelle'], PDO::PARAM_STR);
$statement->bindValue(':id', $id, PDO::PARAM_INT);
return $statement->execute();
}
}
+4 -4
View File
@@ -41,10 +41,10 @@ require_once __DIR__ . '/header.php';
<span class="menu-button__title">Ordre JFG</span>
<span class="menu-button__text">Voir et modifier les ordres JFG</span>
</div>
<span class="menu-button__icon"></span>
<span class="menu-button__icon"></span>
</button>
<button type="button" class="menu-button" data-target="/php/account_gf.php">
<button type="button" class="menu-button" data-target="/php/compteGF.php">
<div class="menu-button__content">
<span class="menu-button__title">Compte GF</span>
<span class="menu-button__text">Voir et modifier le compte GF</span>
@@ -52,12 +52,12 @@ require_once __DIR__ . '/header.php';
<span class="menu-button__icon">💼</span>
</button>
<button type="button" class="menu-button" data-target="/php/account_jfg.php">
<button type="button" class="menu-button" data-target="/php/compteJFG.php">
<div class="menu-button__content">
<span class="menu-button__title">Compte JFG</span>
<span class="menu-button__text">Voir et modifier le compte JFG</span>
</div>
<span class="menu-button__icon">📊</span>
<span class="menu-button__icon">💼</span>
</button>
<button type="button" class="menu-button" data-target="/php/actions.php">