createScene(@RequestBody SceneDTO sceneDTO) {
Scene scene = sceneMapper.toDomain(sceneDTO);
- Scene createdScene = sceneService.createScene(scene.getName(), scene.getDescription(), scene.getChapterId(), scene.getOrder());
+ Scene createdScene = sceneService.createScene(scene.getName(), scene.getDescription(), scene.getChapterId(), scene.getOrder(), scene.getIcon());
return ResponseEntity.ok(sceneMapper.toDTO(createdScene));
}
diff --git a/core/src/main/java/com/loremind/infrastructure/web/dto/campaigncontext/ArcDTO.java b/core/src/main/java/com/loremind/infrastructure/web/dto/campaigncontext/ArcDTO.java
index 76fe8ee..19b5e68 100644
--- a/core/src/main/java/com/loremind/infrastructure/web/dto/campaigncontext/ArcDTO.java
+++ b/core/src/main/java/com/loremind/infrastructure/web/dto/campaigncontext/ArcDTO.java
@@ -17,6 +17,9 @@ public class ArcDTO {
private String campaignId;
private int order;
+ /** Cle d'icone (cf. CAMPAIGN_ICON_OPTIONS cote front). */
+ private String icon;
+
// Champs narratifs enrichis
private String themes;
private String stakes;
diff --git a/core/src/main/java/com/loremind/infrastructure/web/dto/campaigncontext/ChapterDTO.java b/core/src/main/java/com/loremind/infrastructure/web/dto/campaigncontext/ChapterDTO.java
index 4c11713..54a654e 100644
--- a/core/src/main/java/com/loremind/infrastructure/web/dto/campaigncontext/ChapterDTO.java
+++ b/core/src/main/java/com/loremind/infrastructure/web/dto/campaigncontext/ChapterDTO.java
@@ -17,6 +17,9 @@ public class ChapterDTO {
private String arcId;
private int order;
+ /** Cle d'icone (cf. CAMPAIGN_ICON_OPTIONS cote front). */
+ private String icon;
+
// Champs narratifs enrichis
private String gmNotes;
private String playerObjectives;
diff --git a/core/src/main/java/com/loremind/infrastructure/web/dto/campaigncontext/SceneDTO.java b/core/src/main/java/com/loremind/infrastructure/web/dto/campaigncontext/SceneDTO.java
index ead1693..674b86a 100644
--- a/core/src/main/java/com/loremind/infrastructure/web/dto/campaigncontext/SceneDTO.java
+++ b/core/src/main/java/com/loremind/infrastructure/web/dto/campaigncontext/SceneDTO.java
@@ -17,6 +17,9 @@ public class SceneDTO {
private String chapterId;
private int order;
+ /** Cle d'icone (cf. CAMPAIGN_ICON_OPTIONS cote front). */
+ private String icon;
+
// Champs narratifs enrichis
private String location;
private String timing;
diff --git a/core/src/main/java/com/loremind/infrastructure/web/mapper/ArcMapper.java b/core/src/main/java/com/loremind/infrastructure/web/mapper/ArcMapper.java
index 16e0617..5308ffa 100644
--- a/core/src/main/java/com/loremind/infrastructure/web/mapper/ArcMapper.java
+++ b/core/src/main/java/com/loremind/infrastructure/web/mapper/ArcMapper.java
@@ -24,6 +24,7 @@ public class ArcMapper {
dto.setDescription(arc.getDescription());
dto.setCampaignId(arc.getCampaignId());
dto.setOrder(arc.getOrder());
+ dto.setIcon(arc.getIcon());
dto.setThemes(arc.getThemes());
dto.setStakes(arc.getStakes());
dto.setGmNotes(arc.getGmNotes());
@@ -46,6 +47,7 @@ public class ArcMapper {
.description(dto.getDescription())
.campaignId(dto.getCampaignId())
.order(dto.getOrder())
+ .icon(dto.getIcon())
.themes(dto.getThemes())
.stakes(dto.getStakes())
.gmNotes(dto.getGmNotes())
diff --git a/core/src/main/java/com/loremind/infrastructure/web/mapper/ChapterMapper.java b/core/src/main/java/com/loremind/infrastructure/web/mapper/ChapterMapper.java
index 767c29e..41afd6e 100644
--- a/core/src/main/java/com/loremind/infrastructure/web/mapper/ChapterMapper.java
+++ b/core/src/main/java/com/loremind/infrastructure/web/mapper/ChapterMapper.java
@@ -24,6 +24,7 @@ public class ChapterMapper {
dto.setDescription(chapter.getDescription());
dto.setArcId(chapter.getArcId());
dto.setOrder(chapter.getOrder());
+ dto.setIcon(chapter.getIcon());
dto.setGmNotes(chapter.getGmNotes());
dto.setPlayerObjectives(chapter.getPlayerObjectives());
dto.setNarrativeStakes(chapter.getNarrativeStakes());
@@ -44,6 +45,7 @@ public class ChapterMapper {
.description(dto.getDescription())
.arcId(dto.getArcId())
.order(dto.getOrder())
+ .icon(dto.getIcon())
.gmNotes(dto.getGmNotes())
.playerObjectives(dto.getPlayerObjectives())
.narrativeStakes(dto.getNarrativeStakes())
diff --git a/core/src/main/java/com/loremind/infrastructure/web/mapper/SceneMapper.java b/core/src/main/java/com/loremind/infrastructure/web/mapper/SceneMapper.java
index d66b4fe..4cf57e8 100644
--- a/core/src/main/java/com/loremind/infrastructure/web/mapper/SceneMapper.java
+++ b/core/src/main/java/com/loremind/infrastructure/web/mapper/SceneMapper.java
@@ -27,6 +27,7 @@ public class SceneMapper {
dto.setDescription(scene.getDescription());
dto.setChapterId(scene.getChapterId());
dto.setOrder(scene.getOrder());
+ dto.setIcon(scene.getIcon());
dto.setLocation(scene.getLocation());
dto.setTiming(scene.getTiming());
dto.setAtmosphere(scene.getAtmosphere());
@@ -59,6 +60,7 @@ public class SceneMapper {
.description(dto.getDescription())
.chapterId(dto.getChapterId())
.order(dto.getOrder())
+ .icon(dto.getIcon())
.location(dto.getLocation())
.timing(dto.getTiming())
.atmosphere(dto.getAtmosphere())
diff --git a/web/package-lock.json b/web/package-lock.json
index 8ab487d..4f4279d 100644
--- a/web/package-lock.json
+++ b/web/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "loremind-web",
- "version": "0.6.1",
+ "version": "0.6.5",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "loremind-web",
- "version": "0.6.1",
+ "version": "0.6.5",
"dependencies": {
"@angular/animations": "^17.0.0",
"@angular/common": "^17.0.0",
diff --git a/web/package.json b/web/package.json
index 245f8b6..a0ee19a 100644
--- a/web/package.json
+++ b/web/package.json
@@ -1,6 +1,6 @@
{
"name": "loremind-web",
- "version": "0.6.2",
+ "version": "0.6.5",
"description": "LoreMind Frontend - Angular",
"scripts": {
"ng": "ng",
diff --git a/web/src/app/app.component.scss b/web/src/app/app.component.scss
index d89a34a..b8d5308 100644
--- a/web/src/app/app.component.scss
+++ b/web/src/app/app.component.scss
@@ -5,6 +5,10 @@
.main-content {
flex: 1;
- padding: 2rem;
+ // padding-top: 0 — sinon le contenu defile dans la zone de padding
+ // au-dessus du `.page-header` sticky (top: 0 pin sur l'edge interne du
+ // padding-box). Chaque page-wrapper definit deja son propre padding-top
+ // qui devient l'unique source d'espacement haut.
+ padding: 0 2rem 2rem;
overflow-y: auto;
}
diff --git a/web/src/app/campaigns/arc-create/arc-create.component.html b/web/src/app/campaigns/arc-create/arc-create.component.html
index 7b04d28..3e8a2b2 100644
--- a/web/src/app/campaigns/arc-create/arc-create.component.html
+++ b/web/src/app/campaigns/arc-create/arc-create.component.html
@@ -27,6 +27,11 @@
+
+
+
+
+
@@ -63,6 +71,11 @@
+
+
@@ -136,17 +149,6 @@
-
-
-
-
-
-
diff --git a/web/src/app/campaigns/arc-edit/arc-edit.component.ts b/web/src/app/campaigns/arc-edit/arc-edit.component.ts
index 31af867..1d04b08 100644
--- a/web/src/app/campaigns/arc-edit/arc-edit.component.ts
+++ b/web/src/app/campaigns/arc-edit/arc-edit.component.ts
@@ -16,6 +16,8 @@ import { loadCampaignTreeData, buildCampaignTree } from '../campaign-tree.helper
import { LoreLinkPickerComponent } from '../../shared/lore-link-picker/lore-link-picker.component';
import { AiChatDrawerComponent } from '../../shared/ai-chat-drawer/ai-chat-drawer.component';
import { ImageGalleryComponent } from '../../shared/image-gallery/image-gallery.component';
+import { IconPickerComponent } from '../../shared/icon-picker/icon-picker.component';
+import { CAMPAIGN_ICON_OPTIONS } from '../campaign-icons';
/**
* Écran de détail/modification d'un Arc.
@@ -29,13 +31,15 @@ import { ImageGalleryComponent } from '../../shared/image-gallery/image-gallery.
@Component({
selector: 'app-arc-edit',
standalone: true,
- imports: [CommonModule, ReactiveFormsModule, LucideAngularModule, LoreLinkPickerComponent, AiChatDrawerComponent, ImageGalleryComponent],
+ imports: [CommonModule, ReactiveFormsModule, LucideAngularModule, LoreLinkPickerComponent, AiChatDrawerComponent, ImageGalleryComponent, IconPickerComponent],
templateUrl: './arc-edit.component.html',
styleUrls: ['./arc-edit.component.scss']
})
export class ArcEditComponent implements OnInit, OnDestroy {
readonly Trash2 = Trash2;
readonly Sparkles = Sparkles;
+ readonly campaignIconOptions = CAMPAIGN_ICON_OPTIONS;
+ selectedIcon: string | null = null;
/** État drawer chat IA (b5.7 — intégration Campagne). */
chatOpen = false;
@@ -122,6 +126,7 @@ export class ArcEditComponent implements OnInit, OnDestroy {
this.loreId = loreId;
this.availablePages = pages;
this.relatedPageIds = [...(arc.relatedPageIds ?? [])];
+ this.selectedIcon = arc.icon ?? null;
this.illustrationImageIds = [...(arc.illustrationImageIds ?? [])];
this.mapImageIds = [...(arc.mapImageIds ?? [])];
this.pageTitleService.set(arc.name);
@@ -167,7 +172,8 @@ export class ArcEditComponent implements OnInit, OnDestroy {
resolution: this.form.value.resolution,
relatedPageIds: this.relatedPageIds,
illustrationImageIds: this.illustrationImageIds,
- mapImageIds: this.mapImageIds
+ mapImageIds: this.mapImageIds,
+ icon: this.selectedIcon
}).subscribe({
next: () => this.router.navigate(['/campaigns', this.campaignId, 'arcs', this.arcId]),
error: () => console.error('Erreur lors de la sauvegarde')
diff --git a/web/src/app/campaigns/arc-view/arc-view.component.html b/web/src/app/campaigns/arc-view/arc-view.component.html
index a1c1d3d..639fe17 100644
--- a/web/src/app/campaigns/arc-view/arc-view.component.html
+++ b/web/src/app/campaigns/arc-view/arc-view.component.html
@@ -2,7 +2,10 @@