AI рефакторинг !
This commit is contained in:
@@ -1,18 +1,66 @@
|
||||
import TemplateCard from '@/component/TemplateCard'
|
||||
import { Button } from '@/component/ui/button'
|
||||
import {
|
||||
Dialog,
|
||||
DialogClose,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from '@/component/ui/dialog'
|
||||
import { Input } from '@/component/ui/input'
|
||||
import { Label } from '@/component/ui/label'
|
||||
import { Textarea } from '@/component/ui/textarea'
|
||||
import { useTemplateContext } from '@/entitiy/template/model/TemplateContext'
|
||||
import { Plus, Trash2 } from 'lucide-react'
|
||||
import { useState } from 'react'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import TemplateCard from '@/widget/template/ui/TemplateCard'
|
||||
import clsx from 'clsx'
|
||||
import { CheckSquare, Plus, Square, Trash2 } from 'lucide-react'
|
||||
import { useCallback, useState } from 'react'
|
||||
|
||||
export const TemplatesOverviewPage = () => {
|
||||
const navigate = useNavigate()
|
||||
const { templates, deleteTemplate } = useTemplateContext()
|
||||
const { templates, deleteTemplate, addTemplate } = useTemplateContext()
|
||||
|
||||
const [selected, setSelected] = useState<Set<string>>(new Set())
|
||||
|
||||
const [selectionMode, setSelectionMode] = useState(false)
|
||||
|
||||
const [isDialogOpen, setIsDialogOpen] = useState(false)
|
||||
const [newName, setNewName] = useState('')
|
||||
const [newDescription, setNewDescription] = useState('')
|
||||
|
||||
const toggleSelect = useCallback((id: string) => {
|
||||
setSelected(prev => {
|
||||
const next = new Set(prev)
|
||||
next.has(id) ? next.delete(id) : next.add(id)
|
||||
return next
|
||||
})
|
||||
}, [])
|
||||
|
||||
const removeSelected = () => {
|
||||
selected.forEach(deleteTemplate)
|
||||
setSelected(new Set())
|
||||
setSelectionMode(false)
|
||||
}
|
||||
|
||||
const handleCreate = () => {
|
||||
if (newName.trim()) {
|
||||
addTemplate({
|
||||
name: newName,
|
||||
elements: [],
|
||||
description: newDescription,
|
||||
mergedCells: [],
|
||||
})
|
||||
setNewName('')
|
||||
setIsDialogOpen(false)
|
||||
}
|
||||
}
|
||||
|
||||
const toggleSelectionMode = () => {
|
||||
setSelectionMode(v => {
|
||||
if (v) setSelected(new Set())
|
||||
return !v
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -22,25 +70,93 @@ export const TemplatesOverviewPage = () => {
|
||||
<div className="flex gap-3">
|
||||
{!!selected.size && (
|
||||
<Button variant="destructive" onClick={removeSelected}>
|
||||
<Trash2 className="mr-2 h-4 w-4" />
|
||||
Удалить ({selected.size})
|
||||
<Trash2 className="mr-2 h-4 w-4" /> {selected.size}
|
||||
</Button>
|
||||
)}
|
||||
<Button onClick={() => navigate('/templates/new')}>
|
||||
<Plus className="mr-2 h-4 w-4" /> Создать
|
||||
|
||||
<Button
|
||||
variant={selectionMode ? 'secondary' : 'outline'}
|
||||
onClick={toggleSelectionMode}
|
||||
>
|
||||
{selectionMode ? (
|
||||
<>
|
||||
<Square className="mr-2 h-4 w-4" /> Отменить
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<CheckSquare className="mr-2 h-4 w-4" /> Выбрать
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
|
||||
<Dialog open={isDialogOpen} onOpenChange={setIsDialogOpen}>
|
||||
<DialogTrigger asChild>
|
||||
<Button>
|
||||
<Plus className="mr-2 h-4 w-4" /> Создать
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>Новый шаблон</DialogTitle>
|
||||
<DialogDescription>
|
||||
Укажите имя вашего нового шаблона протокола.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="grid gap-4 py-4">
|
||||
<div className="grid grid-cols-4 items-center gap-4">
|
||||
<Label htmlFor="template-name" className="text-right">
|
||||
Название
|
||||
</Label>
|
||||
<Input
|
||||
id="template-name"
|
||||
className="col-span-3"
|
||||
value={newName}
|
||||
onChange={e => setNewName(e.target.value)}
|
||||
placeholder="Введите название"
|
||||
/>
|
||||
</div>
|
||||
<div className="grid grid-cols-4 items-center gap-4">
|
||||
<Label htmlFor="template-description" className="text-right">
|
||||
Описание
|
||||
</Label>
|
||||
<Textarea
|
||||
id="template-description"
|
||||
className="col-span-3"
|
||||
value={newDescription}
|
||||
onChange={e => setNewDescription(e.target.value)}
|
||||
placeholder="Введите описание"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<DialogClose asChild>
|
||||
<Button variant="outline">Отмена</Button>
|
||||
</DialogClose>
|
||||
<Button onClick={handleCreate}>Создать</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section className="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3">
|
||||
<section
|
||||
className={clsx(
|
||||
'grid gap-6',
|
||||
'grid-cols-1 md:grid-cols-2 lg:grid-cols-3'
|
||||
)}
|
||||
>
|
||||
{templates.map(t => (
|
||||
<TemplateCard
|
||||
key={t.id}
|
||||
template={t}
|
||||
selectionMode={selectionMode}
|
||||
isSelected={selected.has(t.id)}
|
||||
onToggleSelect={toggleSelect}
|
||||
/>
|
||||
))}
|
||||
</section>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
|
||||
export default TemplatesOverviewPage
|
||||
|
||||
Reference in New Issue
Block a user