Restructuration sections, contenu administrable, shadoks, palette été
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
- Structure par section : /numerique, /economique, /citoyenne (plus de /gestation) - Chaque section a index + sous-pages avec contenu YAML administrable - API content supporte les chemins imbriqués ([...path]) - Admin : liste des pages + éditeur par section - Page /economique : monnaie libre (picto Ğ1), modèle éco, productions collectives, commande livre - Page /citoyenne : decision (CTA Glibredecision), tarifs-eau (CTA SejeteralO) - BookActions : composant partagé (player, PDF, chapitres, commande) sur home, eco et modele-eco - GrateWizard remonté dans la section économique de la home - Palette été par défaut, choix persisté en localStorage - Fix lisibilité été (text-white/65 + variables CSS) - Shadoks thématiques sur toutes les pages (8-10 par page, métiers variés) - Redirections 301 : /gestation/*, /modele-eco/*, /decision, /lire/* - README, CONTRIBUTING, CLAUDE.md mis à jour Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -23,13 +23,25 @@
|
||||
</NuxtLink>
|
||||
|
||||
<p class="sidebar-section">Pages</p>
|
||||
<NuxtLink to="/admin/pages" class="sidebar-link" exact-active-class="sidebar-link--active">
|
||||
<div class="i-lucide-file-text h-4 w-4" />
|
||||
Toutes les pages
|
||||
</NuxtLink>
|
||||
<NuxtLink to="/admin/pages/home" class="sidebar-link" active-class="sidebar-link--active">
|
||||
<div class="i-lucide-home h-4 w-4" />
|
||||
Accueil
|
||||
</NuxtLink>
|
||||
<NuxtLink to="/admin/pages/modele-eco" class="sidebar-link" active-class="sidebar-link--active">
|
||||
<div class="i-lucide-book-open h-4 w-4" />
|
||||
Modèle éco
|
||||
<NuxtLink to="/admin/pages/numerique" class="sidebar-link" active-class="sidebar-link--active">
|
||||
<div class="i-lucide-monitor h-4 w-4" />
|
||||
Numérique
|
||||
</NuxtLink>
|
||||
<NuxtLink to="/admin/pages/economique" class="sidebar-link" active-class="sidebar-link--active">
|
||||
<div class="i-lucide-coins h-4 w-4" />
|
||||
Économique
|
||||
</NuxtLink>
|
||||
<NuxtLink to="/admin/pages/citoyenne" class="sidebar-link" active-class="sidebar-link--active">
|
||||
<div class="i-lucide-landmark h-4 w-4" />
|
||||
Citoyenne
|
||||
</NuxtLink>
|
||||
<NuxtLink to="/admin/pages/en-musique" class="sidebar-link" active-class="sidebar-link--active">
|
||||
<div class="i-lucide-headphones h-4 w-4" />
|
||||
|
||||
33
app/components/book/Actions.vue
Normal file
33
app/components/book/Actions.vue
Normal file
@@ -0,0 +1,33 @@
|
||||
<template>
|
||||
<div class="mt-8 flex flex-col gap-3 sm:flex-row sm:flex-wrap sm:gap-4">
|
||||
<UiBaseButton @click="$emit('open-player')">
|
||||
<div class="i-lucide-play mr-2 h-5 w-5" />
|
||||
Présentation musicale
|
||||
</UiBaseButton>
|
||||
<UiBaseButton variant="accent" @click="$emit('open-pdf')">
|
||||
<div class="i-lucide-book-open mr-2 h-5 w-5" />
|
||||
Lire le livre
|
||||
</UiBaseButton>
|
||||
<UiBaseButton v-if="showChapters" variant="ghost" to="/economique/modele-eco">
|
||||
<div class="i-lucide-list mr-2 h-5 w-5" />
|
||||
Présentation des chapitres
|
||||
</UiBaseButton>
|
||||
<UiBaseButton variant="ghost" to="/economique/commande">
|
||||
<div class="i-lucide-shopping-bag mr-2 h-5 w-5" />
|
||||
Commandez le livre
|
||||
</UiBaseButton>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
withDefaults(defineProps<{
|
||||
showChapters?: boolean
|
||||
}>(), {
|
||||
showChapters: true,
|
||||
})
|
||||
|
||||
defineEmits<{
|
||||
'open-player': []
|
||||
'open-pdf': []
|
||||
}>()
|
||||
</script>
|
||||
@@ -6,7 +6,7 @@
|
||||
<ul class="flex flex-col gap-1">
|
||||
<li v-for="chapter in chapters" :key="chapter.path">
|
||||
<NuxtLink
|
||||
:to="`/modele-eco/${chapter.stem?.split('/').pop()}`"
|
||||
:to="`/economique/modele-eco/${chapter.stem?.split('/').pop()}`"
|
||||
class="flex items-center gap-3 rounded-lg px-3 py-2 text-sm transition-colors hover:bg-white/5"
|
||||
active-class="bg-primary/10 text-primary font-medium"
|
||||
>
|
||||
|
||||
@@ -56,15 +56,17 @@
|
||||
</div>
|
||||
<!-- Secondary row -->
|
||||
<div v-if="secondaryActions(item.actions).length" class="axis-actions-secondary">
|
||||
<button
|
||||
<component
|
||||
:is="action.to ? resolveComponent('NuxtLink') : 'button'"
|
||||
v-for="action in secondaryActions(item.actions)"
|
||||
:key="action.id"
|
||||
:key="action.label"
|
||||
:to="action.to"
|
||||
class="axis-action-btn axis-action-btn--secondary"
|
||||
@click.stop="handleAction(action.id)"
|
||||
@click.stop="!action.to && handleAction(action.id)"
|
||||
>
|
||||
<div :class="iconClass(action.icon)" class="h-3.5 w-3.5" />
|
||||
{{ action.label }}
|
||||
</button>
|
||||
</component>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -79,6 +81,7 @@ interface AxisAction {
|
||||
icon: string
|
||||
highlight?: boolean
|
||||
secondary?: boolean
|
||||
to?: string
|
||||
}
|
||||
|
||||
interface AxisItem {
|
||||
|
||||
@@ -25,6 +25,24 @@
|
||||
@open-pdf="$emit('open-pdf')"
|
||||
@launch-gratewizard="launchGW"
|
||||
/>
|
||||
|
||||
<!-- Bloc GrateWizard — dans la section économique -->
|
||||
<button v-if="gw" class="gw-block mt-4" @click="launchGW">
|
||||
<div class="gw-icon">
|
||||
<div class="i-lucide-sparkles h-5 w-5" />
|
||||
</div>
|
||||
<div class="gw-text">
|
||||
<h3 class="font-display text-base font-bold text-white sm:text-lg">
|
||||
{{ gw.title }}
|
||||
</h3>
|
||||
<p class="text-white/55 text-xs sm:text-sm mt-0.5">
|
||||
{{ gw.subtitle }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="gw-arrow">
|
||||
<div class="i-lucide-arrow-up-right h-4 w-4" />
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</UiScrollReveal>
|
||||
|
||||
@@ -40,26 +58,6 @@
|
||||
</div>
|
||||
</UiScrollReveal>
|
||||
|
||||
<!-- Bloc GrateWizard -->
|
||||
<UiScrollReveal v-if="gw" :delay="250">
|
||||
<button class="gw-block" @click="launchGW">
|
||||
<div class="gw-icon">
|
||||
<div class="i-lucide-sparkles h-7 w-7" />
|
||||
</div>
|
||||
<div class="gw-text">
|
||||
<h2 class="font-display text-xl font-bold text-white sm:text-2xl">
|
||||
{{ gw.title }}
|
||||
</h2>
|
||||
<p class="text-white/55 text-sm sm:text-base mt-0.5">
|
||||
{{ gw.subtitle }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="gw-arrow">
|
||||
<div class="i-lucide-arrow-up-right h-5 w-5" />
|
||||
</div>
|
||||
</button>
|
||||
</UiScrollReveal>
|
||||
|
||||
<!-- Bloc Événement -->
|
||||
<UiScrollReveal v-if="evenement" :delay="350">
|
||||
<NuxtLink :to="evenement.to" class="event-block">
|
||||
@@ -160,10 +158,10 @@ function launchGW() {
|
||||
.gw-block {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1.25rem;
|
||||
gap: 1rem;
|
||||
width: 100%;
|
||||
padding: 1.75rem 2rem;
|
||||
border-radius: 1rem;
|
||||
padding: 1.25rem 1.5rem;
|
||||
border-radius: 0.75rem;
|
||||
border: none;
|
||||
background: linear-gradient(135deg, hsl(280 50% 20% / 0.35), hsl(260 40% 15% / 0.25));
|
||||
box-shadow: 0 0 40px hsl(280 60% 50% / 0.06), inset 0 1px 0 hsl(280 60% 70% / 0.08);
|
||||
@@ -187,9 +185,9 @@ function launchGW() {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 3.5rem;
|
||||
height: 3.5rem;
|
||||
border-radius: 0.875rem;
|
||||
width: 2.5rem;
|
||||
height: 2.5rem;
|
||||
border-radius: 0.625rem;
|
||||
background: hsl(280 60% 55% / 0.18);
|
||||
color: hsl(280 60% 72%);
|
||||
flex-shrink: 0;
|
||||
@@ -205,8 +203,8 @@ function launchGW() {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 2.5rem;
|
||||
height: 2.5rem;
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
border-radius: 50%;
|
||||
background: hsl(280 60% 55% / 0.1);
|
||||
color: hsl(280 60% 65%);
|
||||
|
||||
@@ -5,23 +5,6 @@
|
||||
<!-- Book cover -->
|
||||
<UiScrollReveal>
|
||||
<div class="book-cover-wrapper relative">
|
||||
<!-- Shadok pumper -->
|
||||
<svg class="shadok-pumper" viewBox="0 0 200 240" fill="none" aria-hidden="true">
|
||||
<ellipse cx="100" cy="130" rx="55" ry="65" fill="currentColor" opacity="0.9"/>
|
||||
<ellipse cx="100" cy="60" rx="30" ry="28" fill="currentColor" opacity="0.85"/>
|
||||
<circle cx="88" cy="54" r="6" fill="currentColor" opacity="0.2"/>
|
||||
<circle cx="112" cy="54" r="6" fill="currentColor" opacity="0.2"/>
|
||||
<circle cx="90" cy="53" r="2.5" fill="currentColor" opacity="0.5"/>
|
||||
<circle cx="114" cy="53" r="2.5" fill="currentColor" opacity="0.5"/>
|
||||
<polygon points="100,68 115,78 85,78" fill="currentColor" opacity="0.6"/>
|
||||
<line x1="80" y1="192" x2="70" y2="230" stroke="currentColor" stroke-width="4" stroke-linecap="round" opacity="0.7"/>
|
||||
<line x1="120" y1="192" x2="130" y2="230" stroke="currentColor" stroke-width="4" stroke-linecap="round" opacity="0.7"/>
|
||||
<line x1="70" y1="230" x2="55" y2="232" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.5"/>
|
||||
<line x1="130" y1="230" x2="145" y2="232" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.5"/>
|
||||
<line x1="155" y1="110" x2="190" y2="90" stroke="currentColor" stroke-width="4" stroke-linecap="round" opacity="0.6"/>
|
||||
<line x1="190" y1="90" x2="190" y2="120" stroke="currentColor" stroke-width="4" stroke-linecap="round" opacity="0.6"/>
|
||||
<rect x="180" y="118" width="18" height="40" rx="3" fill="currentColor" opacity="0.4"/>
|
||||
</svg>
|
||||
<div class="book-cover-3d">
|
||||
<img
|
||||
:src="content?.book.coverImage"
|
||||
@@ -48,16 +31,11 @@
|
||||
</UiScrollReveal>
|
||||
|
||||
<UiScrollReveal :delay="200">
|
||||
<div class="mt-8 flex flex-col gap-3 sm:flex-row sm:gap-4">
|
||||
<UiBaseButton @click="$emit('open-player')">
|
||||
<div class="i-lucide-play mr-2 h-5 w-5" />
|
||||
{{ content?.book.cta.player }}
|
||||
</UiBaseButton>
|
||||
<UiBaseButton variant="accent" @click="$emit('open-pdf')">
|
||||
<div class="i-lucide-book-open mr-2 h-5 w-5" />
|
||||
{{ content?.book.cta.pdf }}
|
||||
</UiBaseButton>
|
||||
</div>
|
||||
<BookActions
|
||||
:show-chapters="showChapters"
|
||||
@open-player="$emit('open-player')"
|
||||
@open-pdf="$emit('open-pdf')"
|
||||
/>
|
||||
</UiScrollReveal>
|
||||
</div>
|
||||
</div>
|
||||
@@ -66,6 +44,12 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
withDefaults(defineProps<{
|
||||
showChapters?: boolean
|
||||
}>(), {
|
||||
showChapters: true,
|
||||
})
|
||||
|
||||
defineEmits<{
|
||||
'open-player': []
|
||||
'open-pdf': []
|
||||
@@ -111,25 +95,4 @@ const { data: content } = await usePageContent('home')
|
||||
.heading-section {
|
||||
font-size: clamp(1.625rem, 4vw, 2.125rem);
|
||||
}
|
||||
|
||||
.shadok-pumper {
|
||||
position: absolute;
|
||||
right: 3%;
|
||||
bottom: 8%;
|
||||
width: clamp(90px, 12vw, 180px);
|
||||
opacity: 0.28;
|
||||
pointer-events: none;
|
||||
color: hsl(var(--color-primary));
|
||||
animation: shadok-float 10s ease-in-out infinite;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
@keyframes shadok-float {
|
||||
0%, 100% { transform: translateY(0); }
|
||||
50% { transform: translateY(-10px); }
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.shadok-pumper { display: none; }
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user