Files
protoc-frontend/src/component/StandardsElement/definition.tsx
2025-07-24 09:10:08 +03:00

156 lines
6.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { Badge } from '@/component/ui/badge'
import { Button } from '@/component/ui/button'
import { Label } from '@/component/ui/label'
import { ElementDefinition } from '@/entitiy/element/model/interface'
import { CellTarget } from '@/type/template'
import { FileText, Settings, Weight } from 'lucide-react'
import { useEffect, useState } from 'react'
import { useStandards } from './hooks'
import { getStandardById } from './mockStandards'
import { StandardsEditor } from './StandardsEditor'
import { StandardsPreview } from './StandardsPreview'
import { StandardsSelector } from './StandardsSelector'
interface StandardsConfig {
sheet: string // Лист Excel
startCell: string // Первая ячейка (например "A10")
maxItems: number // Обычно 7
targetCells: CellTarget[]
selectedStandards?: string[] // Выбранные эталоны (ID)
}
export const standardsDefinition: ElementDefinition<StandardsConfig, string[]> =
{
type: 'standards',
label: 'Измерительные эталоны',
icon: <Weight className="h-4 w-4" />,
version: 1,
defaultConfig: {
sheet: 'L',
startCell: 'A1',
maxItems: 7,
targetCells: [],
selectedStandards: [], // По умолчанию пустой массив
},
Editor: StandardsEditor,
Preview: StandardsPreview, // Использует моки для демонстрации
Render: ({ config, value, onChange }) => {
const [isStandardsDialogOpen, setIsStandardsDialogOpen] = useState(false)
const [selectedStandardIds, setSelectedStandardIds] = useState<string[]>(
// Инициализируем из config.selectedStandards или value
config.selectedStandards || (Array.isArray(value) ? value : [])
)
// Получаем реальные данные эталонов
const { data: standards = [] } = useStandards()
// Синхронизируем selectedStandardIds с config и value
useEffect(() => {
const standards =
config.selectedStandards || (Array.isArray(value) ? value : [])
setSelectedStandardIds(standards)
}, [config.selectedStandards, value])
// Получаем данные выбранных эталонов из реального API
const selectedStandardsData = selectedStandardIds
.map(id => standards.find(s => s.id === id))
.filter(Boolean)
return (
<div className="space-y-2">
{/* Блок с измерительными эталонами */}
<div>
<div className="mb-2 flex items-center justify-between">
<Label className="text-sm font-medium">Эталоны</Label>
<Button
variant="outline"
size="sm"
onClick={() => setIsStandardsDialogOpen(true)}
className="h-7 px-2"
>
<Settings className="mr-1 h-3 w-3" />
Настроить
</Button>
</div>
<div className="space-y-2">
{selectedStandardsData.length > 0 ? (
<div className="space-y-1">
{selectedStandardsData.map(
(standard, index) =>
standard && (
<div
key={standard.id}
className="flex items-center gap-2 rounded-md bg-muted/30 p-2 text-sm"
>
<div className="flex h-4 w-4 shrink-0 items-center justify-center rounded-full bg-primary/10">
<span className="text-xs font-medium text-primary">
{index + 1}
</span>
</div>
<div className="min-w-0 flex-1">
<div className="truncate text-xs font-medium text-foreground">
{standard.name}
</div>
<div className="mt-0.5 flex items-center gap-1 text-xs text-muted-foreground">
<FileText className="h-2.5 w-2.5" />
<span className="hidden text-xs sm:inline">
{standard.registry_number}
</span>
</div>
</div>
<Badge
variant="secondary"
className="shrink-0 px-1.5 py-0.5 text-xs"
>
{standard.range}
</Badge>
</div>
)
)}
</div>
) : (
<div className="rounded-md border border-dashed bg-muted/30 p-3 text-center text-sm text-muted-foreground">
<Settings className="mx-auto mb-1 h-4 w-4 opacity-50" />
Эталоны не выбраны
</div>
)}
</div>
</div>
<StandardsSelector
isOpen={isStandardsDialogOpen}
onClose={() => setIsStandardsDialogOpen(false)}
value={selectedStandardIds}
onChange={standardIds => {
setSelectedStandardIds(standardIds)
// Сохраняем ID эталонов в value для записи в Excel
onChange?.(standardIds)
}}
maxItems={config.maxItems}
/>
</div>
)
},
mapToCells: cfg => {
// Используем только ячейки, указанные пользователем в targetCells
return cfg.targetCells || []
},
mapToCellValues: (cfg, value) => {
// Используем targetCells из конфигурации
const cells = cfg.targetCells || []
// Конвертируем ID эталонов в их названия для записи в Excel
// Здесь используем моки для быстрого доступа к данным при записи в Excel
const standardIds = Array.isArray(value) ? value : []
const standardNames = standardIds.map(
id => getStandardById(id)?.name || ''
)
return cells.map((target, idx) => ({
target,
value: standardNames[idx] || '', // Берем значение по индексу или пустую строку
}))
},
}