142 lines
4.8 KiB
TypeScript
142 lines
4.8 KiB
TypeScript
import { useMutation, useQuery, useQueryClient } from '@tanstack/vue-query'
|
|
import { computed, toValue, type MaybeRefOrGetter } from 'vue'
|
|
import type { components } from './generated/schema'
|
|
import { apiClient } from './client'
|
|
import { throwApiProblem } from './contracts'
|
|
import { queryKeys } from './queryClient'
|
|
import { reportOperationResult } from '../services/operationResults'
|
|
|
|
export type ProjectDto = components['schemas']['ProjectDto']
|
|
export type ProjectTaskDto = components['schemas']['ProjectTaskDto']
|
|
|
|
export interface CreateProjectInput {
|
|
name: string
|
|
description?: string | null
|
|
}
|
|
|
|
export interface UpdateProjectInput {
|
|
name?: string | null
|
|
description?: string | null
|
|
status?: string | null
|
|
}
|
|
|
|
export async function fetchProjects(signal?: AbortSignal): Promise<ProjectDto[]> {
|
|
const { data, error, response } = await apiClient.GET('/api/v1/projects', { signal })
|
|
if (!response.ok || error || !data) {
|
|
await throwApiProblem(response, 'Projekte konnten nicht geladen werden')
|
|
}
|
|
return data as ProjectDto[]
|
|
}
|
|
|
|
export async function fetchProject(id: string, signal?: AbortSignal): Promise<ProjectDto> {
|
|
const { data, error, response } = await apiClient.GET('/api/v1/projects/{id}', {
|
|
params: { path: { id } },
|
|
signal,
|
|
})
|
|
if (!response.ok || error || !data) {
|
|
await throwApiProblem(response, 'Projekt konnte nicht geladen werden')
|
|
}
|
|
return data as ProjectDto
|
|
}
|
|
|
|
async function createProject(input: CreateProjectInput): Promise<ProjectDto> {
|
|
const { data, error, response } = await apiClient.POST('/api/v1/projects', {
|
|
body: {
|
|
name: input.name,
|
|
description: input.description ?? null,
|
|
},
|
|
})
|
|
if (!response.ok || error || !data) {
|
|
await throwApiProblem(response, 'Projekt konnte nicht erstellt werden')
|
|
}
|
|
const project = data as ProjectDto
|
|
reportOperationResult(project.operation, 'Projekt erstellt')
|
|
return withoutProjectOperation(project)
|
|
}
|
|
|
|
export async function updateProject(id: string, input: UpdateProjectInput): Promise<ProjectDto> {
|
|
const { data, error, response } = await apiClient.PATCH('/api/v1/projects/{id}', {
|
|
params: { path: { id } },
|
|
body: input as components['schemas']['UpdateProjectRequest'],
|
|
})
|
|
if (!response.ok || error || !data) {
|
|
await throwApiProblem(response, 'Projekt konnte nicht gespeichert werden')
|
|
}
|
|
const project = data as ProjectDto
|
|
reportOperationResult(project.operation, 'Projekt aktualisiert')
|
|
return withoutProjectOperation(project)
|
|
}
|
|
|
|
function withoutProjectOperation(project: ProjectDto): ProjectDto {
|
|
const { operation: _operation, ...persistedProject } = project
|
|
return persistedProject
|
|
}
|
|
|
|
export async function fetchProjectTasks(
|
|
id: string,
|
|
signal?: AbortSignal,
|
|
): Promise<ProjectTaskDto[]> {
|
|
const { data, error, response } = await apiClient.GET('/api/v1/projects/{id}/tasks', {
|
|
params: { path: { id } },
|
|
signal,
|
|
})
|
|
if (!response.ok || error || !data) {
|
|
await throwApiProblem(response, 'Projektaufgaben konnten nicht geladen werden')
|
|
}
|
|
return data as ProjectTaskDto[]
|
|
}
|
|
|
|
export function useProjects() {
|
|
const client = useQueryClient()
|
|
const query = useQuery<ProjectDto[]>({
|
|
queryKey: queryKeys.projects(),
|
|
queryFn: ({ signal }) => fetchProjects(signal),
|
|
})
|
|
const createMutation = useMutation({
|
|
mutationFn: createProject,
|
|
onSuccess: project => {
|
|
client.setQueryData<ProjectDto[]>(queryKeys.projects(), current =>
|
|
current ? [project, ...current.filter(item => item.id !== project.id)] : [project])
|
|
client.setQueryData(queryKeys.project(project.id), project)
|
|
},
|
|
})
|
|
|
|
return {
|
|
query,
|
|
createProject: (input: CreateProjectInput) => createMutation.mutateAsync(input),
|
|
creating: createMutation.isPending,
|
|
createError: createMutation.error,
|
|
}
|
|
}
|
|
|
|
export function useProject(id: MaybeRefOrGetter<string>) {
|
|
const client = useQueryClient()
|
|
const query = useQuery<ProjectDto>({
|
|
queryKey: computed(() => queryKeys.project(toValue(id))),
|
|
queryFn: ({ signal }) => fetchProject(toValue(id), signal),
|
|
enabled: () => Boolean(toValue(id)),
|
|
})
|
|
const updateMutation = useMutation({
|
|
mutationFn: (input: UpdateProjectInput) => updateProject(toValue(id), input),
|
|
onSuccess: project => {
|
|
client.setQueryData(queryKeys.project(project.id), project)
|
|
client.setQueryData<ProjectDto[]>(queryKeys.projects(), current =>
|
|
current?.map(item => item.id === project.id ? project : item))
|
|
},
|
|
})
|
|
return {
|
|
query,
|
|
updateProject: (input: UpdateProjectInput) => updateMutation.mutateAsync(input),
|
|
updating: updateMutation.isPending,
|
|
updateError: updateMutation.error,
|
|
}
|
|
}
|
|
|
|
export function useProjectTasks(id: MaybeRefOrGetter<string>) {
|
|
return useQuery<ProjectTaskDto[]>({
|
|
queryKey: computed(() => queryKeys.projectTasks(toValue(id))),
|
|
queryFn: ({ signal }) => fetchProjectTasks(toValue(id), signal),
|
|
enabled: () => Boolean(toValue(id)),
|
|
})
|
|
}
|