STYLED - Two-column project form, drop the redundant header card
- Remove the project summary/header card (project name, badges, progress); it added no value while creating a project. Move the on-submit validation alert down to the action bar. - Lay the whole form out in two columns: Basic Information + Localized Content, then Sections + Cover/Assets. Basic Information fields cap at two columns and the Cover/Assets card stacks inside its column. All 375 tests pass; tsc and eslint clean.
This commit is contained in:
@@ -7,7 +7,6 @@ import {
|
|||||||
BookOpenText,
|
BookOpenText,
|
||||||
BriefcaseBusiness,
|
BriefcaseBusiness,
|
||||||
CalendarDays,
|
CalendarDays,
|
||||||
CheckCircle2,
|
|
||||||
CircleAlert,
|
CircleAlert,
|
||||||
FolderTree,
|
FolderTree,
|
||||||
Grid2x2,
|
Grid2x2,
|
||||||
@@ -533,14 +532,6 @@ export function PortfolioProjectForm({
|
|||||||
})),
|
})),
|
||||||
});
|
});
|
||||||
const firstIncompleteStep = getFirstIncompleteWizardStep(progress);
|
const firstIncompleteStep = getFirstIncompleteWizardStep(progress);
|
||||||
const selectedCategory =
|
|
||||||
availableCategories.find((category) => category.id === projectState.categoryId) ?? null;
|
|
||||||
const projectLabel =
|
|
||||||
projectState.titleDe.trim() ||
|
|
||||||
projectState.titleEn.trim() ||
|
|
||||||
projectState.titleAr.trim() ||
|
|
||||||
projectState.slug.trim() ||
|
|
||||||
"Untitled Project";
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
sectionsInputRef.current?.dispatchEvent(new Event("input", { bubbles: true }));
|
sectionsInputRef.current?.dispatchEvent(new Event("input", { bubbles: true }));
|
||||||
@@ -603,53 +594,7 @@ export function PortfolioProjectForm({
|
|||||||
<input ref={assetsInputRef} type="hidden" name="assets" value={assetsPayload} />
|
<input ref={assetsInputRef} type="hidden" name="assets" value={assetsPayload} />
|
||||||
<input ref={intentRef} type="hidden" name="intent" defaultValue="save" />
|
<input ref={intentRef} type="hidden" name="intent" defaultValue="save" />
|
||||||
|
|
||||||
<AppCard level={3} padding="md" contentClassName="space-y-5">
|
<div className="grid gap-6 xl:grid-cols-2 xl:items-start">
|
||||||
<div className="flex flex-col gap-5">
|
|
||||||
<div className="flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between">
|
|
||||||
<div className="space-y-3">
|
|
||||||
<div className="flex flex-wrap items-center gap-2">
|
|
||||||
<Badge variant={projectState.isPublished ? "success" : "warning"}>
|
|
||||||
{projectState.isPublished ? "Published" : "Draft"}
|
|
||||||
</Badge>
|
|
||||||
{projectState.isFeatured ? <Badge variant="outline">Featured</Badge> : null}
|
|
||||||
{!selectedCategory?.isActive ? <Badge variant="warning">Inactive Category</Badge> : null}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h2 className="text-2xl font-semibold text-foreground">{projectLabel}</h2>
|
|
||||||
<p className="mt-1 text-sm text-muted-foreground">
|
|
||||||
{selectedCategory ? `${selectedCategory.name.de || selectedCategory.name.en || selectedCategory.name.ar}` : "No category selected"}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex items-center gap-3 rounded-nested border border-border/70 bg-surface-2 px-4 py-2.5">
|
|
||||||
<CheckCircle2 className="h-5 w-5 shrink-0 text-brand-primary" />
|
|
||||||
<div className="min-w-0">
|
|
||||||
<p className="text-[11px] uppercase tracking-[0.14em] text-muted-foreground">Fortschritt</p>
|
|
||||||
<p className="text-sm font-semibold text-foreground">
|
|
||||||
{progress.filter((step) => step.complete).length}/{progress.length} bereit
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{showValidation && firstIncompleteStep ? (
|
|
||||||
<div className="rounded-nested border border-status-warning/30 bg-status-warning-soft px-4 py-3">
|
|
||||||
<div className="flex items-start gap-3">
|
|
||||||
<CircleAlert className="mt-0.5 h-4 w-4 text-status-warning" />
|
|
||||||
<div className="space-y-1">
|
|
||||||
<p className="text-sm font-medium text-foreground">Some required fields are still missing.</p>
|
|
||||||
<p className="text-sm text-muted-foreground">
|
|
||||||
Fill the Basics and Localized Content fields below, then save.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
</div>
|
|
||||||
</AppCard>
|
|
||||||
|
|
||||||
<div className="space-y-6">
|
|
||||||
<div>
|
<div>
|
||||||
<AppCard level={3} padding="md">
|
<AppCard level={3} padding="md">
|
||||||
<section className="space-y-5">
|
<section className="space-y-5">
|
||||||
@@ -658,7 +603,7 @@ export function PortfolioProjectForm({
|
|||||||
description="Choose the category and the stable project metadata first."
|
description="Choose the category and the stable project metadata first."
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
|
<div className="grid gap-4 sm:grid-cols-2">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label htmlFor="categoryId" className="sr-only">Category</Label>
|
<Label htmlFor="categoryId" className="sr-only">Category</Label>
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
@@ -1071,7 +1016,7 @@ export function PortfolioProjectForm({
|
|||||||
|
|
||||||
<div>
|
<div>
|
||||||
<AppCard level={3} padding="md">
|
<AppCard level={3} padding="md">
|
||||||
<div className="grid gap-6 lg:grid-cols-2">
|
<div className="space-y-6">
|
||||||
<section className="space-y-4">
|
<section className="space-y-4">
|
||||||
<SectionHeader
|
<SectionHeader
|
||||||
title="Cover Media"
|
title="Cover Media"
|
||||||
@@ -1227,7 +1172,21 @@ export function PortfolioProjectForm({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<AppCard level={3} padding="md">
|
<AppCard level={3} padding="md" contentClassName="space-y-4">
|
||||||
|
{showValidation && firstIncompleteStep ? (
|
||||||
|
<div className="rounded-nested border border-status-warning/30 bg-status-warning-soft px-4 py-3">
|
||||||
|
<div className="flex items-start gap-3">
|
||||||
|
<CircleAlert className="mt-0.5 h-4 w-4 text-status-warning" />
|
||||||
|
<div className="space-y-1">
|
||||||
|
<p className="text-sm font-medium text-foreground">Some required fields are still missing.</p>
|
||||||
|
<p className="text-sm text-muted-foreground">
|
||||||
|
Fill the Basics and Localized Content fields, then save.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
|
||||||
<div className="flex flex-col gap-4 md:flex-row md:items-center md:justify-end">
|
<div className="flex flex-col gap-4 md:flex-row md:items-center md:justify-end">
|
||||||
<div className="flex flex-wrap items-center gap-3">
|
<div className="flex flex-wrap items-center gap-3">
|
||||||
{firstIncompleteStep ? (
|
{firstIncompleteStep ? (
|
||||||
|
|||||||
Reference in New Issue
Block a user