118 lines
3.1 KiB
JavaScript
118 lines
3.1 KiB
JavaScript
import { create } from 'zustand'
|
|
import * as projectApi from '../api/projects'
|
|
import * as deliverableApi from '../api/deliverables'
|
|
|
|
const useProjectStore = create((set, get) => ({
|
|
projects: [],
|
|
loading: false,
|
|
error: null,
|
|
|
|
getProjectById: (id) => get().projects.find(p => p.id === id),
|
|
|
|
// Async Actions
|
|
loadProjects: async () => {
|
|
set({ loading: true, error: null })
|
|
try {
|
|
const data = await projectApi.fetchProjects()
|
|
set({ projects: data, loading: false })
|
|
} catch (err) {
|
|
set({ error: err.message, loading: false })
|
|
}
|
|
},
|
|
|
|
createProject: async (data) => {
|
|
set({ loading: true })
|
|
try {
|
|
const newProj = await projectApi.createProject(data)
|
|
set(s => ({ projects: [newProj, ...s.projects], loading: false }))
|
|
return newProj
|
|
} catch (err) {
|
|
set({ error: err.message, loading: false })
|
|
throw err
|
|
}
|
|
},
|
|
|
|
updateProject: async (id, data) => {
|
|
try {
|
|
const updated = await projectApi.updateProject(id, data)
|
|
set(s => ({
|
|
projects: s.projects.map(p => p.id === updated.id ? { ...updated, deliverables: p.deliverables } : p),
|
|
}))
|
|
return updated
|
|
} catch (err) {
|
|
set({ error: err.message })
|
|
throw err
|
|
}
|
|
},
|
|
|
|
deleteProject: async (id) => {
|
|
try {
|
|
await projectApi.deleteProject(id)
|
|
set(s => ({ projects: s.projects.filter(p => p.id !== id) }))
|
|
} catch (err) {
|
|
set({ error: err.message })
|
|
throw err
|
|
}
|
|
},
|
|
|
|
toggleArchive: async (id, isArchived) => {
|
|
try {
|
|
const updated = isArchived
|
|
? await projectApi.unarchiveProject(id)
|
|
: await projectApi.archiveProject(id)
|
|
set(s => ({
|
|
projects: s.projects.map(p => p.id === updated.id ? { ...updated, deliverables: p.deliverables } : p),
|
|
}))
|
|
} catch (err) {
|
|
set({ error: err.message })
|
|
throw err
|
|
}
|
|
},
|
|
|
|
addDeliverable: async (data) => {
|
|
try {
|
|
const d = await deliverableApi.createDeliverable(data)
|
|
set(s => ({
|
|
projects: s.projects.map(p => p.id === d.project_id
|
|
? { ...p, deliverables: [...(p.deliverables||[]), d].sort((a,b) => new Date(a.due_date)-new Date(b.due_date)) }
|
|
: p
|
|
),
|
|
}))
|
|
return d
|
|
} catch (err) {
|
|
set({ error: err.message })
|
|
throw err
|
|
}
|
|
},
|
|
|
|
updateDeliverable: async (id, data) => {
|
|
try {
|
|
const updated = await deliverableApi.updateDeliverable(id, data)
|
|
set(s => ({
|
|
projects: s.projects.map(p => p.id === updated.project_id
|
|
? { ...p, deliverables: (p.deliverables||[]).map(d => d.id === updated.id ? updated : d) }
|
|
: p
|
|
),
|
|
}))
|
|
return updated
|
|
} catch (err) {
|
|
set({ error: err.message })
|
|
throw err
|
|
}
|
|
},
|
|
|
|
removeDeliverable: async (id) => {
|
|
try {
|
|
await deliverableApi.deleteDeliverable(id)
|
|
set(s => ({
|
|
projects: s.projects.map(p => ({ ...p, deliverables: (p.deliverables||[]).filter(d => d.id !== id) })),
|
|
}))
|
|
} catch (err) {
|
|
set({ error: err.message })
|
|
throw err
|
|
}
|
|
},
|
|
}))
|
|
|
|
export default useProjectStore
|