diff --git a/apps/admin/src/components/page-builder/HeroForm.tsx b/apps/admin/src/components/page-builder/HeroForm.tsx index e712e8b..a0e58b7 100644 --- a/apps/admin/src/components/page-builder/HeroForm.tsx +++ b/apps/admin/src/components/page-builder/HeroForm.tsx @@ -9,7 +9,7 @@ interface HeroFormProps { getLocalizedValue: (payload: any, field: string) => string; updateLocalizedValue: (field: string, value: string) => void; updatePayloadValue: (field: string, value: any) => void; - setUploadTarget: (target: { type: 'main' | 'slide'; index?: number } | null) => void; + setUploadTarget: (target: { type: 'main' | 'slide' | 'gallery' | 'tile' | 'seoOgImage' | 'mobileImage'; index?: number } | null) => void; setIsMediaModalOpen: (open: boolean) => void; } @@ -31,12 +31,104 @@ export default function HeroForm({ }: HeroFormProps) { const currentOverlayStyle = editingSection.payload?.overlayStyle || 'gradient'; const currentOverlayOpacity = editingSection.payload?.overlayOpacity !== undefined ? editingSection.payload.overlayOpacity : 45; + const payload = editingSection.payload || {}; return (
- {/* Hero image uploading */} -
- + {/* Global Dimension & Display Settings */} +
+
+ + Carousel Dimension & Display Settings +
+ +
+
+ + +

BEAUTRIUM style uses 21:7 or 21:6 for wide banners without eating vertical screen space.

+
+ +
+ + +
+ +
+ +
+ + + +
+
+
+
+ + {/* Hero Desktop Image */} +
+
{ @@ -60,6 +152,51 @@ export default function HeroForm({
+ {/* Hero Mobile Image (Optional) */} +
+
+ + {editingSection.payload?.mobileImageUrl && ( + + )} +
+
{ + setUploadTarget({ type: 'mobileImage' }); + setIsMediaModalOpen(true); + }} + > + {editingSection.payload?.mobileImageUrl ? ( + <> + Hero Mobile Background +
+ +
+ + ) : ( +
+ +

+ {editingSection.payload?.imageUrl ? 'ใช้รูปเดียวกับ Desktop' : 'Select Mobile Image'} +

+

แนะนำสำหรับสัดส่วน 1:1 หรือ 4:3 บนมือถือ

+
+ )} +
+
+ {editingSection.payload?.imageUrl && (
([]); const [loading, setLoading] = useState(true); const [editingSection, setEditingSection] = useState | null>(null); - const [uploadTarget, setUploadTarget] = useState<{ type: 'main' | 'slide' | 'gallery' | 'tile' | 'seoOgImage'; index?: number } | null>(null); + const [uploadTarget, setUploadTarget] = useState<{ type: 'main' | 'slide' | 'gallery' | 'tile' | 'seoOgImage' | 'mobileImage'; index?: number } | null>(null); const [saveStatus, setSaveStatus] = useState<'idle' | 'saving' | 'saved' | 'error'>('idle'); const [isSavingPageSettings, setIsSavingPageSettings] = useState(false); const [isCopied, setIsCopied] = useState(false); @@ -160,6 +160,11 @@ export default function PageBuilderPage() { const handleMediaSelect = (url: string) => { if (uploadTarget?.type === 'seoOgImage') { setPage(prev => (prev ? { ...prev, ogImageUrl: url } : prev)); + } else if (uploadTarget?.type === 'mobileImage') { + setEditingSection(prev => { + if (!prev) return null; + return { ...prev, payload: { ...(prev.payload || {}), mobileImageUrl: url } }; + }); } else if (uploadTarget?.type === 'tile' && typeof uploadTarget.index === 'number') { const idx = uploadTarget.index; setEditingSection(prev => { @@ -733,7 +738,10 @@ export default function PageBuilderPage() { description: 'Transform your room into a peaceful escape.', imageUrl: '/images/hero.png', buttonText: 'Explore', - buttonLink: '/shop' + buttonLink: '/shop', + aspectRatio: '21/7', + mobileAspectRatio: '16/9', + headerSpacing: 'below_header' }; break; case 'HERO_CAROUSEL': diff --git a/apps/mcp-server/section-toolkit.ts b/apps/mcp-server/section-toolkit.ts index b91acc3..e4cd5e4 100644 --- a/apps/mcp-server/section-toolkit.ts +++ b/apps/mcp-server/section-toolkit.ts @@ -95,8 +95,8 @@ const PAGE_BLOCK_METADATA: Record = { HERO: { type: "HERO", requiredFields: ["tagline", "title", "description", "imageUrl", "buttonText", "buttonLink"], - optionalFields: ["focalPoint", "contentWidth", "textColorScheme", "buttonPosition", "mobileButtonPosition", "overlayStyle", "overlayOpacity", "titleSize"], - renderedFields: ["tagline", "title", "description", "imageUrl", "buttonText", "buttonLink", "focalPoint", "contentWidth", "textColorScheme", "buttonPosition", "mobileButtonPosition", "overlayStyle", "overlayOpacity", "titleSize"], + optionalFields: ["focalPoint", "contentWidth", "textColorScheme", "buttonPosition", "mobileButtonPosition", "overlayStyle", "overlayOpacity", "titleSize", "aspectRatio", "mobileAspectRatio", "headerSpacing", "mobileImageUrl"], + renderedFields: ["tagline", "title", "description", "imageUrl", "buttonText", "buttonLink", "focalPoint", "contentWidth", "textColorScheme", "buttonPosition", "mobileButtonPosition", "overlayStyle", "overlayOpacity", "titleSize", "aspectRatio", "mobileAspectRatio", "headerSpacing", "mobileImageUrl"], storedOnlyFields: [], discoveryToolsNeeded: [], warnings: ["Replace sample image URLs with this tenant's approved media URLs before writing. The website must allow the media host."], diff --git a/apps/spa/src/components/DynamicHero.tsx b/apps/spa/src/components/DynamicHero.tsx index d2a1b06..63c2e71 100644 --- a/apps/spa/src/components/DynamicHero.tsx +++ b/apps/spa/src/components/DynamicHero.tsx @@ -258,23 +258,71 @@ export default function DynamicHero({ payload }: DynamicHeroProps) { const titleSizeClass = getHeroTitleSizeClass(titleSize); const textWrapperWidthClass = titleSize === 'sm' || contentWidth === 'compact' ? 'max-w-xl' : titleSize === 'md' ? 'max-w-2xl' : 'max-w-3xl'; + const aspectRatio = (payload as any).aspectRatio; + const mobileAspectRatio = (payload as any).mobileAspectRatio; + const mobileImageUrl = (payload as any).mobileImageUrl; + const isFullScreen = !aspectRatio || aspectRatio === 'full_screen'; + + const getAspectClass = () => { + switch (aspectRatio) { + case '21/6': return 'md:aspect-[21/6]'; + case '21/7': return 'md:aspect-[21/7]'; + case '21/9': return 'md:aspect-[21/9]'; + case '16/5': return 'md:aspect-[16/5]'; + case '16/6': return 'md:aspect-[16/6]'; + case '4/1': return 'md:aspect-[4/1]'; + case '5/1': return 'md:aspect-[5/1]'; + case 'full_screen': return 'md:h-[90vh] md:aspect-[21/9]'; + default: return 'md:aspect-[21/7]'; + } + }; + + const getMobileAspectClass = () => { + switch (mobileAspectRatio) { + case '16/9': return 'aspect-[16/9]'; + case '4/3': return 'aspect-[4/3]'; + case '1/1': return 'aspect-[1/1]'; + case '21/9': return 'aspect-[21/9]'; + case 'full_screen': return 'min-h-[85vh]'; + default: return 'aspect-[16/9]'; + } + }; + + const sectionHeightClass = isFullScreen + ? 'min-h-[85vh] sm:min-h-[90vh] md:h-[90vh] md:aspect-[21/9]' + : `${getMobileAspectClass()} ${getAspectClass()}`; + const innerHeightClass = isFullScreen + ? 'min-h-[85vh] sm:min-h-[90vh] md:min-h-full' + : 'h-full justify-center'; + return ( -
+
Hero Background { (e.target as HTMLImageElement).style.display = 'none'; }} /> + {mobileImageUrl && ( + Hero Background Mobile { + (e.target as HTMLImageElement).style.display = 'none'; + }} + /> + )} {/* Dynamic Dark / Light Gradient / Solid Overlay */} {renderOverlay()}
-
+
{tagline && (

diff --git a/apps/website/src/components/ProductHeroCarousel.tsx b/apps/website/src/components/ProductHeroCarousel.tsx index e8274b1..0a85b42 100644 --- a/apps/website/src/components/ProductHeroCarousel.tsx +++ b/apps/website/src/components/ProductHeroCarousel.tsx @@ -21,6 +21,7 @@ function aspectClasses( '4/3': 'aspect-[4/3]', '1/1': 'aspect-square', '21/9': 'aspect-[21/9]', + full_screen: 'min-h-[85vh]', auto: 'min-h-[22rem]', }[mobile ?? '16/9'] @@ -32,6 +33,7 @@ function aspectClasses( '16/6': 'md:aspect-[16/6]', '4/1': 'md:aspect-[4/1]', '5/1': 'md:aspect-[5/1]', + full_screen: 'md:aspect-auto md:min-h-[90vh]', auto: 'md:aspect-auto md:min-h-[30rem]', }[desktop ?? '21/7'] diff --git a/apps/website/src/components/dynamic/DynamicPageRenderer.tsx b/apps/website/src/components/dynamic/DynamicPageRenderer.tsx index c30e0b9..ef1470e 100644 --- a/apps/website/src/components/dynamic/DynamicPageRenderer.tsx +++ b/apps/website/src/components/dynamic/DynamicPageRenderer.tsx @@ -374,21 +374,74 @@ function HeroSection({ payload, lang }: { payload: Record, lang ) } + const aspectRatio = typeof payload.aspectRatio === 'string' ? payload.aspectRatio : undefined + const mobileAspectRatio = typeof payload.mobileAspectRatio === 'string' ? payload.mobileAspectRatio : undefined + const mobileImageUrl = typeof payload.mobileImageUrl === 'string' && payload.mobileImageUrl ? payload.mobileImageUrl : imageUrl + const isFullScreen = !aspectRatio || aspectRatio === 'full_screen' + + const getAspectClass = () => { + switch (aspectRatio) { + case '21/6': return 'md:aspect-[21/6]' + case '21/7': return 'md:aspect-[21/7]' + case '21/9': return 'md:aspect-[21/9]' + case '16/5': return 'md:aspect-[16/5]' + case '16/6': return 'md:aspect-[16/6]' + case '4/1': return 'md:aspect-[4/1]' + case '5/1': return 'md:aspect-[5/1]' + case 'full_screen': return 'md:h-[90vh] md:aspect-[21/9]' + default: return 'md:aspect-[21/7]' + } + } + + const getMobileAspectClass = () => { + switch (mobileAspectRatio) { + case '16/9': return 'aspect-[16/9]' + case '4/3': return 'aspect-[4/3]' + case '1/1': return 'aspect-[1/1]' + case '21/9': return 'aspect-[21/9]' + case 'full_screen': return 'min-h-[85vh]' + default: return 'aspect-[16/9]' + } + } + + const sectionHeightClass = isFullScreen + ? 'min-h-[85vh] sm:min-h-[90vh] md:h-[90vh] md:aspect-[21/9]' + : `${getMobileAspectClass()} ${getAspectClass()}` + const innerHeightClass = isFullScreen + ? 'min-h-[85vh] sm:min-h-[90vh] md:min-h-full' + : 'h-full justify-center' + return ( -

+
- {title + {/* Desktop Image */} +
+ {title +
+ {/* Mobile Image (if provided) */} + {mobileImageUrl !== imageUrl && ( +
+ {title +
+ )} {/* Dynamic Dark / Light Gradient / Solid Overlay */} {renderOverlay()}
-
+
{tagline && (

diff --git a/packages/types/index.ts b/packages/types/index.ts index 4a346f1..26b7582 100644 --- a/packages/types/index.ts +++ b/packages/types/index.ts @@ -694,6 +694,7 @@ export const HeroSectionPayloadSchema = z.object({ title: LocalizedStringSchema.optional(), description: LocalizedStringSchema.optional(), imageUrl: z.string().min(1), + mobileImageUrl: z.string().optional(), buttonText: LocalizedStringSchema.optional(), buttonLink: z.string().optional(), focalPoint: z.object({ x: z.string(), y: z.string() }).optional(), @@ -704,6 +705,9 @@ export const HeroSectionPayloadSchema = z.object({ titleSize: DefaultTitleSizeSchema('xl'), overlayStyle: z.enum(['gradient', 'solid', 'none']).optional().default('gradient'), overlayOpacity: z.number().min(0).max(100).optional(), + aspectRatio: z.enum(['21/6', '21/7', '21/9', '16/5', '16/6', '4/1', '5/1', 'auto', 'full_screen']).optional().default('21/7'), + mobileAspectRatio: z.enum(['16/9', '4/3', '1/1', '21/9', 'auto', 'full_screen']).optional().default('16/9'), + headerSpacing: z.enum(['below_header', 'under_header']).optional(), }); export type HeroSectionPayload = z.infer; @@ -874,11 +878,12 @@ export const HeroCarouselSectionPayloadSchema = z.object({ slides: z.array(HeroCarouselSlideSchema).min(1), autoplay: z.boolean().optional().default(true), interval: z.number().optional().default(4500), - aspectRatio: z.enum(['21/6', '21/7', '21/9', '16/5', '16/6', '4/1', '5/1', 'auto']).optional().default('21/7'), - mobileAspectRatio: z.enum(['16/9', '4/3', '1/1', '21/9', 'auto']).optional().default('16/9'), + aspectRatio: z.enum(['21/6', '21/7', '21/9', '16/5', '16/6', '4/1', '5/1', 'auto', 'full_screen']).optional().default('21/7'), + mobileAspectRatio: z.enum(['16/9', '4/3', '1/1', '21/9', 'auto', 'full_screen']).optional().default('16/9'), showArrows: z.boolean().optional().default(true), showDots: z.boolean().optional().default(true), backgroundColor: z.string().optional(), + headerSpacing: z.enum(['below_header', 'under_header']).optional(), }); export type HeroCarouselSectionPayload = z.infer; diff --git a/serverinfo/pkh-nginx/json/products_import_ready.json b/serverinfo/pkh-nginx/json/products_import_ready.json index d258bd9..17b4052 100644 --- a/serverinfo/pkh-nginx/json/products_import_ready.json +++ b/serverinfo/pkh-nginx/json/products_import_ready.json @@ -1,7 +1,7 @@ [ { "name": "TOBAKI DRIVE CHAIN", - "categoryName": "TOBAKI", + "categoryName": "Drive Chain & Sprockets", "brandName": "TOBAKI", "options": [ { @@ -84,7 +84,7 @@ }, { "name": "TOBAKI X CVT SYSTEM PULLEY SPRING RACING", - "categoryName": "TOBAKI RACING", + "categoryName": "Transmission & Clutch", "brandName": "TOBAKI", "options": [ { @@ -186,7 +186,7 @@ }, { "name": "TOBAKI ECU(STD) | MODEL HONDA", - "categoryName": "TOBAKI", + "categoryName": "Electrical & Ignition", "brandName": "TOBAKI", "options": [ { @@ -290,7 +290,7 @@ }, { "name": "TOBAKI RACING CRANKSHAFT NVX155 NMAX155", - "categoryName": "TOBAKI RACING", + "categoryName": "Engine & Cylinder", "brandName": "TOBAKI RACING", "options": [ { @@ -338,7 +338,7 @@ }, { "name": "TOBAKI X CVT SYSTEM CERAMIC PULLEY PIN RACING", - "categoryName": "TOBAKI RACING", + "categoryName": "Transmission & Clutch", "brandName": "TOBAKI", "options": [ { @@ -476,7 +476,7 @@ }, { "name": "TOBAKI X SUPER CLUTCH PLATE(IRON)", - "categoryName": "TOBAKI", + "categoryName": "Transmission & Clutch", "brandName": "TOBAKI", "options": [ { @@ -531,7 +531,7 @@ }, { "name": "TOBAKI X CVT ROLLER", - "categoryName": "TOBAKI", + "categoryName": "Transmission & Clutch", "brandName": "TOBAKI", "options": [ { @@ -1719,7 +1719,7 @@ }, { "name": "TOBAKI X WATER PUMP IMPELLER SHAFT ASSY", - "categoryName": "TOBAKI", + "categoryName": "Cooling System", "brandName": "TOBAKI RACING", "options": [ { @@ -1759,7 +1759,7 @@ }, { "name": "TOBAKI FUEL COCK", - "categoryName": "TOBAKI", + "categoryName": "Fuel & Air Intake", "brandName": "TOBAKI", "options": [ { @@ -1932,7 +1932,7 @@ }, { "name": "TOBAKI x RIKEN PISTON RING SET (2)", - "categoryName": "TOBAKI", + "categoryName": "Engine & Cylinder", "brandName": "TOBAKI", "options": [ { @@ -2011,7 +2011,7 @@ }, { "name": "TOBAKI CAMSHAFT STD CHILLED CAST IRON", - "categoryName": "TOBAKI", + "categoryName": "Engine & Cylinder", "brandName": "TOBAKI", "options": [ { @@ -2280,7 +2280,7 @@ }, { "name": "TOBAKI X PREMIUM DRIVE CHAIN(H) GOLD", - "categoryName": "TOBAKI", + "categoryName": "Drive Chain & Sprockets", "brandName": "TOBAKI", "options": [ { @@ -2370,7 +2370,7 @@ }, { "name": "TOBAKI DRUM GEARSHIFT TRANSMISSION ASSY(FULL SET)", - "categoryName": "TOBAKI", + "categoryName": "Transmission & Clutch", "brandName": "TOBAKI", "options": [ { @@ -2444,7 +2444,7 @@ }, { "name": "TOBAKI X FORK SPRING", - "categoryName": "TOBAKI", + "categoryName": "Suspension & Chassis", "brandName": "TOBAKI", "options": [ { @@ -2624,7 +2624,7 @@ }, { "name": "TOBAKI X Fork Lay Pro Spring", - "categoryName": "TOBAKI", + "categoryName": "Suspension & Chassis", "brandName": "TOBAKI RACING", "options": [ { @@ -2684,7 +2684,7 @@ }, { "name": "TOBAKI STATOR COMP", - "categoryName": "TOBAKI", + "categoryName": "Electrical & Ignition", "brandName": "TOBAKI", "options": [ { @@ -2823,7 +2823,7 @@ }, { "name": "TOBAKI DIGITAL METER", - "categoryName": "TOBAKI", + "categoryName": "Electrical & Ignition", "brandName": "TOBAKI", "options": [ { @@ -2878,7 +2878,7 @@ }, { "name": "TOBAKI | CABLE THROTTLE", - "categoryName": "TOBAKI", + "categoryName": "Fuel & Air Intake", "brandName": "TOBAKI", "options": [ { @@ -3268,7 +3268,7 @@ }, { "name": "TOBAKI FUEL PUMP SENSOR", - "categoryName": "TOBAKI", + "categoryName": "Fuel & Air Intake", "brandName": "TOBAKI", "price": 10.7, "stock": 50, @@ -3291,11 +3291,20 @@ "description": "Y15ZR/FZ150 NEW/NVX155/EGO LC/EGO AVANTIZ/EGO'S FI/NMAX", "details": "AVAILABLE MODEL:\nY15ZR/FZ150 NEW/NVX155/EGO LC/EGO AVANTIZ/EGO'S FI/NMAX" } - } + }, + "options": [], + "variants": [ + { + "option1": "", + "price": 10.7, + "stock": 50, + "sku": "TBK-TSY01-589901234-01" + } + ] }, { "name": "TOBAKI KEVLAR DRIVE BELT WITH CVT ROLLER SET", - "categoryName": "TOBAKI", + "categoryName": "Transmission & Clutch", "brandName": "TOBAKI", "options": [ { @@ -3469,7 +3478,7 @@ }, { "name": "TOBAKI RACING ECU(NO CUT)", - "categoryName": "TOBAKI RACING", + "categoryName": "Electrical & Ignition", "brandName": "TOBAKI", "options": [ { @@ -3570,7 +3579,7 @@ }, { "name": "TOBAKI X THERMO SENSOR RACING", - "categoryName": "TOBAKI RACING", + "categoryName": "Electrical & Ignition", "brandName": "TOBAKI RACING", "options": [ { @@ -3618,7 +3627,7 @@ }, { "name": "TEAMTOBAKI T01 POLO TEE", - "categoryName": "#TEAMTOBAKI MERCHANDISE", + "categoryName": "Apparel & Merchandise", "brandName": "TOBAKI", "options": [ { @@ -3693,7 +3702,7 @@ }, { "name": "TOBAKI TIMING CHAIN RACING- EX5 DREAM | EX5 CLASS", - "categoryName": "TOBAKI RACING", + "categoryName": "Engine & Cylinder", "brandName": "TOBAKI RACING", "options": [ { @@ -3738,7 +3747,7 @@ }, { "name": "TEAMTOBAKI T01 ROUND NECK TEE", - "categoryName": "#TEAMTOBAKI MERCHANDISE", + "categoryName": "Apparel & Merchandise", "brandName": "TOBAKI", "options": [ { @@ -3813,7 +3822,7 @@ }, { "name": "TOBAKI X KEVLAR CLUTCH DISC", - "categoryName": "TOBAKI RACING", + "categoryName": "Transmission & Clutch", "brandName": "TOBAKI", "options": [ { @@ -4045,7 +4054,7 @@ }, { "name": "TOBAKI AUTO SHOE", - "categoryName": "TOBAKI", + "categoryName": "Transmission & Clutch", "brandName": "TOBAKI", "options": [ { @@ -4198,7 +4207,7 @@ }, { "name": "TOBAKI X PLUG COIL NON-FUEL INJECTION UNIVERSAL", - "categoryName": "TOBAKI RACING", + "categoryName": "Electrical & Ignition", "brandName": "TOBAKI", "price": 12.7, "stock": 50, @@ -4221,11 +4230,20 @@ "description": "TOBAKI® X PLUG COIL UNIVERSAL⁣ ⚡️", "details": "TOBAKI® X PLUG COIL UNIVERSAL⁣ ⚡️\n NON FUEL INJECTION (CARBURETOR)\n High Voltage To Increase Power\n Used Of Premium Grade Copper Wire\n Used Of Highly Efficient Conductor\n Suitable For All Std & Racing Spec Motorcycle\n Plug & Play To Elevate Horse Power" } - } + }, + "options": [], + "variants": [ + { + "option1": "", + "price": 12.7, + "stock": 50, + "sku": "TBK-TPC02-261912691-01" + } + ] }, { "name": "TOBAKI X CNC LAY FORK ASSY", - "categoryName": "SHOP BY BIKE", + "categoryName": "Suspension & Chassis", "brandName": "TOBAKI", "options": [ { @@ -4369,7 +4387,7 @@ }, { "name": "TOBAKI X GAS MONOSHOCK Y16ZR/Y15ZR/LC135 (ROTATABLE 360°)(GREY TANK)", - "categoryName": "SHOP BY BIKE", + "categoryName": "Suspension & Chassis", "brandName": "TOBAKI RACING", "options": [ { @@ -4441,7 +4459,7 @@ }, { "name": "TOBAKI RACING LC135 CERAMIC SUPERBLOCK+FORGED PISTON SUPERHEAD FULL SET", - "categoryName": "SHOP BY BIKE", + "categoryName": "Engine & Cylinder", "brandName": "TOBAKI RACING", "options": [ { @@ -4553,7 +4571,7 @@ }, { "name": "TOBAKI X HYPER CLUTCH", - "categoryName": "TOBAKI RACING", + "categoryName": "Transmission & Clutch", "brandName": "TOBAKI", "options": [ { @@ -4712,7 +4730,7 @@ }, { "name": "TOBAKI AUTO CLUTCH HOUSING COMP", - "categoryName": "TOBAKI", + "categoryName": "Transmission & Clutch", "brandName": "TOBAKI", "options": [ { @@ -4865,7 +4883,7 @@ }, { "name": "TOBAKI VALVE RACING IN & EX", - "categoryName": "TOBAKI RACING", + "categoryName": "Engine & Cylinder", "brandName": "TOBAKI RACING", "options": [ { @@ -5178,7 +5196,7 @@ }, { "name": "TOBAKI X MONOSHOCK Y15ZR/Y16ZR | 205MM", - "categoryName": "TOBAKI RACING", + "categoryName": "Suspension & Chassis", "brandName": "TOBAKI RACING", "options": [ { @@ -5270,7 +5288,7 @@ }, { "name": "TOBAKI RACING GEAR EX5/EX5 DREAM", - "categoryName": "SHOP BY BIKE", + "categoryName": "Transmission & Clutch", "brandName": "TOBAKI RACING", "options": [ { @@ -5365,7 +5383,7 @@ }, { "name": "TOBAKI X AIR FILTER UNIVERSAL", - "categoryName": "TOBAKI", + "categoryName": "Fuel & Air Intake", "brandName": "TOBAKI", "options": [ { @@ -5632,7 +5650,7 @@ }, { "name": "TOBAKI X ADJUSTABLE TENSIONER MANUAL", - "categoryName": "SHOP BY BIKE", + "categoryName": "Engine & Cylinder", "brandName": "TOBAKI RACING", "options": [ { @@ -5778,7 +5796,7 @@ }, { "name": "TOBAKI X WATER PUMP", - "categoryName": "TOBAKI RACING", + "categoryName": "Cooling System", "brandName": "TOBAKI", "options": [ { @@ -5843,7 +5861,7 @@ }, { "name": "TOBAKI IRON PLATE RACING", - "categoryName": "TOBAKI RACING", + "categoryName": "Transmission & Clutch", "brandName": "TOBAKI", "options": [ { @@ -6016,7 +6034,7 @@ }, { "name": "TOBAKI X SUPERHEAD ROCKER ARM", - "categoryName": "TOBAKI RACING", + "categoryName": "Engine & Cylinder", "brandName": "TOBAKI", "options": [ { @@ -6095,7 +6113,7 @@ }, { "name": "TOBAKI FORK ASSY", - "categoryName": "TOBAKI", + "categoryName": "Suspension & Chassis", "brandName": "TOBAKI", "options": [ { @@ -6591,7 +6609,7 @@ }, { "name": "TOBAKI KEVLAR CLUTCH DISC", - "categoryName": "TOBAKI RACING", + "categoryName": "Transmission & Clutch", "brandName": "TOBAKI", "options": [ { @@ -6799,7 +6817,7 @@ }, { "name": "TOBAKI RACING CERAMIC BLOCK SETS LC135 | MX135 | EXCITER135 | SPARK135 | CRYPTON X 135", - "categoryName": "SHOP BY BIKE", + "categoryName": "Engine & Cylinder", "brandName": "TOBAKI RACING", "options": [ { @@ -6979,7 +6997,7 @@ }, { "name": "TOBAKI X TIMING BOLT", - "categoryName": "TOBAKI", + "categoryName": "Engine & Cylinder", "brandName": "TOBAKI", "options": [ { @@ -7028,7 +7046,7 @@ }, { "name": "TOBAKI X STARTER ONE WAY CLUTCH⁣ /w GEAR", - "categoryName": "SHOP BY BIKE", + "categoryName": "Transmission & Clutch", "brandName": "TOBAKI", "options": [ { @@ -7079,7 +7097,7 @@ }, { "name": "TOBAKI X PLUG COIL FUEL INJECTION UNIVERSAL", - "categoryName": "TOBAKI RACING", + "categoryName": "Electrical & Ignition", "brandName": "TOBAKI", "price": 14, "stock": 50, @@ -7102,11 +7120,20 @@ "description": "TOBAKI® X PLUG COIL UNIVERSAL⁣ ⚡️", "details": "TOBAKI® X PLUG COIL UNIVERSAL⁣ ⚡️\nFUEL INJECTION \n High Voltage To Increase Power\n Used Of Premium Grade Copper Wire\n Used Of Highly Efficient Conductor\n Suitable For All Std & Racing Spec Motorcycle\n Plug & Play To Elevate Horse Power" } - } + }, + "options": [], + "variants": [ + { + "option1": "", + "price": 14, + "stock": 50, + "sku": "TBK-TPC01-261900875-01" + } + ] }, { "name": "TOBAKI X GAS MONOSHOCK Y15ZR/LC135 (GREY TANK)", - "categoryName": "TOBAKI RACING", + "categoryName": "Suspension & Chassis", "brandName": "TOBAKI RACING", "options": [ { @@ -7173,7 +7200,7 @@ }, { "name": "TOBAKI X GAS MONOSHOCK Y16ZR/Y15ZR/LC135 (ROTATABLE 360°)(GOLD TANK)", - "categoryName": "SHOP BY BIKE", + "categoryName": "Suspension & Chassis", "brandName": "TOBAKI RACING", "options": [ { @@ -7252,7 +7279,7 @@ }, { "name": "TOBAKI X GAS MONOSHOCK RS150R (ROTATABLE 360°)(GOLD TANK)", - "categoryName": "SHOP BY BIKE", + "categoryName": "Suspension & Chassis", "brandName": "TOBAKI RACING", "options": [ { @@ -7324,7 +7351,7 @@ }, { "name": "TOBAKI X GAS MONOSHOCK RS150R (ROTATABLE 360°)(GREY TANK)", - "categoryName": "SHOP BY BIKE", + "categoryName": "Suspension & Chassis", "brandName": "TOBAKI RACING", "options": [ { @@ -7396,7 +7423,7 @@ }, { "name": "TOBAKI X GAS MONOSHOCK Y15ZR/LC135 (GOLD TANK)", - "categoryName": "TOBAKI RACING", + "categoryName": "Suspension & Chassis", "brandName": "TOBAKI RACING", "options": [ { @@ -7456,7 +7483,7 @@ }, { "name": "TOBAKI X CARBURETOR WAVE125 /W INLET PIPE", - "categoryName": "SHOP BY BIKE", + "categoryName": "Fuel & Air Intake", "brandName": "TOBAKI", "options": [ { @@ -7534,7 +7561,7 @@ }, { "name": "TOBAKI X CARBURETOR RXZ", - "categoryName": "SHOP BY BIKE", + "categoryName": "Fuel & Air Intake", "brandName": "TOBAKI", "options": [ { @@ -7580,7 +7607,7 @@ }, { "name": "TOBAKI X CARBURETOR PWK (SQUARE)", - "categoryName": "SHOP BY BIKE", + "categoryName": "Fuel & Air Intake", "brandName": "TOBAKI", "options": [ { @@ -7658,7 +7685,7 @@ }, { "name": "TOBAKI FUEL PUMP", - "categoryName": "TOBAKI", + "categoryName": "Fuel & Air Intake", "brandName": "TOBAKI", "options": [ { @@ -7901,7 +7928,7 @@ }, { "name": "TOBAKI RACING TIMING CHAIN - LC135 | Y15ZR", - "categoryName": "SHOP BY BIKE", + "categoryName": "Engine & Cylinder", "brandName": "TOBAKI RACING", "options": [ { @@ -8004,7 +8031,7 @@ }, { "name": "TOBAKI RACING CNC ADJUSTABLE UNIVERSAL THROTTLE BODY TRUMPET", - "categoryName": "TOBAKI RACING", + "categoryName": "Fuel & Air Intake", "brandName": "TOBAKI", "options": [ { @@ -8064,7 +8091,7 @@ }, { "name": "TOBAKI X CONNECTING ROD RS150R Y16ZR R15 V3", - "categoryName": "TOBAKI", + "categoryName": "Engine & Cylinder", "brandName": "TOBAKI", "options": [ { @@ -8113,7 +8140,7 @@ }, { "name": "TOBAKI RACING THROTTLE BODY /W INLET PIPE Y16ZR", - "categoryName": "TOBAKI RACING", + "categoryName": "Fuel & Air Intake", "brandName": "TOBAKI RACING", "options": [ { @@ -8172,7 +8199,7 @@ }, { "name": "TOBAKI CYLINDER HEAD WITH VALVES RACING", - "categoryName": "TOBAKI RACING", + "categoryName": "Engine & Cylinder", "brandName": "TOBAKI RACING", "options": [ { @@ -8337,7 +8364,7 @@ }, { "name": "TOBAKI X STARTER MOTOR", - "categoryName": "TOBAKI RACING", + "categoryName": "Electrical & Ignition", "brandName": "TOBAKI", "options": [ { @@ -8390,7 +8417,7 @@ }, { "name": "TOBAKI RACING MAGNET ROTOR", - "categoryName": "TOBAKI RACING", + "categoryName": "Electrical & Ignition", "brandName": "TOBAKI RACING", "options": [ { @@ -8429,7 +8456,7 @@ }, { "name": "TOBAKI X CDI UNIT", - "categoryName": "TOBAKI RACING", + "categoryName": "Electrical & Ignition", "brandName": "TOBAKI RACING", "options": [ { @@ -8511,7 +8538,7 @@ }, { "name": "TOBAKI X TPS THROTTLE BODY SENSOR", - "categoryName": "TOBAKI RACING", + "categoryName": "Fuel & Air Intake", "brandName": "TOBAKI RACING", "options": [ { @@ -8587,7 +8614,7 @@ }, { "name": "TOBAKI X ADJUSTABLE TIMING GEAR", - "categoryName": "TOBAKI RACING", + "categoryName": "Engine & Cylinder", "brandName": "TOBAKI RACING", "options": [ { @@ -8717,7 +8744,7 @@ }, { "name": "TOBAKI RACING FORGED ROD Y15ZR/LC135 5S", - "categoryName": "TOBAKI RACING", + "categoryName": "Engine & Cylinder", "brandName": "TOBAKI RACING", "options": [ { @@ -8791,7 +8818,7 @@ }, { "name": "TOBAKI RACING SUPERHEAD VALVE SEAT", - "categoryName": "TOBAKI RACING", + "categoryName": "Engine & Cylinder", "brandName": "TOBAKI RACING", "options": [ { @@ -8837,7 +8864,7 @@ }, { "name": "TOBAKI X CLUTCH PUSH ROD", - "categoryName": "TOBAKI RACING", + "categoryName": "Transmission & Clutch", "brandName": "TOBAKI", "options": [ { @@ -8877,7 +8904,7 @@ }, { "name": "TOBAKI X CAMSHAFT VR SERIES", - "categoryName": "TOBAKI RACING", + "categoryName": "Engine & Cylinder", "brandName": "TOBAKI RACING", "options": [ { @@ -8987,7 +9014,7 @@ }, { "name": "TOBAKI X CAMSHAFT VR PRO SERIES", - "categoryName": "TOBAKI RACING", + "categoryName": "Engine & Cylinder", "brandName": "TOBAKI RACING", "options": [ { @@ -9025,7 +9052,7 @@ }, { "name": "TOBAKI X FORGED PISTON Y15ZR/LC135", - "categoryName": "TOBAKI RACING", + "categoryName": "Engine & Cylinder", "brandName": "TOBAKI RACING", "options": [ { @@ -9134,7 +9161,7 @@ }, { "name": "TOBAKI RACING FORGED PISTON RS150R", - "categoryName": "TOBAKI RACING", + "categoryName": "Engine & Cylinder", "brandName": "TOBAKI RACING", "options": [ { @@ -9194,7 +9221,7 @@ }, { "name": "TOBAKI X CLUTCH SPRING SWOSC-V", - "categoryName": "TOBAKI RACING", + "categoryName": "Transmission & Clutch", "brandName": "TOBAKI RACING", "options": [ { @@ -9352,7 +9379,7 @@ }, { "name": "TOBAKI VALVE RACING (IN27/EX23) (IN28/EX24)", - "categoryName": "TOBAKI RACING", + "categoryName": "Engine & Cylinder", "brandName": "TOBAKI RACING", "options": [ { @@ -9477,7 +9504,7 @@ }, { "name": "TOBAKI VALVE INTAKE EXHAUST SET -INTAKE 1PCS EXHAUST 1PCS", - "categoryName": "TOBAKI", + "categoryName": "Engine & Cylinder", "brandName": "TOBAKI", "options": [ { @@ -9832,7 +9859,7 @@ }, { "name": "TOBAKI VALVE GUIDE", - "categoryName": "TOBAKI", + "categoryName": "Engine & Cylinder", "brandName": "TOBAKI", "options": [ { @@ -9933,7 +9960,7 @@ }, { "name": "FUEL INJECTOR ASSY", - "categoryName": "TOBAKI", + "categoryName": "Fuel & Air Intake", "brandName": "TOBAKI", "options": [ { @@ -10142,7 +10169,7 @@ }, { "name": "TOBAKI FUEL PUMP CORE", - "categoryName": "TOBAKI", + "categoryName": "Fuel & Air Intake", "brandName": "TOBAKI", "options": [ { @@ -10371,7 +10398,7 @@ }, { "name": "TOBAKI THERMO SENSOR", - "categoryName": "TOBAKI", + "categoryName": "Electrical & Ignition", "brandName": "TOBAKI", "options": [ { @@ -10462,7 +10489,7 @@ }, { "name": "TOBAKI FORK OIL SEAL SET 1 BOX 10PCS", - "categoryName": "TOBAKI", + "categoryName": "Suspension & Chassis", "brandName": "TOBAKI", "options": [ { @@ -10544,7 +10571,7 @@ }, { "name": "TOBAKI X O-RING PREMIUM DRIVE CHAIN (H)", - "categoryName": "TOBAKI", + "categoryName": "Drive Chain & Sprockets", "brandName": "TOBAKI", "options": [ { @@ -10625,7 +10652,7 @@ }, { "name": "TOBAKI X HAND CLUTCH CONVERSION KIT (COMPLETE SET)", - "categoryName": "TOBAKI", + "categoryName": "Transmission & Clutch", "brandName": "TOBAKI", "options": [ { @@ -10708,7 +10735,7 @@ }, { "name": "TOBAKI STANDARD BLOCK SET", - "categoryName": "TOBAKI", + "categoryName": "Engine & Cylinder", "brandName": "TOBAKI", "options": [ { @@ -11057,7 +11084,7 @@ }, { "name": "TOBAKI STEPPING MOTOR", - "categoryName": "TOBAKI", + "categoryName": "Electrical & Ignition", "brandName": "TOBAKI", "options": [ { @@ -11175,7 +11202,7 @@ }, { "name": "TOBAKI SPROCKET TIMING CRANKSHAFT", - "categoryName": "TOBAKI", + "categoryName": "Engine & Cylinder", "brandName": "TOBAKI", "options": [ { @@ -11357,7 +11384,7 @@ }, { "name": "TOBAKI VALVE SEAL STANDARD", - "categoryName": "TOBAKI", + "categoryName": "Engine & Cylinder", "brandName": "TOBAKI", "options": [ { @@ -11462,7 +11489,7 @@ }, { "name": "TOBAKI x RIKEN PISTON RING SET", - "categoryName": "TOBAKI", + "categoryName": "Engine & Cylinder", "brandName": "TOBAKI", "options": [ { @@ -11829,7 +11856,7 @@ }, { "name": "TOBAKI RAINCOAT WITH PANTS", - "categoryName": "TOBAKI", + "categoryName": "Apparel & Merchandise", "brandName": "TOBAKI", "options": [ { @@ -11923,7 +11950,7 @@ }, { "name": "TOBAKI RACING CERAMIC BLOCK SETS Y16ZR NMAX NVX155 R15 V3", - "categoryName": "SHOP BY BIKE", + "categoryName": "Engine & Cylinder", "brandName": "TOBAKI RACING", "options": [ { @@ -12040,7 +12067,7 @@ }, { "name": "TOBAKI X SUPER CLUTCH SET", - "categoryName": "SHOP BY BIKE", + "categoryName": "Transmission & Clutch", "brandName": "TOBAKI", "options": [ { @@ -12109,7 +12136,7 @@ }, { "name": "TOBAKI X GUIDE STOPPER FOR JACK ROD USE", - "categoryName": "SHOP BY BIKE", + "categoryName": "Engine & Cylinder", "brandName": "TOBAKI RACING", "options": [ { @@ -12150,7 +12177,7 @@ }, { "name": "TOBAKI X OVAL VALVE SPRING", - "categoryName": "SHOP BY BIKE", + "categoryName": "Engine & Cylinder", "brandName": "TOBAKI", "options": [ { @@ -12219,7 +12246,7 @@ }, { "name": "TOBAKI X AIR FILTER", - "categoryName": "SHOP BY BIKE", + "categoryName": "Fuel & Air Intake", "brandName": "TOBAKI", "options": [ {