feat(mobile): add multiline text with Enter, per-text independent font selection and font size controls

This commit is contained in:
AyrisAI
2026-08-21 00:55:44 +03:00
parent b72846bd91
commit 2530ab4005
8 changed files with 1522 additions and 1608 deletions
@@ -7,246 +7,202 @@ import Svg, {
Text,
Image,
} from "react-native-svg";
import type { QrTemplateProps } from "./index";
import { type QrTemplateProps, getFontFamily, renderSvgLines } from "./index";
const QrTemplateLumiere = ({
qrBase64,
restaurantName = "LUMIÈRE",
subtitle = "RESTAURANT & BAR | MODERN CUISINE",
tableNo = "MASA NO: 01",
ctaText = "MENÜYÜ GÖRMEK İÇİN OKUTUN",
wifiText = "WiFi: Lumiere_Guest | Şifre: lumiere2026",
socialText = "Rezervasyon: 0212 555 0199",
fontFamily = "'Playfair Display', Georgia, serif",
showTableNo = true,
showSubtitle = true,
showCta = true,
showWifi = true,
showSocial = true,
fields,
...props
}: QrTemplateProps) => (
<Svg
viewBox="0 0 600 600"
width={300}
height={300}
{...props}
>
<Path fill="#0b0d13" d="M0 0h600v600H0z" />
<Rect
width={560}
height={560}
x={20}
y={20}
fill="#132034"
stroke="#d4af37"
strokeWidth={1.5}
rx={24}
/>
<Path
fill="none"
stroke="#d4af37"
strokeOpacity={0.85}
strokeWidth={1.5}
d="M56 40h488a16 16 0 0 1 16 16v488a16 16 0 0 1-16 16H56a16 16 0 0 1-16-16V56a16 16 0 0 1 16-16Z"
/>
<Rect
width={504}
height={504}
x={48}
y={48}
fill="none"
stroke="#c5a059"
strokeOpacity={0.45}
strokeWidth={0.8}
rx={8}
/>
{/* Köşe süslemeleri */}
<Path
fill="none"
stroke="#d4af37"
strokeWidth={1.5}
d="M40 68a18 18 0 0 0 28-28"
/>
<Circle cx={52} cy={52} r={2} fill="#d4af37" />
<Path
fill="none"
stroke="#d4af37"
strokeWidth={1.5}
d="M560 68a18 18 0 0 1-28-28"
/>
<Circle cx={548} cy={52} r={2} fill="#d4af37" />
<Path
fill="none"
stroke="#d4af37"
strokeWidth={1.5}
d="M40 532a18 18 0 0 1 28 28"
/>
<Circle cx={52} cy={548} r={2} fill="#d4af37" />
<Path
fill="none"
stroke="#d4af37"
strokeWidth={1.5}
d="M560 532a18 18 0 0 0-28 28"
/>
<Circle cx={548} cy={548} r={2} fill="#d4af37" />
}: QrTemplateProps) => {
const rName = fields?.restaurantName;
const sub = fields?.subtitle;
const table = fields?.tableNo;
const cta = fields?.ctaText;
const wifi = fields?.wifiText;
const social = fields?.socialText;
{/* Merkez amblem */}
<G transform="translate(300 85)">
<Path
fill="none"
stroke="#d4af37"
strokeLinejoin="round"
strokeWidth={2}
d="M0-26C-8-16-8-6 0 0c8-6 8-16 0-26Z"
/>
<Path fill="#d4af37" d="M0-18C-4-12-4-4 0 0c4-4 4-12 0-18" />
<Path
fill="none"
stroke="#d4af37"
strokeLinejoin="round"
strokeWidth={2}
d="M-3 3c-13-2-25 7-21 21C-12 24-3 12-3 3Zm6 0c13-2 25 7 21 21C12 24 3 12 3 3Z"
/>
<Circle cy={10} r={1.8} fill="#d4af37" />
</G>
const rNameFont = getFontFamily(rName?.fontId, "Georgia, 'Playfair Display', serif");
const subFont = getFontFamily(sub?.fontId, "System, -apple-system, Roboto, sans-serif");
const ctaFont = getFontFamily(cta?.fontId, "Georgia, 'Playfair Display', serif");
const infoFont = getFontFamily(wifi?.fontId, "System, -apple-system, Roboto, sans-serif");
{/* Yatay çizgi */}
<Path
stroke="#d4af37"
strokeOpacity={0.4}
strokeWidth={0.8}
d="M120 198h360"
/>
{/* QR Placeholder / Gerçek QR */}
<G transform="translate(190 215)">
return (
<Svg viewBox="0 0 600 600" width={300} height={300} {...props}>
<Path fill="#0b0d13" d="M0 0h600v600H0z" />
<Rect
width={220}
height={220}
fill="#fff"
width={560}
height={560}
x={20}
y={20}
fill="#132034"
stroke="#d4af37"
strokeWidth={2}
rx={20}
strokeWidth={1.5}
rx={24}
/>
{qrBase64 ? (
<Image
href={`data:image/png;base64,${qrBase64}`}
x={10}
y={10}
width={200}
height={200}
<Path
fill="none"
stroke="#d4af37"
strokeOpacity={0.85}
strokeWidth={1.5}
d="M56 40h488a16 16 0 0 1 16 16v488a16 16 0 0 1-16 16H56a16 16 0 0 1-16-16V56a16 16 0 0 1 16-16Z"
/>
<Rect
width={504}
height={504}
x={48}
y={48}
fill="none"
stroke="#c5a059"
strokeOpacity={0.45}
strokeWidth={0.8}
rx={8}
/>
{/* Köşe süslemeleri */}
<Path fill="none" stroke="#d4af37" strokeWidth={1.5} d="M40 68a18 18 0 0 0 28-28" />
<Circle cx={52} cy={52} r={2} fill="#d4af37" />
<Path fill="none" stroke="#d4af37" strokeWidth={1.5} d="M560 68a18 18 0 0 1-28-28" />
<Circle cx={548} cy={52} r={2} fill="#d4af37" />
<Path fill="none" stroke="#d4af37" strokeWidth={1.5} d="M40 532a18 18 0 0 1 28 28" />
<Circle cx={52} cy={548} r={2} fill="#d4af37" />
<Path fill="none" stroke="#d4af37" strokeWidth={1.5} d="M560 532a18 18 0 0 0-28 28" />
<Circle cx={548} cy={548} r={2} fill="#d4af37" />
{/* Merkez amblem */}
<G transform="translate(300 85)">
<Path
fill="none"
stroke="#d4af37"
strokeLinejoin="round"
strokeWidth={2}
d="M0-26C-8-16-8-6 0 0c8-6 8-16 0-26Z"
/>
) : (
<>
<Rect
width={196}
height={196}
x={12}
y={12}
fill="#fafafa"
stroke="#d4af37"
strokeDasharray="4 3"
strokeOpacity={0.4}
rx={14}
<Path fill="#d4af37" d="M0-18C-4-12-4-4 0 0c4-4 4-12 0-18" />
<Path
fill="none"
stroke="#d4af37"
strokeLinejoin="round"
strokeWidth={2}
d="M-3 3c-13-2-25 7-21 21C-12 24-3 12-3 3Zm6 0c13-2 25 7 21 21C12 24 3 12 3 3Z"
/>
<Circle cy={10} r={1.8} fill="#d4af37" />
</G>
{/* Yatay çizgi */}
<Path stroke="#d4af37" strokeOpacity={0.4} strokeWidth={0.8} d="M120 198h360" />
{/* QR Placeholder / Gerçek QR */}
<G transform="translate(190 215)">
<Rect width={220} height={220} fill="#fff" stroke="#d4af37" strokeWidth={2} rx={20} />
{qrBase64 ? (
<Image
href={`data:image/png;base64,${qrBase64}`}
x={10}
y={10}
width={200}
height={200}
/>
<Text
x={110}
y={115}
fill="#71717a"
fontFamily="Inter, Arial, sans-serif"
fontSize={12}
fontWeight={600}
textAnchor="middle"
>
{"QR KOD ALANI"}
</Text>
</>
)}
</G>
) : (
<>
<Rect
width={196}
height={196}
x={12}
y={12}
fill="#fafafa"
stroke="#d4af37"
strokeDasharray="4 3"
strokeOpacity={0.4}
rx={14}
/>
<Text
x={110}
y={115}
fill="#71717a"
fontFamily="System, sans-serif"
fontSize={12}
fontWeight={600}
textAnchor="middle"
>
{"QR KOD ALANI"}
</Text>
</>
)}
</G>
{/* Metinler */}
<G textAnchor="middle">
{/* Restoran Adı */}
{restaurantName ? (
<Text
x={300}
y={150}
fill="#d4af37"
fontFamily={fontFamily}
fontSize={32}
fontWeight={700}
letterSpacing={4}
>
{restaurantName}
</Text>
) : null}
{/* Metinler (Çok satırlı ve bağımsız font destekli) */}
<G textAnchor="middle">
{/* Restoran Adı */}
{rName?.visible !== false &&
renderSvgLines({
text: rName?.text || "LUMIÈRE",
x: 300,
y: 148,
fill: "#d4af37",
fontFamily: rNameFont,
fontSize: rName?.fontSize || 30,
fontWeight: "bold",
letterSpacing: 4,
})}
{/* Slogan / Alt Başlık */}
{showSubtitle && subtitle ? (
<Text
x={300}
y={180}
fill="#e5c378"
fontFamily="Inter, Arial, sans-serif"
fontSize={11}
fontWeight={600}
letterSpacing={3}
>
{subtitle}
</Text>
) : null}
{/* Slogan / Alt Başlık (Enter ile alt satıra geçebilir) */}
{sub?.visible !== false &&
renderSvgLines({
text: sub?.text || "RESTAURANT & BAR | MODERN CUISINE",
x: 300,
y: 178,
fill: "#e5c378",
fontFamily: subFont,
fontSize: sub?.fontSize || 11,
fontWeight: 600,
letterSpacing: 2.5,
})}
{/* CTA / Yönlendirme */}
{showCta && ctaText ? (
<Text
x={300}
y={472}
fill="#d4af37"
fontFamily={fontFamily}
fontSize={13}
fontWeight={700}
letterSpacing={2}
>
{ctaText}
</Text>
) : null}
{/* CTA */}
{cta?.visible !== false &&
renderSvgLines({
text: cta?.text || "MENÜYÜ GÖRMEK İÇİN OKUTUN",
x: 300,
y: 472,
fill: "#d4af37",
fontFamily: ctaFont,
fontSize: cta?.fontSize || 13,
fontWeight: "bold",
letterSpacing: 2,
})}
{/* Sosyal / İletişim */}
{showSocial && socialText ? (
<Text
x={300}
y={508}
fill="#e2ddd2"
fontFamily="Inter, Arial, sans-serif"
fontSize={10.5}
fontWeight={500}
letterSpacing={1}
>
{socialText}
</Text>
) : null}
{/* Sosyal Medya / İletişim */}
{social?.visible !== false &&
renderSvgLines({
text: social?.text || "Rezervasyon: 0212 555 0199",
x: 300,
y: 504,
fill: "#e2ddd2",
fontFamily: infoFont,
fontSize: social?.fontSize || 10.5,
fontWeight: 500,
letterSpacing: 1,
})}
{/* Masa No & WiFi */}
{showTableNo || showWifi ? (
<Text
x={300}
y={528}
fill="#c5a059"
fontFamily="Inter, Arial, sans-serif"
fontSize={10}
fontWeight={600}
letterSpacing={1}
>
{[
showTableNo && tableNo ? tableNo : "",
showWifi && wifiText ? wifiText : "",
]
.filter(Boolean)
.join(" • ")}
</Text>
) : null}
</G>
</Svg>
);
{/* Masa No & WiFi */}
{(table?.visible !== false || wifi?.visible !== false) &&
renderSvgLines({
text: [
table?.visible !== false && table?.text ? table.text : "",
wifi?.visible !== false && wifi?.text ? wifi.text : "",
]
.filter(Boolean)
.join(" • "),
x: 300,
y: 526,
fill: "#c5a059",
fontFamily: infoFont,
fontSize: table?.fontSize || wifi?.fontSize || 10,
fontWeight: 600,
letterSpacing: 1,
})}
</G>
</Svg>
);
};
export default QrTemplateLumiere;