feat: enhance designer canvas with multi-view support and model viewer integration
Some checks failed
Deploy Production / deploy (push) Failing after 1m11s

- Added canvasId prop to DesignerCanvas for identifying multiple canvases.
- Implemented active view selection (front, top, left, right) in designer page.
- Updated DesignerCanvas to maintain aspect ratio and dimensions based on view.
- Integrated @google/model-viewer for 3D model rendering on the index page.
- Refactored useSlipmatDesigner to manage multiple canvases and their states.
- Added LAMESA.glb model file for 3D representation.
- Updated package.json and package-lock.json to include @google/model-viewer dependency.
This commit is contained in:
Frank John Begornia
2026-01-12 23:00:32 +08:00
parent 3ba0b250ed
commit 27dabed2d2
7 changed files with 457 additions and 150 deletions

View File

@@ -18,6 +18,7 @@ const {
previewUrl,
registerCanvas,
unregisterCanvas,
setActiveCanvas,
addTextbox,
addShape,
addImageFromFile,
@@ -41,6 +42,14 @@ const {
resetZoom,
} = useSlipmatDesigner();
// Active view selector for multi-canvas design
const activeView = ref<'front' | 'top' | 'left' | 'right'>('front');
const setActiveView = (view: 'front' | 'top' | 'left' | 'right') => {
activeView.value = view;
setActiveCanvas(view);
};
const DESIGN_PRICE_USD = 39.99;
const { user, backendUser, initAuth, isLoading } = useAuth();
@@ -376,13 +385,13 @@ const handleCheckout = async () => {
<section class="mt-10 flex flex-col gap-8 lg:grid lg:grid-cols-[320px_minmax(0,1fr)] lg:gap-6">
<!-- Left Sidebar - Template Picker and Preview (together on desktop, separate on mobile) -->
<div class="contents lg:block lg:space-y-6">
<div class="order-1">
<!-- <div class="order-1">
<TemplatePicker
:templates="templates"
:selected-template-id="selectedTemplate.id"
@select="handleTemplateSelect"
/>
</div>
</div> -->
<div class="order-3">
<DesignerPreview
@@ -396,6 +405,23 @@ const handleCheckout = async () => {
<!-- Designer Canvas - Second on mobile, right column on desktop -->
<div class="order-2 flex flex-col gap-6 lg:order-0">
<!-- View Selector Tabs -->
<div class="flex gap-2 rounded-lg border border-slate-200 bg-slate-50 p-2">
<button
v-for="view in ['front', 'top', 'left', 'right']"
:key="view"
@click="setActiveView(view as 'front' | 'top' | 'left' | 'right')"
:class="[
'flex-1 rounded-md px-4 py-2 text-sm font-semibold capitalize transition-all',
activeView === view
? 'bg-white text-slate-900 shadow-sm'
: 'text-slate-600 hover:text-slate-900'
]"
>
{{ view }} View
</button>
</div>
<div
class="rounded-3xl border border-slate-200 bg-white shadow-xl"
>
@@ -420,17 +446,55 @@ const handleCheckout = async () => {
:on-zoom-out="zoomOut"
:on-zoom-reset="resetZoom"
/>
<div class="p-6">
<DesignerCanvas
:size="displaySize"
:background-color="selectedTemplate.backgroundColor"
:register-canvas="registerCanvas"
:unregister-canvas="unregisterCanvas"
/>
<div class="p-6 space-y-4">
<!-- Canvas for each view -->
<div v-show="activeView === 'front'" class="canvas-container">
<h3 class="mb-2 text-sm font-semibold text-slate-700">Front View</h3>
<DesignerCanvas
canvas-id="front"
:size="displaySize"
:background-color="selectedTemplate.backgroundColor"
:register-canvas="registerCanvas"
:unregister-canvas="unregisterCanvas"
/>
</div>
<div v-show="activeView === 'top'" class="canvas-container">
<h3 class="mb-2 text-sm font-semibold text-slate-700">Top View</h3>
<DesignerCanvas
canvas-id="top"
:size="displaySize"
:background-color="selectedTemplate.backgroundColor"
:register-canvas="registerCanvas"
:unregister-canvas="unregisterCanvas"
/>
</div>
<div v-show="activeView === 'left'" class="canvas-container">
<h3 class="mb-2 text-sm font-semibold text-slate-700">Left View</h3>
<DesignerCanvas
canvas-id="left"
:size="displaySize"
:background-color="selectedTemplate.backgroundColor"
:register-canvas="registerCanvas"
:unregister-canvas="unregisterCanvas"
/>
</div>
<div v-show="activeView === 'right'" class="canvas-container">
<h3 class="mb-2 text-sm font-semibold text-slate-700">Right View</h3>
<DesignerCanvas
canvas-id="right"
:size="displaySize"
:background-color="selectedTemplate.backgroundColor"
:register-canvas="registerCanvas"
:unregister-canvas="unregisterCanvas"
/>
</div>
<p class="mt-4 text-sm text-slate-600">
Safe zone and bleed guides update automatically when you switch
templates. Use the toolbar to layer text, shapes, and imagery
inside the design area.
Design each view of your table jersey separately. Switch between views using the tabs above.
Safe zone and bleed guides update automatically when you switch templates.
</p>
</div>
</div>