-import { ref, onMounted } from 'vue'
-import { useCollectionsStore } from '@PeopleManager/stores/collectionsStore'
import { CollectionObject } from '@PeopleManager/models/collection';
-// Store
-const collectionsStore = useCollectionsStore()
-
// Props
const props = defineProps<{
+ collections: CollectionObject[]
+ loading?: boolean
selectedCollection?: CollectionObject | null
}>()
@@ -17,43 +14,14 @@ const emit = defineEmits<{
'edit': [collection: CollectionObject]
}>()
-// State
-const loading = ref(false)
-const collections = ref([])
-
-// Lifecycle
-onMounted(async () => {
- loading.value = true
- try {
- collections.value = await collectionsStore.list()
- } catch (error) {
- console.error('[People] - Failed to load collections:', error)
- }
- loading.value = false
-})
-
// Functions
const onCollectionSelect = (collection: CollectionObject) => {
- console.log('[People] - Collection selected', collection)
emit('select', collection)
}
const onCollectionEdit = (collection: CollectionObject) => {
emit('edit', collection)
}
-
-// Expose refresh method
-defineExpose({
- async refresh() {
- loading.value = true
- try {
- collections.value = await collectionsStore.list()
- } catch (error) {
- console.error('[People] - Failed to load collections:', error)
- }
- loading.value = false
- }
-})
@@ -73,18 +41,18 @@ defineExpose({
-
+
- {{ collection.label }}
+ {{ collection.properties.label || 'Unnamed' }}
props.mode)
const entity = computed(() => props.selectedEntity || null)
-const entityObject = computed(() => entity.value?.data ?? null)
-const entityFresh = computed(() => entity.value?.id === null || entity.value?.id === undefined)
-const entityType = computed(() => entityObject.value?.type || 'individual')
+const entityObject = computed(() => entity.value?.properties ?? null)
+const entityFresh = computed(() => !entity.value?.identifier)
+const entityType = computed(() => (entityObject.value as any)?.type || 'individual')
// Determine which sections to show based on entity type
const showNames = computed(() => entityType.value === 'individual')
@@ -194,7 +194,7 @@ const removeVirtualLocation = (key: string) => {
diff --git a/src/stores/peopleStore.ts b/src/stores/peopleStore.ts
new file mode 100644
index 0000000..e572a5f
--- /dev/null
+++ b/src/stores/peopleStore.ts
@@ -0,0 +1,227 @@
+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'
+
+export const usePeopleStore = defineStore('peopleStore', () => {
+ const collectionsStore = useCollectionsStore()
+ const entitiesStore = useEntitiesStore()
+
+ // 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')
+
+ // 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 || '',
+ null,
+ collection.properties,
+ )
+ selectedCollection.value = created
+ } else {
+ await collectionsStore.update(
+ collection.provider,
+ collection.service,
+ collection.identifier,
+ collection.properties,
+ )
+ }
+
+ showCollectionEditor.value = false
+ }
+
+ async function deleteCollection(collection: CollectionObject) {
+ await collectionsStore.delete(collection.provider, collection.service, 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.provider,
+ targetCollection.service,
+ targetCollection.identifier,
+ entity.properties,
+ )
+ } else {
+ // Update
+ entity.properties.modified = new Date()
+ selectedEntity.value = await entitiesStore.update(
+ targetCollection.provider,
+ targetCollection.service,
+ targetCollection.identifier,
+ 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(
+ targetCollection.provider,
+ targetCollection.service,
+ targetCollection.identifier,
+ entity.identifier,
+ )
+
+ closeEntityEditor()
+ }
+
+ // --- Lifecycle ---
+
+ async function initialize() {
+ loading.value = true
+ try {
+ 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,
+
+ // Derived
+ collections,
+ entities,
+
+ // Collection actions
+ selectCollection,
+ openEditCollection,
+ openCreateCollection,
+ saveCollection,
+ deleteCollection,
+
+ // Entity actions
+ createEntity,
+ selectEntity,
+ startEditingEntity,
+ cancelEditingEntity,
+ closeEntityEditor,
+ saveEntity,
+ deleteEntity,
+
+ // Lifecycle
+ initialize,
+ }
+})