Files
LoreMind/web/src/app/campaigns/arc/arc-create/arc-create.component.ts
IETM_FIXE\ietm6 504c4b7b6c
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
Plusieurs ajouts :
- 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
2026-06-03 15:44:48 +02:00

96 lines
3.6 KiB
TypeScript

import { Component, OnInit, OnDestroy } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ReactiveFormsModule, FormBuilder, FormGroup, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { forkJoin } from 'rxjs';
import { LucideAngularModule, BookOpen } from 'lucide-angular';
import { CampaignService } from '../../../services/campaign.service';
import { CharacterService } from '../../../services/character.service';
import { NpcService } from '../../../services/npc.service';
import { LayoutService } from '../../../services/layout.service';
import { loadCampaignTreeData, buildCampaignSidebarConfig } from '../../campaign-tree.helper';
import { IconPickerComponent } from '../../../shared/icon-picker/icon-picker.component';
import { CAMPAIGN_ICON_OPTIONS } from '../../campaign-icons';
/**
* Écran de création d'un nouvel Arc narratif (contexte Campagne).
* Formulaire simple : nom + description. L'ordre est auto-calculé depuis
* le nombre d'arcs existants dans la campagne courante.
*/
@Component({
selector: 'app-arc-create',
standalone: true,
imports: [CommonModule, ReactiveFormsModule, LucideAngularModule, IconPickerComponent],
templateUrl: './arc-create.component.html',
styleUrls: ['./arc-create.component.scss']
})
export class ArcCreateComponent implements OnInit, OnDestroy {
readonly BookOpen = BookOpen;
readonly campaignIconOptions = CAMPAIGN_ICON_OPTIONS;
form: FormGroup;
campaignId = '';
selectedIcon: string | null = null;
private existingArcCount = 0;
constructor(
private fb: FormBuilder,
private route: ActivatedRoute,
private router: Router,
private campaignService: CampaignService,
private characterService: CharacterService,
private npcService: NpcService,
private layoutService: LayoutService
) {
this.form = this.fb.group({
name: ['', Validators.required],
description: [''],
// Type structurel : LINEAR (séquentiel) par défaut, HUB (sandbox/quêtes parallèles).
type: ['LINEAR', Validators.required]
});
}
ngOnInit(): void {
this.campaignId = this.route.snapshot.paramMap.get('campaignId')!;
this.loadLayout();
}
private loadLayout(): void {
forkJoin({
campaign: this.campaignService.getCampaignById(this.campaignId),
allCampaigns: this.campaignService.getAllCampaigns(),
treeData: loadCampaignTreeData(this.campaignService, this.campaignId, this.characterService, this.npcService)
}).subscribe(({ campaign, allCampaigns, treeData }) => {
this.existingArcCount = treeData.arcs.length;
this.layoutService.show(buildCampaignSidebarConfig(campaign, allCampaigns, treeData, this.campaignId));
});
}
submit(): void {
if (this.form.invalid) return;
this.campaignService.createArc({
name: this.form.value.name,
description: this.form.value.description,
campaignId: this.campaignId,
order: this.existingArcCount + 1,
type: this.form.value.type,
icon: this.selectedIcon
}).subscribe({
next: (created) => this.router.navigate(['/campaigns', this.campaignId, 'arcs', created.id]),
error: () => console.error('Erreur lors de la création de l\'arc')
});
}
cancel(): void {
this.router.navigate(['/campaigns', this.campaignId]);
}
ngOnDestroy(): void {
// Volontairement vide : la sidebar reste prise en charge par le composant
// suivant (autre sous-route ou le composant detail parent) qui appellera
// show(). Eviter d'appeler hide() ici previent le clignotement / la
// disparition de la sidebar lors des navigations internes a la section.
}
}