ptitlutins/app/stores/voyageStore.ts
2025-10-07 00:20:32 +02:00

227 lines
5.9 KiB
TypeScript

import { defineStore } from "pinia"
import {
type VoyageLink,
type Event,
type Trip,
type Need,
type Location,
VoyageEntitiesNames,
type VoyageEntity,
} from "../types"
import { voyageService } from "../services/voyageService"
import { useVoyagesLinksStore } from "./voyagesLinksStore"
interface VoyageState {
events: Record<string, Record<string, Event>>
trips: Record<string, Record<string, Trip>>
needs: Record<string, Record<string, Need>>
locations: Record<string, Record<string, Location>>
loading: boolean
error: string | null
}
function getCurrentVoyageLinkId(): string {
const voyagesLinksStore = useVoyagesLinksStore()
const voyageLinkId = voyagesLinksStore.currentVoyageLink?.id
if (!voyageLinkId) {
throw new Error("No current voyage selected")
}
return voyageLinkId
}
function getCurrentVoyageId(): string {
const voyagesLinksStore = useVoyagesLinksStore()
const voyageId = voyagesLinksStore.currentVoyageLink?.voyage.id
if (!voyageId) {
throw new Error("No current voyage selected")
}
return voyageId
}
export const useVoyageStore = defineStore("voyage", {
state: (): VoyageState => ({
events: {},
trips: {},
needs: {},
locations: {},
loading: false,
error: null,
}),
getters: {
getVoyageData: (state) => {
const voyageId = getCurrentVoyageId()
return {
events: state.events[voyageId] ?? {},
trips: state.trips[voyageId] ?? {},
needs: state.needs[voyageId] ?? {},
locations: state.locations[voyageId] ?? {},
}
},
},
actions: {
// Events
async fetchEvents() {
await this.fetchItems<Event>(VoyageEntitiesNames.EVENT)
},
async addEvent(eventData: Omit<Event, "id">) {
return await this.addItem(VoyageEntitiesNames.EVENT, eventData)
},
async updateEvent(eventId: string, eventData: Partial<Event>) {
await this.updateItem(VoyageEntitiesNames.EVENT, eventId, eventData)
},
async removeEvent(eventId: string) {
await this.removeItem(VoyageEntitiesNames.EVENT, eventId)
},
// Trips
async fetchTrips() {
await this.fetchItems<Trip>(VoyageEntitiesNames.TRIP)
},
async addTrip(tripData: Omit<Trip, "id">) {
return await this.addItem(VoyageEntitiesNames.TRIP, tripData)
},
async updateTrip(tripId: string, tripData: Partial<Trip>) {
await this.updateItem(VoyageEntitiesNames.TRIP, tripId, tripData)
},
async removeTrip(tripId: string) {
await this.removeItem(VoyageEntitiesNames.TRIP, tripId)
},
// Needs
async fetchNeeds() {
await this.fetchItems<Need>(VoyageEntitiesNames.NEED)
},
async addNeed(needData: Omit<Need, "id">) {
return await this.addItem(VoyageEntitiesNames.NEED, needData)
},
async updateNeed(needId: string, needData: Partial<Need>) {
await this.updateItem(VoyageEntitiesNames.NEED, needId, needData)
},
async removeNeed(needId: string) {
await this.removeItem(VoyageEntitiesNames.NEED, needId)
},
// Locations
async fetchLocations() {
await this.fetchItems<Location>(VoyageEntitiesNames.LOCATION)
},
async addLocation(locationData: Omit<Location, "id">) {
return await this.addItem(VoyageEntitiesNames.LOCATION, locationData)
},
async updateLocation(locationId: string, locationData: Partial<Location>) {
await this.updateItem(
VoyageEntitiesNames.LOCATION,
locationId,
locationData,
)
},
async removeLocation(locationId: string) {
await this.removeItem(VoyageEntitiesNames.LOCATION, locationId)
},
// Generics function
async fetchItems<T extends VoyageEntity>(entity: VoyageEntitiesNames) {
this.loading = true
this.error = null
try {
const voyageLinkId = getCurrentVoyageLinkId()
const voyageId = getCurrentVoyageId()
const items = await voyageService.getEntityList<T>(voyageLinkId, entity)
this[entity][voyageId] = {}
for (const item of items) {
this[entity][voyageId][item.id] = item
}
} catch (error) {
throw error
} finally {
this.loading = false
}
},
async addItem<T extends VoyageEntity>(
entity: VoyageEntitiesNames,
itemData: Omit<T, "id">,
) {
this.loading = true
this.error = null
try {
const voyageLinkId = getCurrentVoyageLinkId()
const voyageId = getCurrentVoyageId()
const newItem = await voyageService.createEntity<T>(
voyageLinkId,
entity,
itemData,
)
if (!this[entity][voyageId]) {
this[entity][voyageId] = {}
}
this[entity][voyageId][newItem.id] = newItem
return newItem
} catch (error) {
throw error
} finally {
this.loading = false
}
},
async updateItem<T extends VoyageEntity>(
entity: VoyageEntitiesNames,
itemId: string,
itemData: Partial<T>,
) {
this.loading = true
this.error = null
try {
const voyageLinkId = getCurrentVoyageLinkId()
const voyageId = getCurrentVoyageId()
const updatedItem = await voyageService.updateEntity<T>(
voyageLinkId,
entity,
itemId,
itemData,
)
if (!this[entity][voyageId]) {
this[entity][voyageId] = {}
}
this[entity][voyageId][itemId] = updatedItem
} catch (error) {
throw error
} finally {
this.loading = false
}
},
async removeItem(entity: VoyageEntitiesNames, itemId: string) {
this.loading = true
this.error = null
try {
const voyageLinkId = getCurrentVoyageLinkId()
const voyageId = getCurrentVoyageId()
await voyageService.deleteEntity(voyageLinkId, entity, itemId)
delete this[entity][voyageId]?.[itemId]
} catch (error) {
throw error
} finally {
this.loading = false
}
},
},
})