feat(qr-stands): clean SVG template renderer with exact QR placement and no redundant overlays
This commit is contained in:
@@ -82,7 +82,8 @@ export default function QrScreen() {
|
|||||||
})();
|
})();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const displayCategories = categories.length > 0 ? categories.slice(0, 4) : activePreset.categories;
|
const displayCategories =
|
||||||
|
categories.length > 0 ? categories.slice(0, 4) : (activePreset.categories || []);
|
||||||
|
|
||||||
async function handleCopy() {
|
async function handleCopy() {
|
||||||
if (!qr?.targetUrl) return;
|
if (!qr?.targetUrl) return;
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export function QrStandGeneratorClient({
|
|||||||
const targetUrl = `https://menul.io/${slug}`;
|
const targetUrl = `https://menul.io/${slug}`;
|
||||||
|
|
||||||
const displayCategories =
|
const displayCategories =
|
||||||
categoriesList.length > 0 ? categoriesList.slice(0, 4) : activePreset.categories;
|
categoriesList.length > 0 ? categoriesList.slice(0, 4) : (activePreset.categories || []);
|
||||||
|
|
||||||
async function handleDownloadPng() {
|
async function handleDownloadPng() {
|
||||||
if (!standRef.current) return;
|
if (!standRef.current) return;
|
||||||
@@ -139,7 +139,7 @@ export function QrStandGeneratorClient({
|
|||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<div
|
<div
|
||||||
className="w-4 h-4 rounded-full border border-white/20 shadow-sm"
|
className="w-4 h-4 rounded-full border border-white/20 shadow-sm"
|
||||||
style={{ background: preset.plaqueBg }}
|
style={{ background: preset.plaqueBg || preset.plaqueColor || "#1A1A1E" }}
|
||||||
/>
|
/>
|
||||||
<div>
|
<div>
|
||||||
<div className="text-xs font-bold">{preset.name}</div>
|
<div className="text-xs font-bold">{preset.name}</div>
|
||||||
@@ -208,51 +208,22 @@ export function QrStandGeneratorClient({
|
|||||||
{activePreset.svgTemplateUrl ? (
|
{activePreset.svgTemplateUrl ? (
|
||||||
<div
|
<div
|
||||||
ref={standRef}
|
ref={standRef}
|
||||||
className={`w-[360px] sm:w-[380px] rounded-[2.5rem] relative overflow-hidden shadow-[0_25px_60px_rgba(0,0,0,0.6)] border-2 border-white/10 ${
|
className="w-[360px] sm:w-[380px] rounded-[2.5rem] relative overflow-hidden shadow-[0_25px_60px_rgba(0,0,0,0.6)] border-2 border-white/10 aspect-[400/650]"
|
||||||
activePreset.aspectRatio === "672/900" ? "aspect-[672/900]" : "aspect-[400/650]"
|
|
||||||
}`}
|
|
||||||
>
|
>
|
||||||
{/* Exact SVG Template Vector Background Graphic */}
|
{/* Exact SVG Template Vector Background Graphic */}
|
||||||
<img
|
<img
|
||||||
src={activePreset.svgTemplateUrl}
|
src={activePreset.svgTemplateUrl}
|
||||||
alt={activePreset.name}
|
alt={activePreset.name}
|
||||||
className="absolute inset-0 w-full h-full object-cover pointer-events-none"
|
className="absolute inset-0 w-full h-full object-contain pointer-events-none"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Dynamic Restaurant Logo & Name Header Overlay */}
|
{/* Dynamic QR Code Canvas Overlay - Fills the QR Code Box Exactly */}
|
||||||
<div
|
<div className="absolute top-[33.08%] left-1/2 -translate-x-1/2 w-[55%] aspect-square rounded-[20px] p-3 shadow-xl flex items-center justify-center bg-white z-10 border border-zinc-200">
|
||||||
className={`absolute left-0 right-0 flex flex-col items-center justify-center px-6 text-center z-10 ${
|
|
||||||
activePreset.aspectRatio === "672/900" ? "top-[13%]" : "top-[15.5%]"
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
{logoUrl ? (
|
|
||||||
<img
|
|
||||||
src={logoUrl}
|
|
||||||
alt={restaurantName}
|
|
||||||
className="h-8 w-auto max-w-[120px] object-contain mb-1"
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
<span
|
|
||||||
className="font-black text-xl sm:text-2xl tracking-wider uppercase font-['Montserrat'] leading-tight drop-shadow-md"
|
|
||||||
style={{ color: activePreset.accentText }}
|
|
||||||
>
|
|
||||||
{restaurantName}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Dynamic QR Code Canvas Overlay */}
|
|
||||||
<div
|
|
||||||
className={`absolute left-1/2 -translate-x-1/2 rounded-[20px] p-3 shadow-2xl flex items-center justify-center bg-white z-10 border border-zinc-200 ${
|
|
||||||
activePreset.aspectRatio === "672/900"
|
|
||||||
? "top-[37%] w-[52%] aspect-square"
|
|
||||||
: "top-[33.1%] w-[55%] aspect-square"
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
<QRCodeCanvas
|
<QRCodeCanvas
|
||||||
value={targetUrl}
|
value={targetUrl}
|
||||||
size={200}
|
size={220}
|
||||||
bgColor={activePreset.qrBg || "#ffffff"}
|
bgColor="#ffffff"
|
||||||
fgColor={activePreset.qrColor || "#111111"}
|
fgColor="#111111"
|
||||||
level="H"
|
level="H"
|
||||||
style={{ width: "100%", height: "100%" }}
|
style={{ width: "100%", height: "100%" }}
|
||||||
includeMargin={false}
|
includeMargin={false}
|
||||||
@@ -264,8 +235,8 @@ export function QrStandGeneratorClient({
|
|||||||
ref={standRef}
|
ref={standRef}
|
||||||
className="w-[360px] sm:w-[380px] min-h-[660px] rounded-[2.5rem] p-7 flex flex-col items-center text-center relative shadow-[0_25px_60px_rgba(0,0,0,0.6)] border-2"
|
className="w-[360px] sm:w-[380px] min-h-[660px] rounded-[2.5rem] p-7 flex flex-col items-center text-center relative shadow-[0_25px_60px_rgba(0,0,0,0.6)] border-2"
|
||||||
style={{
|
style={{
|
||||||
background: activePreset.plaqueBg,
|
background: activePreset.plaqueBg || activePreset.plaqueColor || "#1A1A1E",
|
||||||
borderColor: activePreset.borderAccent,
|
borderColor: activePreset.borderAccent || "#D4AF37",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{/* Inner Line Accent */}
|
{/* Inner Line Accent */}
|
||||||
|
|||||||
@@ -1,84 +1,65 @@
|
|||||||
export interface QrStandPreset {
|
export interface QrStandPreset {
|
||||||
key: string;
|
key: string;
|
||||||
name: string;
|
name: string;
|
||||||
categoryName: string;
|
categoryName?: string;
|
||||||
bgGradient: string;
|
svgTemplateUrl: string;
|
||||||
plaqueBg: string;
|
|
||||||
plaqueColor: string;
|
|
||||||
borderAccent: string;
|
|
||||||
qrBg: string;
|
|
||||||
qrColor: string;
|
|
||||||
logoBorder: string;
|
|
||||||
logoBg: string;
|
|
||||||
accentText: string;
|
|
||||||
headerText: string;
|
|
||||||
subText: string;
|
|
||||||
dividerColor: string;
|
|
||||||
categories: string[];
|
|
||||||
svgTemplateUrl?: string;
|
|
||||||
aspectRatio?: string;
|
aspectRatio?: string;
|
||||||
|
bgGradient?: string;
|
||||||
|
plaqueBg?: string;
|
||||||
|
plaqueColor?: string;
|
||||||
|
borderAccent?: string;
|
||||||
|
qrBg?: string;
|
||||||
|
qrColor?: string;
|
||||||
|
logoBorder?: string;
|
||||||
|
logoBg?: string;
|
||||||
|
accentText?: string;
|
||||||
|
headerText?: string;
|
||||||
|
subText?: string;
|
||||||
|
dividerColor?: string;
|
||||||
|
categories?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const QR_STAND_PRESETS: Record<string, QrStandPreset> = {
|
export const QR_STAND_PRESETS: Record<string, QrStandPreset> = {
|
||||||
"qr-1": {
|
"qr-1": {
|
||||||
key: "qr-1",
|
key: "qr-1",
|
||||||
name: "Gourmet Bistro Stand (QR-1)",
|
name: "Gourmet Bistro Stand (QR-1)",
|
||||||
categoryName: "Özel Masa Kartı Şablonu",
|
categoryName: "Özel Masa Kartı",
|
||||||
|
svgTemplateUrl: "/qr-1.svg",
|
||||||
|
aspectRatio: "400/650",
|
||||||
bgGradient: "radial-gradient(circle at 50% 50%, #1A1A1E 0%, #0C0C0E 100%)",
|
bgGradient: "radial-gradient(circle at 50% 50%, #1A1A1E 0%, #0C0C0E 100%)",
|
||||||
plaqueBg: "linear-gradient(135deg, #1A1A1E 0%, #121215 100%)",
|
|
||||||
plaqueColor: "#1A1A1E",
|
plaqueColor: "#1A1A1E",
|
||||||
borderAccent: "#D4AF37",
|
borderAccent: "#D4AF37",
|
||||||
qrBg: "#ffffff",
|
|
||||||
qrColor: "#111111",
|
|
||||||
logoBorder: "#D4AF37",
|
|
||||||
logoBg: "rgba(26, 26, 30, 0.8)",
|
|
||||||
accentText: "#D4AF37",
|
accentText: "#D4AF37",
|
||||||
headerText: "#FFFFFF",
|
headerText: "#FFFFFF",
|
||||||
subText: "#8E8E93",
|
subText: "#8E8E93",
|
||||||
dividerColor: "rgba(212, 175, 55, 0.3)",
|
dividerColor: "rgba(212, 175, 55, 0.3)",
|
||||||
categories: ["BAŞLANGIÇLAR", "ANA YEMEKLER", "TATLILAR", "İÇECEKLER"],
|
|
||||||
svgTemplateUrl: "/qr-1.svg",
|
|
||||||
aspectRatio: "400/650",
|
|
||||||
},
|
|
||||||
"qr-4": {
|
|
||||||
key: "qr-4",
|
|
||||||
name: "Gourmet Gold Luxury Stand (QR-4)",
|
|
||||||
categoryName: "Özel Masa Kartı Şablonu",
|
|
||||||
bgGradient: "radial-gradient(circle at 50% 50%, #451A03 0%, #1c0a02 100%)",
|
|
||||||
plaqueBg: "linear-gradient(135deg, #000000 0%, #111111 100%)",
|
|
||||||
plaqueColor: "#000000",
|
|
||||||
borderAccent: "#D4AF37",
|
|
||||||
qrBg: "#ffffff",
|
|
||||||
qrColor: "#111111",
|
|
||||||
logoBorder: "#D4AF37",
|
|
||||||
logoBg: "rgba(0, 0, 0, 0.8)",
|
|
||||||
accentText: "#FFD700",
|
|
||||||
headerText: "#FFFFFF",
|
|
||||||
subText: "#A1A1AA",
|
|
||||||
dividerColor: "rgba(212, 175, 55, 0.3)",
|
|
||||||
categories: ["BAŞLANGIÇLAR", "ANA YEMEKLER", "TATLILAR", "İÇECEKLER"],
|
|
||||||
svgTemplateUrl: "/qr-4.svg",
|
|
||||||
aspectRatio: "400/650",
|
|
||||||
},
|
},
|
||||||
"qr-2": {
|
"qr-2": {
|
||||||
key: "qr-2",
|
key: "qr-2",
|
||||||
name: "Gourmet Bistro Chef Crest (QR-2)",
|
name: "Gourmet Bistro Chef Crest (QR-2)",
|
||||||
categoryName: "Özel Masa Kartı Şablonu",
|
categoryName: "Özel Masa Kartı",
|
||||||
|
svgTemplateUrl: "/qr-2.svg",
|
||||||
|
aspectRatio: "400/650",
|
||||||
bgGradient: "radial-gradient(circle at 50% 50%, #1A1A1E 0%, #0C0C0E 100%)",
|
bgGradient: "radial-gradient(circle at 50% 50%, #1A1A1E 0%, #0C0C0E 100%)",
|
||||||
plaqueBg: "linear-gradient(135deg, #1A1A1E 0%, #121215 100%)",
|
|
||||||
plaqueColor: "#1A1A1E",
|
plaqueColor: "#1A1A1E",
|
||||||
borderAccent: "#D4AF37",
|
borderAccent: "#D4AF37",
|
||||||
qrBg: "#ffffff",
|
|
||||||
qrColor: "#111111",
|
|
||||||
logoBorder: "#D4AF37",
|
|
||||||
logoBg: "rgba(26, 26, 30, 0.8)",
|
|
||||||
accentText: "#D4AF37",
|
accentText: "#D4AF37",
|
||||||
headerText: "#FFFFFF",
|
headerText: "#FFFFFF",
|
||||||
subText: "#8E8E93",
|
subText: "#8E8E93",
|
||||||
dividerColor: "rgba(212, 175, 55, 0.3)",
|
dividerColor: "rgba(212, 175, 55, 0.3)",
|
||||||
categories: ["BAŞLANGIÇLAR", "ANA YEMEKLER", "TATLILAR", "İÇECEKLER"],
|
},
|
||||||
svgTemplateUrl: "/qr-2.svg",
|
"qr-4": {
|
||||||
|
key: "qr-4",
|
||||||
|
name: "Gourmet Gold Luxury Stand (QR-4)",
|
||||||
|
categoryName: "Özel Masa Kartı",
|
||||||
|
svgTemplateUrl: "/qr-4.svg",
|
||||||
aspectRatio: "400/650",
|
aspectRatio: "400/650",
|
||||||
|
bgGradient: "radial-gradient(circle at 50% 50%, #451A03 0%, #1c0a02 100%)",
|
||||||
|
plaqueColor: "#000000",
|
||||||
|
borderAccent: "#D4AF37",
|
||||||
|
accentText: "#FFD700",
|
||||||
|
headerText: "#FFFFFF",
|
||||||
|
subText: "#A1A1AA",
|
||||||
|
dividerColor: "rgba(212, 175, 55, 0.3)",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user