Refonte design : 4 humeurs, onboarding, sections avec boite a outils
- Systeme de themes adaptatifs : Peps (light chaud), Zen (light calme), Chagrine (dark violet), Grave (dark ambre) avec CSS custom properties - Dashboard d'accueil orienté onboarding avec cartes-portes et teaser boite a outils - SectionLayout reutilisable : liste + sidebar toolbox + status pills cliquables (En prepa / En vote / En vigueur / Clos) - ToolboxVignette : vignettes Contexte / Tutos / Choisir / Demarrer - Seed : Acte engagement certification + forgeron, Runtime Upgrade (decision on-chain), 3 modalites de vote (majoritaire, quadratique, permanent) - Backend adapte SQLite (Uuid portable, 204 fix, pool conditionnel) - Correction noms composants (pathPrefix: false), pinia/nuxt ^0.11 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,61 +1,150 @@
|
||||
<script setup lang="ts">
|
||||
const props = defineProps<{
|
||||
const props = withDefaults(defineProps<{
|
||||
status: string
|
||||
type?: 'document' | 'decision' | 'mandate' | 'version' | 'vote'
|
||||
type?: 'document' | 'decision' | 'mandate' | 'vote' | 'version'
|
||||
clickable?: boolean
|
||||
active?: boolean
|
||||
}>(), {
|
||||
clickable: true,
|
||||
active: false,
|
||||
})
|
||||
|
||||
const emit = defineEmits<{
|
||||
click: []
|
||||
}>()
|
||||
|
||||
const statusConfig: Record<string, Record<string, { color: string; label: string }>> = {
|
||||
document: {
|
||||
draft: { color: 'warning', label: 'Brouillon' },
|
||||
active: { color: 'success', label: 'Actif' },
|
||||
archived: { color: 'neutral', label: 'Archive' },
|
||||
},
|
||||
version: {
|
||||
proposed: { color: 'info', label: 'Propose' },
|
||||
voting: { color: 'warning', label: 'En vote' },
|
||||
accepted: { color: 'success', label: 'Accepte' },
|
||||
rejected: { color: 'error', label: 'Rejete' },
|
||||
},
|
||||
decision: {
|
||||
draft: { color: 'warning', label: 'Brouillon' },
|
||||
qualification: { color: 'info', label: 'Qualification' },
|
||||
review: { color: 'info', label: 'Revue' },
|
||||
voting: { color: 'primary', label: 'En vote' },
|
||||
executed: { color: 'success', label: 'Execute' },
|
||||
closed: { color: 'neutral', label: 'Clos' },
|
||||
},
|
||||
mandate: {
|
||||
draft: { color: 'warning', label: 'Brouillon' },
|
||||
candidacy: { color: 'info', label: 'Candidature' },
|
||||
voting: { color: 'primary', label: 'En vote' },
|
||||
active: { color: 'success', label: 'Actif' },
|
||||
reporting: { color: 'info', label: 'Rapport' },
|
||||
completed: { color: 'neutral', label: 'Termine' },
|
||||
revoked: { color: 'error', label: 'Revoque' },
|
||||
},
|
||||
vote: {
|
||||
open: { color: 'success', label: 'Ouvert' },
|
||||
closed: { color: 'warning', label: 'Ferme' },
|
||||
tallied: { color: 'neutral', label: 'Depouille' },
|
||||
},
|
||||
const STATUS_MAP: Record<string, { label: string; cssClass: string }> = {
|
||||
// Universal statuses
|
||||
draft: { label: 'En prepa', cssClass: 'status-prepa' },
|
||||
active: { label: 'En vigueur', cssClass: 'status-vigueur' },
|
||||
closed: { label: 'Clos', cssClass: 'status-clos' },
|
||||
|
||||
// Decision/vote specific
|
||||
qualification: { label: 'En prepa', cssClass: 'status-prepa' },
|
||||
review: { label: 'En prepa', cssClass: 'status-prepa' },
|
||||
voting: { label: 'En vote', cssClass: 'status-vote' },
|
||||
open: { label: 'En vote', cssClass: 'status-vote' },
|
||||
executed: { label: 'En vigueur', cssClass: 'status-vigueur' },
|
||||
|
||||
// Version specific
|
||||
pending: { label: 'En prepa', cssClass: 'status-prepa' },
|
||||
accepted: { label: 'En vigueur', cssClass: 'status-vigueur' },
|
||||
rejected: { label: 'Clos', cssClass: 'status-clos' },
|
||||
|
||||
// Mandate specific
|
||||
formulation: { label: 'En prepa', cssClass: 'status-prepa' },
|
||||
candidature: { label: 'En prepa', cssClass: 'status-prepa' },
|
||||
investiture: { label: 'En vote', cssClass: 'status-vote' },
|
||||
revoked: { label: 'Clos', cssClass: 'status-clos' },
|
||||
completed: { label: 'Clos', cssClass: 'status-clos' },
|
||||
}
|
||||
|
||||
const resolved = computed(() => {
|
||||
const typeKey = props.type || 'document'
|
||||
const typeMap = statusConfig[typeKey]
|
||||
if (typeMap && typeMap[props.status]) {
|
||||
return typeMap[props.status]
|
||||
}
|
||||
return { color: 'neutral', label: props.status }
|
||||
return STATUS_MAP[props.status] ?? { label: props.status, cssClass: 'status-prepa' }
|
||||
})
|
||||
|
||||
function handleClick() {
|
||||
if (props.clickable) {
|
||||
emit('click')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UBadge
|
||||
:color="(resolved.color as any)"
|
||||
variant="subtle"
|
||||
size="xs"
|
||||
<button
|
||||
v-if="clickable"
|
||||
type="button"
|
||||
class="status-pill"
|
||||
:class="[resolved.cssClass, { 'status-pill--active': active }]"
|
||||
@click="handleClick"
|
||||
>
|
||||
{{ resolved.label }}
|
||||
</UBadge>
|
||||
</button>
|
||||
<span
|
||||
v-else
|
||||
class="status-pill"
|
||||
:class="[resolved.cssClass]"
|
||||
>
|
||||
{{ resolved.label }}
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.status-pill {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 2px 10px;
|
||||
border-radius: 9999px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
line-height: 1.5;
|
||||
border: 1px solid transparent;
|
||||
cursor: default;
|
||||
transition: box-shadow 0.15s ease, border-color 0.15s ease;
|
||||
}
|
||||
|
||||
button.status-pill {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button.status-pill:hover {
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
.status-pill--active {
|
||||
box-shadow: 0 0 0 2px currentColor;
|
||||
}
|
||||
|
||||
/* --- En prepa (amber/warning) --- */
|
||||
.status-prepa {
|
||||
background-color: var(--ui-color-amber-50, #fffbeb);
|
||||
color: var(--ui-color-amber-700, #b45309);
|
||||
border-color: var(--ui-color-amber-200, #fde68a);
|
||||
}
|
||||
|
||||
/* --- En vigueur (green/success) --- */
|
||||
.status-vigueur {
|
||||
background-color: var(--ui-color-green-50, #f0fdf4);
|
||||
color: var(--ui-color-green-700, #15803d);
|
||||
border-color: var(--ui-color-green-200, #bbf7d0);
|
||||
}
|
||||
|
||||
/* --- En vote (blue/primary) --- */
|
||||
.status-vote {
|
||||
background-color: var(--ui-color-blue-50, #eff6ff);
|
||||
color: var(--ui-color-blue-700, #1d4ed8);
|
||||
border-color: var(--ui-color-blue-200, #bfdbfe);
|
||||
}
|
||||
|
||||
/* --- Clos (gray/neutral) --- */
|
||||
.status-clos {
|
||||
background-color: var(--ui-color-gray-50, #f9fafb);
|
||||
color: var(--ui-color-gray-500, #6b7280);
|
||||
border-color: var(--ui-color-gray-200, #e5e7eb);
|
||||
}
|
||||
|
||||
/* Dark mode overrides */
|
||||
.dark .status-prepa {
|
||||
background-color: var(--ui-color-amber-950, #451a03);
|
||||
color: var(--ui-color-amber-300, #fcd34d);
|
||||
border-color: var(--ui-color-amber-800, #92400e);
|
||||
}
|
||||
|
||||
.dark .status-vigueur {
|
||||
background-color: var(--ui-color-green-950, #052e16);
|
||||
color: var(--ui-color-green-300, #86efac);
|
||||
border-color: var(--ui-color-green-800, #166534);
|
||||
}
|
||||
|
||||
.dark .status-vote {
|
||||
background-color: var(--ui-color-blue-950, #172554);
|
||||
color: var(--ui-color-blue-300, #93c5fd);
|
||||
border-color: var(--ui-color-blue-800, #1e40af);
|
||||
}
|
||||
|
||||
.dark .status-clos {
|
||||
background-color: var(--ui-color-gray-900, #111827);
|
||||
color: var(--ui-color-gray-400, #9ca3af);
|
||||
border-color: var(--ui-color-gray-700, #374151);
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user