feat(F-071): completed feature

This commit is contained in:
chattie
2026-08-19 19:04:41 +02:00
parent 16e4e86fbe
commit cf67f51d07
22 changed files with 495 additions and 74 deletions

View File

@@ -17,7 +17,7 @@ function CategoryRow({ cat, onEdit, onDelete }: { cat: Category; onEdit: (c: Cat
<tr className="hover:bg-gray-50 transition-colors">
<td className="px-4 py-3">
<div className="flex items-center gap-2">
{cat.children && cat.children.length > 0 && <span className="text-gray-300">📁</span>}
{cat.children && cat.children.length > 0 && <span className="text-gray-300">{cat.emoji ?? '📁'}</span>}
<div>
<p className="text-sm font-medium text-gray-900">{cat.name}</p>
<p className="text-xs text-gray-400">/{cat.slug}</p>
@@ -59,6 +59,8 @@ interface FormState {
description: string;
parentId: string | null;
isParent: boolean;
emoji: string;
color: string;
seoTitle: string;
seoTitleManual: boolean;
seoDescription: string;
@@ -72,6 +74,8 @@ const EMPTY_FORM: FormState = {
description: '',
parentId: null,
isParent: false,
emoji: '',
color: '',
seoTitle: '',
seoTitleManual: false,
seoDescription: '',
@@ -140,6 +144,8 @@ export default function CategoriesPage() {
description: cat.description ?? '',
parentId: cat.parentId,
isParent: cat.isParent ?? false,
emoji: cat.emoji ?? '',
color: cat.color ?? '',
seoTitle: (cat as any).seoTitle ?? '',
seoTitleManual: true,
seoDescription: (cat as any).seoDescription ?? '',
@@ -167,6 +173,8 @@ export default function CategoriesPage() {
description: form.description || undefined,
parentId: form.parentId,
isParent: form.isParent,
emoji: form.emoji || undefined,
color: form.color || undefined,
seoTitle: form.seoTitle || undefined,
seoDescription: form.seoDescription || undefined,
};
@@ -286,6 +294,35 @@ export default function CategoriesPage() {
/>
</div>
{/* Emoji y color de la tarjeta */}
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">Emoji</label>
<div className="flex items-center gap-2">
<input
value={form.emoji}
onChange={(e) => setForm((f) => ({ ...f, emoji: e.target.value }))}
maxLength={10}
placeholder="🥜"
className="w-full px-4 py-2.5 border border-gray-300 rounded-xl text-sm text-2xl text-center focus:ring-2 focus:ring-[#2D6A4F] outline-none"
/>
{form.emoji && <span className="text-3xl">{form.emoji}</span>}
</div>
<p className="text-xs text-gray-400 mt-1">Emoji identificativo que aparecerá en las tarjetas de categoría.</p>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">Color de tarjeta</label>
<input
value={form.color}
onChange={(e) => setForm((f) => ({ ...f, color: e.target.value }))}
maxLength={200}
placeholder="bg-[#70ad47]/10 text-[#70ad47] ó from-[#70ad47] to-[#40916C]"
className="w-full px-4 py-2.5 border border-gray-300 rounded-xl text-sm font-mono focus:ring-2 focus:ring-[#2D6A4F] outline-none"
/>
<p className="text-xs text-gray-400 mt-1">Clase Tailwind para el color de la tarjeta (fondo o gradiente).</p>
</div>
</div>
{/* SEO Title */}
<div>
<div className="flex items-center justify-between mb-1">