feat: ship agent-first mission control v0.2.57
This commit is contained in:
@@ -0,0 +1,141 @@
|
||||
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)),
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user