first commit

This commit is contained in:
2025-08-02 16:30:27 +02:00
commit 23646bfcee
14851 changed files with 1750626 additions and 0 deletions

View File

@@ -0,0 +1,146 @@
import { useQuery, useWidgetProps } from './utils';
import { useEffect, useState, type KeyboardEvent } from 'react';
export type Section = {
name: string;
id: number;
has_subsections: 0 | 1;
}
type SectionRowProps = {
section: { name: string; id: number; full_path?: string };
depth?: number;
hasSubsections?: boolean;
};
function getEndpoint(sectionId: number) {
return `/admin/autocomplete/sections/${sectionId}`;
}
export function SectionRow({ section, hasSubsections, depth = 0 }: SectionRowProps) {
const [showChildren, setShowChildren] = useState(false);
const [shouldFetchChildren, setShouldFetchChildren] = useState(false);
const { data } = useQuery<Section[]>(shouldFetchChildren ? getEndpoint(section.id): undefined);
const { onAddSection, onAddWithSubsections, onSelect, hide, shouldHideAfterSelect } = useWidgetProps();
useEffect(() => {
if (!shouldFetchChildren) {
setShouldFetchChildren(showChildren);
}
}, [showChildren]);
function handleKeyboardNav(ev: KeyboardEvent<HTMLDivElement>) {
switch (ev.key) {
case 'ArrowLeft':
setShowChildren(false);
break;
case 'ArrowRight':
setShowChildren(true);
break;
case 'Enter':
if (ev.ctrlKey) {
if (onAddWithSubsections) {
onAddWithSubsections(section.id);
}
break;
}
if (onAddSection) {
onAddSection(section.id);
}
if (onSelect) {
onSelect(section.id);
}
break;
}
}
return (
<>
<div
tabIndex={-1}
className={`section-row${depth > 0 ? ' subsection' : ''}`}
style={{ paddingLeft: `${depth * 28}px` }}
onKeyUp={handleKeyboardNav}
>
<div
className="SectionRow__content"
onClick={ev => {
if (onSelect) {
ev.stopPropagation();
if (shouldHideAfterSelect) {
hide();
}
onSelect(section.id);
}
}}
>
<div className="SectionRow__left">
{!!hasSubsections && (
<div className="SectionRow__unwrap-button">
<span
onClick={ev => {
ev.stopPropagation();
setShowChildren(prev => !prev);
}}
className={`bi bi-dash-circle opener ${showChildren ? 'minus' : 'plus'}`}
/>
</div>
)}
<div className="SectionRow__name">
<strong>
{section.name}
</strong>
{!!section.full_path && (
<span className="SectionRow__full-path">{section.full_path}</span>
)}
</div>
</div>
<div className="SectionRow__buttons">
{!!onAddSection && (
<button
key="btn-add"
type="button"
className="btn btn-sm btn-primary"
onClick={ev => {
ev.stopPropagation();
onAddSection(section.id);
}}
>
<span className="bi bi-plus-lg m-r-1"></span> Přidat
</button>
)}
{!!onAddWithSubsections && (
<button
type="button"
key="btn-add-all"
className="btn btn-sm btn-secondary"
disabled={!hasSubsections}
onClick={ev => {
ev.stopPropagation();
onAddWithSubsections(section.id);
}}
>
<span className="bi bi-plus-lg m-r-1"></span> Včetně podsekcí
</button>
)}
</div>
</div>
</div>
{showChildren && data?.map((child, i) => (
<SectionRow
section={child}
key={`c${section.id}-${child.id}-${i}`}
depth={depth + 1}
hasSubsections={child.has_subsections === 1}
/>
))}
</>
);
}