parent
d2e6f8d567
commit
a83133a6f0
@ -0,0 +1,73 @@
|
||||
<!-- Spinner pendant le chargement -->
|
||||
<div *ngIf="loading" class="flex justify-center items-center h-64">
|
||||
<div
|
||||
class="animate-spin rounded-full h-12 w-12 border-4 border-blue-500 border-t-transparent"
|
||||
></div>
|
||||
</div>
|
||||
|
||||
<!-- Timeline -->
|
||||
<div
|
||||
*ngIf="!loading && pins.length > 0"
|
||||
class="relative mx-auto max-w-3xl py-10 px-4"
|
||||
>
|
||||
<div
|
||||
class="absolute h-full left-1/2 transform -translate-x-1/2 border-l-2 border-blue-500"
|
||||
></div>
|
||||
|
||||
<div
|
||||
*ngFor="let pin of pins; let i = index"
|
||||
class="mb-12 flex justify-between items-center w-full"
|
||||
>
|
||||
<!-- Si pair, carte à droite, point à gauche -->
|
||||
<div
|
||||
class="w-5/12"
|
||||
[ngClass]="{ 'order-1': i % 2 === 0, 'order-2': i % 2 !== 0 }"
|
||||
></div>
|
||||
|
||||
<div
|
||||
class="z-20 flex items-center bg-blue-600 shadow-lg w-10 h-10 rounded-full"
|
||||
[ngClass]="{ 'order-2': i % 2 === 0, 'order-1': i % 2 !== 0 }"
|
||||
>
|
||||
<span class="text-white font-semibold mx-auto">{{ i + 1 }}</span>
|
||||
</div>
|
||||
|
||||
<!-- Content card -->
|
||||
<div
|
||||
class="bg-white dark:bg-gray-800 rounded-xl shadow-xl px-6 py-5 w-5/12 transition-all duration-300 hover:scale-[1.02]"
|
||||
[ngClass]="{
|
||||
'order-3': i % 2 === 0,
|
||||
'order-0': i % 2 !== 0,
|
||||
'text-right': i % 2 !== 0
|
||||
}"
|
||||
>
|
||||
<div class="text-sm text-gray-400 mb-1">
|
||||
{{ pin.date ? (pin.date | date : "dd/MM/yyyy") : "Date inconnue" }}
|
||||
</div>
|
||||
<div class="text-lg font-bold text-gray-900 dark:text-white mb-1">
|
||||
{{ pin.title || "Titre inconnu" }}
|
||||
</div>
|
||||
<div class="text-gray-700 dark:text-gray-300 mb-3">
|
||||
{{ pin.description || "Aucune description" }}
|
||||
</div>
|
||||
|
||||
<ng-container *ngIf="imageUrls[i] && imageUrls[i].length > 0">
|
||||
<img
|
||||
[src]="imageUrls[i][0]"
|
||||
alt="image"
|
||||
class="rounded-lg mx-auto max-h-40 object-cover shadow"
|
||||
/>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="!imageUrls[i] || imageUrls[i].length === 0">
|
||||
<div class="text-gray-400 italic text-center">Aucune image</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Message si vide -->
|
||||
<div
|
||||
*ngIf="!loading && pins.length === 0"
|
||||
class="text-center text-gray-500 py-12 text-lg"
|
||||
>
|
||||
Aucun souvenir à afficher pour le moment.
|
||||
</div>
|
@ -0,0 +1,47 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
|
||||
import { Pin } from '../../model/Pin';
|
||||
import { ImageService } from '../../services/image/image.service';
|
||||
import { PinService } from '../../services/pin/pin.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-timeline',
|
||||
standalone: true,
|
||||
imports: [CommonModule],
|
||||
templateUrl: './timeline.component.html',
|
||||
})
|
||||
export class TimelineComponent implements OnInit {
|
||||
pins: Pin[] = [];
|
||||
imageUrls: SafeUrl[][] = [];
|
||||
loading = true;
|
||||
|
||||
constructor(
|
||||
private pinService: PinService,
|
||||
private imageService: ImageService,
|
||||
private sanitizer: DomSanitizer
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.pinService.getPins().subscribe((pins: Pin[]) => {
|
||||
this.pins = pins
|
||||
.filter((pin) => !!pin.date)
|
||||
.sort((a, b) => (a.date! > b.date! ? 1 : -1));
|
||||
this.imageUrls = this.pins.map(() => []); // initialise le tableau d'images
|
||||
|
||||
this.pins.forEach((pin, index) => {
|
||||
if (pin.files && pin.files.length > 0) {
|
||||
pin.files.forEach((imageId) => {
|
||||
this.imageService.getImage(imageId).subscribe((blob) => {
|
||||
const objectUrl = URL.createObjectURL(blob);
|
||||
const safeUrl = this.sanitizer.bypassSecurityTrustUrl(objectUrl);
|
||||
this.imageUrls[index].push(safeUrl);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.loading = false;
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Reference in new issue