/** * Documents store: reference documents, their items, and item versions. * * Maps to the backend /api/v1/documents endpoints. */ export interface DocumentItem { id: string document_id: string position: string item_type: string title: string | null current_text: string voting_protocol_id: string | null sort_order: number section_tag: string | null inertia_preset: string is_permanent_vote: boolean created_at: string updated_at: string } export interface Document { id: string slug: string title: string doc_type: string version: string status: string description: string | null ipfs_cid: string | null chain_anchor: string | null genesis_json: string | null created_at: string updated_at: string items_count: number } export interface ItemVersion { id: string item_id: string version_number: number proposed_text: string rationale: string | null diff: string | null status: string proposed_by: string | null reviewed_by: string | null created_at: string updated_at: string } export interface DocumentCreate { slug: string title: string doc_type: string description?: string | null version?: string } export interface VersionProposal { proposed_text: string rationale?: string | null } interface DocumentsState { list: Document[] current: Document | null items: DocumentItem[] versions: ItemVersion[] loading: boolean error: string | null } export const useDocumentsStore = defineStore('documents', { state: (): DocumentsState => ({ list: [], current: null, items: [], versions: [], loading: false, error: null, }), getters: { byType: (state) => { return (docType: string) => state.list.filter(d => d.doc_type === docType) }, activeDocuments: (state): Document[] => { return state.list.filter(d => d.status === 'active') }, draftDocuments: (state): Document[] => { return state.list.filter(d => d.status === 'draft') }, }, actions: { /** * Fetch all documents with optional filters. */ async fetchAll(params?: { doc_type?: string; status?: string }) { this.loading = true this.error = null try { const { $api } = useApi() const query: Record = {} if (params?.doc_type) query.doc_type = params.doc_type if (params?.status) query.status = params.status this.list = await $api('/documents/', { query }) } catch (err: any) { this.error = err?.data?.detail || err?.message || 'Erreur lors du chargement des documents' } finally { this.loading = false } }, /** * Fetch a single document by slug and its items. */ async fetchBySlug(slug: string) { this.loading = true this.error = null try { const { $api } = useApi() const [doc, items] = await Promise.all([ $api(`/documents/${slug}`), $api(`/documents/${slug}/items`), ]) this.current = doc this.items = items } catch (err: any) { this.error = err?.data?.detail || err?.message || 'Document introuvable' } finally { this.loading = false } }, /** * Create a new reference document. */ async createDocument(payload: DocumentCreate) { this.loading = true this.error = null try { const { $api } = useApi() const doc = await $api('/documents/', { method: 'POST', body: payload, }) this.list.unshift(doc) return doc } catch (err: any) { this.error = err?.data?.detail || err?.message || 'Erreur lors de la creation du document' throw err } finally { this.loading = false } }, /** * Fetch all versions for a specific item within a document. */ async fetchItemVersions(slug: string, itemId: string) { this.loading = true this.error = null try { const { $api } = useApi() this.versions = await $api( `/documents/${slug}/items/${itemId}/versions`, ) } catch (err: any) { this.error = err?.data?.detail || err?.message || 'Erreur lors du chargement des versions' } finally { this.loading = false } }, /** * Propose a new version for a document item. */ async proposeVersion(slug: string, itemId: string, data: VersionProposal) { this.error = null try { const { $api } = useApi() const version = await $api( `/documents/${slug}/items/${itemId}/versions`, { method: 'POST', body: data, }, ) this.versions.unshift(version) return version } catch (err: any) { this.error = err?.data?.detail || err?.message || 'Erreur lors de la proposition' throw err } }, /** * Accept a proposed version. */ async acceptVersion(slug: string, itemId: string, versionId: string) { this.error = null try { const { $api } = useApi() const updated = await $api( `/documents/${slug}/items/${itemId}/versions/${versionId}/accept`, { method: 'POST' }, ) const idx = this.versions.findIndex(v => v.id === versionId) if (idx >= 0) this.versions[idx] = updated return updated } catch (err: any) { this.error = err?.data?.detail || err?.message || 'Erreur lors de l\'acceptation' throw err } }, /** * Reject a proposed version. */ async rejectVersion(slug: string, itemId: string, versionId: string) { this.error = null try { const { $api } = useApi() const updated = await $api( `/documents/${slug}/items/${itemId}/versions/${versionId}/reject`, { method: 'POST' }, ) const idx = this.versions.findIndex(v => v.id === versionId) if (idx >= 0) this.versions[idx] = updated return updated } catch (err: any) { this.error = err?.data?.detail || err?.message || 'Erreur lors du rejet' throw err } }, /** * Archive a document into the Sanctuary. */ async archiveDocument(slug: string) { this.error = null try { const { $api } = useApi() const doc = await $api( `/documents/${slug}/archive`, { method: 'POST' }, ) // Update current if viewing this document if (this.current?.slug === slug) { this.current = doc } // Update in list const idx = this.list.findIndex(d => d.slug === slug) if (idx >= 0) this.list[idx] = doc return doc } catch (err: any) { this.error = err?.data?.detail || err?.message || 'Erreur lors de l\'archivage' throw err } }, /** * Clear the current document, items and versions. */ clearCurrent() { this.current = null this.items = [] this.versions = [] }, }, })