x
This commit is contained in:
1 parent
ce4502d123
commit
acee55a633
14 files changed
+634
-104
No files matched your search
@@ -126,8 +126,62 @@ export default function ProductCarouselForm({
|
||||
}
|
||||
className="admin-input w-full bg-slate-900 border-white/10"
|
||||
>
|
||||
<option value="standard">Standard (Retail with Add to Cart)</option>
|
||||
<option value="minimal_swatch">Minimal Swatch (Editorial with Color Dots)</option>
|
||||
<option value="standard">Standard Retail (1:1 Boxed with Add to Cart)</option>
|
||||
<option value="minimal">Fashion Minimal (3:4 Portrait, Pomelo/Zara Style)</option>
|
||||
<option value="swatch">Editorial Swatch (Lookbook with Swatch Dots)</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<label className="text-[10px] uppercase font-bold tracking-widest text-slate-400">ความกว้างบล็อก (Width)</label>
|
||||
<select
|
||||
value={editingSection.payload?.containerWidth || 'standard'}
|
||||
onChange={(e) =>
|
||||
setEditingSection(prev => prev ? {
|
||||
...prev,
|
||||
payload: { ...(prev.payload || {}), containerWidth: e.target.value }
|
||||
} : null)
|
||||
}
|
||||
className="admin-input w-full bg-slate-900 border-white/10"
|
||||
>
|
||||
<option value="standard">Standard (กรอบ 1280px)</option>
|
||||
<option value="wide">Wide (ขยายกว้าง 1600px)</option>
|
||||
<option value="full">Full Width (เต็มพื้นที่ 100%)</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<label className="text-[10px] uppercase font-bold tracking-widest text-slate-400">ขนาดการ์ด (Card Size)</label>
|
||||
<select
|
||||
value={editingSection.payload?.cardSize || 'medium'}
|
||||
onChange={(e) =>
|
||||
setEditingSection(prev => prev ? {
|
||||
...prev,
|
||||
payload: { ...(prev.payload || {}), cardSize: e.target.value }
|
||||
} : null)
|
||||
}
|
||||
className="admin-input w-full bg-slate-900 border-white/10"
|
||||
>
|
||||
<option value="medium">Medium (~4 ใบต่อหน้าจอ สไตล์ Pomelo - แนะนำ)</option>
|
||||
<option value="large">Large (~3-4 ใบต่อหน้าจอ ขนาดใหญ่พิเศษ)</option>
|
||||
<option value="compact">Compact (~5-6 ใบต่อหน้าจอ ขนาดกะทัดรัด)</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<label className="text-[10px] uppercase font-bold tracking-widest text-slate-400">รูปแบบการแสดง (Display Layout)</label>
|
||||
<select
|
||||
value={editingSection.payload?.layout || 'carousel'}
|
||||
onChange={(e) =>
|
||||
setEditingSection(prev => prev ? {
|
||||
...prev,
|
||||
payload: { ...(prev.payload || {}), layout: e.target.value }
|
||||
} : null)
|
||||
}
|
||||
className="admin-input w-full bg-slate-900 border-white/10"
|
||||
>
|
||||
<option value="carousel">Carousel Slider (สไลด์เลื่อนแนวนอน)</option>
|
||||
<option value="grid">Grid Layout (ตารางสินค้า แถวละ 4 ใบ แบบ Pomelo)</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -116,6 +116,42 @@ export default function ProductsForm({
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<label className="text-[10px] uppercase font-bold tracking-widest text-slate-400">ความกว้างบล็อก (Width)</label>
|
||||
<select
|
||||
value={editingSection.payload?.containerWidth || 'standard'}
|
||||
onChange={(e) =>
|
||||
setEditingSection(prev => prev ? {
|
||||
...prev,
|
||||
payload: { ...(prev.payload || {}), containerWidth: e.target.value }
|
||||
} : null)
|
||||
}
|
||||
className="admin-input w-full bg-slate-900 border-white/10"
|
||||
>
|
||||
<option value="standard">Standard (กรอบ 1280px)</option>
|
||||
<option value="wide">Wide (ขยายกว้าง 1600px)</option>
|
||||
<option value="full">Full Width (เต็มพื้นที่ 100%)</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<label className="text-[10px] uppercase font-bold tracking-widest text-slate-400">ขนาดการ์ด (Card Size)</label>
|
||||
<select
|
||||
value={editingSection.payload?.cardSize || 'medium'}
|
||||
onChange={(e) =>
|
||||
setEditingSection(prev => prev ? {
|
||||
...prev,
|
||||
payload: { ...(prev.payload || {}), cardSize: e.target.value }
|
||||
} : null)
|
||||
}
|
||||
className="admin-input w-full bg-slate-900 border-white/10"
|
||||
>
|
||||
<option value="medium">Medium (~4 ใบต่อหน้าจอ สไตล์ Pomelo - แนะนำ)</option>
|
||||
<option value="large">Large (~3-4 ใบต่อหน้าจอ ขนาดใหญ่พิเศษ)</option>
|
||||
<option value="compact">Compact (~5-6 ใบต่อหน้าจอ ขนาดกะทัดรัด)</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2 flex flex-col justify-end">
|
||||
<label className="flex items-center gap-3 p-3 border border-white/5 bg-white/5 rounded-xl cursor-pointer select-none">
|
||||
<input
|
||||
|
||||
@@ -935,6 +935,9 @@ export default function PageBuilderPage() {
|
||||
showPrice: true,
|
||||
showAddToCart: true,
|
||||
cardStyle: 'standard',
|
||||
containerWidth: 'standard',
|
||||
cardSize: 'medium',
|
||||
layout: 'carousel',
|
||||
};
|
||||
break;
|
||||
case 'PRODUCT_MAIN':
|
||||
|
||||
@@ -18,7 +18,8 @@ import {
|
||||
Bot,
|
||||
ArrowUpDown,
|
||||
Monitor,
|
||||
Smartphone
|
||||
Smartphone,
|
||||
LayoutGrid
|
||||
} from 'lucide-react'
|
||||
|
||||
const defaultThemeTokens = {
|
||||
@@ -167,6 +168,7 @@ export default function ThemeSettingsPage() {
|
||||
const [headerBehavior, setHeaderBehavior] = useState<'always_sticky' | 'hide_on_scroll'>('hide_on_scroll')
|
||||
const [mobileHeaderStyle, setMobileHeaderStyle] = useState<'logo_center' | 'logo_left' | 'search_bar_below'>('logo_center')
|
||||
const [mobileHeaderBehavior, setMobileHeaderBehavior] = useState<'always_sticky' | 'hide_on_scroll'>('hide_on_scroll')
|
||||
const [cardPreset, setCardPreset] = useState<'standard' | 'minimal' | 'swatch'>('standard')
|
||||
|
||||
// JSON Quick Copy / Paste State
|
||||
const [isJsonBoxOpen, setIsJsonBoxOpen] = useState(false)
|
||||
@@ -197,6 +199,8 @@ export default function ThemeSettingsPage() {
|
||||
setHeaderBehavior(pcBehavior)
|
||||
setMobileHeaderStyle((data as any).mobileHeaderStyle || (data.themeTokens as any)?.mobileHeaderStyle || 'logo_center')
|
||||
setMobileHeaderBehavior((data as any).mobileHeaderBehavior || (data.themeTokens as any)?.mobileHeaderBehavior || pcBehavior)
|
||||
const cp = (data as any).cardPreset || (data.themeTokens as any)?.cardPreset || 'standard'
|
||||
setCardPreset(cp === 'minimal_swatch' ? 'swatch' : cp)
|
||||
})
|
||||
.catch(console.error)
|
||||
.finally(() => setLoading(false))
|
||||
@@ -217,7 +221,9 @@ export default function ThemeSettingsPage() {
|
||||
headerBehavior,
|
||||
mobileHeaderBehavior,
|
||||
mobileHeaderStyle,
|
||||
cardPreset,
|
||||
},
|
||||
cardPreset,
|
||||
scrollRevealEnabled,
|
||||
scrollRevealStyle,
|
||||
scrollRevealDuration: parseInt(scrollRevealDuration) || 700,
|
||||
@@ -444,7 +450,9 @@ export default function ThemeSettingsPage() {
|
||||
headerBehavior,
|
||||
mobileHeaderBehavior,
|
||||
mobileHeaderStyle,
|
||||
cardPreset,
|
||||
},
|
||||
cardPreset,
|
||||
scrollRevealEnabled,
|
||||
scrollRevealStyle,
|
||||
scrollRevealDuration: parseInt(scrollRevealDuration) || 700,
|
||||
@@ -1064,7 +1072,84 @@ export default function ThemeSettingsPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* ── 4. Desktop (PC) Header Settings ── */}
|
||||
{/* ── 4. Product Card UI Presets ── */}
|
||||
<div className="admin-card p-6 md:p-8 space-y-6">
|
||||
<div className="flex items-center gap-3 border-b border-white/10 pb-4">
|
||||
<div className="p-2 bg-emerald-500/10 rounded-xl text-emerald-400">
|
||||
<LayoutGrid className="w-5 h-5" />
|
||||
</div>
|
||||
<div>
|
||||
<h2 className="text-lg font-bold text-white">Product Card UI Preset</h2>
|
||||
<p className="text-xs text-slate-400">เลือกรูปแบบการ์ดสินค้าหลักสำหรับทั้งร้านค้า (Catalog, Search & Default)</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-6 md:grid-cols-3">
|
||||
{[
|
||||
{
|
||||
id: 'standard',
|
||||
title: 'Standard Retail',
|
||||
badge: 'Default Retail',
|
||||
desc: 'กล่องการ์ดมีขอบ, ภาพ 1:1 จัตุรัส, ปุ่ม Select Options / Add to Cart ใต้ราคา เหมาะกับร้านค้าทั่วไปหรือสินค้าอิเล็กทรอนิกส์/ของใช้',
|
||||
features: ['1:1 Square Image', 'Bordered Card Container', 'Action Button (Add to Cart)', 'Category Badge'],
|
||||
},
|
||||
{
|
||||
id: 'minimal',
|
||||
title: 'Fashion Minimal',
|
||||
badge: 'Pomelo / Zara Style',
|
||||
desc: 'สไตล์แฟชั่นมินิมอล ภาพแนวตั้ง 3:4 ไร้กรอบแบนราบ แบรนด์ตัวหนา หัวใจ Wishlist แสดงยอดขาย คลีนหรูหรา',
|
||||
features: ['3:4 Portrait Image', 'Borderless Flat Layout', 'Brand Name & Wishlist Heart', 'Price & Stock Status'],
|
||||
},
|
||||
{
|
||||
id: 'swatch',
|
||||
title: 'Editorial Swatch',
|
||||
badge: 'Lookbook / New Arrivals',
|
||||
desc: 'สไตล์นิตยสารมินิมอล เน้นจุดสีกลม (Color Swatch Dots) และชื่อสินค้าแบบเรียบหรู เหมาะกับสินค้าหลายเฉดสี',
|
||||
features: ['Color Swatch Dots', 'Clean Typography', 'Frameless Lookbook', 'Price with Subtitle'],
|
||||
},
|
||||
].map((preset) => {
|
||||
const isSelected = cardPreset === preset.id
|
||||
return (
|
||||
<div
|
||||
key={preset.id}
|
||||
onClick={() => setCardPreset(preset.id as any)}
|
||||
className={`relative p-5 rounded-2xl border transition-all cursor-pointer flex flex-col justify-between ${
|
||||
isSelected
|
||||
? 'border-emerald-500/60 bg-emerald-500/10 ring-1 ring-emerald-500/40 shadow-lg'
|
||||
: 'border-white/10 bg-night-900/60 hover:border-white/20 hover:bg-white/5'
|
||||
}`}
|
||||
>
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-[10px] font-bold uppercase tracking-wider px-2 py-0.5 rounded-full bg-white/10 text-slate-300">
|
||||
{preset.badge}
|
||||
</span>
|
||||
<div className={`w-4 h-4 rounded-full border flex items-center justify-center ${isSelected ? 'border-emerald-400 bg-emerald-400' : 'border-slate-500'}`}>
|
||||
{isSelected && <div className="w-1.5 h-1.5 rounded-full bg-black" />}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="text-base font-bold text-white">{preset.title}</h3>
|
||||
<p className="text-xs text-slate-400 mt-1 leading-relaxed">{preset.desc}</p>
|
||||
</div>
|
||||
|
||||
<div className="pt-2 border-t border-white/5 space-y-1">
|
||||
{preset.features.map((feat, idx) => (
|
||||
<div key={idx} className="flex items-center gap-1.5 text-[11px] text-slate-300">
|
||||
<span className="text-emerald-400 font-bold">✓</span>
|
||||
<span>{feat}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* ── 5. Desktop (PC) Header Settings ── */}
|
||||
<div className="admin-card p-6 md:p-8 space-y-6">
|
||||
<div className="flex items-center gap-3 border-b border-white/10 pb-4">
|
||||
<div className="p-2 bg-amber-500/10 rounded-xl text-amber-400">
|
||||
|
||||
Reference in new issue
Block a user