feat(qr-stands): set qr-4 as exclusive vector stand template
|
Before Width: | Height: | Size: 1.6 MiB |
|
Before Width: | Height: | Size: 357 KiB |
|
Before Width: | Height: | Size: 119 KiB |
@@ -0,0 +1,71 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 650" width="400" height="650">
|
||||
<defs>
|
||||
<!-- Define a linear gradient for gold effect -->
|
||||
<linearGradient id="goldGradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" stop-color="#D4AF37"/>
|
||||
<stop offset="100%" stop-color="#FFD700"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<!-- Background Canvas -->
|
||||
<rect id="bg-canvas" fill="#451A03" width="400" height="650"/>
|
||||
<!-- Main Menu Card Panel -->
|
||||
<rect id="main-card" x="20" y="20" width="360" height="610" rx="24" fill="#000000" stroke="url(#goldGradient)" stroke-width="2"/>
|
||||
<!-- Layer for Icons/Graphics -->
|
||||
<g id="layer-icons">
|
||||
<!-- Top decorative line -->
|
||||
<line x1="80" y1="165" x2="320" y2="165" stroke="url(#goldGradient)" stroke-width="1" fill="#D97706"/>
|
||||
<!-- Bottom decorative line -->
|
||||
<line x1="80" y1="535" x2="320" y2="535" stroke="url(#goldGradient)" stroke-width="1" fill="#B45309"/>
|
||||
<!-- Subtle corner accents (L-shapes) -->
|
||||
<path d="M40 40 L40 70 M40 40 L70 40" stroke="url(#goldGradient)" stroke-width="1.5" stroke-linecap="round" fill="#D97706"/>
|
||||
<path d="M360 40 L360 70 M360 40 L330 40" stroke="url(#goldGradient)" stroke-width="1.5" stroke-linecap="round" fill="#B45309"/>
|
||||
<path d="M40 610 L40 580 M40 610 L70 610" stroke="url(#goldGradient)" stroke-width="1.5" stroke-linecap="round" fill="#D97706"/>
|
||||
<path d="M360 610 L360 580 M360 610 L330 610" stroke="url(#goldGradient)" stroke-width="1.5" stroke-linecap="round" fill="#B45309"/>
|
||||
<!-- Minimalist Fork and Knife Line Art -->
|
||||
<g transform="translate(0, 15)">
|
||||
<!-- Fork -->
|
||||
<path d="M185 550 L185 560 M188 550 L188 560 M191 550 L191 560 M188 560 L188 565" stroke="url(#goldGradient)" stroke-width="1.5" stroke-linecap="round" fill="#D97706"/>
|
||||
<!-- Knife -->
|
||||
<path d="M205 550 L205 560 L208 560 L208 552 C208 550 206.5 549 205 549 Z M206.5 560 L206.5 565" stroke="url(#goldGradient)" stroke-width="1.5" stroke-linecap="round" fill="#B45309"/>
|
||||
</g>
|
||||
</g>
|
||||
<!-- QR Placeholder -->
|
||||
<g id="qr-placeholder" transform="translate(90, 215)">
|
||||
<rect width="220" height="220" rx="20" fill="#FFFFFF" stroke="#E4E4E7" stroke-width="2"/>
|
||||
<rect x="12" y="12" width="196" height="196" rx="14" fill="#FAFAFA" stroke="#E4E4E7" stroke-dasharray="4 3"/>
|
||||
<text x="110" y="115" font-family="Inter, sans-serif" font-size="12" font-weight="600" fill="#71717A" text-anchor="middle">
|
||||
QR KOD ALANI
|
||||
</text>
|
||||
</g>
|
||||
<!-- Layer for Texts -->
|
||||
<g id="layer-texts" fill="#c10101">
|
||||
<!-- Table Info badge -->
|
||||
<rect x="140" y="40" width="120" height="30" rx="15" fill="url(#goldGradient)"/>
|
||||
<text x="200" y="60" font-family="Inter, sans-serif" font-size="14" font-weight="600" fill="#1A1A1D" text-anchor="middle">
|
||||
MASA NO: 01
|
||||
</text>
|
||||
<!-- Restaurant Name -->
|
||||
<text x="200" y="120" font-family="Inter, sans-serif" font-size="26" font-weight="700" fill="url(#goldGradient)" text-anchor="middle">
|
||||
Gourmet Bistro
|
||||
</text>
|
||||
<!-- Tagline / Subtitle -->
|
||||
<text x="200" y="145" font-family="Inter, sans-serif" font-size="12" font-weight="400" fill="#E4E4E7" text-anchor="middle">
|
||||
Temassız Dijital Menü
|
||||
</text>
|
||||
<!-- "MENÜYÜ GÖRMEK İÇİN OKUTUN" -->
|
||||
<text x="200" y="480" font-family="Inter, sans-serif" font-size="16" font-weight="700" fill="url(#goldGradient)" text-anchor="middle">
|
||||
MENÜYÜ GÖRMEK İÇİN OKUTUN
|
||||
</text>
|
||||
<!-- Instruction note -->
|
||||
<text x="200" y="505" font-family="Inter, sans-serif" font-size="11" font-weight="400" fill="#A1A1AA" text-anchor="middle">
|
||||
Kameranızı QR Koda Odaklayın
|
||||
</text>
|
||||
<!-- WiFi & Social Media footer info -->
|
||||
<text x="200" y="595" font-family="Inter, sans-serif" font-size="11" font-weight="400" fill="#A1A1AA" text-anchor="middle">
|
||||
Ücretsiz Wi-Fi: GourmetBistro_Guest
|
||||
</text>
|
||||
<text x="200" y="610" font-family="Inter, sans-serif" font-size="11" font-weight="400" fill="#A1A1AA" text-anchor="middle">
|
||||
Bizi Takip Edin: @GourmetBistro
|
||||
</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.0 KiB |
@@ -33,7 +33,7 @@ export default function QrScreen() {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [copied, setCopied] = useState(false);
|
||||
const [selectedKey, setSelectedKey] = useState<string>("urban");
|
||||
const [selectedKey, setSelectedKey] = useState<string>("qr-4");
|
||||
const [categories, setCategories] = useState<string[]>([]);
|
||||
const [exportingPng, setExportingPng] = useState(false);
|
||||
const [exportingPdf, setExportingPdf] = useState(false);
|
||||
@@ -41,7 +41,7 @@ export default function QrScreen() {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const viewShotRef = useRef<any>(null);
|
||||
|
||||
const activePreset: QrStandPreset = (QR_STAND_PRESETS[selectedKey] || QR_STAND_PRESETS.urban)!;
|
||||
const activePreset: QrStandPreset = (QR_STAND_PRESETS[selectedKey] || Object.values(QR_STAND_PRESETS)[0])!;
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
|
||||
|
Before Width: | Height: | Size: 1.6 MiB |
|
Before Width: | Height: | Size: 357 KiB |
|
Before Width: | Height: | Size: 119 KiB |
@@ -0,0 +1,71 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 650" width="400" height="650">
|
||||
<defs>
|
||||
<!-- Define a linear gradient for gold effect -->
|
||||
<linearGradient id="goldGradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" stop-color="#D4AF37"/>
|
||||
<stop offset="100%" stop-color="#FFD700"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<!-- Background Canvas -->
|
||||
<rect id="bg-canvas" fill="#451A03" width="400" height="650"/>
|
||||
<!-- Main Menu Card Panel -->
|
||||
<rect id="main-card" x="20" y="20" width="360" height="610" rx="24" fill="#000000" stroke="url(#goldGradient)" stroke-width="2"/>
|
||||
<!-- Layer for Icons/Graphics -->
|
||||
<g id="layer-icons">
|
||||
<!-- Top decorative line -->
|
||||
<line x1="80" y1="165" x2="320" y2="165" stroke="url(#goldGradient)" stroke-width="1" fill="#D97706"/>
|
||||
<!-- Bottom decorative line -->
|
||||
<line x1="80" y1="535" x2="320" y2="535" stroke="url(#goldGradient)" stroke-width="1" fill="#B45309"/>
|
||||
<!-- Subtle corner accents (L-shapes) -->
|
||||
<path d="M40 40 L40 70 M40 40 L70 40" stroke="url(#goldGradient)" stroke-width="1.5" stroke-linecap="round" fill="#D97706"/>
|
||||
<path d="M360 40 L360 70 M360 40 L330 40" stroke="url(#goldGradient)" stroke-width="1.5" stroke-linecap="round" fill="#B45309"/>
|
||||
<path d="M40 610 L40 580 M40 610 L70 610" stroke="url(#goldGradient)" stroke-width="1.5" stroke-linecap="round" fill="#D97706"/>
|
||||
<path d="M360 610 L360 580 M360 610 L330 610" stroke="url(#goldGradient)" stroke-width="1.5" stroke-linecap="round" fill="#B45309"/>
|
||||
<!-- Minimalist Fork and Knife Line Art -->
|
||||
<g transform="translate(0, 15)">
|
||||
<!-- Fork -->
|
||||
<path d="M185 550 L185 560 M188 550 L188 560 M191 550 L191 560 M188 560 L188 565" stroke="url(#goldGradient)" stroke-width="1.5" stroke-linecap="round" fill="#D97706"/>
|
||||
<!-- Knife -->
|
||||
<path d="M205 550 L205 560 L208 560 L208 552 C208 550 206.5 549 205 549 Z M206.5 560 L206.5 565" stroke="url(#goldGradient)" stroke-width="1.5" stroke-linecap="round" fill="#B45309"/>
|
||||
</g>
|
||||
</g>
|
||||
<!-- QR Placeholder -->
|
||||
<g id="qr-placeholder" transform="translate(90, 215)">
|
||||
<rect width="220" height="220" rx="20" fill="#FFFFFF" stroke="#E4E4E7" stroke-width="2"/>
|
||||
<rect x="12" y="12" width="196" height="196" rx="14" fill="#FAFAFA" stroke="#E4E4E7" stroke-dasharray="4 3"/>
|
||||
<text x="110" y="115" font-family="Inter, sans-serif" font-size="12" font-weight="600" fill="#71717A" text-anchor="middle">
|
||||
QR KOD ALANI
|
||||
</text>
|
||||
</g>
|
||||
<!-- Layer for Texts -->
|
||||
<g id="layer-texts" fill="#c10101">
|
||||
<!-- Table Info badge -->
|
||||
<rect x="140" y="40" width="120" height="30" rx="15" fill="url(#goldGradient)"/>
|
||||
<text x="200" y="60" font-family="Inter, sans-serif" font-size="14" font-weight="600" fill="#1A1A1D" text-anchor="middle">
|
||||
MASA NO: 01
|
||||
</text>
|
||||
<!-- Restaurant Name -->
|
||||
<text x="200" y="120" font-family="Inter, sans-serif" font-size="26" font-weight="700" fill="url(#goldGradient)" text-anchor="middle">
|
||||
Gourmet Bistro
|
||||
</text>
|
||||
<!-- Tagline / Subtitle -->
|
||||
<text x="200" y="145" font-family="Inter, sans-serif" font-size="12" font-weight="400" fill="#E4E4E7" text-anchor="middle">
|
||||
Temassız Dijital Menü
|
||||
</text>
|
||||
<!-- "MENÜYÜ GÖRMEK İÇİN OKUTUN" -->
|
||||
<text x="200" y="480" font-family="Inter, sans-serif" font-size="16" font-weight="700" fill="url(#goldGradient)" text-anchor="middle">
|
||||
MENÜYÜ GÖRMEK İÇİN OKUTUN
|
||||
</text>
|
||||
<!-- Instruction note -->
|
||||
<text x="200" y="505" font-family="Inter, sans-serif" font-size="11" font-weight="400" fill="#A1A1AA" text-anchor="middle">
|
||||
Kameranızı QR Koda Odaklayın
|
||||
</text>
|
||||
<!-- WiFi & Social Media footer info -->
|
||||
<text x="200" y="595" font-family="Inter, sans-serif" font-size="11" font-weight="400" fill="#A1A1AA" text-anchor="middle">
|
||||
Ücretsiz Wi-Fi: GourmetBistro_Guest
|
||||
</text>
|
||||
<text x="200" y="610" font-family="Inter, sans-serif" font-size="11" font-weight="400" fill="#A1A1AA" text-anchor="middle">
|
||||
Bizi Takip Edin: @GourmetBistro
|
||||
</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.0 KiB |
@@ -20,12 +20,12 @@ export function QrStandGeneratorClient({
|
||||
slug = "kebapci-sinan-3",
|
||||
categoriesList = [],
|
||||
}: QrStandGeneratorClientProps) {
|
||||
const [selectedKey, setSelectedKey] = useState<string>("urban");
|
||||
const [selectedKey, setSelectedKey] = useState<string>("qr-4");
|
||||
const [downloadingPng, setDownloadingPng] = useState(false);
|
||||
const [downloadingPdf, setDownloadingPdf] = useState(false);
|
||||
const standRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const activePreset: QrStandPreset = (QR_STAND_PRESETS[selectedKey] || QR_STAND_PRESETS.urban)!;
|
||||
const activePreset: QrStandPreset = (QR_STAND_PRESETS[selectedKey] || Object.values(QR_STAND_PRESETS)[0])!;
|
||||
const targetUrl = `https://menul.io/${slug}`;
|
||||
|
||||
const displayCategories =
|
||||
@@ -208,70 +208,43 @@ export function QrStandGeneratorClient({
|
||||
{activePreset.svgTemplateUrl ? (
|
||||
<div
|
||||
ref={standRef}
|
||||
className="w-[360px] sm:w-[380px] aspect-[672/900] 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] aspect-[400/650] rounded-[2.5rem] relative overflow-hidden shadow-[0_25px_60px_rgba(0,0,0,0.6)] border-2 border-white/10"
|
||||
>
|
||||
{/* SVG Template Vector Background Graphic */}
|
||||
<img
|
||||
src={activePreset.svgTemplateUrl}
|
||||
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 */}
|
||||
<div className="absolute top-[13%] left-0 right-0 flex flex-col items-center justify-center px-6 text-center z-10">
|
||||
<div className="absolute top-[15.5%] left-0 right-0 flex flex-col items-center justify-center px-6 text-center z-10">
|
||||
{logoUrl ? (
|
||||
<img
|
||||
src={logoUrl}
|
||||
alt={restaurantName}
|
||||
className="h-9 w-auto max-w-[130px] object-contain mb-1"
|
||||
className="h-8 w-auto max-w-[120px] object-contain mb-1"
|
||||
/>
|
||||
) : null}
|
||||
<span
|
||||
className="font-black text-lg sm:text-xl tracking-wider uppercase font-['Montserrat'] leading-tight drop-shadow-md"
|
||||
style={{ color: activePreset.accentText }}
|
||||
className="font-black text-xl sm:text-2xl tracking-wider uppercase font-['Montserrat'] leading-tight drop-shadow-md bg-clip-text text-transparent bg-gradient-to-r from-[#D4AF37] to-[#FFD700]"
|
||||
>
|
||||
{restaurantName}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Dynamic QR Code Canvas Overlay */}
|
||||
<div className="absolute top-[37%] left-1/2 -translate-x-1/2 w-[52%] aspect-square rounded-2xl p-2.5 shadow-2xl flex items-center justify-center bg-[#f8f3eb] z-10 border border-black/10">
|
||||
<div className="absolute top-[33.1%] left-1/2 -translate-x-1/2 w-[55%] aspect-square rounded-[20px] p-3 shadow-2xl flex items-center justify-center bg-white z-10 border border-zinc-200">
|
||||
<QRCodeCanvas
|
||||
value={targetUrl}
|
||||
size={170}
|
||||
bgColor={activePreset.qrBg || "#f8f3eb"}
|
||||
fgColor={activePreset.qrColor || "#a64d2a"}
|
||||
size={200}
|
||||
bgColor={activePreset.qrBg || "#ffffff"}
|
||||
fgColor={activePreset.qrColor || "#111111"}
|
||||
level="H"
|
||||
style={{ width: "100%", height: "100%" }}
|
||||
includeMargin={false}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Dynamic Categories Overlay */}
|
||||
<div className="absolute bottom-[8%] left-0 right-0 flex flex-col items-center justify-center px-6 text-center z-10">
|
||||
<p
|
||||
className="text-[11px] sm:text-xs tracking-wide mb-2 font-semibold"
|
||||
style={{ color: activePreset.subText }}
|
||||
>
|
||||
Telefonunuzun kamerasını doğrultun
|
||||
</p>
|
||||
<div
|
||||
className="flex flex-col gap-1 max-w-[200px] w-full font-['Montserrat'] font-extrabold uppercase tracking-widest text-xs sm:text-sm"
|
||||
style={{ color: activePreset.headerText }}
|
||||
>
|
||||
{displayCategories.map((cat, idx) => (
|
||||
<div key={idx} className="w-full">
|
||||
<div className="py-0.5">{cat}</div>
|
||||
{idx < displayCategories.length - 1 && (
|
||||
<div
|
||||
className="w-full h-[1px] my-0.5"
|
||||
style={{ backgroundColor: activePreset.dividerColor }}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div
|
||||
|
||||