Files
protoc-frontend/src/components/TemplateManager/TemplateManager.tsx
Artyom Tsyrulnikov 6bd5bba15a система инит
2025-07-15 06:42:04 +03:00

229 lines
8.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 { FileText, Plus, Settings, Upload } from 'lucide-react';
import React, { useState } from 'react';
import { Template } from '../../types/template';
import { Button } from '../ui/button';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '../ui/card';
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from '../ui/dialog';
import { Input } from '../ui/input';
import { TemplateEditor } from './TemplateEditor';
import { TemplateRenderer } from './TemplateRenderer';
interface TemplateManagerProps {
onTemplateSelect?: (template: Template) => void;
}
export const TemplateManager: React.FC<TemplateManagerProps> = ({ onTemplateSelect }) => {
const [templates, setTemplates] = useState<Template[]>([]);
const [selectedTemplate, setSelectedTemplate] = useState<Template | null>(null);
const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false);
const [isEditMode, setIsEditMode] = useState(false);
const [newTemplateName, setNewTemplateName] = useState('');
const [newTemplateDescription, setNewTemplateDescription] = useState('');
const handleCreateTemplate = () => {
if (!newTemplateName.trim()) return;
const newTemplate: Template = {
id: Date.now().toString(),
name: newTemplateName.trim(),
description: newTemplateDescription.trim(),
elements: [],
createdAt: new Date(),
updatedAt: new Date(),
};
setTemplates(prev => [...prev, newTemplate]);
setSelectedTemplate(newTemplate);
setIsEditMode(true);
setIsCreateDialogOpen(false);
setNewTemplateName('');
setNewTemplateDescription('');
};
const handleTemplateUpdate = (updatedTemplate: Template) => {
setTemplates(prev => prev.map(t =>
t.id === updatedTemplate.id ? updatedTemplate : t
));
setSelectedTemplate(updatedTemplate);
};
const handleTemplateDelete = (templateId: string) => {
setTemplates(prev => prev.filter(t => t.id !== templateId));
if (selectedTemplate?.id === templateId) {
setSelectedTemplate(null);
setIsEditMode(false);
}
};
const handleTemplateSelect = (template: Template) => {
setSelectedTemplate(template);
setIsEditMode(false);
onTemplateSelect?.(template);
};
const handleEditTemplate = (template: Template) => {
setSelectedTemplate(template);
setIsEditMode(true);
};
if (selectedTemplate && !isEditMode) {
return (
<TemplateRenderer
template={selectedTemplate}
onBack={() => setSelectedTemplate(null)}
onEdit={() => setIsEditMode(true)}
/>
);
}
if (selectedTemplate && isEditMode) {
return (
<TemplateEditor
template={selectedTemplate}
onSave={handleTemplateUpdate}
onCancel={() => setIsEditMode(false)}
onBack={() => {
setSelectedTemplate(null);
setIsEditMode(false);
}}
/>
);
}
return (
<div className="p-6 max-w-7xl mx-auto">
<div className="flex items-center justify-between mb-6">
<div>
<h1 className="text-3xl font-bold text-gray-900">Система протоколов</h1>
<p className="text-gray-600 mt-2">Управление шаблонами и создание отчетов</p>
</div>
<Dialog open={isCreateDialogOpen} onOpenChange={setIsCreateDialogOpen}>
<DialogTrigger asChild>
<Button className="flex items-center gap-2">
<Plus className="h-4 w-4" />
Создать шаблон
</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-[425px]">
<DialogHeader>
<DialogTitle>Создать новый шаблон</DialogTitle>
</DialogHeader>
<div className="space-y-4 py-4">
<div className="space-y-2">
<label className="text-sm font-medium">Название шаблона</label>
<Input
placeholder="Введите название шаблона"
value={newTemplateName}
onChange={(e) => setNewTemplateName(e.target.value)}
/>
</div>
<div className="space-y-2">
<label className="text-sm font-medium">Описание (опционально)</label>
<Input
placeholder="Введите описание шаблона"
value={newTemplateDescription}
onChange={(e) => setNewTemplateDescription(e.target.value)}
/>
</div>
</div>
<div className="flex justify-end gap-2">
<Button
variant="outline"
onClick={() => setIsCreateDialogOpen(false)}
>
Отмена
</Button>
<Button
onClick={handleCreateTemplate}
disabled={!newTemplateName.trim()}
>
Создать
</Button>
</div>
</DialogContent>
</Dialog>
</div>
{templates.length === 0 ? (
<div className="text-center py-12">
<FileText className="h-16 w-16 text-gray-400 mx-auto mb-4" />
<h3 className="text-lg font-medium text-gray-900 mb-2">Нет созданных шаблонов</h3>
<p className="text-gray-600 mb-6">Создайте первый шаблон для начала работы</p>
<Button onClick={() => setIsCreateDialogOpen(true)}>
<Plus className="h-4 w-4 mr-2" />
Создать шаблон
</Button>
</div>
) : (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{templates.map((template) => (
<Card key={template.id} className="hover:shadow-lg transition-shadow cursor-pointer">
<CardHeader>
<div className="flex items-start justify-between">
<div className="flex-1">
<CardTitle className="text-lg">{template.name}</CardTitle>
{template.description && (
<CardDescription className="mt-1">
{template.description}
</CardDescription>
)}
</div>
<div className="flex gap-1 ml-2">
<Button
variant="ghost"
size="icon"
onClick={(e) => {
e.stopPropagation();
handleEditTemplate(template);
}}
>
<Settings className="h-4 w-4" />
</Button>
</div>
</div>
</CardHeader>
<CardContent>
<div className="space-y-2 text-sm text-gray-600">
<div className="flex items-center gap-2">
<Upload className="h-4 w-4" />
<span>
{template.excelFile ? 'Excel файл загружен' : 'Excel файл не загружен'}
</span>
</div>
<div className="flex items-center gap-2">
<Settings className="h-4 w-4" />
<span>{template.elements.length} элементов интерфейса</span>
</div>
<div className="text-xs text-gray-500 mt-2">
Создан: {template.createdAt.toLocaleDateString()}
</div>
</div>
<div className="flex gap-2 mt-4">
<Button
variant="outline"
size="sm"
className="flex-1"
onClick={() => handleTemplateSelect(template)}
>
Использовать
</Button>
<Button
variant="outline"
size="sm"
onClick={(e) => {
e.stopPropagation();
handleEditTemplate(template);
}}
>
Настроить
</Button>
</div>
</CardContent>
</Card>
))}
</div>
)}
</div>
);
};