228 lines
8.8 KiB
TypeScript
228 lines
8.8 KiB
TypeScript
import { Badge } from '@/component/ui/badge'
|
||
import { Card, CardContent, CardHeader, CardTitle } from '@/component/ui/card'
|
||
import { Label } from '@/component/ui/label'
|
||
import {
|
||
Select,
|
||
SelectContent,
|
||
SelectItem,
|
||
SelectTrigger,
|
||
SelectValue,
|
||
} from '@/component/ui/select'
|
||
import { Building2, Target } from 'lucide-react'
|
||
import { useLaboratories } from './hooks'
|
||
import { mockApiHelpers } from './mockData'
|
||
import { ConditionCellMapping, VerificationConditionsConfig } from './types'
|
||
|
||
interface VerificationConditionsEditorProps {
|
||
config: VerificationConditionsConfig
|
||
onChange: (config: VerificationConditionsConfig) => void
|
||
}
|
||
|
||
export function VerificationConditionsEditor({
|
||
config,
|
||
onChange,
|
||
}: VerificationConditionsEditorProps) {
|
||
const { data: laboratories = [], isLoading } = useLaboratories()
|
||
|
||
const updateConfig = (updates: Partial<VerificationConditionsConfig>) => {
|
||
onChange({ ...config, ...updates })
|
||
}
|
||
|
||
// Получаем выбранную лабораторию
|
||
const selectedLab = laboratories.find(
|
||
lab => lab.id === config.selectedLaboratoryId
|
||
)
|
||
|
||
// Получаем все доступные условия (либо все из БД, либо условия конкретной лаборатории)
|
||
const availableConditions = config.selectedLaboratoryId
|
||
? mockApiHelpers.getLaboratoryConditions(config.selectedLaboratoryId)
|
||
: mockApiHelpers.getAllConditions()
|
||
|
||
// Обновление привязки условия к ячейке
|
||
const updateConditionMapping = (cellIndex: number, conditionKey: string) => {
|
||
const conditionName =
|
||
availableConditions.find(c => c.key === conditionKey)?.name ||
|
||
conditionKey
|
||
|
||
const newMappings = [...(config.conditionMappings || [])]
|
||
const existingIndex = newMappings.findIndex(m => m.cellIndex === cellIndex)
|
||
|
||
if (conditionKey === '__none__') {
|
||
// Убираем привязку
|
||
if (existingIndex >= 0) {
|
||
newMappings.splice(existingIndex, 1)
|
||
}
|
||
} else {
|
||
// Добавляем или обновляем привязку
|
||
const mapping: ConditionCellMapping = {
|
||
cellIndex,
|
||
conditionKey,
|
||
conditionName,
|
||
}
|
||
|
||
if (existingIndex >= 0) {
|
||
newMappings[existingIndex] = mapping
|
||
} else {
|
||
newMappings.push(mapping)
|
||
}
|
||
}
|
||
|
||
updateConfig({ conditionMappings: newMappings })
|
||
}
|
||
|
||
// Получить выбранное условие для ячейки
|
||
const getSelectedCondition = (cellIndex: number): string => {
|
||
const mapping = config.conditionMappings?.find(
|
||
m => m.cellIndex === cellIndex
|
||
)
|
||
return mapping?.conditionKey || '__none__'
|
||
}
|
||
|
||
return (
|
||
<div className="space-y-4">
|
||
{/* Выбор лаборатории */}
|
||
<Card>
|
||
<CardHeader>
|
||
<CardTitle className="flex items-center gap-2">
|
||
<Building2 className="h-4 w-4" />
|
||
Лаборатория
|
||
</CardTitle>
|
||
</CardHeader>
|
||
<CardContent>
|
||
<div>
|
||
<Label htmlFor="laboratory">Выберите лабораторию</Label>
|
||
<Select
|
||
value={config.selectedLaboratoryId?.toString() || '__none__'}
|
||
onValueChange={value => {
|
||
const laboratoryId =
|
||
value === '__none__' ? undefined : parseInt(value)
|
||
updateConfig({
|
||
selectedLaboratoryId: laboratoryId,
|
||
conditionMappings: [], // Сбрасываем привязки при смене лаборатории
|
||
})
|
||
}}
|
||
>
|
||
<SelectTrigger>
|
||
<SelectValue placeholder="Выберите лабораторию" />
|
||
</SelectTrigger>
|
||
<SelectContent>
|
||
<SelectItem value="__none__">Все условия из БД</SelectItem>
|
||
{laboratories.map(lab => (
|
||
<SelectItem key={lab.id} value={lab.id.toString()}>
|
||
{lab.name}
|
||
</SelectItem>
|
||
))}
|
||
</SelectContent>
|
||
</Select>
|
||
<p className="mt-1 text-xs text-muted-foreground">
|
||
{config.selectedLaboratoryId
|
||
? 'Доступны только условия выбранной лаборатории'
|
||
: 'Доступны все условия из базы данных'}
|
||
</p>
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
|
||
{/* Привязка условий к ячейкам */}
|
||
{config.targetCells.length > 0 && (
|
||
<Card>
|
||
<CardHeader>
|
||
<CardTitle className="flex items-center gap-2">
|
||
<Target className="h-4 w-4" />
|
||
Привязка условий к ячейкам
|
||
</CardTitle>
|
||
</CardHeader>
|
||
<CardContent className="space-y-4">
|
||
<div className="rounded-md bg-blue-50 p-3 text-sm text-blue-800 dark:bg-blue-950 dark:text-blue-200">
|
||
<p className="font-medium">Настройка записи данных</p>
|
||
<p className="mt-1">
|
||
Выберите какое условие будет записываться в каждую целевую
|
||
ячейку.
|
||
</p>
|
||
</div>
|
||
|
||
<div className="space-y-3">
|
||
{config.targetCells.map((cell, index) => (
|
||
<div
|
||
key={index}
|
||
className="flex items-center gap-3 rounded-md border p-3"
|
||
>
|
||
<Badge variant="outline" className="shrink-0">
|
||
{cell.sheet}!{cell.cell}
|
||
</Badge>
|
||
|
||
<div className="flex-1">
|
||
<Label className="text-xs text-muted-foreground">
|
||
Ячейка {index + 1} - выберите условие:
|
||
</Label>
|
||
<Select
|
||
value={getSelectedCondition(index)}
|
||
onValueChange={value =>
|
||
updateConditionMapping(index, value)
|
||
}
|
||
>
|
||
<SelectTrigger className="mt-1">
|
||
<SelectValue placeholder="Выберите условие" />
|
||
</SelectTrigger>
|
||
<SelectContent>
|
||
<SelectItem value="__none__">Не выбрано</SelectItem>
|
||
{availableConditions.map(condition => (
|
||
<SelectItem key={condition.key} value={condition.key}>
|
||
<div className="flex items-center gap-2">
|
||
<span>{condition.name}</span>
|
||
{condition.unit && (
|
||
<Badge variant="secondary" className="text-xs">
|
||
{condition.unit}
|
||
</Badge>
|
||
)}
|
||
</div>
|
||
</SelectItem>
|
||
))}
|
||
</SelectContent>
|
||
</Select>
|
||
</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
|
||
{/* Подсказка с доступными условиями */}
|
||
<div className="rounded-md bg-muted/50 p-3 text-sm text-muted-foreground">
|
||
<p className="font-medium">
|
||
Доступные условия{' '}
|
||
{selectedLab ? `для ${selectedLab.name}` : 'из базы данных'}:
|
||
</p>
|
||
<ul className="mt-1 space-y-1">
|
||
{availableConditions.map(condition => (
|
||
<li key={condition.key}>
|
||
• <strong>{condition.name}</strong>
|
||
{condition.unit && ` (${condition.unit})`}
|
||
{'isRequired' in condition &&
|
||
condition.isRequired &&
|
||
' - обязательное'}
|
||
</li>
|
||
))}
|
||
</ul>
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
)}
|
||
|
||
{/* Подсказка если нет целевых ячеек */}
|
||
{config.targetCells.length === 0 && (
|
||
<Card>
|
||
<CardContent className="pt-6">
|
||
<div className="text-center text-sm text-muted-foreground">
|
||
<Target className="mx-auto mb-2 h-8 w-8 opacity-50" />
|
||
<p className="font-medium">Целевые ячейки не настроены</p>
|
||
<p className="mt-1">
|
||
Сначала настройте целевые ячейки в основном редакторе элементов,
|
||
затем вернитесь сюда для привязки условий.
|
||
</p>
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
)}
|
||
</div>
|
||
)
|
||
}
|