diff --git a/apps/mobile/package.json b/apps/mobile/package.json index 61fdf2e..b6e8939 100644 --- a/apps/mobile/package.json +++ b/apps/mobile/package.json @@ -35,6 +35,7 @@ "react-native-purchases": "^8.2.0", "react-native-safe-area-context": "4.12.0", "react-native-screens": "~4.4.0", + "react-native-svg": "^15.15.5", "react-native-url-polyfill": "^2.0.0", "react-native-view-shot": "^5.1.1" }, diff --git a/apps/mobile/src/app/menu/qr.tsx b/apps/mobile/src/app/menu/qr.tsx index 183c3b8..22a1fd1 100644 --- a/apps/mobile/src/app/menu/qr.tsx +++ b/apps/mobile/src/app/menu/qr.tsx @@ -15,9 +15,11 @@ import * as Clipboard from "expo-clipboard"; import ViewShot from "react-native-view-shot"; import * as Sharing from "expo-sharing"; import * as Print from "expo-print"; +import { SvgXml } from "react-native-svg"; import { QR_STAND_PRESETS, type QrStandPreset } from "@menulio/shared"; import { api } from "@/lib/api"; import { getActiveRestaurant, type ActiveRestaurant } from "@/lib/active-restaurant"; +import { MOBILE_SVG_TEMPLATES } from "@/lib/svg-templates"; interface QrResponse { id: string; @@ -28,13 +30,12 @@ interface QrResponse { export default function QrScreen() { const [active, setActive] = useState(null); - const [restaurantName, setRestaurantName] = useState("THE URBAN BURGER"); + const [restaurantName, setRestaurantName] = useState("Gourmet Bistro"); const [qr, setQr] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [copied, setCopied] = useState(false); const [selectedKey, setSelectedKey] = useState("qr-4"); - const [categories, setCategories] = useState([]); const [exportingPng, setExportingPng] = useState(false); const [exportingPdf, setExportingPdf] = useState(false); @@ -42,6 +43,7 @@ export default function QrScreen() { const viewShotRef = useRef(null); const activePreset: QrStandPreset = (QR_STAND_PRESETS[selectedKey] || Object.values(QR_STAND_PRESETS)[0])!; + const currentSvgRaw = MOBILE_SVG_TEMPLATES[selectedKey] || MOBILE_SVG_TEMPLATES["qr-4"] || Object.values(MOBILE_SVG_TEMPLATES)[0] || ""; useEffect(() => { (async () => { @@ -62,18 +64,6 @@ export default function QrScreen() { } catch { // fallback } - - // Fetch categories for preview - if (activeRest.menuId) { - try { - const menuRes = await api.get<{ categories: { name: string }[] }>(`/menus/${activeRest.menuId}`); - if (menuRes?.categories?.length) { - setCategories(menuRes.categories.map((c) => c.name)); - } - } catch { - // ignore fallback - } - } } catch (err) { setError(err instanceof Error ? err.message : "QR oluşturulamadı"); } finally { @@ -82,9 +72,6 @@ export default function QrScreen() { })(); }, []); - const displayCategories = - categories.length > 0 ? categories.slice(0, 4) : (activePreset.categories || []); - async function handleCopy() { if (!qr?.targetUrl) return; await Clipboard.setStringAsync(qr.targetUrl); @@ -120,21 +107,19 @@ export default function QrScreen() { } async function handleExportPdf() { - if (!qr || !active) return; + if (!qr || !active || !currentSvgRaw) return; setExportingPdf(true); try { - const restTitle = restaurantName.toUpperCase(); const qrImageUri = `data:image/png;base64,${qr.pngBase64}`; - const catsHtml = displayCategories - .map( - (c, i) => - `
${c}
${ - i < displayCategories.length - 1 - ? '
' - : "" - }`, - ) - .join(""); + + // Inject QR code directly into the SVG for print-ready A5 PDF + const svgWithQr = currentSvgRaw.replace( + /]*>[\s\S]*?<\/g>/, + ` + + + ` + ); const htmlContent = ` @@ -143,69 +128,30 @@ export default function QrScreen() { -
-
-
🔥 ${restTitle}
-
DIGITAL MENU
SCAN TO ORDER
-
- -
-
Use your phone's camera
- +
+ ${svgWithQr}
@@ -255,13 +201,13 @@ export default function QrScreen() { } return ( - + {/* Header Badge */} - - + + MASA QR STANT JENERATÖRÜ - + Masa Stant Tasarımları - + Şablon seçin; QR kodunuz otomatik yerleşsin. Baskıya hazır A5 PDF veya PNG olarak indirin. - {/* Horizontal Theme Selector (rendered only if multiple themes exist) */} + {/* Horizontal Theme Selector */} {Object.values(QR_STAND_PRESETS).length > 1 && ( setSelectedKey(preset.key)} style={{ - backgroundColor: isSelected ? "#1C1917" : "#FFFFFF", + backgroundColor: isSelected ? "#D4AF37" : "#1A1A1E", borderWidth: 1.5, - borderColor: isSelected ? "#1C1917" : "#E7E5E4", + borderColor: isSelected ? "#D4AF37" : "#2B2B32", borderRadius: 14, paddingHorizontal: 16, paddingVertical: 10, @@ -314,7 +262,7 @@ export default function QrScreen() { width: 14, height: 14, borderRadius: 7, - backgroundColor: preset.plaqueColor, + backgroundColor: preset.plaqueColor || "#1A1A1E", borderWidth: 1, borderColor: "rgba(255,255,255,0.4)", }} @@ -323,7 +271,7 @@ export default function QrScreen() { style={{ fontSize: 13, fontWeight: "700", - color: isSelected ? "#FFFFFF" : "#1C1917", + color: isSelected ? "#0C0C0E" : "#FFFFFF", }} > {preset.name} @@ -339,173 +287,61 @@ export default function QrScreen() { style={{ alignItems: "center", justifyContent: "center", - padding: 18, + padding: 16, borderRadius: 28, - backgroundColor: "#1c3e2b", // Ambient forest green tabletop environment backdrop + backgroundColor: "#18181B", marginBottom: 20, shadowColor: "#000", shadowOffset: { width: 0, height: 10 }, - shadowOpacity: 0.35, + shadowOpacity: 0.5, shadowRadius: 20, elevation: 8, + borderWidth: 1, + borderColor: "rgba(255,255,255,0.08)", }} > - {/* Inner Border Accent Line */} + {/* Exact Vector SVG Artwork */} + {currentSvgRaw ? ( + + ) : null} + + {/* Centered QR Code Box Overlay */} - - {/* Top Restaurant Badge with Flame Icon */} - - - {restaurantName.toUpperCase()} - - - - - {/* Title Callout */} - - DIGITAL MENU{"\n"} - SCAN TO ORDER - - - {/* Auto Placed QR Code Container */} - - - {/* Instructional Subtext */} - - Use your phone's camera - - - {/* Category Quick Preview List Flanked by Icons */} - - {/* Floating Left Line Icon (Burger) */} - - - - - {/* Floating Right Line Icon (Drink) */} - - - - - {/* Center Category Stack */} - - {displayCategories.map((cat, idx) => ( - - - {cat} - - {idx < displayCategories.length - 1 && ( - - )} - - ))} - - @@ -517,7 +353,7 @@ export default function QrScreen() { onPress={handleExportPdf} disabled={exportingPdf} style={({ pressed }) => ({ - backgroundColor: "#C8A96B", + backgroundColor: "#D4AF37", borderRadius: 14, padding: 16, flexDirection: "row", @@ -525,33 +361,35 @@ export default function QrScreen() { justifyContent: "center", gap: 8, opacity: pressed || exportingPdf ? 0.85 : 1, - shadowColor: "#C8A96B", + shadowColor: "#D4AF37", shadowOffset: { width: 0, height: 4 }, shadowOpacity: 0.2, - shadowRadius: 10, - elevation: 4, + shadowRadius: 8, + elevation: 3, })} > {exportingPdf ? ( - + ) : ( <> - - - A5 Baskı PDF Dosyası İndir / Paylaş + + + PDF Olarak İndir (A5 Matbaa Baskı) )} - {/* PNG Export Button */} + {/* PNG Download Button */} ({ - backgroundColor: "#1C1917", + backgroundColor: "#1A1A1E", + borderWidth: 1.5, + borderColor: "#2B2B32", borderRadius: 14, - padding: 15, + padding: 16, flexDirection: "row", alignItems: "center", justifyContent: "center", @@ -560,76 +398,64 @@ export default function QrScreen() { })} > {exportingPng ? ( - + ) : ( <> - + - PNG Görsel Olarak Kaydet / Paylaş + PNG Olarak Kaydet / Paylaş )} - {/* Secondary Quick Share & Copy */} - - ({ - flex: 1, - backgroundColor: "#FFFFFF", - borderWidth: 1, - borderColor: "#E7E5E4", - borderRadius: 12, - padding: 12, - flexDirection: "row", - alignItems: "center", - justifyContent: "center", - gap: 6, - opacity: pressed ? 0.85 : 1, - })} - > - - Linki Paylaş - - - ({ - flex: 1, - backgroundColor: "#FFFFFF", - borderWidth: 1, - borderColor: "#E7E5E4", - borderRadius: 12, - padding: 12, - flexDirection: "row", - alignItems: "center", - justifyContent: "center", - gap: 6, - opacity: pressed ? 0.85 : 1, - })} - > - - - {copied ? "Kopyalandı!" : "Linki Kopyala"} - - - - - {/* Back button */} + {/* Direct Link Share Button */} router.back()} - style={{ padding: 12, alignItems: "center", flexDirection: "row", justifyContent: "center", gap: 6 }} + onPress={handleShareQuick} + style={({ pressed }) => ({ + backgroundColor: "#1A1A1E", + borderWidth: 1, + borderColor: "#2B2B32", + borderRadius: 14, + padding: 14, + flexDirection: "row", + alignItems: "center", + justifyContent: "center", + gap: 8, + opacity: pressed ? 0.85 : 1, + })} > - - - Menü Editörüne Dön + + + Menü Linkini Paylaş + + {/* Quick Copy Link Box */} + + + {qr.targetUrl} + + + diff --git a/apps/mobile/src/lib/svg-templates.ts b/apps/mobile/src/lib/svg-templates.ts new file mode 100644 index 0000000..976fe35 --- /dev/null +++ b/apps/mobile/src/lib/svg-templates.ts @@ -0,0 +1,5 @@ +// Auto-generated SVG Templates dictionary +export const MOBILE_SVG_TEMPLATES: Record = { + "qr-1": "\n \n \n \n \n \n \n \n\n \n \n \n \n \n \n\n \n \n \n \n\n \n \n\n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n\n \n \n \n \n \n \n\n \n \n \n \n \n \n \n\n \n \n \n \n QR KOD ALANI\n \n\n \n \n \n GOURMET BISTRO\n TEMASSIZ D\u0130J\u0130TAL MEN\u00dc\n\n \n MEN\u00dcY\u00dc G\u00d6RMEK \u0130\u00c7\u0130N OKUTUN\n Kameran\u0131z ile QR kodu tarat\u0131n\n\n \n \n Masa No: 01\n\n \n Bistro_Guest\n @gourmetbistro\n \n\n", + "qr-4": "\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n QR KOD ALANI\n \n \n \n \n \n \n \n MASA NO: 01\n \n \n \n Gourmet Bistro\n \n \n \n Temass\u0131z Dijital Men\u00fc\n \n \n \n MEN\u00dcY\u00dc G\u00d6RMEK \u0130\u00c7\u0130N OKUTUN\n \n \n \n Kameran\u0131z\u0131 QR Koda Odaklay\u0131n\n \n \n \n \u00dccretsiz Wi-Fi: GourmetBistro_Guest\n \n \n Bizi Takip Edin: @GourmetBistro\n \n \n" +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1ba57e4..f14dfac 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -119,6 +119,9 @@ importers: react-native-screens: specifier: ~4.4.0 version: 4.4.0(react-native@0.76.9(@babel/core@7.29.7(supports-color@8.1.1))(@babel/preset-env@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@18.3.31)(react@18.3.1)(supports-color@8.1.1))(react@18.3.1) + react-native-svg: + specifier: ^15.15.5 + version: 15.15.5(react-native@0.76.9(@babel/core@7.29.7(supports-color@8.1.1))(@babel/preset-env@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@18.3.31)(react@18.3.1)(supports-color@8.1.1))(react@18.3.1) react-native-url-polyfill: specifier: ^2.0.0 version: 2.0.0(react-native@0.76.9(@babel/core@7.29.7(supports-color@8.1.1))(@babel/preset-env@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@18.3.31)(react@18.3.1)(supports-color@8.1.1)) @@ -2323,6 +2326,9 @@ packages: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} + boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + bplist-creator@0.0.7: resolution: {integrity: sha512-xp/tcaV3T5PCiaY04mXga7o/TE+t95gqeLmADeBI1CvZtdWTbgBt3uLpvh4UWtenKeBhCV6oVxGk38yZr2uYEA==} @@ -2601,6 +2607,17 @@ packages: css-line-break@2.1.0: resolution: {integrity: sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==} + css-select@5.2.2: + resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} + + css-tree@1.1.3: + resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==} + engines: {node: '>=8.0.0'} + + css-what@6.2.2: + resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==} + engines: {node: '>= 6'} + cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} @@ -2703,9 +2720,22 @@ packages: dlv@1.1.3: resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + dom-serializer@2.0.0: + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + + domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + + domhandler@5.0.3: + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} + dompurify@3.4.14: resolution: {integrity: sha512-dVoH9z+MY+C9IilgGCk3YfFqjLi3fChm2OiKJMzh6axrJ5qwxqWaZamgmHrpv22CN/KdbZJuGEGgfQoL00LTdg==} + domutils@3.2.2: + resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} + dotenv-expand@11.0.7: resolution: {integrity: sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==} engines: {node: '>=12'} @@ -2748,6 +2778,10 @@ packages: end-of-stream@1.4.5: resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + env-editor@0.4.2: resolution: {integrity: sha512-ObFo8v4rQJAE59M69QzwloxPZtd33TpYEIjtKD1rrFDcM1Gd7IkDxEBU+HriziN6HSHQnBJi8Dmy+JWkav5HKA==} engines: {node: '>=8'} @@ -3646,6 +3680,9 @@ packages: md5@2.3.0: resolution: {integrity: sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==} + mdn-data@2.0.14: + resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==} + memoize-one@5.2.1: resolution: {integrity: sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==} @@ -3896,6 +3933,9 @@ packages: resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} engines: {node: '>=8'} + nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + nullthrows@1.1.1: resolution: {integrity: sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==} @@ -4292,6 +4332,12 @@ packages: react: '*' react-native: '*' + react-native-svg@15.15.5: + resolution: {integrity: sha512-L4go5jA+GWutdJ/JucuN20cjAbMg1HmMtAP+wZ+3JLCf6Jd0bhXQHxciRP/AQm/FlrIEZwkMcHNZP+FXAiic0w==} + peerDependencies: + react: '*' + react-native: '*' + react-native-url-polyfill@2.0.0: resolution: {integrity: sha512-My330Do7/DvKnEvwQc0WdcBnFPploYKp9CYlefDXzIdEaA+PAhDYllkvGeEroEzvc4Kzzj2O4yVdz8v6fjRvhA==} peerDependencies: @@ -7512,6 +7558,8 @@ snapshots: binary-extensions@2.3.0: {} + boolbase@1.0.0: {} + bplist-creator@0.0.7: dependencies: stream-buffers: 2.2.0 @@ -7832,6 +7880,21 @@ snapshots: dependencies: utrie: 1.0.2 + css-select@5.2.2: + dependencies: + boolbase: 1.0.0 + css-what: 6.2.2 + domhandler: 5.0.3 + domutils: 3.2.2 + nth-check: 2.1.1 + + css-tree@1.1.3: + dependencies: + mdn-data: 2.0.14 + source-map: 0.6.1 + + css-what@6.2.2: {} + cssesc@3.0.0: {} csstype@3.2.3: {} @@ -7907,11 +7970,29 @@ snapshots: dlv@1.1.3: {} + dom-serializer@2.0.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.5.0 + + domelementtype@2.3.0: {} + + domhandler@5.0.3: + dependencies: + domelementtype: 2.3.0 + dompurify@3.4.14: optionalDependencies: '@types/trusted-types': 2.0.7 optional: true + domutils@3.2.2: + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + dotenv-expand@11.0.7: dependencies: dotenv: 16.4.7 @@ -7944,6 +8025,8 @@ snapshots: dependencies: once: 1.4.0 + entities@4.5.0: {} + env-editor@0.4.2: {} error-ex@1.3.4: @@ -8971,6 +9054,8 @@ snapshots: crypt: 0.0.2 is-buffer: 1.1.6 + mdn-data@2.0.14: {} + memoize-one@5.2.1: {} merge-options@3.0.4: @@ -9304,6 +9389,10 @@ snapshots: dependencies: path-key: 3.1.1 + nth-check@2.1.1: + dependencies: + boolbase: 1.0.0 + nullthrows@1.1.1: {} ob1@0.81.5: @@ -9679,6 +9768,13 @@ snapshots: react-native: 0.76.9(@babel/core@7.29.7(supports-color@8.1.1))(@babel/preset-env@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@18.3.31)(react@18.3.1)(supports-color@8.1.1) warn-once: 0.1.1 + react-native-svg@15.15.5(react-native@0.76.9(@babel/core@7.29.7(supports-color@8.1.1))(@babel/preset-env@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@18.3.31)(react@18.3.1)(supports-color@8.1.1))(react@18.3.1): + dependencies: + css-select: 5.2.2 + css-tree: 1.1.3 + react: 18.3.1 + react-native: 0.76.9(@babel/core@7.29.7(supports-color@8.1.1))(@babel/preset-env@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@18.3.31)(react@18.3.1)(supports-color@8.1.1) + react-native-url-polyfill@2.0.0(react-native@0.76.9(@babel/core@7.29.7(supports-color@8.1.1))(@babel/preset-env@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@18.3.31)(react@18.3.1)(supports-color@8.1.1)): dependencies: react-native: 0.76.9(@babel/core@7.29.7(supports-color@8.1.1))(@babel/preset-env@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@18.3.31)(react@18.3.1)(supports-color@8.1.1) diff --git a/svg/qr-2.svg b/svg/qr-2.svg deleted file mode 100644 index d397c3a..0000000 --- a/svg/qr-2.svg +++ /dev/null @@ -1,88 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - QR KOD ALANI - - - - - - GOURMET BISTRO - TEMASSIZ DİJİTAL MENÜ - - - MENÜYÜ GÖRMEK İÇİN OKUTUN - Kameranız ile QR kodu taratın - - - - Masa No: 01 - - - Bistro_Guest - @gourmetbistro - -