feat: Implement mock API service with endpoints for system, recipes, process control, hardware, safety, and user management
This commit is contained in:
569
python_rewrite/frontend/src/services/mockApi.ts
Normal file
569
python_rewrite/frontend/src/services/mockApi.ts
Normal file
@@ -0,0 +1,569 @@
|
|||||||
|
import type {
|
||||||
|
SystemInfo,
|
||||||
|
SystemStatus,
|
||||||
|
Recipe,
|
||||||
|
RecipeCreate,
|
||||||
|
RecipeUpdate,
|
||||||
|
RecipeList,
|
||||||
|
ProcessStatus,
|
||||||
|
ProcessStartRequest,
|
||||||
|
ProcessActionResponse,
|
||||||
|
HardwareStatus,
|
||||||
|
SafetyStatus,
|
||||||
|
User,
|
||||||
|
UserCreate,
|
||||||
|
UserUpdate,
|
||||||
|
} from '../types'
|
||||||
|
|
||||||
|
// Mock data
|
||||||
|
const mockSystemInfo: SystemInfo = {
|
||||||
|
name: 'Chocolate Tempering Machine',
|
||||||
|
version: '2.0.0-mock',
|
||||||
|
environment: 'mock',
|
||||||
|
api_version: '1.0.0',
|
||||||
|
features: {
|
||||||
|
recipe_management: true,
|
||||||
|
process_control: true,
|
||||||
|
hardware_monitoring: false, // Disabled in mock mode
|
||||||
|
safety_monitoring: true,
|
||||||
|
user_management: true,
|
||||||
|
real_time_monitoring: true,
|
||||||
|
},
|
||||||
|
endpoints: {
|
||||||
|
recipes: '/api/v1/recipes',
|
||||||
|
process: '/api/v1/process',
|
||||||
|
hardware: '/api/v1/hardware',
|
||||||
|
users: '/api/v1/users',
|
||||||
|
system: '/api/v1/system',
|
||||||
|
health: '/health',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const mockSystemStatus: SystemStatus = {
|
||||||
|
system_status: 'warning', // Warning due to mock mode
|
||||||
|
process_status: 'idle',
|
||||||
|
hardware_status: 'disconnected', // No hardware in mock mode
|
||||||
|
safety_status: 'safe',
|
||||||
|
active_alarms: 0,
|
||||||
|
uptime_seconds: 3600,
|
||||||
|
last_updated: new Date().toISOString(),
|
||||||
|
}
|
||||||
|
|
||||||
|
const mockRecipes: Recipe[] = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: 'Dark Chocolate 70%',
|
||||||
|
description: 'Premium dark chocolate tempering recipe',
|
||||||
|
heating_temp: 50.0,
|
||||||
|
cooling_temp: 27.0,
|
||||||
|
working_temp: 31.0,
|
||||||
|
heating_time: 300,
|
||||||
|
cooling_time: 180,
|
||||||
|
working_time: 600,
|
||||||
|
mixer_speed: 50,
|
||||||
|
fountain_delay: 30,
|
||||||
|
pedal_enabled: true,
|
||||||
|
is_active: true,
|
||||||
|
created_at: '2024-01-01T00:00:00Z',
|
||||||
|
updated_at: '2024-01-01T00:00:00Z',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: 'Milk Chocolate',
|
||||||
|
description: 'Creamy milk chocolate tempering recipe',
|
||||||
|
heating_temp: 45.0,
|
||||||
|
cooling_temp: 26.0,
|
||||||
|
working_temp: 29.0,
|
||||||
|
heating_time: 240,
|
||||||
|
cooling_time: 150,
|
||||||
|
working_time: 480,
|
||||||
|
mixer_speed: 45,
|
||||||
|
fountain_delay: 25,
|
||||||
|
pedal_enabled: true,
|
||||||
|
is_active: true,
|
||||||
|
created_at: '2024-01-02T00:00:00Z',
|
||||||
|
updated_at: '2024-01-02T00:00:00Z',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: 'White Chocolate',
|
||||||
|
description: 'Delicate white chocolate tempering recipe',
|
||||||
|
heating_temp: 43.0,
|
||||||
|
cooling_temp: 25.0,
|
||||||
|
working_temp: 28.0,
|
||||||
|
heating_time: 200,
|
||||||
|
cooling_time: 120,
|
||||||
|
working_time: 400,
|
||||||
|
mixer_speed: 40,
|
||||||
|
fountain_delay: 20,
|
||||||
|
pedal_enabled: false,
|
||||||
|
is_active: true,
|
||||||
|
created_at: '2024-01-03T00:00:00Z',
|
||||||
|
updated_at: '2024-01-03T00:00:00Z',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const mockProcessStatus: ProcessStatus = {
|
||||||
|
is_running: false,
|
||||||
|
current_phase: 'idle',
|
||||||
|
recipe_id: null,
|
||||||
|
recipe_name: null,
|
||||||
|
progress_percentage: 0,
|
||||||
|
phase_time_remaining: 0,
|
||||||
|
total_time_remaining: 0,
|
||||||
|
current_temperatures: {
|
||||||
|
tank_bottom: 22.5,
|
||||||
|
tank_wall: 22.3,
|
||||||
|
pump: 22.1,
|
||||||
|
fountain: 22.0,
|
||||||
|
},
|
||||||
|
target_temperatures: {
|
||||||
|
tank_bottom: 0,
|
||||||
|
tank_wall: 0,
|
||||||
|
pump: 0,
|
||||||
|
fountain: 0,
|
||||||
|
},
|
||||||
|
motor_speeds: {
|
||||||
|
mixer: 0,
|
||||||
|
pump: 0,
|
||||||
|
},
|
||||||
|
session_id: null,
|
||||||
|
started_at: null,
|
||||||
|
estimated_completion: null,
|
||||||
|
error: null,
|
||||||
|
}
|
||||||
|
|
||||||
|
const mockHardwareStatus: HardwareStatus = {
|
||||||
|
connected: false,
|
||||||
|
port: '/dev/ttyUSB0',
|
||||||
|
baud_rate: 9600,
|
||||||
|
modbus_address: 1,
|
||||||
|
last_communication: null,
|
||||||
|
communication_errors: 0,
|
||||||
|
temperatures: {
|
||||||
|
tank_bottom: 22.5,
|
||||||
|
tank_wall: 22.3,
|
||||||
|
pump: 22.1,
|
||||||
|
fountain: 22.0,
|
||||||
|
},
|
||||||
|
motors: {
|
||||||
|
mixer: { running: false, speed: 0, current: 0 },
|
||||||
|
pump: { running: false, speed: 0, current: 0 },
|
||||||
|
},
|
||||||
|
inputs: {
|
||||||
|
pedal: false,
|
||||||
|
emergency_stop: false,
|
||||||
|
door_sensor: true,
|
||||||
|
},
|
||||||
|
outputs: {
|
||||||
|
heating_element_1: false,
|
||||||
|
heating_element_2: false,
|
||||||
|
alarm: false,
|
||||||
|
fountain_valve: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const mockSafetyStatus: SafetyStatus = {
|
||||||
|
emergency_stop_active: false,
|
||||||
|
door_open: false,
|
||||||
|
temperature_alarms: [],
|
||||||
|
motor_alarms: [],
|
||||||
|
system_alarms: [],
|
||||||
|
last_safety_check: new Date().toISOString(),
|
||||||
|
}
|
||||||
|
|
||||||
|
const mockUsers: User[] = [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
username: 'admin',
|
||||||
|
email: 'admin@example.com',
|
||||||
|
role: 'admin',
|
||||||
|
full_name: 'System Administrator',
|
||||||
|
is_active: true,
|
||||||
|
created_at: '2024-01-01T00:00:00Z',
|
||||||
|
last_login: new Date().toISOString(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
username: 'operator',
|
||||||
|
email: 'operator@example.com',
|
||||||
|
role: 'operator',
|
||||||
|
full_name: 'Machine Operator',
|
||||||
|
is_active: true,
|
||||||
|
created_at: '2024-01-01T00:00:00Z',
|
||||||
|
last_login: '2024-01-15T08:30:00Z',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
// Helper function to simulate API delays
|
||||||
|
const delay = (ms: number = 500) => new Promise(resolve => setTimeout(resolve, ms))
|
||||||
|
|
||||||
|
// Mock API service class
|
||||||
|
class MockApiService {
|
||||||
|
private currentUser: User = mockUsers[0]
|
||||||
|
private recipes: Recipe[] = [...mockRecipes]
|
||||||
|
private processStatus: ProcessStatus = { ...mockProcessStatus }
|
||||||
|
private hardwareStatus: HardwareStatus = { ...mockHardwareStatus }
|
||||||
|
|
||||||
|
// System endpoints
|
||||||
|
async getSystemInfo(): Promise<SystemInfo> {
|
||||||
|
await delay(300)
|
||||||
|
return mockSystemInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
async getSystemStatus(): Promise<SystemStatus> {
|
||||||
|
await delay(200)
|
||||||
|
return mockSystemStatus
|
||||||
|
}
|
||||||
|
|
||||||
|
async getHealthCheck(): Promise<{ status: string }> {
|
||||||
|
await delay(100)
|
||||||
|
return { status: 'healthy' }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recipe endpoints
|
||||||
|
async getRecipes(params?: {
|
||||||
|
skip?: number
|
||||||
|
limit?: number
|
||||||
|
active_only?: boolean
|
||||||
|
search?: string
|
||||||
|
}): Promise<RecipeList> {
|
||||||
|
await delay(300)
|
||||||
|
|
||||||
|
let filteredRecipes = [...this.recipes]
|
||||||
|
|
||||||
|
if (params?.active_only) {
|
||||||
|
filteredRecipes = filteredRecipes.filter(r => r.is_active)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params?.search) {
|
||||||
|
const search = params.search.toLowerCase()
|
||||||
|
filteredRecipes = filteredRecipes.filter(r =>
|
||||||
|
r.name.toLowerCase().includes(search) ||
|
||||||
|
r.description.toLowerCase().includes(search)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const skip = params?.skip || 0
|
||||||
|
const limit = params?.limit || 10
|
||||||
|
|
||||||
|
return {
|
||||||
|
recipes: filteredRecipes.slice(skip, skip + limit),
|
||||||
|
total: filteredRecipes.length,
|
||||||
|
skip,
|
||||||
|
limit,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async getRecipe(id: number): Promise<Recipe> {
|
||||||
|
await delay(200)
|
||||||
|
const recipe = this.recipes.find(r => r.id === id)
|
||||||
|
if (!recipe) {
|
||||||
|
throw new Error(`Recipe with id ${id} not found`)
|
||||||
|
}
|
||||||
|
return recipe
|
||||||
|
}
|
||||||
|
|
||||||
|
async createRecipe(recipe: RecipeCreate): Promise<Recipe> {
|
||||||
|
await delay(500)
|
||||||
|
const newRecipe: Recipe = {
|
||||||
|
...recipe,
|
||||||
|
id: Math.max(...this.recipes.map(r => r.id)) + 1,
|
||||||
|
created_at: new Date().toISOString(),
|
||||||
|
updated_at: new Date().toISOString(),
|
||||||
|
}
|
||||||
|
this.recipes.push(newRecipe)
|
||||||
|
return newRecipe
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateRecipe(id: number, recipe: RecipeUpdate): Promise<Recipe> {
|
||||||
|
await delay(500)
|
||||||
|
const index = this.recipes.findIndex(r => r.id === id)
|
||||||
|
if (index === -1) {
|
||||||
|
throw new Error(`Recipe with id ${id} not found`)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.recipes[index] = {
|
||||||
|
...this.recipes[index],
|
||||||
|
...recipe,
|
||||||
|
updated_at: new Date().toISOString(),
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.recipes[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteRecipe(id: number): Promise<void> {
|
||||||
|
await delay(300)
|
||||||
|
const index = this.recipes.findIndex(r => r.id === id)
|
||||||
|
if (index === -1) {
|
||||||
|
throw new Error(`Recipe with id ${id} not found`)
|
||||||
|
}
|
||||||
|
this.recipes.splice(index, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process control endpoints
|
||||||
|
async getProcessStatus(): Promise<ProcessStatus> {
|
||||||
|
await delay(200)
|
||||||
|
// Simulate temperature fluctuations if process is running
|
||||||
|
if (this.processStatus.is_running) {
|
||||||
|
const temps = this.processStatus.current_temperatures
|
||||||
|
temps.tank_bottom += (Math.random() - 0.5) * 0.2
|
||||||
|
temps.tank_wall += (Math.random() - 0.5) * 0.2
|
||||||
|
temps.pump += (Math.random() - 0.5) * 0.1
|
||||||
|
temps.fountain += (Math.random() - 0.5) * 0.1
|
||||||
|
}
|
||||||
|
return { ...this.processStatus }
|
||||||
|
}
|
||||||
|
|
||||||
|
async startProcess(request: ProcessStartRequest): Promise<ProcessActionResponse> {
|
||||||
|
await delay(800)
|
||||||
|
const recipe = this.recipes.find(r => r.id === request.recipe_id)
|
||||||
|
if (!recipe) {
|
||||||
|
throw new Error(`Recipe with id ${request.recipe_id} not found`)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.processStatus = {
|
||||||
|
...this.processStatus,
|
||||||
|
is_running: true,
|
||||||
|
current_phase: 'heating',
|
||||||
|
recipe_id: recipe.id,
|
||||||
|
recipe_name: recipe.name,
|
||||||
|
progress_percentage: 0,
|
||||||
|
phase_time_remaining: recipe.heating_time,
|
||||||
|
total_time_remaining: recipe.heating_time + recipe.cooling_time + recipe.working_time,
|
||||||
|
target_temperatures: {
|
||||||
|
tank_bottom: recipe.heating_temp,
|
||||||
|
tank_wall: recipe.heating_temp,
|
||||||
|
pump: recipe.heating_temp,
|
||||||
|
fountain: recipe.heating_temp,
|
||||||
|
},
|
||||||
|
session_id: `mock-session-${Date.now()}`,
|
||||||
|
started_at: new Date().toISOString(),
|
||||||
|
estimated_completion: new Date(Date.now() + (recipe.heating_time + recipe.cooling_time + recipe.working_time) * 1000).toISOString(),
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: `Started tempering process with recipe: ${recipe.name}`,
|
||||||
|
session_id: this.processStatus.session_id!,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async pauseProcess(): Promise<ProcessActionResponse> {
|
||||||
|
await delay(300)
|
||||||
|
this.processStatus.current_phase = 'paused'
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: 'Process paused successfully',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async resumeProcess(): Promise<ProcessActionResponse> {
|
||||||
|
await delay(300)
|
||||||
|
this.processStatus.current_phase = 'heating' // or whatever phase it was in
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: 'Process resumed successfully',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async stopProcess(): Promise<ProcessActionResponse> {
|
||||||
|
await delay(500)
|
||||||
|
this.processStatus = {
|
||||||
|
...mockProcessStatus,
|
||||||
|
session_id: null,
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: 'Process stopped successfully',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async emergencyStop(): Promise<ProcessActionResponse> {
|
||||||
|
await delay(100)
|
||||||
|
this.processStatus = {
|
||||||
|
...mockProcessStatus,
|
||||||
|
session_id: null,
|
||||||
|
error: 'Emergency stop activated',
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: 'Emergency stop activated',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hardware endpoints
|
||||||
|
async getHardwareStatus(): Promise<HardwareStatus> {
|
||||||
|
await delay(300)
|
||||||
|
return { ...this.hardwareStatus }
|
||||||
|
}
|
||||||
|
|
||||||
|
async getTemperatures(): Promise<any[]> {
|
||||||
|
await delay(200)
|
||||||
|
return [
|
||||||
|
{ sensor: 'tank_bottom', temperature: this.hardwareStatus.temperatures.tank_bottom, timestamp: new Date().toISOString() },
|
||||||
|
{ sensor: 'tank_wall', temperature: this.hardwareStatus.temperatures.tank_wall, timestamp: new Date().toISOString() },
|
||||||
|
{ sensor: 'pump', temperature: this.hardwareStatus.temperatures.pump, timestamp: new Date().toISOString() },
|
||||||
|
{ sensor: 'fountain', temperature: this.hardwareStatus.temperatures.fountain, timestamp: new Date().toISOString() },
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
async getMotorStatus(): Promise<any[]> {
|
||||||
|
await delay(200)
|
||||||
|
return [
|
||||||
|
{ motor: 'mixer', ...this.hardwareStatus.motors.mixer },
|
||||||
|
{ motor: 'pump', ...this.hardwareStatus.motors.pump },
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
async setMotorSpeed(motorId: string, speed: number): Promise<void> {
|
||||||
|
await delay(400)
|
||||||
|
if (motorId in this.hardwareStatus.motors) {
|
||||||
|
(this.hardwareStatus.motors as any)[motorId].speed = speed
|
||||||
|
;(this.hardwareStatus.motors as any)[motorId].running = speed > 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Safety endpoints
|
||||||
|
async getSafetyStatus(): Promise<SafetyStatus> {
|
||||||
|
await delay(200)
|
||||||
|
return mockSafetyStatus
|
||||||
|
}
|
||||||
|
|
||||||
|
async acknowledgeAlarm(alarmId: string): Promise<void> {
|
||||||
|
await delay(300)
|
||||||
|
// Mock alarm acknowledgment
|
||||||
|
}
|
||||||
|
|
||||||
|
async clearAlarms(): Promise<void> {
|
||||||
|
await delay(500)
|
||||||
|
// Mock alarm clearing
|
||||||
|
}
|
||||||
|
|
||||||
|
// User management endpoints
|
||||||
|
async getUsers(params?: {
|
||||||
|
skip?: number
|
||||||
|
limit?: number
|
||||||
|
active_only?: boolean
|
||||||
|
}): Promise<{ users: User[]; total: number }> {
|
||||||
|
await delay(300)
|
||||||
|
|
||||||
|
let filteredUsers = [...mockUsers]
|
||||||
|
|
||||||
|
if (params?.active_only) {
|
||||||
|
filteredUsers = filteredUsers.filter(u => u.is_active)
|
||||||
|
}
|
||||||
|
|
||||||
|
const skip = params?.skip || 0
|
||||||
|
const limit = params?.limit || 10
|
||||||
|
|
||||||
|
return {
|
||||||
|
users: filteredUsers.slice(skip, skip + limit),
|
||||||
|
total: filteredUsers.length,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async getUser(id: string): Promise<User> {
|
||||||
|
await delay(200)
|
||||||
|
const user = mockUsers.find(u => u.id === id)
|
||||||
|
if (!user) {
|
||||||
|
throw new Error(`User with id ${id} not found`)
|
||||||
|
}
|
||||||
|
return user
|
||||||
|
}
|
||||||
|
|
||||||
|
async createUser(user: UserCreate): Promise<User> {
|
||||||
|
await delay(500)
|
||||||
|
const newUser: User = {
|
||||||
|
...user,
|
||||||
|
id: (mockUsers.length + 1).toString(),
|
||||||
|
created_at: new Date().toISOString(),
|
||||||
|
last_login: null,
|
||||||
|
}
|
||||||
|
mockUsers.push(newUser)
|
||||||
|
return newUser
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateUser(id: string, user: UserUpdate): Promise<User> {
|
||||||
|
await delay(500)
|
||||||
|
const index = mockUsers.findIndex(u => u.id === id)
|
||||||
|
if (index === -1) {
|
||||||
|
throw new Error(`User with id ${id} not found`)
|
||||||
|
}
|
||||||
|
|
||||||
|
mockUsers[index] = {
|
||||||
|
...mockUsers[index],
|
||||||
|
...user,
|
||||||
|
}
|
||||||
|
|
||||||
|
return mockUsers[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteUser(id: string): Promise<void> {
|
||||||
|
await delay(300)
|
||||||
|
const index = mockUsers.findIndex(u => u.id === id)
|
||||||
|
if (index === -1) {
|
||||||
|
throw new Error(`User with id ${id} not found`)
|
||||||
|
}
|
||||||
|
mockUsers.splice(index, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Authentication endpoints
|
||||||
|
async login(username: string, password: string): Promise<{ access_token: string; token_type: string; user: User }> {
|
||||||
|
await delay(800)
|
||||||
|
|
||||||
|
// Mock authentication - accept any user from mockUsers with password "password"
|
||||||
|
const user = mockUsers.find(u => u.username === username)
|
||||||
|
if (!user || password !== 'password') {
|
||||||
|
throw new Error('Invalid username or password')
|
||||||
|
}
|
||||||
|
|
||||||
|
const token = `mock-token-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
|
||||||
|
|
||||||
|
// Store token
|
||||||
|
localStorage.setItem('auth_token', token)
|
||||||
|
|
||||||
|
return {
|
||||||
|
access_token: token,
|
||||||
|
token_type: 'bearer',
|
||||||
|
user,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async logout(): Promise<void> {
|
||||||
|
await delay(200)
|
||||||
|
localStorage.removeItem('auth_token')
|
||||||
|
}
|
||||||
|
|
||||||
|
async refreshToken(): Promise<{ access_token: string }> {
|
||||||
|
await delay(300)
|
||||||
|
const token = `mock-token-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
|
||||||
|
localStorage.setItem('auth_token', token)
|
||||||
|
return { access_token: token }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Data export endpoints
|
||||||
|
async exportProcessData(sessionId: string, format: 'csv' | 'json' = 'csv'): Promise<Blob> {
|
||||||
|
await delay(1000)
|
||||||
|
const mockData = format === 'csv'
|
||||||
|
? 'timestamp,temperature,phase\n2024-01-01T00:00:00Z,25.0,heating\n2024-01-01T00:01:00Z,26.0,heating'
|
||||||
|
: JSON.stringify({ session: sessionId, data: [] })
|
||||||
|
|
||||||
|
return new Blob([mockData], {
|
||||||
|
type: format === 'csv' ? 'text/csv' : 'application/json'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async getProcessMetrics(days: number = 30): Promise<any> {
|
||||||
|
await delay(500)
|
||||||
|
return {
|
||||||
|
total_sessions: 42,
|
||||||
|
successful_sessions: 38,
|
||||||
|
average_duration: 3600,
|
||||||
|
temperature_stability: 98.5,
|
||||||
|
efficiency_rating: 94.2,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const mockApi = new MockApiService()
|
||||||
Reference in New Issue
Block a user