Plusieurs ajouts :
Some checks failed
Build & Push Images / build (brain) (push) Has been cancelled
Build & Push Images / build (core) (push) Has been cancelled
Build & Push Images / build (web) (push) Has been cancelled
Build & Push Images / build-switcher (push) Has been cancelled

- Possibilité de configurer des lieux dans une scène : permet de configurer un donjon par exemple avec les pièces, les trésors par pièce, la narration..... Mise en place également de conditions permettant de conditionner le déblocage des quêtes.
- Possibilité de transformé un arc en instance non linéaire afin de faire un hub. Permet de jouer de préparer des campagnes type Dragon of Icespire peak plus facilement.
- Configuration de partie : chaque partie va contenir les séances, ce qui permettra de suivre le déblocage des conditions pour les quêtes.

Passage en 0.9.1-beta
This commit is contained in:
2026-06-03 15:44:48 +02:00
parent e3fc96a1bc
commit 504c4b7b6c
147 changed files with 5347 additions and 392 deletions

View File

@@ -1,6 +1,6 @@
<div class="session-detail" *ngIf="session">
<a class="back-link" [routerLink]="['/campaigns', session.campaignId]">
<a class="back-link" [routerLink]="campaignId ? ['/campaigns', campaignId] : ['/campaigns']">
<lucide-icon [img]="ArrowLeft" [size]="14"></lucide-icon>
Retour à la campagne
</a>
@@ -175,7 +175,8 @@
<!-- Colonne droite : panneau référence (Dés / Personnages / Scènes) -->
<aside class="play-aside">
<app-session-reference-panel
[campaignId]="session.campaignId"
[campaignId]="campaignId ?? ''"
[playthroughId]="session.playthroughId"
[sessionId]="session.id"
[canAddToJournal]="session.active"
(rolled)="onDiceRolled($event)"

View File

@@ -11,6 +11,7 @@ import { catchError, switchMap, filter, map } from 'rxjs/operators';
import { of } from 'rxjs';
import { SessionService } from '../../services/session.service';
import { Session } from '../../services/session.model';
import { PlaythroughService } from '../../services/playthrough.service';
import {
SessionEntry, SessionEntryInput, EntryType, ENTRY_TYPE_META
} from '../../services/session-entry.model';
@@ -54,6 +55,8 @@ export class SessionDetailComponent implements OnInit, OnDestroy {
readonly entryTypeMeta = ENTRY_TYPE_META;
session: Session | null = null;
/** Résolu via Playthrough.campaignId (Session → Playthrough → Campaign). */
campaignId: string | null = null;
/** Timeline triée du plus récent au plus ancien (DESC) pour l'UX en partie. */
entries: SessionEntry[] = [];
@@ -74,6 +77,7 @@ export class SessionDetailComponent implements OnInit, OnDestroy {
private route: ActivatedRoute,
private router: Router,
private sessionService: SessionService,
private playthroughService: PlaythroughService,
private entryService: SessionEntryService,
private layoutService: LayoutService,
private pageTitleService: PageTitleService,
@@ -93,6 +97,11 @@ export class SessionDetailComponent implements OnInit, OnDestroy {
if (session) {
this.pageTitleService.set(session.name);
this.loadEntries(session.id);
if (session.playthroughId) {
this.playthroughService.getById(session.playthroughId).pipe(
catchError(() => of(null))
).subscribe(pt => { this.campaignId = pt ? pt.campaignId : null; });
}
}
});
}
@@ -168,9 +177,12 @@ export class SessionDetailComponent implements OnInit, OnDestroy {
variant: 'danger'
}).then(ok => {
if (!ok) return;
const campaignId = session.campaignId;
const cid = this.campaignId;
this.sessionService.deleteSession(session.id).subscribe({
next: () => this.router.navigate(['/campaigns', campaignId]),
next: () => {
if (cid) this.router.navigate(['/campaigns', cid]);
else this.router.navigate(['/campaigns']);
},
error: () => console.error('Erreur lors de la suppression de la session')
});
});

View File

@@ -42,6 +42,8 @@ export class SessionReferencePanelComponent implements OnChanges {
readonly Sparkles = Sparkles;
@Input() campaignId!: string;
/** Partie active — nécessaire pour charger les PJ (refonte Playthrough). */
@Input() playthroughId: string | null = null;
@Input() sessionId!: string;
@Input() canAddToJournal = true;
@Output() rolled = new EventEmitter<DiceRollResult>();
@@ -85,7 +87,11 @@ export class SessionReferencePanelComponent implements OnChanges {
private ensureCharactersLoaded(): void {
if (this.charsLoaded || this.loadingChars || !this.campaignId) return;
this.loadingChars = true;
this.characterService.getByCampaign(this.campaignId).pipe(catchError(() => of([] as Character[])))
// PJ : propres à la Partie. PNJ : campagne-scope.
const chars$ = this.playthroughId
? this.characterService.getByPlaythrough(this.playthroughId)
: of([] as Character[]);
chars$.pipe(catchError(() => of([] as Character[])))
.subscribe(list => { this.characters = list; this.tryFinishCharsLoad(); });
this.npcService.getByCampaign(this.campaignId).pipe(catchError(() => of([] as Npc[])))
.subscribe(list => { this.npcs = list; this.tryFinishCharsLoad(); });