diff --git a/loko/contracts/locale/en/LC_MESSAGES/django.mo b/loko/contracts/locale/en/LC_MESSAGES/django.mo index d61ce0c..de1f0d4 100644 Binary files a/loko/contracts/locale/en/LC_MESSAGES/django.mo and b/loko/contracts/locale/en/LC_MESSAGES/django.mo differ diff --git a/loko/contracts/locale/en/LC_MESSAGES/django.po b/loko/contracts/locale/en/LC_MESSAGES/django.po index bd89c9a..6629525 100644 --- a/loko/contracts/locale/en/LC_MESSAGES/django.po +++ b/loko/contracts/locale/en/LC_MESSAGES/django.po @@ -2399,3 +2399,93 @@ msgstr "Map color" msgid "Couleur d'affichage du lot sur la carte (code hexadécimal, ex: #28a745)." msgstr "Display color of the lot on the map (hexadecimal code, e.g. #28a745)." +#: contracts/templates/contracts/contracts_index.html +msgid "Filtrer les commandes et marchés" +msgstr "Filter orders and contracts" + +#: contracts/templates/contracts/contracts_index.html +msgid "Sélectionnez les critères de recherche" +msgstr "Select search criteria" + +#: contracts/templates/contracts/contracts_index.html +msgid "Aucun" +msgstr "None" + +#: contracts/templates/contracts/contracts_index.html +msgid "Marchés" +msgstr "Contracts" + +#: contracts/templates/contracts/contracts_index.html +msgid "Filtrer la liste des marchés..." +msgstr "Filter contract list..." + +#: contracts/templates/contracts/contracts_index.html +msgid "Période de commande" +msgstr "Order period" + +#: contracts/templates/contracts/contracts_index.html +msgid "Rechercher une commande, un marché, une description, un prestataire..." +msgstr "Search order, contract, description, provider..." + +#: contracts/templates/contracts/contracts_index.html +msgid "Effacer la recherche" +msgstr "Clear search" + +#: contracts/templates/contracts/contracts_index.html +msgid "Filtres" +msgstr "Filters" + +#: contracts/templates/contracts/contracts_index.html +msgid "Afficher par" +msgstr "Show by" + +#: contracts/templates/contracts/contracts_index.html +msgid "Filtres actifs" +msgstr "Active filters" + +#: contracts/templates/contracts/contracts_index.html +msgid "Supprimer ce critère" +msgstr "Remove this filter" + +#: contracts/templates/contracts/contracts_index.html +msgid "Tout effacer" +msgstr "Clear all" + +#: contracts/templates/contracts/contracts_index.html +msgid "Télécharger le bon de commande" +msgstr "Download order document" + +#: contracts/templates/contracts/contracts_index.html +msgid "Aucune commande ne correspond à vos critères de recherche actuels." +msgstr "No orders match your current search criteria." + +#: contracts/templates/contracts/contracts_index.html +msgid "Réinitialiser les filtres" +msgstr "Reset filters" + +#: contracts/templates/contracts/contracts_index.html +msgid "Affichage de %(start)s à %(end)s sur %(total)s commande(s)" +msgstr "Showing %(start)s to %(end)s of %(total)s order(s)" + +#: contracts/templates/contracts/contracts_index.html +msgid "Pagination des commandes" +msgstr "Orders pagination" + +#: contracts/templates/contracts/contracts_index.html +msgid "Détail du contrat" +msgstr "Contract details" + +#: contracts/templates/contracts/contracts_index.html +msgid "Aucun marché ne correspond à vos critères de recherche actuels." +msgstr "No contracts match your current search criteria." + +#: contracts/templates/contracts/contracts_index.html +msgid "Affichage de %(start)s à %(end)s sur %(total)s marché(s)" +msgstr "Showing %(start)s to %(end)s of %(total)s contract(s)" + +#: contracts/templates/contracts/contracts_index.html +msgid "Pagination des marchés" +msgstr "Contracts pagination" + + + diff --git a/loko/contracts/locale/fr/LC_MESSAGES/django.mo b/loko/contracts/locale/fr/LC_MESSAGES/django.mo index 4c62d55..751b3c4 100644 Binary files a/loko/contracts/locale/fr/LC_MESSAGES/django.mo and b/loko/contracts/locale/fr/LC_MESSAGES/django.mo differ diff --git a/loko/contracts/locale/fr/LC_MESSAGES/django.po b/loko/contracts/locale/fr/LC_MESSAGES/django.po index 417a16d..d40a097 100644 --- a/loko/contracts/locale/fr/LC_MESSAGES/django.po +++ b/loko/contracts/locale/fr/LC_MESSAGES/django.po @@ -2449,3 +2449,93 @@ msgstr "Couleur cartographique" msgid "Couleur d'affichage du lot sur la carte (code hexadécimal, ex: #28a745)." msgstr "Couleur d'affichage du lot sur la carte (code hexadécimal, ex: #28a745)." +#: contracts/templates/contracts/contracts_index.html +msgid "Filtrer les commandes et marchés" +msgstr "Filtrer les commandes et marchés" + +#: contracts/templates/contracts/contracts_index.html +msgid "Sélectionnez les critères de recherche" +msgstr "Sélectionnez les critères de recherche" + +#: contracts/templates/contracts/contracts_index.html +msgid "Aucun" +msgstr "Aucun" + +#: contracts/templates/contracts/contracts_index.html +msgid "Marchés" +msgstr "Marchés" + +#: contracts/templates/contracts/contracts_index.html +msgid "Filtrer la liste des marchés..." +msgstr "Filtrer la liste des marchés..." + +#: contracts/templates/contracts/contracts_index.html +msgid "Période de commande" +msgstr "Période de commande" + +#: contracts/templates/contracts/contracts_index.html +msgid "Rechercher une commande, un marché, une description, un prestataire..." +msgstr "Rechercher une commande, un marché, une description, un prestataire..." + +#: contracts/templates/contracts/contracts_index.html +msgid "Effacer la recherche" +msgstr "Effacer la recherche" + +#: contracts/templates/contracts/contracts_index.html +msgid "Filtres" +msgstr "Filtres" + +#: contracts/templates/contracts/contracts_index.html +msgid "Afficher par" +msgstr "Afficher par" + +#: contracts/templates/contracts/contracts_index.html +msgid "Filtres actifs" +msgstr "Filtres actifs" + +#: contracts/templates/contracts/contracts_index.html +msgid "Supprimer ce critère" +msgstr "Supprimer ce critère" + +#: contracts/templates/contracts/contracts_index.html +msgid "Tout effacer" +msgstr "Tout effacer" + +#: contracts/templates/contracts/contracts_index.html +msgid "Télécharger le bon de commande" +msgstr "Télécharger le bon de commande" + +#: contracts/templates/contracts/contracts_index.html +msgid "Aucune commande ne correspond à vos critères de recherche actuels." +msgstr "Aucune commande ne correspond à vos critères de recherche actuels." + +#: contracts/templates/contracts/contracts_index.html +msgid "Réinitialiser les filtres" +msgstr "Réinitialiser les filtres" + +#: contracts/templates/contracts/contracts_index.html +msgid "Affichage de %(start)s à %(end)s sur %(total)s commande(s)" +msgstr "Affichage de %(start)s à %(end)s sur %(total)s commande(s)" + +#: contracts/templates/contracts/contracts_index.html +msgid "Pagination des commandes" +msgstr "Pagination des commandes" + +#: contracts/templates/contracts/contracts_index.html +msgid "Détail du contrat" +msgstr "Détail du contrat" + +#: contracts/templates/contracts/contracts_index.html +msgid "Aucun marché ne correspond à vos critères de recherche actuels." +msgstr "Aucun marché ne correspond à vos critères de recherche actuels." + +#: contracts/templates/contracts/contracts_index.html +msgid "Affichage de %(start)s à %(end)s sur %(total)s marché(s)" +msgstr "Affichage de %(start)s à %(end)s sur %(total)s marché(s)" + +#: contracts/templates/contracts/contracts_index.html +msgid "Pagination des marchés" +msgstr "Pagination des marchés" + + + diff --git a/loko/contracts/locale/nl/LC_MESSAGES/django.mo b/loko/contracts/locale/nl/LC_MESSAGES/django.mo index c738f01..0f988eb 100644 Binary files a/loko/contracts/locale/nl/LC_MESSAGES/django.mo and b/loko/contracts/locale/nl/LC_MESSAGES/django.mo differ diff --git a/loko/contracts/locale/nl/LC_MESSAGES/django.po b/loko/contracts/locale/nl/LC_MESSAGES/django.po index 1433fbe..71d80dd 100644 --- a/loko/contracts/locale/nl/LC_MESSAGES/django.po +++ b/loko/contracts/locale/nl/LC_MESSAGES/django.po @@ -2405,3 +2405,93 @@ msgstr "Kaartkleur" msgid "Couleur d'affichage du lot sur la carte (code hexadécimal, ex: #28a745)." msgstr "Weergavekleur van het perceel op de kaart (hexadecimale code, bijv. #28a745)." +#: contracts/templates/contracts/contracts_index.html +msgid "Filtrer les commandes et marchés" +msgstr "Bestellingen en opdrachten filteren" + +#: contracts/templates/contracts/contracts_index.html +msgid "Sélectionnez les critères de recherche" +msgstr "Selecteer de zoekcriteria" + +#: contracts/templates/contracts/contracts_index.html +msgid "Aucun" +msgstr "Geen" + +#: contracts/templates/contracts/contracts_index.html +msgid "Marchés" +msgstr "Opdrachten" + +#: contracts/templates/contracts/contracts_index.html +msgid "Filtrer la liste des marchés..." +msgstr "Lijst met opdrachten filteren..." + +#: contracts/templates/contracts/contracts_index.html +msgid "Période de commande" +msgstr "Bestelperiode" + +#: contracts/templates/contracts/contracts_index.html +msgid "Rechercher une commande, un marché, une description, un prestataire..." +msgstr "Zoeken op bestelnummer, opdracht, omschrijving, dienstverlener..." + +#: contracts/templates/contracts/contracts_index.html +msgid "Effacer la recherche" +msgstr "Zoekopdracht wissen" + +#: contracts/templates/contracts/contracts_index.html +msgid "Filtres" +msgstr "Filters" + +#: contracts/templates/contracts/contracts_index.html +msgid "Afficher par" +msgstr "Weergeven per" + +#: contracts/templates/contracts/contracts_index.html +msgid "Filtres actifs" +msgstr "Actieve filters" + +#: contracts/templates/contracts/contracts_index.html +msgid "Supprimer ce critère" +msgstr "Dit criterium verwijderen" + +#: contracts/templates/contracts/contracts_index.html +msgid "Tout effacer" +msgstr "Alles wissen" + +#: contracts/templates/contracts/contracts_index.html +msgid "Télécharger le bon de commande" +msgstr "Bestelbon downloaden" + +#: contracts/templates/contracts/contracts_index.html +msgid "Aucune commande ne correspond à vos critères de recherche actuels." +msgstr "Geen enkele bestelling voldoet aan de huidige zoekcriteria." + +#: contracts/templates/contracts/contracts_index.html +msgid "Réinitialiser les filtres" +msgstr "Filters opnieuw instellen" + +#: contracts/templates/contracts/contracts_index.html +msgid "Affichage de %(start)s à %(end)s sur %(total)s commande(s)" +msgstr "Weergave van %(start)s tot %(end)s van %(total)s bestelling(en)" + +#: contracts/templates/contracts/contracts_index.html +msgid "Pagination des commandes" +msgstr "Paginering van bestellingen" + +#: contracts/templates/contracts/contracts_index.html +msgid "Détail du contrat" +msgstr "Contractdetail" + +#: contracts/templates/contracts/contracts_index.html +msgid "Aucun marché ne correspond à vos critères de recherche actuels." +msgstr "Geen enkele opdracht voldoet aan de huidige zoekcriteria." + +#: contracts/templates/contracts/contracts_index.html +msgid "Affichage de %(start)s à %(end)s sur %(total)s marché(s)" +msgstr "Weergave van %(start)s tot %(end)s van %(total)s opdracht(en)" + +#: contracts/templates/contracts/contracts_index.html +msgid "Pagination des marchés" +msgstr "Paginering van opdrachten" + + + diff --git a/loko/contracts/static/contracts/css/contracts_index.css b/loko/contracts/static/contracts/css/contracts_index.css new file mode 100644 index 0000000..0c29e8c --- /dev/null +++ b/loko/contracts/static/contracts/css/contracts_index.css @@ -0,0 +1,831 @@ +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@500;600&display=swap'); + +/* Main Page Container */ +.contracts-page-container { + max-width: 1440px; + margin: 1.5rem auto 3rem auto; + padding: 0 1.25rem; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; +} + +/* Page Header */ +.contracts-header { + display: flex; + justify-content: space-between; + align-items: center; + flex-wrap: wrap; + gap: 1rem; + margin-bottom: 1.25rem; +} + +.contracts-tabs { + border-bottom: 2px solid #e2e8f0; + margin-bottom: 0; +} + +.contracts-tabs .nav-link { + font-size: 0.95rem; + font-weight: 600; + color: #64748b; + border: none; + border-bottom: 2px solid transparent; + margin-bottom: -2px; + padding: 0.65rem 1.25rem; + background: transparent; + transition: all 0.15s ease; + display: inline-flex; + align-items: center; + gap: 0.5rem; +} + +.contracts-tabs .nav-link:hover { + color: #0f172a; + border-color: #cbd5e1; +} + +.contracts-tabs .nav-link.active { + color: #0f172a; + border-bottom-color: #0f172a; + background: transparent; +} + +.tab-counter-badge { + font-size: 0.75rem; + font-weight: 600; + padding: 2px 7px; + border-radius: 9999px; + background-color: #f1f5f9; + color: #475569; + border: 1px solid #e2e8f0; +} + +.contracts-tabs .nav-link.active .tab-counter-badge { + background-color: #0f172a; + color: #ffffff; + border-color: #0f172a; +} + +/* Primary Action Button */ +.btn-new-order { + background-color: #0f172a; + color: #ffffff; + border: 1px solid #0f172a; + border-radius: 9px; + padding: 0.5rem 1rem; + font-size: 0.88rem; + font-weight: 600; + display: inline-flex; + align-items: center; + gap: 0.5rem; + transition: all 0.15s ease; + text-decoration: none; + box-shadow: 0 1px 2px rgba(15, 23, 42, 0.08); +} + +.btn-new-order:hover { + background-color: #1e293b; + color: #ffffff; + border-color: #1e293b; + transform: translateY(-1px); + box-shadow: 0 4px 6px -1px rgba(15, 23, 42, 0.12); +} + +/* Toolbar: Search, Filters & Settings */ +.contracts-toolbar { + background-color: #ffffff; + border: 1px solid #e2e8f0; + border-radius: 12px; + padding: 0.85rem 1.15rem; + margin-bottom: 1rem; + display: flex; + align-items: center; + justify-content: space-between; + flex-wrap: wrap; + gap: 0.85rem; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.02); +} + +.search-widget { + position: relative; + flex: 1 1 360px; + max-width: 550px; +} + +.search-input-wrapper { + position: relative; + display: flex; + align-items: center; + width: 100%; +} + +.search-icon-left { + position: absolute; + left: 0.85rem; + color: #94a3b8; + font-size: 0.95rem; + pointer-events: none; +} + +.search-input { + width: 100%; + padding: 0.5rem 2.25rem 0.5rem 2.35rem; + font-size: 0.88rem; + border: 1.5px solid #e2e8f0; + border-radius: 9999px; + background-color: #f8fafc; + color: #0f172a; + transition: all 0.15s ease; +} + +.search-input:focus { + outline: none; + background-color: #ffffff; + border-color: #2563eb; + box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1); +} + +.search-clear-btn { + position: absolute; + right: 0.75rem; + top: 50%; + transform: translateY(-50%); + background: none; + border: none; + color: #94a3b8; + padding: 2px 4px; + cursor: pointer; + font-size: 0.8rem; + line-height: 1; + display: none; + transition: color 0.15s ease; +} + +.search-clear-btn:hover { + color: #0f172a; +} + +.toolbar-actions { + display: flex; + align-items: center; + gap: 0.65rem; +} + +.filter-trigger-btn { + background-color: #ffffff; + border: 1.5px solid #e2e8f0; + border-radius: 9999px; + padding: 0.45rem 1rem; + font-size: 0.85rem; + font-weight: 600; + color: #334155; + display: inline-flex; + align-items: center; + gap: 0.45rem; + transition: all 0.15s ease; +} + +.filter-trigger-btn:hover { + background-color: #f8fafc; + border-color: #cbd5e1; + color: #0f172a; +} + +.filter-count-badge { + background-color: #0f172a; + color: #ffffff; + font-size: 0.7rem; + font-weight: 700; + border-radius: 9999px; + padding: 1px 6px; + margin-left: 2px; +} + +.page-size-selector { + display: flex; + align-items: center; + gap: 0.4rem; + font-size: 0.82rem; + color: #64748b; +} + +.page-size-select { + padding: 0.35rem 0.65rem; + font-size: 0.82rem; + border: 1.5px solid #e2e8f0; + border-radius: 7px; + background-color: #ffffff; + color: #334155; + cursor: pointer; + font-weight: 500; +} + +.page-size-select:focus { + outline: none; + border-color: #2563eb; +} + +/* Active Filters Pills */ +.active-filters-bar { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 0.5rem; + margin-bottom: 1rem; + padding: 0 0.25rem; +} + +.active-filter-label { + font-size: 0.78rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.04em; + color: #94a3b8; + margin-right: 0.25rem; +} + +.active-filter-chip { + display: inline-flex; + align-items: center; + gap: 0.35rem; + padding: 0.25rem 0.65rem; + font-size: 0.78rem; + font-weight: 500; + border-radius: 9999px; + background-color: #f1f5f9; + border: 1px solid #e2e8f0; + color: #334155; + transition: all 0.12s ease; +} + +.active-filter-chip .remove-filter-btn { + border: none; + background: none; + padding: 0; + margin-left: 2px; + color: #94a3b8; + cursor: pointer; + display: inline-flex; + align-items: center; + font-size: 0.75rem; + line-height: 1; +} + +.active-filter-chip .remove-filter-btn:hover { + color: #dc2626; +} + +.btn-clear-all-filters { + font-size: 0.78rem; + color: #dc2626; + text-decoration: none; + font-weight: 600; + padding: 0.25rem 0.5rem; + border-radius: 6px; + transition: background-color 0.12s ease; +} + +.btn-clear-all-filters:hover { + background-color: #fef2f2; + color: #b91c1c; +} + +/* Table Container & Design */ +.contracts-table-card { + background-color: #ffffff; + border: 1px solid #e2e8f0; + border-radius: 14px; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.03); + overflow: hidden; +} + +.table-responsive { + margin-bottom: 0; +} + +.contracts-table { + width: 100%; + margin-bottom: 0; + border-collapse: separate; + border-spacing: 0; +} + +.contracts-table thead th { + background-color: #f8fafc; + color: #475569; + font-size: 0.74rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.04em; + padding: 0.75rem 1rem; + border-bottom: 1.5px solid #e2e8f0; + vertical-align: middle; + white-space: nowrap; +} + +.contracts-table thead th.sortable { + cursor: pointer; + user-select: none; + transition: background-color 0.12s ease; +} + +.contracts-table thead th.sortable:hover { + background-color: #f1f5f9; + color: #0f172a; +} + +.sort-link { + display: flex; + align-items: center; + justify-content: space-between; + gap: 0.5rem; + text-decoration: none; + color: inherit; +} + +.contracts-table tbody tr { + transition: background-color 0.12s ease; +} + +.contracts-table tbody tr:hover { + background-color: #f8fafc; +} + +.contracts-table tbody td { + padding: 0.65rem 1rem; + font-size: 0.85rem; + color: #334155; + border-bottom: 1px solid #f1f5f9; + vertical-align: middle; +} + +.contracts-table tbody tr:last-child td { + border-bottom: none; +} + +/* Code Link Badge */ +.table-code-link { + font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace !important; + font-size: 0.82rem !important; + font-weight: 600 !important; + color: #0f172a !important; + text-decoration: none !important; + white-space: nowrap !important; + display: inline-block; + padding: 3px 8px; + border-radius: 6px; + background-color: #f8fafc; + border: 1px solid #e2e8f0; + transition: all 0.15s ease; +} + +.table-code-link:hover { + color: #2563eb !important; + border-color: #93c5fd; + background-color: #eff6ff; +} + +/* Table Action Button */ +.table-action-btn { + display: inline-flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + border-radius: 8px; + color: #64748b; + background-color: transparent; + border: 1px solid transparent; + transition: all 0.15s ease; + text-decoration: none; +} + +.table-action-btn:hover { + color: #0f172a; + background-color: #f1f5f9; + border-color: #cbd5e1; +} + +/* Status Badges */ +.status-badge { + font-size: 0.74rem; + font-weight: 600; + padding: 0.32rem 0.7rem; + border-radius: 9999px; + display: inline-flex; + align-items: center; + gap: 0.3rem; + border: 1px solid transparent; + white-space: nowrap; +} + +.status-badge.pending { + background-color: #fffbeb; + color: #b45309; + border-color: #fde68a; +} + +.status-badge.sent { + background-color: #f0f9ff; + color: #0284c7; + border-color: #bae6fd; +} + +.status-badge.completed { + background-color: #f0fdf4; + color: #16a34a; + border-color: #bbf7d0; +} + +.status-badge.invoiced { + background-color: #faf5ff; + color: #7c3aed; + border-color: #e9d5ff; +} + +.status-badge.paid { + background-color: #ecfdf5; + color: #059669; + border-color: #a7f3d0; +} + +.status-badge.cancelled { + background-color: #fef2f2; + color: #dc2626; + border-color: #fecaca; +} + +/* File Icon Link */ +.file-download-btn { + color: #dc2626; + font-size: 1.15rem; + display: inline-flex; + align-items: center; + justify-content: center; + width: 30px; + height: 30px; + border-radius: 6px; + transition: all 0.15s ease; +} + +.file-download-btn:hover { + color: #b91c1c; + background-color: #fef2f2; +} + +/* Empty State */ +.table-empty-state { + padding: 4rem 1.5rem; + text-align: center; + color: #64748b; +} + +.empty-icon { + font-size: 3rem; + color: #cbd5e1; + margin-bottom: 1rem; +} + +.empty-title { + font-size: 1.1rem; + font-weight: 700; + color: #0f172a; + margin-bottom: 0.35rem; +} + +.empty-desc { + font-size: 0.88rem; + max-width: 420px; + margin: 0 auto 1.25rem auto; +} + +/* Pagination Bar */ +.contracts-pagination-bar { + padding: 0.85rem 1.25rem; + background-color: #ffffff; + border-top: 1px solid #f1f5f9; + display: flex; + justify-content: space-between; + align-items: center; + flex-wrap: wrap; + gap: 1rem; +} + +.pagination-info { + font-size: 0.85rem; + color: #64748b; +} + +.pagination-nav .pagination { + margin-bottom: 0; + gap: 3px; +} + +.pagination-nav .page-link { + border-radius: 7px; + border: 1px solid #e2e8f0; + color: #334155; + font-size: 0.82rem; + font-weight: 500; + padding: 0.35rem 0.65rem; + min-width: 32px; + text-align: center; + transition: all 0.15s ease; +} + +.pagination-nav .page-link:hover { + background-color: #f1f5f9; + color: #0f172a; + border-color: #cbd5e1; +} + +.pagination-nav .page-item.active .page-link { + background-color: #0f172a; + border-color: #0f172a; + color: #ffffff; + font-weight: 600; +} + +.pagination-nav .page-item.disabled .page-link { + color: #94a3b8; + background-color: #f8fafc; + border-color: #e2e8f0; +} + +/* ─── Airbnb-style Modern Filter Modal ──────────────────── */ +#filterModal .modal-dialog { + max-width: 820px; + margin: 1.5rem auto; +} + +#filterModal .modal-content { + border: 1px solid #e2e8f0; + border-radius: 18px; + box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25); + display: flex; + flex-direction: column; + max-height: 88vh; + overflow: hidden; + background-color: #ffffff; +} + +#filterModal .modal-header { + padding: 1.25rem 1.5rem; + border-bottom: 1px solid #f1f5f9; + background-color: #ffffff; +} + +#filterModal .modal-title { + font-size: 1.25rem; + font-weight: 700; + color: #0f172a; + letter-spacing: -0.02em; +} + +#filterModal .btn-close { + font-size: 0.85rem; + padding: 0.5rem; + opacity: 0.5; + transition: opacity 0.15s ease; +} + +#filterModal .btn-close:hover { + opacity: 1; +} + +#filterModal .modal-body { + padding: 1.5rem; + background-color: #f8fafc; + flex: 1; + overflow-y: auto; +} + +#filterModal .modal-footer { + padding: 1rem 1.5rem; + background-color: #ffffff; + border-top: 1px solid #f1f5f9; + flex-shrink: 0; + display: flex; + justify-content: space-between; + align-items: center; +} + +/* Filter Sections */ +.filter-section { + background-color: #ffffff; + border: 1px solid #e2e8f0; + border-radius: 14px; + padding: 1.15rem; + margin-bottom: 1rem; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.02); + transition: border-color 0.15s ease, box-shadow 0.15s ease; +} + +.filter-section:hover { + border-color: #cbd5e1; +} + +.filter-section-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 0.85rem; + gap: 1rem; +} + +.filter-section-header label, +.filter-section-header .section-title { + font-size: 0.95rem; + font-weight: 700; + color: #0f172a; + margin: 0; + letter-spacing: -0.01em; +} + +.filter-section-buttons { + display: flex; + gap: 0.35rem; + margin-left: auto; +} + +.filter-section-buttons button { + padding: 0.25rem 0.65rem; + font-size: 0.75rem; + font-weight: 500; + border-radius: 6px; + border: 1px solid #e2e8f0; + background-color: #ffffff; + color: #64748b; + transition: all 0.15s ease; +} + +.filter-section-buttons button:hover { + background-color: #f1f5f9; + color: #0f172a; + border-color: #cbd5e1; +} + +/* Filter Chips */ +.filter-options { + display: flex; + flex-wrap: wrap; + gap: 0.45rem; +} + +.filter-option { + display: inline-flex; + align-items: center; +} + +.filter-option input[type="checkbox"] { + position: absolute; + opacity: 0; + width: 0; + height: 0; + pointer-events: none; +} + +.filter-option label { + display: inline-flex; + align-items: center; + gap: 0.35rem; + padding: 0.4rem 0.85rem; + font-size: 0.82rem; + font-weight: 500; + color: #334155; + background-color: #ffffff; + border: 1.5px solid #e2e8f0; + border-radius: 9999px; + cursor: pointer; + transition: all 0.15s ease; + user-select: none; + white-space: nowrap; + margin: 0; +} + +.filter-option label:hover { + background-color: #f8fafc; + border-color: #94a3b8; + color: #0f172a; +} + +/* Default Chips Checked (Thematics) */ +.filter-option input[type="checkbox"]:checked + label:not(.context-badge) { + background-color: #0f172a !important; + border-color: #0f172a !important; + color: #ffffff !important; + font-weight: 600; + box-shadow: 0 2px 6px rgba(15, 23, 42, 0.16); +} + +/* Contextual Status Badges (Filter Modal) */ +.filter-option label.context-badge { + background-color: #ffffff; + border-width: 1.5px; + border-style: solid; + font-weight: 600; +} + +.filter-option label.context-badge.pending { border-color: #f59e0b; color: #d97706; } +.filter-option label.context-badge.sent { border-color: #0284c7; color: #0284c7; } +.filter-option label.context-badge.completed { border-color: #16a34a; color: #16a34a; } +.filter-option label.context-badge.invoiced { border-color: #7c3aed; color: #7c3aed; } +.filter-option label.context-badge.paid { border-color: #059669; color: #059669; } +.filter-option label.context-badge.cancelled { border-color: #dc2626; color: #dc2626; } + +.filter-option input[type="checkbox"]:not(:checked):hover + label.context-badge.pending { background-color: #fffbeb; } +.filter-option input[type="checkbox"]:not(:checked):hover + label.context-badge.sent { background-color: #f0f9ff; } +.filter-option input[type="checkbox"]:not(:checked):hover + label.context-badge.completed { background-color: #f0fdf4; } +.filter-option input[type="checkbox"]:not(:checked):hover + label.context-badge.invoiced { background-color: #faf5ff; } +.filter-option input[type="checkbox"]:not(:checked):hover + label.context-badge.paid { background-color: #ecfdf5; } +.filter-option input[type="checkbox"]:not(:checked):hover + label.context-badge.cancelled { background-color: #fef2f2; } + +.filter-option input[type="checkbox"]:checked + label.context-badge { + color: #ffffff !important; + font-weight: 600; + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12); +} + +.filter-option input[type="checkbox"]:checked + label.context-badge.pending { background-color: #f59e0b !important; border-color: #f59e0b !important; } +.filter-option input[type="checkbox"]:checked + label.context-badge.sent { background-color: #0284c7 !important; border-color: #0284c7 !important; } +.filter-option input[type="checkbox"]:checked + label.context-badge.completed { background-color: #16a34a !important; border-color: #16a34a !important; } +.filter-option input[type="checkbox"]:checked + label.context-badge.invoiced { background-color: #7c3aed !important; border-color: #7c3aed !important; } +.filter-option input[type="checkbox"]:checked + label.context-badge.paid { background-color: #059669 !important; border-color: #059669 !important; } +.filter-option input[type="checkbox"]:checked + label.context-badge.cancelled { background-color: #dc2626 !important; border-color: #dc2626 !important; } + +/* Contracts scrollable list in Filter Modal */ +.contracts-filter-container { + background-color: #ffffff; + border: 1.5px solid #e2e8f0; + border-radius: 10px; + padding: 0.5rem; +} + +.contracts-filter-search-box { + position: relative; + margin-bottom: 0.5rem; +} + +.contracts-filter-search-box input { + padding-left: 2rem; + font-size: 0.82rem; + border-radius: 7px; + border-color: #e2e8f0; +} + +.contracts-filter-search-box .search-icon { + position: absolute; + left: 0.65rem; + top: 50%; + transform: translateY(-50%); + color: #94a3b8; + font-size: 0.82rem; +} + +.contracts-filter-scroll { + max-height: 200px; + overflow-y: auto; + padding-right: 0.25rem; +} + +.contract-filter-item { + padding: 0.35rem 0.5rem; + border-radius: 6px; + transition: background-color 0.12s ease; + display: flex; + align-items: center; + gap: 0.5rem; +} + +.contract-filter-item:hover { + background-color: #f8fafc; +} + +.contract-filter-item label { + margin-bottom: 0; + font-size: 0.84rem; + color: #334155; + cursor: pointer; + width: 100%; +} + +@media (max-width: 768px) { + .contracts-header { + flex-direction: column; + align-items: stretch; + } + + .toolbar-actions { + width: 100%; + justify-content: space-between; + } + + .search-widget { + max-width: 100%; + } + + .contracts-pagination-bar { + flex-direction: column; + align-items: center; + text-align: center; + } +} diff --git a/loko/contracts/static/contracts/js/contracts_index.js b/loko/contracts/static/contracts/js/contracts_index.js new file mode 100644 index 0000000..5231145 --- /dev/null +++ b/loko/contracts/static/contracts/js/contracts_index.js @@ -0,0 +1,155 @@ +document.addEventListener('DOMContentLoaded', function() { + // ─── Recherche principale ─── + const searchInput = document.getElementById('main-search-input'); + const searchClearBtn = document.getElementById('main-search-clear'); + const searchBtn = document.getElementById('main-search-btn'); + + function toggleClearBtn() { + if (!searchClearBtn) return; + if (searchInput && searchInput.value.trim().length > 0) { + searchClearBtn.style.display = 'block'; + } else { + searchClearBtn.style.display = 'none'; + } + } + + if (searchInput) { + toggleClearBtn(); + searchInput.addEventListener('input', toggleClearBtn); + + searchInput.addEventListener('keydown', function(e) { + if (e.key === 'Enter') { + e.preventDefault(); + executeSearch(searchInput.value.trim()); + } + }); + } + + if (searchBtn && searchInput) { + searchBtn.addEventListener('click', function() { + executeSearch(searchInput.value.trim()); + }); + } + + if (searchClearBtn) { + searchClearBtn.addEventListener('click', function() { + if (searchInput) { + searchInput.value = ''; + toggleClearBtn(); + } + executeSearch(''); + }); + } + + function executeSearch(query) { + const url = new URL(window.location.href); + if (query) { + url.searchParams.set('search', query); + } else { + url.searchParams.delete('search'); + } + url.searchParams.delete('page'); + url.searchParams.delete('contracts_page'); + window.location.href = url.toString(); + } + + // ─── Sélecteur de taille de page ─── + const pageSizeSelect = document.getElementById('page-size-select'); + if (pageSizeSelect) { + pageSizeSelect.addEventListener('change', function() { + const url = new URL(window.location.href); + url.searchParams.set('page_size', this.value); + url.searchParams.delete('page'); + window.location.href = url.toString(); + }); + } + + // ─── Suppression rapide des filtres actifs (chips) ─── + document.querySelectorAll('.remove-filter-btn').forEach(function(btn) { + btn.addEventListener('click', function(e) { + e.preventDefault(); + const param = this.dataset.param; + const val = this.dataset.val; + const url = new URL(window.location.href); + + if (param === 'search' || param === 'date_from' || param === 'date_to') { + url.searchParams.delete(param); + } else { + const remaining = url.searchParams.getAll(param).filter(v => v !== val); + url.searchParams.delete(param); + remaining.forEach(v => url.searchParams.append(param, v)); + } + + url.searchParams.delete('page'); + url.searchParams.delete('contracts_page'); + window.location.href = url.toString(); + }); + }); + + // ─── Modal de Filtres : Boutons "Tous" / "Aucun" ─── + document.querySelectorAll('.select-all-btn').forEach(function(btn) { + btn.addEventListener('click', function() { + const section = this.closest('.filter-section'); + if (section) { + section.querySelectorAll('input[type="checkbox"]').forEach(function(cb) { + cb.checked = true; + }); + } + }); + }); + + document.querySelectorAll('.deselect-all-btn').forEach(function(btn) { + btn.addEventListener('click', function() { + const section = this.closest('.filter-section'); + if (section) { + section.querySelectorAll('input[type="checkbox"]').forEach(function(cb) { + cb.checked = false; + }); + } + }); + }); + + // ─── Filtrage rapide dans la liste des marchés dans la modale ─── + const contractSearchInput = document.getElementById('contract-filter-search'); + if (contractSearchInput) { + contractSearchInput.addEventListener('input', function() { + const term = this.value.toLowerCase().trim(); + document.querySelectorAll('.contract-filter-item').forEach(function(item) { + const text = item.textContent.toLowerCase(); + if (!term || text.includes(term)) { + item.style.display = 'flex'; + } else { + item.style.display = 'none'; + } + }); + }); + } + + // ─── Synchronisation de l'onglet actif ─── + const tabButtons = document.querySelectorAll('button[data-bs-toggle="tab"]'); + const filterTabInput = document.getElementById('filter-tab-input'); + + tabButtons.forEach(function(btn) { + btn.addEventListener('shown.bs.tab', function(e) { + const targetId = e.target.getAttribute('data-bs-target'); + const tabName = targetId === '#contracts-content' ? 'contracts' : 'orders'; + + if (filterTabInput) { + filterTabInput.value = tabName; + } + + const url = new URL(window.location.href); + url.searchParams.set('tab', tabName); + window.history.replaceState({}, '', url); + }); + }); + + // Restaurer l'onglet actif si spécifié dans l'URL + const currentTabParam = new URLSearchParams(window.location.search).get('tab'); + if (currentTabParam === 'contracts') { + const contractsTabBtn = document.getElementById('contracts-tab'); + if (contractsTabBtn && window.bootstrap && bootstrap.Tab) { + bootstrap.Tab.getOrCreateInstance(contractsTabBtn).show(); + } + } +}); diff --git a/loko/contracts/templates/contracts/contracts_index.html b/loko/contracts/templates/contracts/contracts_index.html index 9e71896..d5de0b6 100644 --- a/loko/contracts/templates/contracts/contracts_index.html +++ b/loko/contracts/templates/contracts/contracts_index.html @@ -3,298 +3,512 @@ {% load i18n %} {% block head %} - - - + {% endblock head %} - {% block content %} -
-
- {% if is_add_order_allowed == True %} - - {% translate "Nouvelle commande" %} - - {% endif %} -
- -
-
- -
-
-
- -
- -
- -
- - -
- -
- - -
- -
- - -
- -
- - -
- -
- - -
- -
- - -
+ +