Add improved production UI 3

This commit is contained in:
Urtzi Alfaro
2025-09-23 19:24:22 +02:00
parent 7f871fc933
commit 7892c5a739
47 changed files with 6211 additions and 267 deletions

View File

@@ -0,0 +1,205 @@
// frontend/src/api/services/qualityTemplates.ts
/**
* Quality Check Template API service
*/
import { apiClient } from '../client';
import type {
QualityCheckTemplate,
QualityCheckTemplateCreate,
QualityCheckTemplateUpdate,
QualityCheckTemplateList,
QualityTemplateQueryParams,
ProcessStage,
QualityCheckExecutionRequest,
QualityCheckExecutionResponse
} from '../types/qualityTemplates';
class QualityTemplateService {
private readonly baseURL = '/production/api/v1/quality-templates';
/**
* Create a new quality check template
*/
async createTemplate(
tenantId: string,
templateData: QualityCheckTemplateCreate
): Promise<QualityCheckTemplate> {
const response = await apiClient.post(this.baseURL, templateData, {
headers: { 'X-Tenant-ID': tenantId }
});
return response.data;
}
/**
* Get quality check templates with filtering and pagination
*/
async getTemplates(
tenantId: string,
params?: QualityTemplateQueryParams
): Promise<QualityCheckTemplateList> {
const response = await apiClient.get(this.baseURL, {
params,
headers: { 'X-Tenant-ID': tenantId }
});
return response.data;
}
/**
* Get a specific quality check template
*/
async getTemplate(
tenantId: string,
templateId: string
): Promise<QualityCheckTemplate> {
const response = await apiClient.get(`${this.baseURL}/${templateId}`, {
headers: { 'X-Tenant-ID': tenantId }
});
return response.data;
}
/**
* Update a quality check template
*/
async updateTemplate(
tenantId: string,
templateId: string,
templateData: QualityCheckTemplateUpdate
): Promise<QualityCheckTemplate> {
const response = await apiClient.put(`${this.baseURL}/${templateId}`, templateData, {
headers: { 'X-Tenant-ID': tenantId }
});
return response.data;
}
/**
* Delete a quality check template
*/
async deleteTemplate(tenantId: string, templateId: string): Promise<void> {
await apiClient.delete(`${this.baseURL}/${templateId}`, {
headers: { 'X-Tenant-ID': tenantId }
});
}
/**
* Get templates applicable to a specific process stage
*/
async getTemplatesForStage(
tenantId: string,
stage: ProcessStage,
isActive: boolean = true
): Promise<QualityCheckTemplateList> {
const response = await apiClient.get(`${this.baseURL}/stages/${stage}`, {
params: { is_active: isActive },
headers: { 'X-Tenant-ID': tenantId }
});
return response.data;
}
/**
* Duplicate an existing quality check template
*/
async duplicateTemplate(
tenantId: string,
templateId: string
): Promise<QualityCheckTemplate> {
const response = await apiClient.post(`${this.baseURL}/${templateId}/duplicate`, {}, {
headers: { 'X-Tenant-ID': tenantId }
});
return response.data;
}
/**
* Execute a quality check using a template
*/
async executeQualityCheck(
tenantId: string,
executionData: QualityCheckExecutionRequest
): Promise<QualityCheckExecutionResponse> {
const response = await apiClient.post('/production/api/v1/quality-checks/execute', executionData, {
headers: { 'X-Tenant-ID': tenantId }
});
return response.data;
}
/**
* Get quality check history for a batch
*/
async getQualityCheckHistory(
tenantId: string,
batchId: string,
stage?: ProcessStage
): Promise<any[]> {
const response = await apiClient.get('/production/api/v1/quality-checks', {
params: { batch_id: batchId, process_stage: stage },
headers: { 'X-Tenant-ID': tenantId }
});
return response.data;
}
/**
* Get quality check templates for recipe configuration
*/
async getTemplatesForRecipe(
tenantId: string,
recipeId: string
): Promise<Record<ProcessStage, QualityCheckTemplate[]>> {
const allTemplates = await this.getTemplates(tenantId, { is_active: true });
// Group templates by applicable stages
const templatesByStage: Record<ProcessStage, QualityCheckTemplate[]> = {} as any;
Object.values(ProcessStage).forEach(stage => {
templatesByStage[stage] = allTemplates.templates.filter(template =>
!template.applicable_stages ||
template.applicable_stages.length === 0 ||
template.applicable_stages.includes(stage)
);
});
return templatesByStage;
}
/**
* Validate template configuration
*/
async validateTemplate(
tenantId: string,
templateData: Partial<QualityCheckTemplateCreate | QualityCheckTemplateUpdate>
): Promise<{ valid: boolean; errors: string[] }> {
try {
const response = await apiClient.post(`${this.baseURL}/validate`, templateData, {
headers: { 'X-Tenant-ID': tenantId }
});
return response.data;
} catch (error: any) {
if (error.response?.status === 400) {
return {
valid: false,
errors: [error.response.data.detail || 'Validation failed']
};
}
throw error;
}
}
/**
* Get default template suggestions based on product type
*/
async getDefaultTemplates(
tenantId: string,
productCategory: string
): Promise<QualityCheckTemplate[]> {
const templates = await this.getTemplates(tenantId, {
is_active: true,
category: productCategory
});
// Return commonly used templates for the product category
return templates.templates.filter(template =>
template.is_required || template.weight > 5.0
).sort((a, b) => b.weight - a.weight);
}
}
export const qualityTemplateService = new QualityTemplateService();