Files
protoc-frontend/src/pages/ElementsCreation/ui/Page/Page.tsx

241 lines
7.4 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 { Plus, Wrench } from 'lucide-react'
import { FC, useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { ElementConstructor } from '../../../../components/TemplateManager/ElementConstructor'
import { Button } from '../../../../components/ui/button'
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from '../../../../components/ui/card'
import { useTemplateContext } from '../../../../contexts/TemplateContext'
import {
FormLayoutSettings,
Template,
TemplateElement,
} from '../../../../types/template'
export const ElementsCreation: FC = () => {
const navigate = useNavigate()
const { templates, updateTemplate } = useTemplateContext()
const [selectedTemplate, setSelectedTemplate] = useState<Template | null>(
null,
)
const handleTemplateSelect = (template: Template) => {
setSelectedTemplate(template)
}
const handleElementAdd = (element: TemplateElement) => {
console.log('handleElementAdd called with element:', element)
if (!selectedTemplate) {
console.log('No selected template')
return
}
const updatedTemplate = {
...selectedTemplate,
elements: [...selectedTemplate.elements, element],
updatedAt: new Date(),
}
console.log('Updated template:', updatedTemplate)
console.log('Elements count:', updatedTemplate.elements.length)
updateTemplate(updatedTemplate)
setSelectedTemplate(updatedTemplate)
}
const handleElementUpdate = (
elementId: string,
updates: Partial<TemplateElement>,
) => {
if (!selectedTemplate) return
const updatedTemplate = {
...selectedTemplate,
elements: selectedTemplate.elements.map((el) =>
el.id === elementId ? { ...el, ...updates } : el,
),
updatedAt: new Date(),
}
updateTemplate(updatedTemplate)
setSelectedTemplate(updatedTemplate)
}
const handleElementDelete = (elementId: string) => {
if (!selectedTemplate) return
const updatedTemplate = {
...selectedTemplate,
elements: selectedTemplate.elements.filter((el) => el.id !== elementId),
updatedAt: new Date(),
}
updateTemplate(updatedTemplate)
setSelectedTemplate(updatedTemplate)
}
const handleElementsReorder = (reorderedElements: TemplateElement[]) => {
if (!selectedTemplate) return
// Обновляем порядок элементов
const elementsWithOrder = reorderedElements.map((element, index) => ({
...element,
order: index,
}))
const updatedTemplate = {
...selectedTemplate,
elements: elementsWithOrder,
updatedAt: new Date(),
}
updateTemplate(updatedTemplate)
setSelectedTemplate(updatedTemplate)
}
const handleLayoutSettingsChange = (settings: FormLayoutSettings) => {
if (!selectedTemplate) return
const updatedTemplate = {
...selectedTemplate,
layoutSettings: settings,
updatedAt: new Date(),
}
updateTemplate(updatedTemplate)
setSelectedTemplate(updatedTemplate)
}
const handleBack = () => {
setSelectedTemplate(null)
}
// Настройки отображения по умолчанию
const defaultLayoutSettings: FormLayoutSettings = {
gridSize: 20,
showGrid: true,
}
if (selectedTemplate) {
return (
<div className="h-full">
<div className="sticky top-0 z-50 border-b border-gray-200 bg-white p-4">
<div className="flex items-center justify-between">
<div className="flex items-center gap-4">
<Button variant="ghost" onClick={handleBack}>
Назад
</Button>
<div>
<h1 className="text-xl font-semibold text-gray-800">
Конструктор элементов: {selectedTemplate.name}
</h1>
<p className="mt-1 text-sm text-gray-600">
Создайте элементы формы и разместите их на холсте
перетаскиванием
</p>
</div>
</div>
</div>
</div>
<div className="h-[calc(100vh-104px)]">
<ElementConstructor
elements={selectedTemplate.elements}
layoutSettings={
selectedTemplate.layoutSettings || defaultLayoutSettings
}
onElementAdd={handleElementAdd}
onElementUpdate={handleElementUpdate}
onElementDelete={handleElementDelete}
onElementsReorder={handleElementsReorder}
onLayoutSettingsChange={handleLayoutSettingsChange}
/>
</div>
</div>
)
}
return (
<div className="mx-auto max-w-7xl p-6">
<div className="mb-6 flex items-center justify-between">
<div>
<h1 className="text-3xl font-bold text-gray-900">
Создание элементов
</h1>
<p className="mt-2 text-gray-600">
Выберите шаблон для создания элементов интерфейса
</p>
</div>
<Button
variant="outline"
onClick={() => navigate('/templates')}
className="flex items-center gap-2"
>
<Plus className="h-4 w-4" />
Создать шаблон
</Button>
</div>
{templates.length === 0 ? (
<div className="py-12 text-center">
<Wrench className="mx-auto mb-4 h-16 w-16 text-gray-400" />
<h3 className="mb-2 text-lg font-medium text-gray-900">
Нет доступных шаблонов
</h3>
<p className="mb-6 text-gray-600">
Создайте шаблон протокола для начала работы с элементами
</p>
<Button onClick={() => navigate('/templates')}>
<Plus className="mr-2 h-4 w-4" />
Создать шаблон
</Button>
</div>
) : (
<div className="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3">
{templates.map((template) => (
<Card
key={template.id}
className="cursor-pointer transition-shadow hover:shadow-lg"
>
<CardHeader>
<CardTitle className="text-lg">{template.name}</CardTitle>
{template.description && (
<CardDescription className="mt-1">
{template.description}
</CardDescription>
)}
</CardHeader>
<CardContent>
<div className="space-y-2 text-sm text-gray-600">
<div className="flex items-center gap-2">
<Wrench className="h-4 w-4" />
<span>{template.elements.length} элементов создано</span>
</div>
<div className="mt-2 text-xs text-gray-500">
Обновлен: {template.updatedAt.toLocaleDateString('ru-RU')}
</div>
</div>
<div className="mt-4">
<Button
className="w-full"
onClick={() => handleTemplateSelect(template)}
>
Создать элементы
</Button>
</div>
</CardContent>
</Card>
))}
</div>
)}
</div>
)
}