feat(#17): CRUD de categorias — API Go + tela Vue + testes unitários

API REST /api/categories (GET/POST/PUT/DELETE) com regras de negócio:
categorias padrão não podem ser excluídas; categorias com transações vinculadas
também bloqueadas. Tela Vue com formulário inline de criação/edição, indicador
visual de categorias padrão e botão de exclusão condicional.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
This commit is contained in:
2026-05-26 20:11:54 -03:00
co-authored by Claude Sonnet 4.6
parent a3d8f363a5
commit d6782d51a5
12 changed files with 720 additions and 1 deletions
+50
View File
@@ -0,0 +1,50 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
import { api } from '@/services/api'
export interface Category {
id: number
name: string
color: string
is_default: boolean
created_at: string
updated_at: string
}
export const useCategoriesStore = defineStore('categories', () => {
const categories = ref<Category[]>([])
const loading = ref(false)
const error = ref<string | null>(null)
async function fetchAll() {
loading.value = true
error.value = null
try {
categories.value = await api.get<Category[]>('/categories')
} catch (e: any) {
error.value = e.message
} finally {
loading.value = false
}
}
async function create(name: string, color: string) {
const cat = await api.post<Category>('/categories', { name, color })
categories.value.push(cat)
return cat
}
async function update(id: number, name: string, color: string) {
const cat = await api.put<Category>(`/categories/${id}`, { name, color })
const idx = categories.value.findIndex((c) => c.id === id)
if (idx !== -1) categories.value[idx] = cat
return cat
}
async function remove(id: number) {
await api.delete(`/categories/${id}`)
categories.value = categories.value.filter((c) => c.id !== id)
}
return { categories, loading, error, fetchAll, create, update, remove }
})