This commit is contained in:
@@ -5,9 +5,11 @@ import { useSearchParams } from "next/navigation";
|
||||
import {
|
||||
FileText,
|
||||
FolderPlus,
|
||||
FolderTree,
|
||||
Hash,
|
||||
Layers3,
|
||||
Pencil,
|
||||
CheckCircle2,
|
||||
ShieldCheck,
|
||||
ShieldOff,
|
||||
Text,
|
||||
@@ -18,6 +20,7 @@ import type { deleteCategoryAction, upsertCategoryAction } from "@/app/_admin/po
|
||||
import { AppCard } from "@/components/ui/app-card";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { StatsCard } from "@/components/dashboard/stats-card";
|
||||
import { CardContent } from "@/components/ui/card";
|
||||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
import {
|
||||
@@ -107,11 +110,11 @@ function CategoryLocaleFields({
|
||||
const descriptionKey = `description${locale.key}` as const;
|
||||
|
||||
return (
|
||||
<AppCard key={`${idPrefix}-${locale.key}`} level={2} padding="sm" className="space-y-4 rounded-nested">
|
||||
<AppCard key={`${idPrefix}-${locale.key}`} level={2} layer="single" padding="sm" className="space-y-4 rounded-nested">
|
||||
<p className="text-sm font-medium text-foreground">{locale.label}</p>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor={`${idPrefix}-${nameKey}`}>Name</Label>
|
||||
<Label htmlFor={`${idPrefix}-${nameKey}`} className="sr-only">Name</Label>
|
||||
<div className="relative">
|
||||
<Text className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
|
||||
<Input
|
||||
@@ -126,7 +129,7 @@ function CategoryLocaleFields({
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor={`${idPrefix}-${descriptionKey}`}>{copy.description}</Label>
|
||||
<Label htmlFor={`${idPrefix}-${descriptionKey}`} className="sr-only">{copy.description}</Label>
|
||||
<div className="relative">
|
||||
<FileText className="pointer-events-none absolute left-3 top-3 h-4 w-4 text-muted-foreground" />
|
||||
<Textarea
|
||||
@@ -165,7 +168,7 @@ function CategoryStatusFields({
|
||||
</div>
|
||||
|
||||
<div className="grid gap-4 lg:grid-cols-[minmax(0,1fr)_220px]">
|
||||
<AppCard level={2} padding="sm" className="rounded-nested">
|
||||
<AppCard level={2} layer="single" padding="sm" className="rounded-nested">
|
||||
<div className="flex items-start gap-3">
|
||||
{isActive ? (
|
||||
<ShieldCheck className="mt-0.5 h-4 w-4 text-status-success" />
|
||||
@@ -224,7 +227,7 @@ function CategoryForm({
|
||||
|
||||
<div className="grid gap-4 lg:grid-cols-3">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor={`${formId}-slug`}>Slug</Label>
|
||||
<Label htmlFor={`${formId}-slug`} className="sr-only">Slug</Label>
|
||||
<div className="relative">
|
||||
<Text className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
|
||||
<Input
|
||||
@@ -239,7 +242,7 @@ function CategoryForm({
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor={`${formId}-sortOrder`}>{copy.sortOrder}</Label>
|
||||
<Label htmlFor={`${formId}-sortOrder`} className="sr-only">{copy.sortOrder}</Label>
|
||||
<div className="relative">
|
||||
<Hash className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
|
||||
<Input
|
||||
@@ -249,6 +252,7 @@ function CategoryForm({
|
||||
min="0"
|
||||
defaultValue={values?.sortOrder ?? 0}
|
||||
required
|
||||
placeholder={copy.sortOrder}
|
||||
className="pl-9"
|
||||
/>
|
||||
</div>
|
||||
@@ -291,11 +295,11 @@ function EditCategoryDialog({
|
||||
</DialogHeader>
|
||||
|
||||
<div className="grid gap-3 sm:grid-cols-3">
|
||||
<AppCard level={2} padding="sm" className="rounded-nested">
|
||||
<AppCard level={2} layer="single" padding="sm" className="rounded-nested">
|
||||
<p className="text-xs uppercase tracking-[0.18em] text-muted-foreground">Projects</p>
|
||||
<p className="mt-2 text-lg font-semibold text-foreground">{category.projectCount}</p>
|
||||
</AppCard>
|
||||
<AppCard level={2} padding="sm" className="rounded-nested">
|
||||
<AppCard level={2} layer="single" padding="sm" className="rounded-nested">
|
||||
<p className="text-xs uppercase tracking-[0.18em] text-muted-foreground">Status</p>
|
||||
<div className="mt-2">
|
||||
<Badge variant={category.isActive ? "success" : "warning"}>
|
||||
@@ -303,7 +307,7 @@ function EditCategoryDialog({
|
||||
</Badge>
|
||||
</div>
|
||||
</AppCard>
|
||||
<AppCard level={2} padding="sm" className="rounded-nested">
|
||||
<AppCard level={2} layer="single" padding="sm" className="rounded-nested">
|
||||
<p className="text-xs uppercase tracking-[0.18em] text-muted-foreground">Order</p>
|
||||
<p className="mt-2 text-lg font-semibold text-foreground">{category.sortOrder}</p>
|
||||
</AppCard>
|
||||
@@ -371,23 +375,11 @@ export function PortfolioCategoriesManager({
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between">
|
||||
<div className="flex flex-wrap items-center gap-x-4 gap-y-2 text-sm text-muted-foreground">
|
||||
<span>
|
||||
Total:
|
||||
{" "}
|
||||
<span className="font-semibold text-foreground">{categories.length}</span>
|
||||
</span>
|
||||
<span>
|
||||
Active:
|
||||
{" "}
|
||||
<span className="font-semibold text-foreground">{activeCount}</span>
|
||||
</span>
|
||||
<span>
|
||||
Assigned:
|
||||
{" "}
|
||||
<span className="font-semibold text-foreground">{assignedProjects}</span>
|
||||
</span>
|
||||
<div className="flex flex-col gap-4 xl:flex-row xl:items-end xl:justify-between">
|
||||
<div className="grid gap-4 md:grid-cols-3 xl:min-w-[620px]">
|
||||
<StatsCard title="Total" value={String(categories.length)} icon={FolderTree} />
|
||||
<StatsCard title="Active" value={String(activeCount)} icon={CheckCircle2} />
|
||||
<StatsCard title="Assigned" value={String(assignedProjects)} icon={Layers3} />
|
||||
</div>
|
||||
|
||||
<Dialog open={createOpen} onOpenChange={setCreateOpen}>
|
||||
@@ -403,7 +395,7 @@ export function PortfolioCategoriesManager({
|
||||
<DialogDescription>{copy.modalDescription}</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<AppCard level={2} padding="sm" className="rounded-nested">
|
||||
<AppCard level={2} layer="single" padding="sm" className="rounded-nested">
|
||||
<div className="grid gap-3 sm:grid-cols-3">
|
||||
<div className="space-y-1">
|
||||
<p className="text-sm font-medium text-foreground">1. Basics</p>
|
||||
@@ -434,7 +426,7 @@ export function PortfolioCategoriesManager({
|
||||
</Dialog>
|
||||
</div>
|
||||
|
||||
<AppCard level={3}>
|
||||
<AppCard level={3} layer="single">
|
||||
<CardContent className="space-y-4 p-6">
|
||||
<div className="flex items-center gap-3">
|
||||
<Layers3 className="h-5 w-5 text-brand-primary" />
|
||||
@@ -449,6 +441,7 @@ export function PortfolioCategoriesManager({
|
||||
<AppCard
|
||||
key={category.id}
|
||||
level={2}
|
||||
layer="single"
|
||||
padding="sm"
|
||||
className="rounded-nested"
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user