feat: material alias seeds expansion, bulk product delete, dashboard stats widgets
- Material alias seeds: 95 → 855 aliases covering German variants, DIN standards, Werkstoffnummern, industry terms, English equivalents, polymer abbreviations - Batch product delete/deactivate endpoint (POST /products/batch-delete) - Multi-select UI on Products page with floating action bar - Dashboard: RenderThroughput + MaterialCoverage widgets - Dashboard stats endpoint (GET /admin/dashboard-stats) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -16,6 +16,8 @@ export type WidgetType =
|
||||
| 'TopProducts'
|
||||
| 'OrdersByUser'
|
||||
| 'RenderBackendStats'
|
||||
| 'RenderThroughput'
|
||||
| 'MaterialCoverage'
|
||||
|
||||
export interface WidgetPosition {
|
||||
col: number
|
||||
@@ -64,3 +66,53 @@ export async function updateTenantDefaultDashboard(
|
||||
)
|
||||
return data.widgets
|
||||
}
|
||||
|
||||
// ── Dashboard Stats ──────────────────────────────────────────────────────────
|
||||
|
||||
export interface RenderThroughputStats {
|
||||
completed_today: number
|
||||
completed_this_week: number
|
||||
completed_this_month: number
|
||||
failed_today: number
|
||||
failed_this_week: number
|
||||
failed_this_month: number
|
||||
avg_render_time_s: number | null
|
||||
median_render_time_s: number | null
|
||||
}
|
||||
|
||||
export interface MaterialCoverageStats {
|
||||
total_unique_materials: number
|
||||
mapped_materials: number
|
||||
unmapped_materials: number
|
||||
coverage_pct: number
|
||||
library_material_count: number
|
||||
alias_count: number
|
||||
}
|
||||
|
||||
export interface ProductStatsOverview {
|
||||
total_products: number
|
||||
with_step_files: number
|
||||
without_step_files: number
|
||||
step_coverage_pct: number
|
||||
}
|
||||
|
||||
export interface OrderStatusBreakdown {
|
||||
draft: number
|
||||
submitted: number
|
||||
processing: number
|
||||
completed: number
|
||||
rejected: number
|
||||
total: number
|
||||
}
|
||||
|
||||
export interface DashboardStats {
|
||||
render_throughput: RenderThroughputStats
|
||||
material_coverage: MaterialCoverageStats
|
||||
product_stats: ProductStatsOverview
|
||||
order_status: OrderStatusBreakdown
|
||||
}
|
||||
|
||||
export async function getDashboardStats(): Promise<DashboardStats> {
|
||||
const { data } = await api.get<DashboardStats>('/admin/dashboard-stats')
|
||||
return data
|
||||
}
|
||||
|
||||
@@ -109,6 +109,17 @@ export async function deleteProduct(id: string, hard = false): Promise<void> {
|
||||
await api.delete(`/products/${id}`, { params: hard ? { hard: true } : undefined })
|
||||
}
|
||||
|
||||
export async function batchDeleteProducts(
|
||||
productIds: string[],
|
||||
hard = false,
|
||||
): Promise<{ deleted: number; not_found: number }> {
|
||||
const res = await api.post<{ deleted: number; not_found: number }>(
|
||||
'/products/batch-delete',
|
||||
{ product_ids: productIds, hard },
|
||||
)
|
||||
return res.data
|
||||
}
|
||||
|
||||
export interface ProductCadUploadResponse {
|
||||
cad_file_id: string
|
||||
original_name: string
|
||||
|
||||
Reference in New Issue
Block a user