{# @tailwind-safelist bg-primary/10 bg-cohorts/10 bg-warning/10 bg-error/10 bg-success/10 bg-info/10 bg-pink/10 #} {% extends 'base.html.twig' %} {% block title %}{{ contract.name }} - {{ isAdmin ? 'Admin' : 'Contrat' }}{% endblock %} {% block body %} {% set status = contract.status %} {# ================================================================ BREADCRUMB ================================================================ #}
{% if isAdmin and company %} {# Admin : Entreprises > Entreprise > Contrat #} {% include '_molecules/breadcrumb/breadcrumb.html.twig' with { homeHref: path('app_dashboard'), items: [ { label: 'Entreprises', href: path('admin_company_list') }, { label: company.name, href: path('admin_company_show', {uuid: company.uuid}) }, { label: contract.name } ] } only %} {% else %} {# Manager ou contrat orphelin : Contrats > Contrat #} {% include '_molecules/breadcrumb/breadcrumb.html.twig' with { homeHref: path('app_dashboard'), items: [ { label: 'Contrats', href: path('admin_contract_list') }, { label: contract.name } ] } only %} {% endif %}
{# Configuration centralisée via extension Twig #} {% set config = contract_status_config(status) %}
{# ================================================================ HEADER DU CONTRAT ================================================================ #}
{# Info principale #}
{# Badge statut #}
{% include '_atoms/icon/icon.html.twig' with { name: config.icon, size: 'lg', color: status == 'active' ? 'success' : (status == 'expired' ? 'error' : (status == 'upcoming' ? 'info' : 'gray')) } only %}

{{ contract.name }}

{% include '_atoms/badge/badge.html.twig' with { preset: 'contract-' ~ status, size: 'sm' } only %}
{% if company %} {% include '_atoms/icon/icon.html.twig' with { name: 'buildings', size: 'sm' } only %} {{ company.name }} {% else %} Entreprise non attribuée {% endif %} {% include '_atoms/icon/icon.html.twig' with { name: 'calendar', size: 'sm' } only %} {{ contract.startDate|date('d/m/Y') }} → {{ contract.endDate|date('d/m/Y') }} {% if status == 'active' and contract.isExpiringSoon(30) %} {% include '_atoms/icon/icon.html.twig' with { name: 'warning', size: 'sm', color: 'warning' } only %} Expire dans {{ contract.daysRemaining }} jour{{ contract.daysRemaining > 1 ? 's' : '' }} {% endif %}
{# Actions #}
{% include '_atoms/button/button.html.twig' with { label: 'Retour', variant: 'ghost', size: 'lg', icon: 'arrow-left', href: isAdmin and company ? path('admin_company_show', {uuid: company.uuid}) : path('admin_contract_list') } only %} {% if isAdmin and company %} {% include '_atoms/button/button.html.twig' with { label: 'Modifier', variant: 'primary', size: 'lg', icon: 'edit', href: path('admin_contract_edit', {companyUuid: company.uuid, contractUuid: contract.uuid}) } only %} {% endif %}
{# ================================================================ STATISTIQUES ================================================================ #}
{% include '_molecules/stat-card/stat-card.html.twig' with { label: 'Utilisateurs max', value: contract.maxUsers, icon: 'users', variant: 'info', size: 'sm', layout: 'horizontal' } only %} {% include '_molecules/stat-card/stat-card.html.twig' with { label: 'Prix par licence', value: contract.pricePerLicense ? (contract.pricePerLicense|number_format(2, ',', ' ') ~ ' €') : '-', subtitle: 'TTC / mois', icon: 'wallet', variant: 'primary', size: 'sm', layout: 'horizontal' } only %} {% include '_molecules/stat-card/stat-card.html.twig' with { label: 'Tokens mensuels', value: contract.monthlyTokens|number_format(0, ',', ' '), icon: 'token', variant: 'success', size: 'sm', layout: 'horizontal' } only %} {% include '_molecules/stat-card/stat-card.html.twig' with { label: 'Jours restants', value: contract.daysRemaining > 0 ? contract.daysRemaining : 0, icon: 'clock', variant: contract.daysRemaining > 30 ? 'info' : (contract.daysRemaining > 0 ? 'warning' : 'error'), size: 'sm', layout: 'horizontal' } only %}
{# Colonne principale (2/3) #}
{# ================================================================ ACCÈS SAM ================================================================ #} {% set hasSam = contract.company is defined and contract.company is not null and contract.company.hasSamAccess %}
{% include '_atoms/logo/logo-with-text.html.twig' with { variant: 'sam', subtitle: 'Suivi Apprenants Moodle', showBadge: false, size: 'md', disabled: not hasSam } %} {% include '_atoms/badge/badge.html.twig' with { label: hasSam ? 'Activé' : 'Désactivé', variant: hasSam ? 'success' : 'neutral' } only %}
{# Historique des actions (admin uniquement) #} {% if isAdmin %} {% include '_organisms/activity-log/activity-log-section.html.twig' with { logs: logs ?? [] } only %} {% endif %}
{# Colonne latérale (1/3) #}
{# ================================================================ INFORMATIONS COMPLÉMENTAIRES ================================================================ #}
{% include '_atoms/icon/icon.html.twig' with { name: 'info', size: 'md', color: 'info' } only %}

Informations

{% include '_molecules/data-row/data-row.html.twig' with { label: 'Créé le', value: contract.createdAt|date('d/m/Y'), size: 'sm' } only %} {% if contract.updatedAt %} {% include '_molecules/data-row/data-row.html.twig' with { label: 'Modifié le', value: contract.updatedAt|date('d/m/Y H:i'), size: 'sm' } only %} {% endif %} {% set duration = date(contract.endDate).diff(date(contract.startDate)) %} {% include '_molecules/data-row/data-row.html.twig' with { label: 'Durée totale', value: duration.days ~ ' jours', size: 'sm' } only %} {% include '_molecules/data-row/data-row.html.twig' with { label: 'Valeur mensuelle', value: contract.pricePerLicense ? ((contract.pricePerLicense * contract.maxUsers)|number_format(2, ',', ' ') ~ ' € TTC/mois') : null, size: 'sm' } only %} {% include '_atoms/divider/divider.html.twig' with { spacing: 'sm', color: 'light' } only %} {% include '_molecules/data-row/data-row.html.twig' with { label: 'Contact support', action: { label: 'contact@bubul.app', href: 'mailto:contact@bubul.app' }, size: 'sm' } only %}
{# ================================================================ NOTES INTERNES (Admin uniquement) ================================================================ #} {% if isAdmin %}
{% include '_atoms/icon/icon.html.twig' with { name: 'file-text', size: 'md', color: 'warning' } only %}

Notes internes

Visibles uniquement par les administrateurs

{% if contract.notes %}
{{ contract.notes|nl2br }}
{% else %} {% include '_molecules/empty-state/empty-state.html.twig' with { title: 'Aucune note interne', icon: 'file-text', size: 'sm', variant: 'minimal' } only %} {% endif %}
{% endif %} {# ================================================================ STATUT DU CONTRAT ================================================================ #} {% if company %} {% if status == 'expired' %} {# Contrat expiré - affichage simple en rouge #}
{% include '_atoms/icon/icon.html.twig' with { name: 'x', size: 'md', color: 'error' } only %}

Contrat expiré

Ce contrat a expiré le {{ contract.endDate|date('d/m/Y') }}

{% else %} {# Contrat actif ou désactivé - avec bouton d'action #}
{% include '_atoms/icon/icon.html.twig' with { name: 'power', size: 'md', color: contract.isActive ? 'success-dark' : 'gray', opacitySecondary: '1' } only %}

{{ contract.isActive ? 'Contrat actif' : 'Contrat désactivé' }}

{% if contract.isActive %} Les droits sont comptabilisés {% else %} Les droits ne sont plus comptabilisés {% endif %}

{% if isAdmin %} {% endif %}
{% endif %} {% endif %}
{# ================================================================ MODAL DE CONFIRMATION TOGGLE STATUS ================================================================ #} {% if isAdmin and company %} {% endif %} {% endblock %}