f0dd952f63
- 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>
119 lines
2.8 KiB
TypeScript
119 lines
2.8 KiB
TypeScript
import api from './client'
|
|
|
|
export type WidgetType =
|
|
| 'ProductionStats'
|
|
| 'QueueStatus'
|
|
| 'RecentRenders'
|
|
| 'CostOverview'
|
|
| 'WorkerStatus'
|
|
| 'KPISummary'
|
|
| 'OrderThroughput'
|
|
| 'RevenueChart'
|
|
| 'ItemStatus'
|
|
| 'ProcessingTimes'
|
|
| 'RenderTimeByOutputType'
|
|
| 'OutputTypeUsage'
|
|
| 'TopProducts'
|
|
| 'OrdersByUser'
|
|
| 'RenderBackendStats'
|
|
| 'RenderThroughput'
|
|
| 'MaterialCoverage'
|
|
|
|
export interface WidgetPosition {
|
|
col: number
|
|
row: number
|
|
w: number
|
|
h: number
|
|
}
|
|
|
|
export interface WidgetConfig {
|
|
widget_type: WidgetType
|
|
position: WidgetPosition
|
|
config?: Record<string, unknown>
|
|
}
|
|
|
|
interface DashboardConfigResponse {
|
|
widgets: WidgetConfig[]
|
|
}
|
|
|
|
export async function getDashboardConfig(): Promise<WidgetConfig[]> {
|
|
const { data } = await api.get<DashboardConfigResponse>('/dashboard/config')
|
|
return data.widgets
|
|
}
|
|
|
|
export async function updateDashboardConfig(
|
|
widgets: WidgetConfig[]
|
|
): Promise<WidgetConfig[]> {
|
|
const { data } = await api.put<DashboardConfigResponse>('/dashboard/config', {
|
|
widgets,
|
|
})
|
|
return data.widgets
|
|
}
|
|
|
|
export async function getTenantDefaultDashboard(): Promise<WidgetConfig[]> {
|
|
const { data } = await api.get<DashboardConfigResponse>(
|
|
'/dashboard/tenant-default'
|
|
)
|
|
return data.widgets
|
|
}
|
|
|
|
export async function updateTenantDefaultDashboard(
|
|
widgets: WidgetConfig[]
|
|
): Promise<WidgetConfig[]> {
|
|
const { data } = await api.put<DashboardConfigResponse>(
|
|
'/dashboard/tenant-default',
|
|
{ widgets }
|
|
)
|
|
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
|
|
}
|