forked from yvv/decision
- stores/collective.ts (état local-first, gabarits, import/export, seeds) + stores/decisions.ts (cycle de vie complet : capture→chemin→fenêtres→ sessions→cristallisation→épreuve du réel→révocation) - data/templates.ts : 7 gabarits (Page blanche observatoire-d'abord, 5 points de départ, Institution symétrique) - composables useFeed (13 sections du Fil en sélecteurs purs) + useSearch (index unique Cmd+K/Q0) - shell : layouts default/bare, app.vue mince, useMood v2 (Source/Margelle/ Nappe/Minuit), sceau 井 = logo, LdWorkspaceSelector avec finalité A1, LdAvatarStack (premier/second lieu), LdCountdown (suspension striée) - 338 tests vitest verts, npm run build zéro erreur Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
72 lines
2.0 KiB
TypeScript
72 lines
2.0 KiB
TypeScript
export interface Organization {
|
|
id: string
|
|
name: string
|
|
slug: string
|
|
org_type: string
|
|
is_transparent: boolean
|
|
color: string | null
|
|
icon: string | null
|
|
description: string | null
|
|
created_at: string
|
|
}
|
|
|
|
interface OrgState {
|
|
organizations: Organization[]
|
|
activeSlug: string | null
|
|
loading: boolean
|
|
error: string | null
|
|
}
|
|
|
|
export const useOrganizationsStore = defineStore('organizations', {
|
|
state: (): OrgState => ({
|
|
organizations: [],
|
|
activeSlug: null,
|
|
loading: false,
|
|
error: null,
|
|
}),
|
|
|
|
getters: {
|
|
active: (state): Organization | null =>
|
|
state.organizations.find(o => o.slug === state.activeSlug) ?? state.organizations[0] ?? null,
|
|
|
|
hasOrganizations: (state): boolean => state.organizations.length > 0,
|
|
},
|
|
|
|
actions: {
|
|
async fetchOrganizations() {
|
|
this.loading = true
|
|
this.error = null
|
|
try {
|
|
const { $api } = useApi()
|
|
const orgs = await $api<Organization[]>('/organizations/')
|
|
// Duniter G1 first, then alphabetical
|
|
this.organizations = orgs.sort((a, b) => {
|
|
if (a.slug === 'duniter-g1') return -1
|
|
if (b.slug === 'duniter-g1') return 1
|
|
return a.name.localeCompare(b.name)
|
|
})
|
|
// Restore persisted active slug, or default to first org
|
|
const stored = import.meta.client ? localStorage.getItem('libredecision_org') : null
|
|
if (stored && this.organizations.some(o => o.slug === stored)) {
|
|
this.activeSlug = stored
|
|
} else if (this.organizations[0]) {
|
|
this.activeSlug = this.organizations[0].slug
|
|
}
|
|
} catch (err: any) {
|
|
this.error = err?.message || 'Erreur lors du chargement des organisations'
|
|
} finally {
|
|
this.loading = false
|
|
}
|
|
},
|
|
|
|
setActive(slug: string) {
|
|
if (this.organizations.some(o => o.slug === slug)) {
|
|
this.activeSlug = slug
|
|
if (import.meta.client) {
|
|
localStorage.setItem('libredecision_org', slug)
|
|
}
|
|
}
|
|
},
|
|
},
|
|
})
|