dcb-backoffice/src/app/modules/subscriptions/subscription-details/subscription-details.html

269 lines
12 KiB
HTML

<div class="subscription-details">
<!-- Message d'accès refusé -->
@if (accessDenied) {
<div class="text-center py-5">
<ng-icon name="lucideLock" class="text-danger fs-1 mb-3"></ng-icon>
<h5 class="text-danger">Accès refusé</h5>
<p class="text-muted mb-4">Vous n'avez pas la permission d'accéder à cet abonnement.</p>
<button class="btn btn-primary" routerLink="/subscriptions">
<ng-icon name="lucideArrowLeft" class="me-1"></ng-icon>
Retour à la liste
</button>
</div>
} @else {
<!-- Loading State -->
@if (loading && !subscription) {
<div class="text-center py-5">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Chargement...</span>
</div>
<p class="mt-2 text-muted">Chargement des détails de l'abonnement...</p>
</div>
}
<!-- Messages -->
@if (error) {
<div class="alert alert-danger d-flex align-items-center">
<ng-icon name="lucideAlertCircle" class="me-2"></ng-icon>
<div class="flex-grow-1">{{ error }}</div>
<button class="btn-close" (click)="error = ''"></button>
</div>
}
@if (success) {
<div class="alert alert-success d-flex align-items-center">
<ng-icon name="lucideCheckCircle" class="me-2"></ng-icon>
<div class="flex-grow-1">{{ success }}</div>
<button class="btn-close" (click)="success = ''"></button>
</div>
}
@if (subscription && !loading) {
<div class="row">
<!-- Colonne principale -->
<div class="col-lg-8">
<!-- En-tête de l'abonnement -->
<div class="card mb-4">
<div class="card-header bg-light d-flex justify-content-between align-items-center">
<div class="d-flex align-items-center">
<h5 class="card-title mb-0 me-3">Abonnement #{{ subscription.id }}</h5>
<span [class]="getStatusBadgeClass(subscription.status)" class="badge">
<ng-icon [name]="getStatusIcon(subscription.status)" class="me-1"></ng-icon>
{{ getStatusDisplayName(subscription.status) }}
</span>
</div>
<div class="d-flex gap-2">
<button class="btn btn-outline-secondary btn-sm" (click)="copyToClipboard(subscription.id)"
ngbTooltip="Copier l'ID">
<ng-icon name="lucideCopy"></ng-icon>
</button>
<button class="btn btn-outline-secondary btn-sm" (click)="printDetails()"
ngbTooltip="Imprimer">
<ng-icon name="lucidePrinter"></ng-icon>
</button>
<button class="btn btn-outline-primary btn-sm" (click)="loadSubscriptionDetails()"
[disabled]="loading" ngbTooltip="Actualiser">
<ng-icon name="lucideRefreshCw" [class.spin]="loading"></ng-icon>
</button>
</div>
</div>
<div class="card-body">
<!-- Montant et informations principales -->
<div class="row mb-4">
<div class="col-md-6">
<div class="d-flex align-items-center">
<div class="subscription-amount-icon bg-primary rounded-circle p-3 me-3">
<ng-icon name="lucideEuro" class="text-white fs-4"></ng-icon>
</div>
<div>
<div class="text-muted small">Montant</div>
<div class="h3 mb-0 text-success">
{{ formatCurrency(subscription.amount, subscription.currency) }}
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="d-flex align-items-center h-100">
<div class="subscription-periodicity-icon bg-info rounded-circle p-3 me-3">
<ng-icon name="lucideRepeat" class="text-white fs-4"></ng-icon>
</div>
<div>
<div class="text-muted small">Périodicité</div>
<div class="h6 mb-0">
<span [class]="getPeriodicityBadgeClass(subscription.periodicity)" class="badge">
{{ getPeriodicityDisplayName(subscription.periodicity) }}
</span>
</div>
</div>
</div>
</div>
</div>
<!-- Informations détaillées -->
<div class="row">
<div class="col-12">
<h6 class="border-bottom pb-2 mb-3">Informations de l'abonnement</h6>
</div>
<div class="col-md-6 mb-3">
<label class="form-label text-muted small mb-1">Date de début</label>
<div class="d-flex align-items-center">
<ng-icon name="lucideCalendar" class="me-2 text-muted"></ng-icon>
<div>
<div class="fw-medium">{{ formatDate(subscription.startDate) }}</div>
<small class="text-muted">{{ formatRelativeTime(subscription.startDate) }}</small>
</div>
</div>
</div>
@if (subscription.nextPaymentDate) {
<div class="col-md-6 mb-3">
<label class="form-label text-muted small mb-1">Prochain paiement</label>
<div class="d-flex align-items-center">
<ng-icon name="lucideCalendar" class="me-2 text-muted"></ng-icon>
<div>
<div class="fw-medium">{{ formatDate(subscription.nextPaymentDate) }}</div>
<small class="text-muted">Dans {{ getDaysUntilNextPayment() }} jour(s)</small>
</div>
</div>
</div>
}
@if (subscription.endDate) {
<div class="col-md-6 mb-3">
<label class="form-label text-muted small mb-1">Date de fin</label>
<div class="d-flex align-items-center">
<ng-icon name="lucideCalendar" class="me-2 text-muted"></ng-icon>
<div>
<div class="fw-medium">{{ formatDate(subscription.endDate) }}</div>
@if (isExpiringSoon()) {
<small class="text-warning">
<ng-icon name="lucideAlertCircle" class="me-1"></ng-icon>
Expire bientôt
</small>
} @else if (isExpired()) {
<small class="text-danger">
<ng-icon name="lucideXCircle" class="me-1"></ng-icon>
Expiré
</small>
}
</div>
</div>
</div>
}
@if (subscription.externalReference) {
<div class="col-md-6 mb-3">
<label class="form-label text-muted small mb-1">Référence externe</label>
<div class="d-flex align-items-center">
<span class="font-monospace small">{{ subscription.externalReference }}</span>
<button class="btn btn-sm btn-link p-0 ms-2" (click)="copyToClipboard(subscription.externalReference!)">
<ng-icon name="lucideCopy" class="text-muted"></ng-icon>
</button>
</div>
</div>
}
</div>
<!-- Informations techniques -->
<div class="row mt-4">
<div class="col-12">
<h6 class="border-bottom pb-2 mb-3">Informations techniques</h6>
</div>
<div class="col-md-6 mb-2">
<label class="form-label text-muted small mb-1">Créé le</label>
<div class="small">{{ formatDate(subscription.createdAt) }}</div>
</div>
<div class="col-md-6 mb-2">
<label class="form-label text-muted small mb-1">Mis à jour le</label>
<div class="small">{{ formatDate(subscription.updatedAt) }}</div>
</div>
<div class="col-md-6 mb-2">
<label class="form-label text-muted small mb-1">Token</label>
<div class="small font-monospace text-truncate" [title]="subscription.token">
{{ subscription.token.substring(0, 30) }}...
</div>
</div>
<div class="col-md-6 mb-2">
<label class="form-label text-muted small mb-1">Échecs</label>
<div class="small">{{ subscription.failureCount || 0 }}</div>
</div>
</div>
</div>
</div>
</div>
<!-- Colonne latérale - Informations complémentaires -->
<div class="col-lg-4">
<!-- Informations marchand et client -->
<div class="card mb-3">
<div class="card-header bg-light">
<h6 class="card-title mb-0">Informations marchand & client</h6>
</div>
<div class="card-body">
<div class="small">
<div class="d-flex justify-content-between mb-2">
<span class="text-muted">Merchant ID:</span>
<span class="font-monospace">{{ subscription.merchantPartnerId }}</span>
</div>
@if (subscription.customerId) {
<div class="d-flex justify-content-between mb-2">
<span class="text-muted">Client ID:</span>
<span class="font-monospace small">{{ subscription.customerId }}</span>
</div>
}
@if (subscription.planId) {
<div class="d-flex justify-content-between mb-2">
<span class="text-muted">Plan ID:</span>
<span class="font-monospace small">{{ subscription.planId }}</span>
</div>
}
@if (subscription.serviceId) {
<div class="d-flex justify-content-between mb-2">
<span class="text-muted">Service ID:</span>
<span class="font-monospace small">{{ subscription.serviceId }}</span>
</div>
}
</div>
</div>
</div>
<!-- Métadonnées -->
@if (subscription.metadata) {
<div class="card">
<div class="card-header bg-light">
<h6 class="card-title mb-0">Métadonnées</h6>
</div>
<div class="card-body">
<pre class="small mb-0">{{ subscription.metadata | json }}</pre>
</div>
</div>
}
</div>
</div>
}
<!-- Abonnement non trouvé -->
@if (!subscription && !loading) {
<div class="text-center py-5">
<ng-icon name="lucideAlertCircle" class="text-muted fs-1 mb-3"></ng-icon>
<h5 class="text-muted">Abonnement non trouvé</h5>
<p class="text-muted mb-4">L'abonnement avec l'ID "{{ subscriptionId }}" n'existe pas ou a été supprimé.</p>
<button class="btn btn-primary" routerLink="/subscriptions">
<ng-icon name="lucideArrowLeft" class="me-1"></ng-icon>
Retour à la liste
</button>
</div>
}
}
</div>