- Mobile responsive CSS (touch targets 44px, iOS anti-zoom, reduced motion) - Vitest setup s 39 testy (formatters, attendanceHelpers, useTableSort) - Klavesove zkratky (Shift+? napoveda, Ctrl+S ulozit, navigace) - Drag & drop pro polozky nabidek (@dnd-kit, SortableRow, useSortableList) - Univerzalizace: odstraneni BOHA brandingu z UI, emailu, PDF - Smazany nepotrebne soubory (deploy.sh, AUTH_SYSTEM.md, example_design, .htaccess) - CORS konfigurovatelny pres env promennou Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
54 lines
1.3 KiB
JavaScript
54 lines
1.3 KiB
JavaScript
import { useSortable } from '@dnd-kit/sortable'
|
|
import { CSS } from '@dnd-kit/utilities'
|
|
|
|
export function DragHandle({ listeners, attributes }) {
|
|
return (
|
|
<button
|
|
type="button"
|
|
className="admin-drag-handle"
|
|
{...attributes}
|
|
{...listeners}
|
|
title="Přetáhnout"
|
|
aria-label="Přetáhnout pro změnu pořadí"
|
|
>
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor">
|
|
<circle cx="9" cy="5" r="1.5" />
|
|
<circle cx="15" cy="5" r="1.5" />
|
|
<circle cx="9" cy="12" r="1.5" />
|
|
<circle cx="15" cy="12" r="1.5" />
|
|
<circle cx="9" cy="19" r="1.5" />
|
|
<circle cx="15" cy="19" r="1.5" />
|
|
</svg>
|
|
</button>
|
|
)
|
|
}
|
|
|
|
export default function SortableRow({ id, children, disabled }) {
|
|
const {
|
|
attributes,
|
|
listeners,
|
|
setNodeRef,
|
|
transform,
|
|
transition,
|
|
isDragging,
|
|
} = useSortable({ id, disabled })
|
|
|
|
const style = {
|
|
transform: CSS.Transform.toString(transform),
|
|
transition,
|
|
opacity: isDragging ? 0.5 : 1,
|
|
position: 'relative',
|
|
zIndex: isDragging ? 10 : undefined,
|
|
background: isDragging ? 'var(--bg-secondary)' : undefined,
|
|
}
|
|
|
|
return (
|
|
<tr ref={setNodeRef} style={style}>
|
|
{typeof children === 'function'
|
|
? children({ attributes, listeners })
|
|
: children
|
|
}
|
|
</tr>
|
|
)
|
|
}
|