269 lines
12 KiB
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> |