import { computed, ref, shallowRef } from 'vue' import { defineStore } from 'pinia' import { CollectionObject } from '@PeopleManager/models/collection' import { EntityObject } from '@PeopleManager/models/entity' import { IndividualObject } from '@PeopleManager/models/individual' import { OrganizationObject } from '@PeopleManager/models/organization' import { GroupObject } from '@PeopleManager/models/group' import type { ServiceObject } from '@PeopleManager/models/service' import { useCollectionsStore } from '@PeopleManager/stores/collectionsStore' import { useEntitiesStore } from '@PeopleManager/stores/entitiesStore' import { useServicesStore } from '@PeopleManager/stores/servicesStore' import { useImportStore } from '@PeopleManager/stores/importStore' export const usePeopleStore = defineStore('peopleStore', () => { const servicesStore = useServicesStore() const collectionsStore = useCollectionsStore() const entitiesStore = useEntitiesStore() const importStore = useImportStore() // UI state const sidebarVisible = ref(true) const loading = ref(false) // Selection state const selectedCollection = shallowRef(null) const selectedEntity = shallowRef(null) // Entity editor state const entityEditorMode = ref<'edit' | 'view'>('view') // Collection editor state const showCollectionEditor = ref(false) const editingCollection = shallowRef(null) const collectionEditorMode = ref<'create' | 'edit'>('create') // Import state const showImportDialog = ref(false) // Derived state const collections = computed(() => collectionsStore.collections) const entities = computed(() => entitiesStore.entities) // --- Collection actions --- function selectCollection(collection: CollectionObject) { selectedCollection.value = collection selectedEntity.value = null } function openEditCollection(collection: CollectionObject) { editingCollection.value = collection collectionEditorMode.value = 'edit' showCollectionEditor.value = true } function openCreateCollection() { editingCollection.value = new CollectionObject() collectionEditorMode.value = 'create' showCollectionEditor.value = true } async function saveCollection(collection: CollectionObject, service: ServiceObject) { if (collectionEditorMode.value === 'create') { const created = await collectionsStore.create( service.provider, service.identifier ?? '', collection.properties, ) selectedCollection.value = created } else { await collectionsStore.update( collection.identifier, collection.properties, ) } showCollectionEditor.value = false } async function deleteCollection(collection: CollectionObject) { await collectionsStore.delete(collection.identifier) if (selectedCollection.value?.identifier === collection.identifier) { selectedCollection.value = null selectedEntity.value = null } showCollectionEditor.value = false } // --- Entity actions --- function createEntity(type: string) { const entity = new EntityObject() if (type === 'organization') { entity.properties = new OrganizationObject() } else if (type === 'group') { entity.properties = new GroupObject() } else { entity.properties = new IndividualObject() } selectedEntity.value = entity entityEditorMode.value = 'edit' } function selectEntity(entity: EntityObject) { selectedEntity.value = entity entityEditorMode.value = 'view' } function startEditingEntity() { entityEditorMode.value = 'edit' } function cancelEditingEntity() { entityEditorMode.value = 'view' } function closeEntityEditor() { selectedEntity.value = null entityEditorMode.value = 'view' } async function saveEntity(entity: EntityObject, collection?: CollectionObject | null) { const targetCollection = collection instanceof CollectionObject ? collection : selectedCollection.value if (!targetCollection) { throw new Error('[People] - No collection selected, cannot save entity') } if (!entity.identifier) { // Create entity.properties.created = new Date() selectedEntity.value = await entitiesStore.create( targetCollection.identifier, entity.properties, ) } else { // Update entity.properties.modified = new Date() selectedEntity.value = await entitiesStore.update( entity.identifier, entity.properties, ) } selectedCollection.value = targetCollection entityEditorMode.value = 'view' } async function deleteEntity(entity: EntityObject, collection?: CollectionObject | null) { const targetCollection = collection instanceof CollectionObject ? collection : selectedCollection.value if (!targetCollection) { throw new Error('[People] - No collection selected, cannot delete entity') } await entitiesStore.delete([entity.identifier]) closeEntityEditor() } // --- Import actions --- /** * Queue selected VCF files and open the import dialog. * Defaults each file's target to the currently selected collection. */ async function openImport(files: File[]) { importStore.removeAllFiles() importStore.reset() for (const file of files) { const contents = await file.text() const id = importStore.addFile({ name: file.name, contents, size: file.size, type: file.type, }) if (selectedCollection.value) { importStore.setCollectionForFile(id, selectedCollection.value.identifier) } } importStore.stage = 'selecting' showImportDialog.value = true } /** * Close the import dialog. When refresh is requested, reload the entity lists for * every collection that received contacts, then clear the import queue. */ async function closeImport(refresh: boolean = false) { showImportDialog.value = false if (refresh) { const targets = new Set() for (const id of importStore.order) { const target = importStore.sessions[id]?.targetIdentifier if (target) targets.add(target) } for (const target of targets) { await entitiesStore.list([target]) } } importStore.removeAllFiles() importStore.reset() } // --- Lifecycle --- async function initialize() { loading.value = true try { await servicesStore.list() await collectionsStore.list() if ( selectedCollection.value && !collections.value.find(c => c.identifier === selectedCollection.value?.identifier) ) { selectedCollection.value = null } } finally { loading.value = false } } return { // State sidebarVisible, loading, selectedCollection, selectedEntity, entityEditorMode, showCollectionEditor, editingCollection, collectionEditorMode, showImportDialog, // Derived collections, entities, // Collection actions selectCollection, openEditCollection, openCreateCollection, saveCollection, deleteCollection, // Entity actions createEntity, selectEntity, startEditingEntity, cancelEditingEntity, closeEntityEditor, saveEntity, deleteEntity, // Import actions openImport, closeImport, // Lifecycle initialize, } })