x
This commit is contained in:
1 parent
f258e3e176
commit
3631f59bba
7 files changed
+524
-57
No files matched your search
@@ -127,6 +127,7 @@ export default function ProductEditPage() {
|
||||
const [options, setOptions] = useState<{name: Record<string, string>, values: Record<string, string>[]}[]>([])
|
||||
const [variants, setVariants] = useState<Partial<Variant>[]>([])
|
||||
const [images, setImages] = useState<EditableProductImage[]>([])
|
||||
const [titleGraphicUrl, setTitleGraphicUrl] = useState<string>('')
|
||||
const [availableAttributes, setAvailableAttributes] = useState<AttributeDefinition[]>([])
|
||||
const [attributes, setAttributes] = useState<EditableAttribute[]>([])
|
||||
const [selectedDefinitionId, setSelectedDefinitionId] = useState<number>(0)
|
||||
@@ -211,6 +212,7 @@ export default function ProductEditPage() {
|
||||
setOptions(parseOptions(prodData.options))
|
||||
setVariants(prodData.variants || [])
|
||||
setImages(prodData.images || [])
|
||||
setTitleGraphicUrl(prodData.titleGraphicUrl || '')
|
||||
setAttributes((prodData.attributes || []).map(parseEditableAttribute))
|
||||
await fetchAttributeDefinitions(prodData.categoryId)
|
||||
} else {
|
||||
@@ -219,6 +221,7 @@ export default function ProductEditPage() {
|
||||
setName({ th: '', en: '' })
|
||||
setDescription({ th: '', en: '' })
|
||||
setDetails({ th: '', en: '' })
|
||||
setTitleGraphicUrl('')
|
||||
setOptions([])
|
||||
setVariants([])
|
||||
setImages([])
|
||||
@@ -384,6 +387,7 @@ export default function ProductEditPage() {
|
||||
body: JSON.stringify({
|
||||
categoryId,
|
||||
name,
|
||||
titleGraphicUrl: titleGraphicUrl.trim() || null,
|
||||
description,
|
||||
details,
|
||||
options,
|
||||
@@ -395,7 +399,8 @@ export default function ProductEditPage() {
|
||||
price: Number(v.price) || 0,
|
||||
stock: Number(v.stock) || 0,
|
||||
sku: v.sku || '',
|
||||
barcode: v.barcode || ''
|
||||
barcode: v.barcode || '',
|
||||
imageUrl: v.imageUrl || null,
|
||||
})),
|
||||
images: images.filter(img => img.url).map((img, idx) => ({
|
||||
...(img.id ? { id: img.id } : {}),
|
||||
@@ -550,6 +555,57 @@ export default function ProductEditPage() {
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="md:col-span-2 space-y-2 p-4 rounded-xl border border-white/10 bg-white/[0.02]">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<ImageIcon className="w-4 h-4 text-cyan-glow" />
|
||||
<label className="text-[10px] uppercase font-bold tracking-widest text-slate-400">
|
||||
Title Graphic / Series Logo (Wide PNG Transparent / SVG ~5:1)
|
||||
</label>
|
||||
</div>
|
||||
{titleGraphicUrl && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setTitleGraphicUrl('')}
|
||||
className="text-xs text-rose-400 hover:text-rose-300 transition-colors"
|
||||
>
|
||||
Remove Graphic
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{titleGraphicUrl ? (
|
||||
<div className="flex items-center justify-between gap-4 p-3 bg-night-950/80 border border-white/10 rounded-xl">
|
||||
<div className="relative h-12 w-64 max-w-full bg-black/60 rounded-lg p-2 border border-white/5 flex items-center">
|
||||
<img
|
||||
src={titleGraphicUrl}
|
||||
alt="Title graphic preview"
|
||||
className="h-full w-auto max-w-full object-contain"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => openMediaModal((url) => setTitleGraphicUrl(url))}
|
||||
className="px-4 py-2 bg-white/5 hover:bg-white/10 border border-white/10 rounded-lg text-xs font-semibold text-white transition-all shrink-0"
|
||||
>
|
||||
Change Graphic
|
||||
</button>
|
||||
</div>
|
||||
) : (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => openMediaModal((url) => setTitleGraphicUrl(url))}
|
||||
className="w-full py-4 border-2 border-dashed border-white/10 hover:border-cyan-glow/40 bg-night-950/40 hover:bg-night-950/80 rounded-xl text-xs font-semibold text-slate-400 hover:text-cyan-glow transition-all flex items-center justify-center gap-2"
|
||||
>
|
||||
<ImagePlus className="w-4 h-4" />
|
||||
Upload Title Graphic (e.g. "NORIFUMI Oil Cup GP Series" Logo PNG)
|
||||
</button>
|
||||
)}
|
||||
<p className="text-[11px] text-slate-500">
|
||||
Optional. Displays as a branded logo banner above the product title on the website.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="md:col-span-2 space-y-2">
|
||||
<label className="text-[10px] uppercase font-bold tracking-widest text-slate-500 ml-1">Short Description ({activeLang.toUpperCase()})</label>
|
||||
<textarea
|
||||
@@ -1068,6 +1124,7 @@ export default function ProductEditPage() {
|
||||
)) : (
|
||||
<th className="py-3 px-4 font-bold">Variant</th>
|
||||
)}
|
||||
<th className="py-3 px-4 font-bold">Swatch (1:1)</th>
|
||||
<th className="py-3 px-4 font-bold">Price (THB)</th>
|
||||
<th className="py-3 px-4 font-bold">Stock</th>
|
||||
<th className="py-3 px-4 font-bold">SKU</th>
|
||||
@@ -1086,6 +1143,40 @@ export default function ProductEditPage() {
|
||||
}) : (
|
||||
<td className="py-3 px-4 text-sm font-medium text-white">{v.option1 || 'Default'}</td>
|
||||
)}
|
||||
<td className="py-3 px-4">
|
||||
{v.imageUrl ? (
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="relative w-10 h-10 rounded-lg overflow-hidden border border-white/15 bg-black/60 shrink-0">
|
||||
<img src={v.imageUrl} alt="Variant swatch" className="w-full h-full object-cover" />
|
||||
</div>
|
||||
<div className="flex flex-col gap-0.5">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => openMediaModal((url) => handleUpdateVariant(idx, 'imageUrl', url))}
|
||||
className="text-[10px] text-cyan-glow hover:underline text-left"
|
||||
>
|
||||
Change
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleUpdateVariant(idx, 'imageUrl', '')}
|
||||
className="text-[10px] text-rose-400 hover:underline text-left"
|
||||
>
|
||||
Remove
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => openMediaModal((url) => handleUpdateVariant(idx, 'imageUrl', url))}
|
||||
className="px-2.5 py-1.5 rounded-lg border border-dashed border-white/15 hover:border-cyan-glow/40 bg-white/5 hover:bg-white/10 text-[11px] text-slate-400 hover:text-cyan-glow flex items-center gap-1.5 transition-all"
|
||||
>
|
||||
<ImagePlus className="w-3.5 h-3.5" />
|
||||
<span>1:1 Image</span>
|
||||
</button>
|
||||
)}
|
||||
</td>
|
||||
<td className="py-3 px-4">
|
||||
<input
|
||||
type="number"
|
||||
|
||||
Reference in new issue
Block a user