Sprint 1 : scaffolding complet de Glibredecision
Plateforme de decisions collectives pour Duniter/G1. Backend FastAPI async + PostgreSQL (14 tables, 8 routers, 6 services, moteur de vote avec formule d'inertie WoT/Smith/TechComm). Frontend Nuxt 4 + Nuxt UI v3 + Pinia (9 pages, 5 stores). Infrastructure Docker + Woodpecker CI + Traefik. Documentation technique et utilisateur (15 fichiers). Seed : Licence G1, Engagement Forgeron v2.0.0, 4 protocoles de vote. 30 tests unitaires (formules, mode params, vote nuance) -- tous verts. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
128
frontend/app/app.vue
Normal file
128
frontend/app/app.vue
Normal file
@@ -0,0 +1,128 @@
|
||||
<script setup lang="ts">
|
||||
const auth = useAuthStore()
|
||||
const route = useRoute()
|
||||
|
||||
const navigationItems = [
|
||||
{
|
||||
label: 'Documents de reference',
|
||||
icon: 'i-lucide-book-open',
|
||||
to: '/documents',
|
||||
},
|
||||
{
|
||||
label: 'Decisions',
|
||||
icon: 'i-lucide-scale',
|
||||
to: '/decisions',
|
||||
},
|
||||
{
|
||||
label: 'Mandats',
|
||||
icon: 'i-lucide-user-check',
|
||||
to: '/mandates',
|
||||
},
|
||||
{
|
||||
label: 'Protocoles',
|
||||
icon: 'i-lucide-settings',
|
||||
to: '/protocols',
|
||||
},
|
||||
{
|
||||
label: 'Sanctuaire',
|
||||
icon: 'i-lucide-archive',
|
||||
to: '/sanctuary',
|
||||
},
|
||||
]
|
||||
|
||||
onMounted(async () => {
|
||||
auth.hydrateFromStorage()
|
||||
if (auth.token) {
|
||||
try {
|
||||
await auth.fetchMe()
|
||||
} catch {
|
||||
auth.logout()
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UApp>
|
||||
<div class="min-h-screen flex flex-col">
|
||||
<!-- Header -->
|
||||
<header class="border-b border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-900">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="flex items-center justify-between h-16">
|
||||
<NuxtLink to="/" class="flex items-center gap-2">
|
||||
<UIcon name="i-lucide-vote" class="text-primary text-2xl" />
|
||||
<span class="text-xl font-bold text-gray-900 dark:text-white">Glibredecision</span>
|
||||
</NuxtLink>
|
||||
|
||||
<div class="flex items-center gap-4">
|
||||
<template v-if="auth.isAuthenticated">
|
||||
<UBadge
|
||||
:color="auth.identity?.is_smith ? 'success' : 'neutral'"
|
||||
variant="subtle"
|
||||
>
|
||||
{{ auth.identity?.display_name || auth.identity?.address?.slice(0, 12) + '...' }}
|
||||
</UBadge>
|
||||
<UBadge v-if="auth.identity?.is_techcomm" color="info" variant="subtle">
|
||||
Comite Tech
|
||||
</UBadge>
|
||||
<UButton
|
||||
icon="i-lucide-log-out"
|
||||
variant="ghost"
|
||||
color="neutral"
|
||||
size="sm"
|
||||
@click="auth.logout()"
|
||||
/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<UButton
|
||||
to="/login"
|
||||
icon="i-lucide-log-in"
|
||||
label="Se connecter"
|
||||
variant="soft"
|
||||
color="primary"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Main content with sidebar -->
|
||||
<div class="flex flex-1">
|
||||
<!-- Sidebar navigation -->
|
||||
<aside class="w-64 border-r border-gray-200 dark:border-gray-800 bg-gray-50 dark:bg-gray-900/50 hidden md:block">
|
||||
<nav class="p-4">
|
||||
<UNavigationMenu
|
||||
:items="navigationItems"
|
||||
orientation="vertical"
|
||||
class="w-full"
|
||||
/>
|
||||
</nav>
|
||||
</aside>
|
||||
|
||||
<!-- Mobile navigation -->
|
||||
<div class="md:hidden border-b border-gray-200 dark:border-gray-800 w-full absolute top-16 bg-white dark:bg-gray-900 z-10">
|
||||
<UNavigationMenu
|
||||
:items="navigationItems"
|
||||
class="px-4 py-2 overflow-x-auto"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Page content -->
|
||||
<main class="flex-1 p-4 sm:p-6 lg:p-8 md:mt-0 mt-12">
|
||||
<NuxtPage />
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="border-t border-gray-200 dark:border-gray-800 bg-gray-50 dark:bg-gray-900/50">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
|
||||
<div class="flex items-center justify-between text-sm text-gray-500">
|
||||
<span>Glibredecision v0.1.0 - Decisions collectives pour Duniter/G1</span>
|
||||
<span>Licence libre</span>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</UApp>
|
||||
</template>
|
||||
Reference in New Issue
Block a user