Initial Switch to V2. Completely Overhauled Backend, Frontend and General Structure.

This commit is contained in:
2026-04-17 14:37:36 +03:00
parent eb773c5531
commit 0a8a42d69b
447 changed files with 70696 additions and 492 deletions

View File

@@ -0,0 +1,71 @@
// src/v2/components/ui/PageHeader.jsx
// Standard page title block. Every page starts with this component.
//
// Props:
// title — string (required) — main page heading
// subtitle — string — muted description below the title
// breadcrumbs — Array<{ label: string, href?: string }> — shown above the title
// children — ReactNode — action buttons rendered top-right
// className — extra classes on the wrapper
//
// Layout:
// [breadcrumbs?]
// [title] [children / actions →]
// [subtitle?]
//
// Styles: src/v2/styles/components.css (.page-header*, .breadcrumbs*)
export default function PageHeader({
title,
subtitle,
breadcrumbs,
children,
className = '',
}) {
return (
<header className={`page-header ${className}`}>
{/* Breadcrumb trail — only on detail pages */}
{breadcrumbs?.length > 0 && (
<nav aria-label="Breadcrumb" className="breadcrumbs">
{breadcrumbs.map((crumb, i) => {
const isLast = i === breadcrumbs.length - 1
return (
<span key={i} className="contents">
{i > 0 && (
<span className="breadcrumbs-sep" aria-hidden="true">
/
</span>
)}
{isLast || !crumb.href ? (
<span
className="breadcrumbs-current"
aria-current={isLast ? 'page' : undefined}
>
{crumb.label}
</span>
) : (
<a href={crumb.href}>{crumb.label}</a>
)}
</span>
)
})}
</nav>
)}
{/* Title row */}
<div className="page-header-row">
<div className="min-w-0 flex-1">
<h1 className="page-header-title">{title}</h1>
{subtitle && (
<p className="page-header-subtitle">{subtitle}</p>
)}
</div>
{/* Action slot — top-right buttons */}
{children && (
<div className="page-header-actions">{children}</div>
)}
</div>
</header>
)
}