259 lines
8.4 KiB
TypeScript
259 lines
8.4 KiB
TypeScript
import {
|
||
ConditionType,
|
||
CreateDailyConditionInput,
|
||
CreateDailyConditionOutput,
|
||
DailyCondition,
|
||
DailyConditionsFilters,
|
||
GetDailyConditionOutput,
|
||
GetDailyConditionsOutput,
|
||
GetLaboratoriesOutput,
|
||
GetLaboratoryOutput,
|
||
Laboratory,
|
||
UpdateDailyConditionInput,
|
||
UpdateDailyConditionOutput,
|
||
} from './types'
|
||
|
||
// Базовый URL для API (может быть настроен через переменные окружения)
|
||
const BASE_URL = import.meta.env.VITE_API_BASE_URL || '/api'
|
||
|
||
// API для лабораторий
|
||
export const laboratoriesApi = {
|
||
// Получить все лаборатории
|
||
getAll: async (): Promise<Laboratory[]> => {
|
||
const response = await fetch(`${BASE_URL}/laboratories/`)
|
||
if (!response.ok) {
|
||
throw new Error('Ошибка загрузки лабораторий')
|
||
}
|
||
const data: GetLaboratoriesOutput = await response.json()
|
||
return data.laboratories
|
||
},
|
||
|
||
// Получить лабораторию по ID
|
||
getById: async (id: string): Promise<Laboratory | null> => {
|
||
const response = await fetch(`${BASE_URL}/laboratories/${id}`)
|
||
if (!response.ok) {
|
||
if (response.status === 404) {
|
||
return null
|
||
}
|
||
throw new Error('Ошибка получения лаборатории')
|
||
}
|
||
const data: GetLaboratoryOutput = await response.json()
|
||
return data.laboratory
|
||
},
|
||
}
|
||
|
||
// API для ежедневных условий
|
||
export const dailyConditionsApi = {
|
||
// Получить условия по фильтрам
|
||
get: async (
|
||
filters: DailyConditionsFilters = {}
|
||
): Promise<DailyCondition[]> => {
|
||
const searchParams = new URLSearchParams()
|
||
if (filters.laboratory_id) {
|
||
searchParams.append('laboratory_id', filters.laboratory_id)
|
||
}
|
||
if (filters.start_date) {
|
||
searchParams.append('start_date', filters.start_date)
|
||
}
|
||
if (filters.end_date) {
|
||
searchParams.append('end_date', filters.end_date)
|
||
}
|
||
|
||
const url = searchParams.toString()
|
||
? `${BASE_URL}/daily-conditions/?${searchParams}`
|
||
: `${BASE_URL}/daily-conditions/`
|
||
|
||
const response = await fetch(url)
|
||
if (!response.ok) {
|
||
throw new Error('Ошибка загрузки условий')
|
||
}
|
||
const data: GetDailyConditionsOutput = await response.json()
|
||
return data.daily_conditions
|
||
},
|
||
|
||
// Получить конкретное условие по ID
|
||
getById: async (id: string): Promise<DailyCondition | null> => {
|
||
const response = await fetch(`${BASE_URL}/daily-conditions/${id}`)
|
||
if (!response.ok) {
|
||
if (response.status === 404) {
|
||
return null
|
||
}
|
||
throw new Error('Ошибка получения условия')
|
||
}
|
||
const data: GetDailyConditionOutput = await response.json()
|
||
return data.daily_condition
|
||
},
|
||
|
||
// Создать новые условия
|
||
create: async (input: CreateDailyConditionInput): Promise<string> => {
|
||
const response = await fetch(`${BASE_URL}/daily-conditions/`, {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
},
|
||
body: JSON.stringify(input),
|
||
})
|
||
if (!response.ok) {
|
||
const error = await response
|
||
.json()
|
||
.catch(() => ({ message: 'Ошибка сохранения условий' }))
|
||
throw new Error(error.message || 'Ошибка сохранения условий')
|
||
}
|
||
const data: CreateDailyConditionOutput = await response.json()
|
||
return data.id
|
||
},
|
||
|
||
// Обновить условия
|
||
update: async (
|
||
id: string,
|
||
input: UpdateDailyConditionInput
|
||
): Promise<string> => {
|
||
const response = await fetch(`${BASE_URL}/daily-conditions/${id}`, {
|
||
method: 'PATCH',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
},
|
||
body: JSON.stringify(input),
|
||
})
|
||
if (!response.ok) {
|
||
throw new Error('Ошибка обновления условий')
|
||
}
|
||
const data: UpdateDailyConditionOutput = await response.json()
|
||
return data.id
|
||
},
|
||
|
||
// Удалить условия
|
||
delete: async (id: string): Promise<void> => {
|
||
const response = await fetch(`${BASE_URL}/daily-conditions/${id}`, {
|
||
method: 'DELETE',
|
||
})
|
||
if (!response.ok) {
|
||
throw new Error('Ошибка удаления условий')
|
||
}
|
||
},
|
||
}
|
||
|
||
// Комбинированный API для работы с элементом
|
||
export const elementApi = {
|
||
// Получить лабораторию с её типами условий
|
||
getLaboratoryData: async (
|
||
laboratoryId: string
|
||
): Promise<{
|
||
laboratory: Laboratory
|
||
conditionTypes: ConditionType[]
|
||
}> => {
|
||
const laboratory = await laboratoriesApi.getById(laboratoryId)
|
||
if (!laboratory) {
|
||
throw new Error('Лаборатория не найдена')
|
||
}
|
||
|
||
return {
|
||
laboratory,
|
||
conditionTypes: laboratory.condition_types,
|
||
}
|
||
},
|
||
|
||
// Получить ежедневные условия для конкретной лаборатории и даты
|
||
getDailyConditions: async (
|
||
laboratoryId: string,
|
||
date: string
|
||
): Promise<DailyCondition | null> => {
|
||
const conditions = await dailyConditionsApi.get({
|
||
laboratory_id: laboratoryId,
|
||
start_date: date,
|
||
end_date: date,
|
||
})
|
||
return conditions.length > 0 ? conditions[0] : null
|
||
},
|
||
|
||
// Сохранить или обновить условия из элемента
|
||
saveElementConditions: async (data: {
|
||
laboratoryId: string
|
||
date: string
|
||
conditions: Record<string, any>
|
||
existingConditionId?: string
|
||
}): Promise<DailyCondition> => {
|
||
const input: CreateDailyConditionInput | UpdateDailyConditionInput = {
|
||
laboratory_id: data.laboratoryId,
|
||
measurement_date: data.date,
|
||
conditions: data.conditions,
|
||
}
|
||
|
||
let conditionId: string
|
||
|
||
if (data.existingConditionId) {
|
||
// Обновляем существующие условия
|
||
conditionId = await dailyConditionsApi.update(
|
||
data.existingConditionId,
|
||
input as UpdateDailyConditionInput
|
||
)
|
||
} else {
|
||
// Создаем новые условия
|
||
conditionId = await dailyConditionsApi.create(
|
||
input as CreateDailyConditionInput
|
||
)
|
||
}
|
||
|
||
// Получаем обновленные данные
|
||
const savedCondition = await dailyConditionsApi.getById(conditionId)
|
||
if (!savedCondition) {
|
||
throw new Error('Ошибка получения сохраненных условий')
|
||
}
|
||
|
||
return savedCondition
|
||
},
|
||
}
|
||
|
||
// Вспомогательные функции
|
||
export const verificationConditionsUtils = {
|
||
// Валидация значения условия
|
||
validateConditionValue: (
|
||
value: any,
|
||
dataType: string = 'string',
|
||
minValue?: number,
|
||
maxValue?: number
|
||
): { isValid: boolean; error?: string } => {
|
||
if (dataType === 'number') {
|
||
const numValue = parseFloat(value)
|
||
if (isNaN(numValue)) {
|
||
return { isValid: false, error: 'Должно быть числом' }
|
||
}
|
||
if (minValue !== undefined && numValue < minValue) {
|
||
return { isValid: false, error: `Минимальное значение: ${minValue}` }
|
||
}
|
||
if (maxValue !== undefined && numValue > maxValue) {
|
||
return { isValid: false, error: `Максимальное значение: ${maxValue}` }
|
||
}
|
||
}
|
||
return { isValid: true }
|
||
},
|
||
|
||
// Форматирование значения с единицей измерения
|
||
formatValueWithUnit: (value: any, unit?: string): string => {
|
||
if (value === undefined || value === null || value === '') {
|
||
return '-'
|
||
}
|
||
return unit ? `${value} ${unit}` : value.toString()
|
||
},
|
||
|
||
// Получение ключа условия для хранения в conditions JSON (обычно используется ID типа условия)
|
||
getConditionKey: (conditionTypeId: string): string => {
|
||
return conditionTypeId
|
||
},
|
||
|
||
// Генерация ключа на основе названия условия (для обратной совместимости)
|
||
generateConditionKey: (conditionTypeName: string): string => {
|
||
return conditionTypeName
|
||
.toLowerCase()
|
||
.replace(/\s+/g, '_')
|
||
.replace(/[^\w]/g, '')
|
||
},
|
||
|
||
// Проверка, является ли строка валидным UUID
|
||
isValidUUID: (str: string): boolean => {
|
||
const uuidRegex =
|
||
/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
|
||
return uuidRegex.test(str)
|
||
},
|
||
}
|