Corrections visuel ; optimisation du chargement des pages (préchargement anticité, sinon temps de latence chaque fois qu'on visite un type de page une première fois)
This commit is contained in:
@@ -70,7 +70,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="characters-section">
|
||||
<section class="detail-section characters-section">
|
||||
<div class="section-header">
|
||||
<h2>Personnages joueurs</h2>
|
||||
<button class="btn-add" (click)="createCharacter()">
|
||||
@@ -97,33 +97,33 @@
|
||||
Créer votre premier PJ
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="arcs-section">
|
||||
<section class="detail-section arcs-section">
|
||||
<div class="section-header">
|
||||
<h2>Arcs narratifs</h2>
|
||||
<button class="btn-add">
|
||||
<button class="btn-add" (click)="createArc()">
|
||||
<lucide-icon [img]="Plus" [size]="14"></lucide-icon>
|
||||
Nouvel arc
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="arcs-grid" *ngIf="arcs.length > 0">
|
||||
<div class="arc-card" *ngFor="let arc of arcs">
|
||||
<div class="arc-card" *ngFor="let arc of arcs" (click)="openArc(arc)">
|
||||
<lucide-icon [img]="Swords" [size]="24" class="arc-icon"></lucide-icon>
|
||||
<span class="arc-name">{{ arc.name }}</span>
|
||||
<span class="arc-meta">{{ arc.chapterCount || 0 }} chapitres</span>
|
||||
<span class="arc-meta">{{ chapterCountByArc[arc.id!] || 0 }} chapitres</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="empty-state" *ngIf="arcs.length === 0">
|
||||
<lucide-icon [img]="Swords" [size]="40" class="empty-icon"></lucide-icon>
|
||||
<p>Aucun arc narratif pour le moment.</p>
|
||||
<button class="btn-add-first">
|
||||
<button class="btn-add-first" (click)="createArc()">
|
||||
<lucide-icon [img]="Plus" [size]="14"></lucide-icon>
|
||||
Créer votre premier arc
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -1,9 +1,23 @@
|
||||
.campaign-detail {
|
||||
padding: 2.5rem 2rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Chaque bloc (resume, PJ, arcs) est encapsule dans une carte distincte
|
||||
* pour separer visuellement les zones. Le gap au niveau du parent gere
|
||||
* les espacements — les sections ne portent plus de margin-bottom.
|
||||
*/
|
||||
.detail-section {
|
||||
background: #0d1117;
|
||||
border: 1px solid #1f2937;
|
||||
border-radius: 12px;
|
||||
padding: 1.5rem 1.75rem;
|
||||
}
|
||||
|
||||
.detail-header {
|
||||
margin-bottom: 2.5rem;
|
||||
|
||||
h1 {
|
||||
font-size: 1.75rem;
|
||||
@@ -173,9 +187,6 @@
|
||||
.arc-meta { color: #6b7280; font-size: 0.75rem; }
|
||||
}
|
||||
|
||||
.characters-section {
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
|
||||
.characters-grid {
|
||||
display: grid;
|
||||
|
||||
@@ -36,6 +36,8 @@ export class CampaignDetailComponent implements OnInit, OnDestroy {
|
||||
|
||||
campaign: Campaign | null = null;
|
||||
arcs: Arc[] = [];
|
||||
/** Nombre de chapitres par arc — alimente le compteur des cartes. */
|
||||
chapterCountByArc: Record<string, number> = {};
|
||||
/** Lore associé si `campaign.loreId` est renseigné ; sinon null. */
|
||||
linkedLore: Lore | null = null;
|
||||
/** Lores disponibles pour changer l'association en mode édition. */
|
||||
@@ -86,11 +88,20 @@ export class CampaignDetailComponent implements OnInit, OnDestroy {
|
||||
this.loadLinkedGameSystem(campaign);
|
||||
this.loadCharacters(campaign.id!);
|
||||
this.arcs = treeData.arcs;
|
||||
this.chapterCountByArc = this.computeChapterCounts(treeData);
|
||||
this.showLayout(allCampaigns, treeData);
|
||||
this.pageTitleService.set(campaign.name);
|
||||
});
|
||||
}
|
||||
|
||||
private computeChapterCounts(data: CampaignTreeData): Record<string, number> {
|
||||
const counts: Record<string, number> = {};
|
||||
for (const arcId of Object.keys(data.chaptersByArc)) {
|
||||
counts[arcId] = data.chaptersByArc[arcId].length;
|
||||
}
|
||||
return counts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recharge explicitement après une mise à jour locale (ex: saveEdit).
|
||||
* Contrairement au flux ngOnInit, on bypass le filter sur l'ID puisqu'on
|
||||
@@ -110,6 +121,7 @@ export class CampaignDetailComponent implements OnInit, OnDestroy {
|
||||
this.loadLinkedGameSystem(campaign);
|
||||
this.loadCharacters(campaign.id!);
|
||||
this.arcs = treeData.arcs;
|
||||
this.chapterCountByArc = this.computeChapterCounts(treeData);
|
||||
this.showLayout(allCampaigns, treeData);
|
||||
this.pageTitleService.set(campaign.name);
|
||||
});
|
||||
@@ -157,6 +169,16 @@ export class CampaignDetailComponent implements OnInit, OnDestroy {
|
||||
this.router.navigate(['/campaigns', this.campaign.id, 'characters', character.id, 'edit']);
|
||||
}
|
||||
|
||||
createArc(): void {
|
||||
if (!this.campaign) return;
|
||||
this.router.navigate(['/campaigns', this.campaign.id, 'arcs', 'create']);
|
||||
}
|
||||
|
||||
openArc(arc: Arc): void {
|
||||
if (!this.campaign || !arc.id) return;
|
||||
this.router.navigate(['/campaigns', this.campaign.id, 'arcs', arc.id]);
|
||||
}
|
||||
|
||||
/** Extrait une ligne de résumé depuis le markdown (1re ligne non-vide, non-titre). */
|
||||
characterSnippet(c: Character): string {
|
||||
if (!c.markdownContent) return '(Fiche vide)';
|
||||
|
||||
Reference in New Issue
Block a user