feat: use module store

Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
This commit is contained in:
2026-02-17 19:11:12 -05:00
parent 6a7b28b86d
commit b663efbb3e
10 changed files with 883 additions and 612 deletions
+424
View File
@@ -0,0 +1,424 @@
import { computed, ref, shallowRef } from 'vue'
import { defineStore } from 'pinia'
import { useUserStore } from '@KTXC/stores/userStore'
import { CollectionObject } from '@ChronoManager/models/collection'
import { EntityObject } from '@ChronoManager/models/entity'
import { EventObject } from '@ChronoManager/models/event'
import { TaskObject } from '@ChronoManager/models/task'
import { ServiceObject } from '@ChronoManager/models/service'
import { useCollectionsStore } from '@ChronoManager/stores/collectionsStore'
import { useEntitiesStore } from '@ChronoManager/stores/entitiesStore'
import type { SourceSelector } from '@ChronoManager/types'
import type { CalendarView as CalendarViewType } from '@/types'
import {
AGENDA_VIEW_SPANS,
DAYS_VIEW_SPANS,
type AgendaViewSpan,
type DaysViewSpan,
} from '@/types/spans'
import { useChronoEntityActions } from '@/composables/useChronoEntityActions'
type EntitySources = Record<string, Record<string, Record<string | number, true>>>
export const useChronoStore = defineStore('chronoStore', () => {
const userStore = useUserStore()
const collectionsStore = useCollectionsStore()
const entitiesStore = useEntitiesStore()
const entityActions = useChronoEntityActions(entitiesStore, collectionsStore)
const savedCalendarView = userStore.getSetting('chrono.calendarView')
const savedDaysViewSpan = userStore.getSetting('chrono.daysViewSpan')
const savedAgendaViewSpan = userStore.getSetting('chrono.agendaViewSpan')
const viewMode = ref<'calendar' | 'tasks'>('calendar')
const calendarView = ref<CalendarViewType>(
savedCalendarView === 'month' || savedCalendarView === 'agenda' || savedCalendarView === 'days'
? savedCalendarView
: 'days',
)
const daysViewSpan = ref<DaysViewSpan>(
typeof savedDaysViewSpan === 'string' && DAYS_VIEW_SPANS.includes(savedDaysViewSpan as DaysViewSpan)
? (savedDaysViewSpan as DaysViewSpan)
: '7d',
)
const agendaViewSpan = ref<AgendaViewSpan>(
typeof savedAgendaViewSpan === 'string' && AGENDA_VIEW_SPANS.includes(savedAgendaViewSpan as AgendaViewSpan)
? (savedAgendaViewSpan as AgendaViewSpan)
: '1w',
)
const currentDate = ref(new Date())
const sidebarVisible = ref(true)
const selectedCollection = shallowRef<CollectionObject | null>(null)
const selectedEntity = shallowRef<EntityObject | null>(null)
const showEventEditor = ref(false)
const showTaskEditor = ref(false)
const showCollectionEditor = ref(false)
const entityEditorMode = ref<'edit' | 'view'>('view')
const editingCollection = shallowRef<CollectionObject | null>(null)
const collectionEditorMode = ref<'create' | 'edit'>('create')
const collectionEditorType = ref<'calendar' | 'tasklist'>('calendar')
const loading = ref(false)
const collections = computed(() => collectionsStore.collections)
const entities = computed(() => entitiesStore.entities)
const calendars = computed(() => {
return collections.value.filter(col => col.properties.contents?.event)
})
const taskLists = computed(() => {
return collections.value.filter(col => col.properties.contents?.task)
})
const events = computed(() => {
return entities.value.filter(entity => entity.properties instanceof EventObject)
})
const tasks = computed(() => {
return entities.value.filter(entity => entity.properties instanceof TaskObject)
})
const isTaskView = computed(() => viewMode.value === 'tasks')
const filteredEvents = computed(() => {
const visibleCalendarIds = calendars.value
.filter(cal => cal.properties.visibility !== false)
.map(cal => cal.identifier)
return events.value.filter(event => visibleCalendarIds.includes(event.collection))
})
const filteredTasks = computed(() => tasks.value)
function buildSources(collectionItems: CollectionObject[]): EntitySources {
return collectionItems.reduce<EntitySources>((acc, collection) => {
if (!acc[collection.provider]) {
acc[collection.provider] = {}
}
const serviceKey = String(collection.service)
if (!acc[collection.provider][serviceKey]) {
acc[collection.provider][serviceKey] = {}
}
acc[collection.provider][serviceKey][collection.identifier] = true
return acc
}, {})
}
function setViewMode(mode: 'calendar' | 'tasks') {
viewMode.value = mode
}
function setCalendarView(view: CalendarViewType) {
calendarView.value = view
userStore.setSetting('chrono.calendarView', view)
}
function setDaysViewSpan(span: DaysViewSpan) {
if (!DAYS_VIEW_SPANS.includes(span)) {
return
}
daysViewSpan.value = span
userStore.setSetting('chrono.daysViewSpan', span)
}
function setAgendaViewSpan(span: AgendaViewSpan) {
agendaViewSpan.value = span
userStore.setSetting('chrono.agendaViewSpan', span)
}
function selectCalendar(calendar: CollectionObject) {
selectedCollection.value = calendar
}
function selectTaskList(list: CollectionObject) {
selectedCollection.value = list
}
function openCreateCalendar() {
editingCollection.value = new CollectionObject()
editingCollection.value.properties.fromJson({
...editingCollection.value.properties.toJson(),
contents: { event: true },
})
collectionEditorMode.value = 'create'
collectionEditorType.value = 'calendar'
showCollectionEditor.value = true
}
function openCreateTaskList() {
editingCollection.value = new CollectionObject()
editingCollection.value.properties.fromJson({
...editingCollection.value.properties.toJson(),
contents: { task: true },
})
collectionEditorMode.value = 'create'
collectionEditorType.value = 'tasklist'
showCollectionEditor.value = true
}
function openEditCalendar(collection: CollectionObject) {
editingCollection.value = collection
collectionEditorMode.value = 'edit'
collectionEditorType.value = 'calendar'
showCollectionEditor.value = true
}
function openEditTaskList(collection: CollectionObject) {
editingCollection.value = collection
collectionEditorMode.value = 'edit'
collectionEditorType.value = 'tasklist'
showCollectionEditor.value = true
}
function ensureSelectedCollection(targetType: 'calendar' | 'tasklist'): CollectionObject | null {
const list = targetType === 'calendar' ? calendars.value : taskLists.value
if (!selectedCollection.value && list.length > 0) {
selectedCollection.value = list[0]
}
return selectedCollection.value
}
function createEvent() {
const collection = ensureSelectedCollection('calendar')
if (!collection) {
return
}
const entity = new EntityObject()
entity.properties = new EventObject()
selectedEntity.value = entity
entityEditorMode.value = 'edit'
showEventEditor.value = true
}
function editEvent(entity: EntityObject) {
selectedEntity.value = entity
entityEditorMode.value = 'view'
showEventEditor.value = true
}
function createTask() {
const collection = ensureSelectedCollection('tasklist')
if (!collection) {
return
}
const entity = new EntityObject()
entity.properties = new TaskObject()
selectedEntity.value = entity
entityEditorMode.value = 'edit'
showTaskEditor.value = true
}
function editTask(entity: EntityObject) {
selectedEntity.value = entity
entityEditorMode.value = 'view'
showTaskEditor.value = true
}
function createEventFromDate(date: Date) {
const collection = ensureSelectedCollection('calendar')
if (!collection) {
return
}
const entity = new EntityObject()
entity.properties = new EventObject()
const eventData = entity.properties as EventObject
eventData.startsOn = date.toISOString()
eventData.endsOn = new Date(date.getTime() + 60 * 60 * 1000).toISOString()
selectedEntity.value = entity
entityEditorMode.value = 'edit'
showEventEditor.value = true
}
function startEditingSelectedEntity() {
entityEditorMode.value = 'edit'
}
function cancelEditingSelectedEntity() {
entityEditorMode.value = 'view'
}
function closeEntityEditor() {
selectedEntity.value = null
entityEditorMode.value = 'view'
showEventEditor.value = false
showTaskEditor.value = false
}
async function toggleCalendarVisibility(collection: CollectionObject) {
const nextVisibility = collection.properties.visibility === false
const updated = collection.clone()
updated.properties.visibility = nextVisibility
await collectionsStore.update(
updated.provider,
updated.service,
updated.identifier,
updated.properties,
)
}
async function saveEvent(entity: EntityObject, collection?: CollectionObject | null) {
const targetCollection = collection instanceof CollectionObject
? collection
: selectedCollection.value
if (!targetCollection) {
throw new Error('No calendar collection selected')
}
selectedEntity.value = await entityActions.saveEntity(entity, targetCollection)
selectedCollection.value = targetCollection
entityEditorMode.value = 'view'
}
async function saveTask(entity: EntityObject, collection?: CollectionObject | null) {
const targetCollection = collection instanceof CollectionObject
? collection
: selectedCollection.value
if (!targetCollection) {
throw new Error('No task list selected')
}
selectedEntity.value = await entityActions.saveEntity(entity, targetCollection)
selectedCollection.value = targetCollection
entityEditorMode.value = 'view'
}
async function deleteEvent(entity: EntityObject, collection?: CollectionObject | null) {
await entityActions.deleteEntity(entity, collection)
closeEntityEditor()
}
async function deleteTask(entity: EntityObject, collection?: CollectionObject | null) {
await entityActions.deleteEntity(entity, collection)
closeEntityEditor()
}
async function toggleTaskComplete(taskId: string | number) {
const taskEntity = tasks.value.find(task => task.identifier === taskId)
if (!taskEntity) {
return
}
await entityActions.toggleTaskCompletion(taskEntity)
}
async function saveCollection(collection: CollectionObject, service: ServiceObject) {
if (collectionEditorMode.value === 'create') {
await collectionsStore.create(
service.provider,
service.identifier || '',
null,
collection.properties,
)
} else {
await collectionsStore.update(
collection.provider,
collection.service,
collection.identifier,
collection.properties,
)
}
}
async function deleteCollection(collection: CollectionObject) {
await collectionsStore.delete(collection.provider, collection.service, collection.identifier)
if (selectedCollection.value?.identifier === collection.identifier) {
selectedCollection.value = null
}
}
async function initialize() {
loading.value = true
try {
await collectionsStore.list()
const sources = buildSources(collections.value)
if (Object.keys(sources).length > 0) {
await entitiesStore.list(sources as SourceSelector)
}
if (
selectedCollection.value
&& !collections.value.find(collection => collection.identifier === selectedCollection.value?.identifier)
) {
selectedCollection.value = null
}
} finally {
loading.value = false
}
}
return {
viewMode,
calendarView,
daysViewSpan,
agendaViewSpan,
currentDate,
sidebarVisible,
selectedCollection,
selectedEntity,
showEventEditor,
showTaskEditor,
showCollectionEditor,
entityEditorMode,
editingCollection,
collectionEditorMode,
collectionEditorType,
loading,
collections,
entities,
calendars,
taskLists,
events,
tasks,
isTaskView,
filteredEvents,
filteredTasks,
setViewMode,
setCalendarView,
setDaysViewSpan,
setAgendaViewSpan,
selectCalendar,
selectTaskList,
openCreateCalendar,
openCreateTaskList,
openEditCalendar,
openEditTaskList,
createEvent,
editEvent,
createTask,
editTask,
createEventFromDate,
startEditingSelectedEntity,
cancelEditingSelectedEntity,
closeEntityEditor,
toggleCalendarVisibility,
toggleTaskComplete,
saveEvent,
deleteEvent,
saveTask,
deleteTask,
saveCollection,
deleteCollection,
initialize,
}
})