feat(categories): detail page with fleet insights
CI / Lint · Typecheck · Test · Build (push) Successful in 46s
CI / Playwright (smoke) (push) Has been skipped
CI / Build & push images (push) Successful in 1m6s

Clicking a category anywhere in the app now opens /categories/:id with
MPN breakdown, manufacturer mix, failures by MPN, and past-EOL exposure
— a dual of the manufacturer detail page.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-04-17 15:41:47 -04:00
parent 62a3d615f4
commit a2b088463d
15 changed files with 1016 additions and 7 deletions
+15 -1
View File
@@ -1,4 +1,8 @@
import type { CreateCategoryRequest, UpdateCategoryRequest } from '@vector/shared';
import type {
CategoryInsights,
CreateCategoryRequest,
UpdateCategoryRequest,
} from '@vector/shared';
import { api } from './client.js';
import { getList } from './paginated.js';
import type { Category } from './types.js';
@@ -7,6 +11,16 @@ export function listCategories(filters: { page?: number; pageSize?: number } = {
return getList<Category>('/categories', filters);
}
export async function getCategory(id: string): Promise<Category> {
const res = await api.get<Category>(`/categories/${id}`);
return res.data;
}
export async function getCategoryInsights(id: string): Promise<CategoryInsights> {
const res = await api.get<CategoryInsights>(`/categories/${id}/insights`);
return res.data;
}
export async function createCategory(input: CreateCategoryRequest): Promise<Category> {
const res = await api.post<Category>('/categories', input);
return res.data;
+2
View File
@@ -165,8 +165,10 @@ export interface Tag {
export interface Category {
id: string;
name: string;
description?: string | null;
createdAt: string;
updatedAt: string;
_count?: { partModels: number };
}
export interface FmProblemPart {
+2
View File
@@ -86,6 +86,8 @@ export const queryKeys = {
all: ['categories'] as const,
list: (filters?: Record<string, unknown>) =>
[...queryKeys.categories.all, 'list', filters ?? {}] as const,
detail: (id: string) => [...queryKeys.categories.all, 'detail', id] as const,
insights: (id: string) => [...queryKeys.categories.all, 'insights', id] as const,
},
webhooks: {
all: ['webhooks'] as const,