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:
@@ -9,8 +9,8 @@
|
||||
<p class="text-sm text-white/50">Identité, navigation, footer</p>
|
||||
</NuxtLink>
|
||||
|
||||
<NuxtLink to="/admin/pages/home" class="dash-card">
|
||||
<div class="i-lucide-home h-8 w-8 text-primary mb-2" />
|
||||
<NuxtLink to="/admin/pages" class="dash-card">
|
||||
<div class="i-lucide-file-text h-8 w-8 text-primary mb-2" />
|
||||
<h2 class="text-lg font-semibold text-white">Pages</h2>
|
||||
<p class="text-sm text-white/50">Contenus des pages publiques</p>
|
||||
</NuxtLink>
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
<div>
|
||||
<div class="flex items-center justify-between mb-6">
|
||||
<div>
|
||||
<NuxtLink to="/admin" class="text-sm text-white/40 hover:text-white/60 transition-colors">
|
||||
← Dashboard
|
||||
<NuxtLink to="/admin/pages" class="text-sm text-white/40 hover:text-white/60 transition-colors">
|
||||
← Pages
|
||||
</NuxtLink>
|
||||
<h1 class="font-display text-2xl font-bold text-white mt-1">
|
||||
Page : {{ pageName }}
|
||||
Page : {{ pagePath }}
|
||||
</h1>
|
||||
</div>
|
||||
<AdminSaveButton :saving="saving" :saved="saved" @save="save" />
|
||||
@@ -40,9 +40,12 @@ definePageMeta({
|
||||
})
|
||||
|
||||
const route = useRoute()
|
||||
const pageName = computed(() => route.params.name as string)
|
||||
const pagePath = computed(() => {
|
||||
const p = route.params.path
|
||||
return Array.isArray(p) ? p.join('/') : p
|
||||
})
|
||||
|
||||
const { data, error } = await useFetch(() => `/api/content/pages/${pageName.value}`)
|
||||
const { data, error } = await useFetch(() => `/api/content/pages/${pagePath.value}`)
|
||||
|
||||
const yamlContent = ref('')
|
||||
|
||||
@@ -60,7 +63,7 @@ async function save() {
|
||||
saved.value = false
|
||||
try {
|
||||
const parsed = yaml.parse(yamlContent.value)
|
||||
await $fetch(`/api/admin/content/pages/${pageName.value}`, {
|
||||
await $fetch(`/api/admin/content/pages/${pagePath.value}`, {
|
||||
method: 'PUT',
|
||||
body: parsed,
|
||||
})
|
||||
97
app/pages/admin/pages/index.vue
Normal file
97
app/pages/admin/pages/index.vue
Normal file
@@ -0,0 +1,97 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="flex items-center justify-between mb-6">
|
||||
<div>
|
||||
<NuxtLink to="/admin" class="text-sm text-white/40 hover:text-white/60 transition-colors">
|
||||
← Dashboard
|
||||
</NuxtLink>
|
||||
<h1 class="font-display text-2xl font-bold text-white mt-1">Pages</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="pages" class="flex flex-col gap-6">
|
||||
<!-- Root pages -->
|
||||
<div v-if="rootPages.length">
|
||||
<h2 class="font-display text-lg font-semibold text-white/80 mb-3">Pages principales</h2>
|
||||
<div class="grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
|
||||
<NuxtLink
|
||||
v-for="page in rootPages"
|
||||
:key="page.path"
|
||||
:to="`/admin/pages/${page.path}`"
|
||||
class="page-card"
|
||||
>
|
||||
<div class="i-lucide-file-text h-5 w-5 text-primary mb-1" />
|
||||
<span class="font-mono text-sm text-white">{{ page.label }}</span>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Section pages -->
|
||||
<div v-for="[section, sectionPages] in sections" :key="section">
|
||||
<h2 class="font-display text-lg font-semibold text-white/80 mb-3">
|
||||
<span class="i-lucide-folder h-4 w-4 inline-block mr-1 text-accent" />
|
||||
{{ section }}
|
||||
</h2>
|
||||
<div class="grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
|
||||
<NuxtLink
|
||||
v-for="page in sectionPages"
|
||||
:key="page.path"
|
||||
:to="`/admin/pages/${page.path}`"
|
||||
class="page-card"
|
||||
>
|
||||
<div class="i-lucide-file-text h-5 w-5 text-primary/60 mb-1" />
|
||||
<span class="font-mono text-sm text-white">{{ page.label }}</span>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
definePageMeta({
|
||||
layout: 'admin',
|
||||
middleware: 'admin',
|
||||
})
|
||||
|
||||
interface PageEntry {
|
||||
path: string
|
||||
label: string
|
||||
section?: string
|
||||
}
|
||||
|
||||
const { data: pages } = await useFetch<PageEntry[]>('/api/admin/content/pages')
|
||||
|
||||
const rootPages = computed(() =>
|
||||
(pages.value ?? []).filter(p => !p.section),
|
||||
)
|
||||
|
||||
const sections = computed(() => {
|
||||
const map = new Map<string, PageEntry[]>()
|
||||
for (const p of pages.value ?? []) {
|
||||
if (p.section) {
|
||||
if (!map.has(p.section)) map.set(p.section, [])
|
||||
map.get(p.section)!.push(p)
|
||||
}
|
||||
}
|
||||
return Array.from(map.entries())
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.page-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 1rem;
|
||||
border-radius: 0.5rem;
|
||||
border: 1px solid hsl(20 8% 14%);
|
||||
background: hsl(20 8% 6%);
|
||||
text-decoration: none;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.page-card:hover {
|
||||
border-color: hsl(12 76% 48% / 0.3);
|
||||
background: hsl(20 8% 8%);
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user