feat(mobile): add multiline text with Enter, per-text independent font selection and font size controls
This commit is contained in:
+241
-288
@@ -23,7 +23,8 @@ import {
|
||||
COMPONENT_TEMPLATES,
|
||||
TEMPLATE_ASPECT_RATIOS,
|
||||
FONT_OPTIONS,
|
||||
type QrCustomTextConfig,
|
||||
type QrCustomFields,
|
||||
type TextItemConfig,
|
||||
} from "@/components/qr-templates";
|
||||
|
||||
|
||||
@@ -45,24 +46,49 @@ export default function QrScreen() {
|
||||
(p) => !!COMPONENT_TEMPLATES[p.key]
|
||||
);
|
||||
const [selectedKey, setSelectedKey] = useState<string>(
|
||||
availablePresets[0]?.key || "qr-lumiere"
|
||||
availablePresets[0]?.key || "qr-1"
|
||||
);
|
||||
const [exportingPng, setExportingPng] = useState(false);
|
||||
const [exportingPdf, setExportingPdf] = useState(false);
|
||||
const [showCustomizePanel, setShowCustomizePanel] = useState(false);
|
||||
const [selectedFontId, setSelectedFontId] = useState<string>("didot");
|
||||
const [customText, setCustomText] = useState<QrCustomTextConfig>({
|
||||
restaurantName: "Gourmet Bistro",
|
||||
subtitle: "RESTAURANT & BAR | MODERN CUISINE",
|
||||
tableNo: "MASA NO: 01",
|
||||
ctaText: "MENÜYÜ GÖRMEK İÇİN OKUTUN",
|
||||
wifiText: "WiFi: Gourmet_Guest | Şifre: lezzetli01",
|
||||
socialText: "@gourmetbistro",
|
||||
showTableNo: true,
|
||||
showSubtitle: true,
|
||||
showCta: true,
|
||||
showWifi: true,
|
||||
showSocial: true,
|
||||
|
||||
const [fields, setFields] = useState<QrCustomFields>({
|
||||
restaurantName: {
|
||||
text: "Gourmet Bistro",
|
||||
fontSize: 26,
|
||||
fontId: "serif",
|
||||
visible: true,
|
||||
},
|
||||
subtitle: {
|
||||
text: "RESTAURANT & BAR\nMODERN CUISINE",
|
||||
fontSize: 11,
|
||||
fontId: "sans",
|
||||
visible: true,
|
||||
},
|
||||
tableNo: {
|
||||
text: "MASA NO: 01",
|
||||
fontSize: 11,
|
||||
fontId: "sans",
|
||||
visible: true,
|
||||
},
|
||||
ctaText: {
|
||||
text: "MENÜYÜ GÖRMEK İÇİN OKUTUN",
|
||||
fontSize: 13,
|
||||
fontId: "serif",
|
||||
visible: true,
|
||||
},
|
||||
wifiText: {
|
||||
text: "WiFi: Gourmet_Guest | Şifre: lezzetli01",
|
||||
fontSize: 10,
|
||||
fontId: "sans",
|
||||
visible: true,
|
||||
},
|
||||
socialText: {
|
||||
text: "@gourmetbistro",
|
||||
fontSize: 10,
|
||||
fontId: "sans",
|
||||
visible: true,
|
||||
},
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
@@ -71,10 +97,6 @@ export default function QrScreen() {
|
||||
const activePreset: QrStandPreset =
|
||||
QR_STAND_PRESETS[selectedKey] || availablePresets[0] || Object.values(QR_STAND_PRESETS)[0]!;
|
||||
|
||||
const activeFont =
|
||||
FONT_OPTIONS.find((f) => f.id === selectedFontId)?.fontFamily ||
|
||||
"'Playfair Display', Georgia, serif";
|
||||
|
||||
// Component-based template sistemi
|
||||
const TemplateComponent =
|
||||
COMPONENT_TEMPLATES[selectedKey] ?? Object.values(COMPONENT_TEMPLATES)[0];
|
||||
@@ -84,6 +106,7 @@ export default function QrScreen() {
|
||||
|
||||
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
const activeRest = await getActiveRestaurant();
|
||||
@@ -99,9 +122,12 @@ export default function QrScreen() {
|
||||
const restDetail = await api.get<{ name?: string }>(`/restaurants/${activeRest.restaurantId}`);
|
||||
if (restDetail?.name) {
|
||||
setRestaurantName(restDetail.name);
|
||||
setCustomText((prev) => ({
|
||||
setFields((prev) => ({
|
||||
...prev,
|
||||
restaurantName: restDetail.name,
|
||||
restaurantName: {
|
||||
...prev.restaurantName,
|
||||
text: restDetail.name || "Gourmet Bistro",
|
||||
},
|
||||
}));
|
||||
}
|
||||
} catch {
|
||||
@@ -116,6 +142,7 @@ export default function QrScreen() {
|
||||
}, []);
|
||||
|
||||
|
||||
|
||||
async function handleCopy() {
|
||||
if (!qr?.targetUrl) return;
|
||||
await Clipboard.setStringAsync(qr.targetUrl);
|
||||
@@ -355,25 +382,14 @@ export default function QrScreen() {
|
||||
qrBase64={qr.pngBase64}
|
||||
width={displayWidth}
|
||||
height={displayHeight}
|
||||
restaurantName={customText.restaurantName}
|
||||
subtitle={customText.subtitle}
|
||||
tableNo={customText.tableNo}
|
||||
ctaText={customText.ctaText}
|
||||
wifiText={customText.wifiText}
|
||||
socialText={customText.socialText}
|
||||
fontFamily={activeFont}
|
||||
showTableNo={customText.showTableNo}
|
||||
showSubtitle={customText.showSubtitle}
|
||||
showCta={customText.showCta}
|
||||
showWifi={customText.showWifi}
|
||||
showSocial={customText.showSocial}
|
||||
fields={fields}
|
||||
/>
|
||||
) : null}
|
||||
</View>
|
||||
</ViewShot>
|
||||
</View>
|
||||
|
||||
{/* Metin & Font Özelleştirme Kartı (Açılır/Kapanır) */}
|
||||
{/* Metin & Font & Boyut Özelleştirme Kartı (Açılır/Kapanır) */}
|
||||
<View
|
||||
style={{
|
||||
backgroundColor: "#18181B",
|
||||
@@ -395,22 +411,22 @@ export default function QrScreen() {
|
||||
<View style={{ flexDirection: "row", alignItems: "center", gap: 10 }}>
|
||||
<View
|
||||
style={{
|
||||
width: 32,
|
||||
height: 32,
|
||||
borderRadius: 8,
|
||||
width: 34,
|
||||
height: 34,
|
||||
borderRadius: 10,
|
||||
backgroundColor: "rgba(212, 175, 55, 0.15)",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
>
|
||||
<Ionicons name="text-outline" size={18} color="#D4AF37" />
|
||||
<Ionicons name="text-outline" size={19} color="#D4AF37" />
|
||||
</View>
|
||||
<View>
|
||||
<Text style={{ color: "#FFFFFF", fontSize: 15, fontWeight: "700" }}>
|
||||
Metin ve Yazı Tipi Özelleştir
|
||||
Metin, Font & Boyut Özelleştir
|
||||
</Text>
|
||||
<Text style={{ color: "#A1A1AA", fontSize: 12 }}>
|
||||
İstediğiniz alanları düzenleyin veya kaldırın
|
||||
Çok satırlı metin (Enter), özel font ve boyut ayarı
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
@@ -423,264 +439,201 @@ export default function QrScreen() {
|
||||
|
||||
{showCustomizePanel && (
|
||||
<View style={{ marginTop: 16, gap: 16, borderTopWidth: 1, borderTopColor: "rgba(255,255,255,0.06)", paddingTop: 16 }}>
|
||||
{/* Yazı Tipi (Font) Seçici */}
|
||||
<View>
|
||||
<Text style={{ color: "#D4AF37", fontSize: 12, fontWeight: "700", marginBottom: 8, letterSpacing: 0.5 }}>
|
||||
YAZI TİPİ (FONT)
|
||||
{/* Yardımcı Açıklama */}
|
||||
<View
|
||||
style={{
|
||||
backgroundColor: "rgba(212, 175, 55, 0.08)",
|
||||
borderRadius: 10,
|
||||
padding: 10,
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
gap: 8,
|
||||
}}
|
||||
>
|
||||
<Ionicons name="information-circle-outline" size={16} color="#D4AF37" />
|
||||
<Text style={{ color: "#E5C378", fontSize: 11.5, flex: 1 }}>
|
||||
İpucu: Uzun metinlerde alt satıra geçmek için klavyeden Enter'a basabilirsiniz.
|
||||
</Text>
|
||||
<ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={{ gap: 8 }}>
|
||||
{FONT_OPTIONS.map((f) => {
|
||||
const isSelected = f.id === selectedFontId;
|
||||
return (
|
||||
<Pressable
|
||||
key={f.id}
|
||||
onPress={() => setSelectedFontId(f.id)}
|
||||
style={{
|
||||
backgroundColor: isSelected ? "#D4AF37" : "#242429",
|
||||
paddingHorizontal: 14,
|
||||
paddingVertical: 8,
|
||||
borderRadius: 10,
|
||||
borderWidth: 1,
|
||||
borderColor: isSelected ? "#D4AF37" : "rgba(255,255,255,0.08)",
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
style={{
|
||||
color: isSelected ? "#0C0C0E" : "#FFFFFF",
|
||||
fontSize: 12,
|
||||
fontWeight: isSelected ? "700" : "500",
|
||||
}}
|
||||
>
|
||||
{f.label}
|
||||
</View>
|
||||
|
||||
{/* Alan Düzenleyicileri */}
|
||||
{(
|
||||
[
|
||||
{ key: "restaurantName", label: "RESTORAN BAŞLIĞI", placeholder: "Restoran Adı", min: 14, max: 48 },
|
||||
{ key: "subtitle", label: "SLOGAN / ALT BAŞLIK", placeholder: "Slogan (Enter ile alt satıra geçebilir)", min: 8, max: 24 },
|
||||
{ key: "ctaText", label: "YÖNLENDİRME (CTA) METNİ", placeholder: "Yönlendirme Metni", min: 9, max: 28 },
|
||||
{ key: "tableNo", label: "MASA NUMARASI", placeholder: "Örn: MASA NO: 01", min: 8, max: 22 },
|
||||
{ key: "wifiText", label: "WIFI BİLGİSİ", placeholder: "Örn: WiFi: Bistro | Şifre: 12345", min: 7, max: 20 },
|
||||
{ key: "socialText", label: "SOSYAL MEDYA / İLETİŞİM", placeholder: "Örn: @menulio", min: 7, max: 20 },
|
||||
] as const
|
||||
).map(({ key, label, placeholder, min, max }) => {
|
||||
const item = fields[key];
|
||||
return (
|
||||
<View
|
||||
key={key}
|
||||
style={{
|
||||
gap: 8,
|
||||
paddingBottom: 12,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: "rgba(255,255,255,0.06)",
|
||||
}}
|
||||
>
|
||||
{/* Başlık ve Görünürlük Anahtarı */}
|
||||
<View style={{ flexDirection: "row", justifyContent: "space-between", alignItems: "center" }}>
|
||||
<Text style={{ color: "#D4AF37", fontSize: 12, fontWeight: "700" }}>{label}</Text>
|
||||
<View style={{ flexDirection: "row", alignItems: "center", gap: 8 }}>
|
||||
<Text style={{ color: item.visible ? "#10B981" : "#71717A", fontSize: 11, fontWeight: "600" }}>
|
||||
{item.visible ? "Açık" : "Gizli"}
|
||||
</Text>
|
||||
</Pressable>
|
||||
);
|
||||
})}
|
||||
</ScrollView>
|
||||
</View>
|
||||
<Switch
|
||||
value={item.visible}
|
||||
onValueChange={(v) =>
|
||||
setFields((prev) => ({
|
||||
...prev,
|
||||
[key]: { ...prev[key], visible: v },
|
||||
}))
|
||||
}
|
||||
trackColor={{ false: "#27272A", true: "#D4AF37" }}
|
||||
thumbColor="#FFFFFF"
|
||||
ios_backgroundColor="#27272A"
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* Alan 1: Restoran Başlığı */}
|
||||
<View style={{ gap: 6 }}>
|
||||
<Text style={{ color: "#D4AF37", fontSize: 12, fontWeight: "700" }}>
|
||||
RESTORAN BAŞLIĞI
|
||||
</Text>
|
||||
<TextInput
|
||||
value={customText.restaurantName}
|
||||
onChangeText={(t) => setCustomText((p) => ({ ...p, restaurantName: t }))}
|
||||
placeholder="Restoran Adı"
|
||||
placeholderTextColor="#71717A"
|
||||
style={{
|
||||
backgroundColor: "#121215",
|
||||
borderWidth: 1,
|
||||
borderColor: "rgba(255,255,255,0.1)",
|
||||
borderRadius: 12,
|
||||
paddingHorizontal: 14,
|
||||
paddingVertical: 10,
|
||||
color: "#FFFFFF",
|
||||
fontSize: 14,
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
{item.visible && (
|
||||
<>
|
||||
{/* Çok Satırlı TextInput */}
|
||||
<TextInput
|
||||
value={item.text}
|
||||
onChangeText={(t) =>
|
||||
setFields((prev) => ({
|
||||
...prev,
|
||||
[key]: { ...prev[key], text: t },
|
||||
}))
|
||||
}
|
||||
placeholder={placeholder}
|
||||
placeholderTextColor="#71717A"
|
||||
multiline
|
||||
style={{
|
||||
backgroundColor: "#121215",
|
||||
borderWidth: 1,
|
||||
borderColor: "rgba(255,255,255,0.1)",
|
||||
borderRadius: 12,
|
||||
paddingHorizontal: 12,
|
||||
paddingVertical: 8,
|
||||
color: "#FFFFFF",
|
||||
fontSize: 13,
|
||||
minHeight: 42,
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Alan 2: Slogan / Alt Başlık */}
|
||||
<View style={{ gap: 6 }}>
|
||||
<View style={{ flexDirection: "row", justifyContent: "space-between", alignItems: "center" }}>
|
||||
<Text style={{ color: "#D4AF37", fontSize: 12, fontWeight: "700" }}>
|
||||
SLOGAN / ALT BAŞLIK
|
||||
</Text>
|
||||
<View style={{ flexDirection: "row", alignItems: "center", gap: 6 }}>
|
||||
<Text style={{ color: "#71717A", fontSize: 11 }}>
|
||||
{customText.showSubtitle ? "Göster" : "Gizle"}
|
||||
</Text>
|
||||
<Switch
|
||||
value={customText.showSubtitle}
|
||||
onValueChange={(v) => setCustomText((p) => ({ ...p, showSubtitle: v }))}
|
||||
trackColor={{ false: "#27272A", true: "#D4AF37" }}
|
||||
thumbColor="#FFFFFF"
|
||||
ios_backgroundColor="#27272A"
|
||||
/>
|
||||
{/* Font ve Boyut Kontrol Çubuğu */}
|
||||
<View style={{ flexDirection: "row", alignItems: "center", justifyContent: "space-between", gap: 8 }}>
|
||||
{/* Font Hapları */}
|
||||
<ScrollView
|
||||
horizontal
|
||||
showsHorizontalScrollIndicator={false}
|
||||
contentContainerStyle={{ gap: 6 }}
|
||||
style={{ flex: 1 }}
|
||||
>
|
||||
{FONT_OPTIONS.map((f) => {
|
||||
const isSelected = item.fontId === f.id;
|
||||
return (
|
||||
<Pressable
|
||||
key={f.id}
|
||||
onPress={() =>
|
||||
setFields((prev) => ({
|
||||
...prev,
|
||||
[key]: { ...prev[key], fontId: f.id },
|
||||
}))
|
||||
}
|
||||
style={{
|
||||
backgroundColor: isSelected ? "#D4AF37" : "#242429",
|
||||
paddingHorizontal: 9,
|
||||
paddingVertical: 5,
|
||||
borderRadius: 8,
|
||||
borderWidth: 1,
|
||||
borderColor: isSelected ? "#D4AF37" : "rgba(255,255,255,0.06)",
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
style={{
|
||||
color: isSelected ? "#0C0C0E" : "#D4D4D8",
|
||||
fontSize: 10.5,
|
||||
fontWeight: isSelected ? "700" : "500",
|
||||
}}
|
||||
>
|
||||
{f.label}
|
||||
</Text>
|
||||
</Pressable>
|
||||
);
|
||||
})}
|
||||
</ScrollView>
|
||||
|
||||
{/* Boyut Artır / Azalt */}
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
backgroundColor: "#242429",
|
||||
borderRadius: 8,
|
||||
paddingHorizontal: 4,
|
||||
borderWidth: 1,
|
||||
borderColor: "rgba(255,255,255,0.06)",
|
||||
}}
|
||||
>
|
||||
<Pressable
|
||||
onPress={() =>
|
||||
setFields((prev) => ({
|
||||
...prev,
|
||||
[key]: {
|
||||
...prev[key],
|
||||
fontSize: Math.max(min, (prev[key].fontSize || 12) - 1),
|
||||
},
|
||||
}))
|
||||
}
|
||||
style={{ padding: 6 }}
|
||||
>
|
||||
<Ionicons name="remove" size={13} color="#FFFFFF" />
|
||||
</Pressable>
|
||||
<Text
|
||||
style={{
|
||||
color: "#D4AF37",
|
||||
fontSize: 11,
|
||||
fontWeight: "700",
|
||||
minWidth: 26,
|
||||
textAlign: "center",
|
||||
}}
|
||||
>
|
||||
{item.fontSize || 12}
|
||||
</Text>
|
||||
<Pressable
|
||||
onPress={() =>
|
||||
setFields((prev) => ({
|
||||
...prev,
|
||||
[key]: {
|
||||
...prev[key],
|
||||
fontSize: Math.min(max, (prev[key].fontSize || 12) + 1),
|
||||
},
|
||||
}))
|
||||
}
|
||||
style={{ padding: 6 }}
|
||||
>
|
||||
<Ionicons name="add" size={13} color="#FFFFFF" />
|
||||
</Pressable>
|
||||
</View>
|
||||
</View>
|
||||
</>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
{customText.showSubtitle && (
|
||||
<TextInput
|
||||
value={customText.subtitle}
|
||||
onChangeText={(t) => setCustomText((p) => ({ ...p, subtitle: t }))}
|
||||
placeholder="Slogan / Açıklama"
|
||||
placeholderTextColor="#71717A"
|
||||
style={{
|
||||
backgroundColor: "#121215",
|
||||
borderWidth: 1,
|
||||
borderColor: "rgba(255,255,255,0.1)",
|
||||
borderRadius: 12,
|
||||
paddingHorizontal: 14,
|
||||
paddingVertical: 10,
|
||||
color: "#FFFFFF",
|
||||
fontSize: 14,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
|
||||
{/* Alan 3: Masa Numarası */}
|
||||
<View style={{ gap: 6 }}>
|
||||
<View style={{ flexDirection: "row", justifyContent: "space-between", alignItems: "center" }}>
|
||||
<Text style={{ color: "#D4AF37", fontSize: 12, fontWeight: "700" }}>
|
||||
MASA NUMARASI
|
||||
</Text>
|
||||
<View style={{ flexDirection: "row", alignItems: "center", gap: 6 }}>
|
||||
<Text style={{ color: "#71717A", fontSize: 11 }}>
|
||||
{customText.showTableNo ? "Göster" : "Gizle"}
|
||||
</Text>
|
||||
<Switch
|
||||
value={customText.showTableNo}
|
||||
onValueChange={(v) => setCustomText((p) => ({ ...p, showTableNo: v }))}
|
||||
trackColor={{ false: "#27272A", true: "#D4AF37" }}
|
||||
thumbColor="#FFFFFF"
|
||||
ios_backgroundColor="#27272A"
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
{customText.showTableNo && (
|
||||
<TextInput
|
||||
value={customText.tableNo}
|
||||
onChangeText={(t) => setCustomText((p) => ({ ...p, tableNo: t }))}
|
||||
placeholder="Örn: MASA NO: 01"
|
||||
placeholderTextColor="#71717A"
|
||||
style={{
|
||||
backgroundColor: "#121215",
|
||||
borderWidth: 1,
|
||||
borderColor: "rgba(255,255,255,0.1)",
|
||||
borderRadius: 12,
|
||||
paddingHorizontal: 14,
|
||||
paddingVertical: 10,
|
||||
color: "#FFFFFF",
|
||||
fontSize: 14,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
|
||||
{/* Alan 4: Yönlendirme (CTA) */}
|
||||
<View style={{ gap: 6 }}>
|
||||
<View style={{ flexDirection: "row", justifyContent: "space-between", alignItems: "center" }}>
|
||||
<Text style={{ color: "#D4AF37", fontSize: 12, fontWeight: "700" }}>
|
||||
YÖNLENDİRME (CTA) METNİ
|
||||
</Text>
|
||||
<View style={{ flexDirection: "row", alignItems: "center", gap: 6 }}>
|
||||
<Text style={{ color: "#71717A", fontSize: 11 }}>
|
||||
{customText.showCta ? "Göster" : "Gizle"}
|
||||
</Text>
|
||||
<Switch
|
||||
value={customText.showCta}
|
||||
onValueChange={(v) => setCustomText((p) => ({ ...p, showCta: v }))}
|
||||
trackColor={{ false: "#27272A", true: "#D4AF37" }}
|
||||
thumbColor="#FFFFFF"
|
||||
ios_backgroundColor="#27272A"
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
{customText.showCta && (
|
||||
<TextInput
|
||||
value={customText.ctaText}
|
||||
onChangeText={(t) => setCustomText((p) => ({ ...p, ctaText: t }))}
|
||||
placeholder="Örn: MENÜYÜ GÖRMEK İÇİN OKUTUN"
|
||||
placeholderTextColor="#71717A"
|
||||
style={{
|
||||
backgroundColor: "#121215",
|
||||
borderWidth: 1,
|
||||
borderColor: "rgba(255,255,255,0.1)",
|
||||
borderRadius: 12,
|
||||
paddingHorizontal: 14,
|
||||
paddingVertical: 10,
|
||||
color: "#FFFFFF",
|
||||
fontSize: 14,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
|
||||
{/* Alan 5: WiFi Bilgileri */}
|
||||
<View style={{ gap: 6 }}>
|
||||
<View style={{ flexDirection: "row", justifyContent: "space-between", alignItems: "center" }}>
|
||||
<Text style={{ color: "#D4AF37", fontSize: 12, fontWeight: "700" }}>
|
||||
WIFI BİLGİSİ
|
||||
</Text>
|
||||
<View style={{ flexDirection: "row", alignItems: "center", gap: 6 }}>
|
||||
<Text style={{ color: "#71717A", fontSize: 11 }}>
|
||||
{customText.showWifi ? "Göster" : "Gizle"}
|
||||
</Text>
|
||||
<Switch
|
||||
value={customText.showWifi}
|
||||
onValueChange={(v) => setCustomText((p) => ({ ...p, showWifi: v }))}
|
||||
trackColor={{ false: "#27272A", true: "#D4AF37" }}
|
||||
thumbColor="#FFFFFF"
|
||||
ios_backgroundColor="#27272A"
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
{customText.showWifi && (
|
||||
<TextInput
|
||||
value={customText.wifiText}
|
||||
onChangeText={(t) => setCustomText((p) => ({ ...p, wifiText: t }))}
|
||||
placeholder="Örn: WiFi: Bistro | Şifre: 12345"
|
||||
placeholderTextColor="#71717A"
|
||||
style={{
|
||||
backgroundColor: "#121215",
|
||||
borderWidth: 1,
|
||||
borderColor: "rgba(255,255,255,0.1)",
|
||||
borderRadius: 12,
|
||||
paddingHorizontal: 14,
|
||||
paddingVertical: 10,
|
||||
color: "#FFFFFF",
|
||||
fontSize: 14,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
|
||||
{/* Alan 6: Sosyal Medya / İletişim */}
|
||||
<View style={{ gap: 6 }}>
|
||||
<View style={{ flexDirection: "row", justifyContent: "space-between", alignItems: "center" }}>
|
||||
<Text style={{ color: "#D4AF37", fontSize: 12, fontWeight: "700" }}>
|
||||
SOSYAL MEDYA / İLETİŞİM
|
||||
</Text>
|
||||
<View style={{ flexDirection: "row", alignItems: "center", gap: 6 }}>
|
||||
<Text style={{ color: "#71717A", fontSize: 11 }}>
|
||||
{customText.showSocial ? "Göster" : "Gizle"}
|
||||
</Text>
|
||||
<Switch
|
||||
value={customText.showSocial}
|
||||
onValueChange={(v) => setCustomText((p) => ({ ...p, showSocial: v }))}
|
||||
trackColor={{ false: "#27272A", true: "#D4AF37" }}
|
||||
thumbColor="#FFFFFF"
|
||||
ios_backgroundColor="#27272A"
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
{customText.showSocial && (
|
||||
<TextInput
|
||||
value={customText.socialText}
|
||||
onChangeText={(t) => setCustomText((p) => ({ ...p, socialText: t }))}
|
||||
placeholder="Örn: @menulio"
|
||||
placeholderTextColor="#71717A"
|
||||
style={{
|
||||
backgroundColor: "#121215",
|
||||
borderWidth: 1,
|
||||
borderColor: "rgba(255,255,255,0.1)",
|
||||
borderRadius: 12,
|
||||
paddingHorizontal: 14,
|
||||
paddingVertical: 10,
|
||||
color: "#FFFFFF",
|
||||
fontSize: 14,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
|
||||
|
||||
|
||||
{/* Output Action Buttons */}
|
||||
<View style={{ width: "100%", gap: 10 }}>
|
||||
{/* PDF Download Button */}
|
||||
|
||||
@@ -8,313 +8,300 @@ import Svg, {
|
||||
Text,
|
||||
Image,
|
||||
} from "react-native-svg";
|
||||
import type { QrTemplateProps } from "./index";
|
||||
import { type QrTemplateProps, getFontFamily, renderSvgLines } from "./index";
|
||||
|
||||
const QrTemplate2 = ({
|
||||
qrBase64,
|
||||
restaurantName = "The Daily Grind",
|
||||
subtitle = "COFFEE & KITCHEN",
|
||||
tableNo = "MASA NO: 04",
|
||||
ctaText = "MENÜYÜ GÖRMEK İÇİN OKUTUN",
|
||||
wifiText = "WiFi: DailyGrind | Şifre: coffee2026",
|
||||
socialText = "@dailygrind",
|
||||
fontFamily = "'Playfair Display', Georgia, serif",
|
||||
showTableNo = true,
|
||||
showSubtitle = true,
|
||||
showCta = true,
|
||||
showWifi = true,
|
||||
showSocial = true,
|
||||
fields,
|
||||
...props
|
||||
}: QrTemplateProps) => (
|
||||
<Svg
|
||||
viewBox="0 0 400 650"
|
||||
width={300}
|
||||
height={487.5}
|
||||
{...props}
|
||||
>
|
||||
{/* Arka Plan */}
|
||||
<Path fill="#252c36" d="M0 0h400v650H0z" />
|
||||
}: 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;
|
||||
|
||||
{/* Ana Kart */}
|
||||
<Rect
|
||||
width={360}
|
||||
height={610}
|
||||
x={20}
|
||||
y={20}
|
||||
fill="#f6efe2"
|
||||
stroke="#3a2312"
|
||||
strokeWidth={1.5}
|
||||
rx={20}
|
||||
/>
|
||||
<Rect
|
||||
width={344}
|
||||
height={594}
|
||||
x={28}
|
||||
y={28}
|
||||
fill="none"
|
||||
stroke="#8c6239"
|
||||
strokeOpacity={0.4}
|
||||
rx={14}
|
||||
/>
|
||||
<Rect
|
||||
width={336}
|
||||
height={586}
|
||||
x={32}
|
||||
y={32}
|
||||
fill="none"
|
||||
stroke="#8c6239"
|
||||
strokeOpacity={0.25}
|
||||
strokeWidth={0.5}
|
||||
rx={10}
|
||||
/>
|
||||
const rNameFont = getFontFamily(rName?.fontId, "Georgia, 'Times New Roman', serif");
|
||||
const subFont = getFontFamily(sub?.fontId, "System, -apple-system, Roboto, sans-serif");
|
||||
const ctaFont = getFontFamily(cta?.fontId, "Georgia, 'Times New Roman', serif");
|
||||
const infoFont = getFontFamily(wifi?.fontId, "System, -apple-system, Roboto, sans-serif");
|
||||
|
||||
{/* Sol Üst Botanik Dal */}
|
||||
<G fill="none" stroke="#3a2312" strokeLinecap="round" strokeWidth={1.05}>
|
||||
<Path d="M36 36c11.25 11.25 18.75 26.25 22.5 48.75" />
|
||||
<Path
|
||||
fill="#eadcc7"
|
||||
d="M43.5 45c-3.75-7.5 7.5-10.5 9-3 0 7.5-9 3-9 3Zm6 11.25C45 51 57 46.5 60 53.25c0 6.75-10.5 3-10.5 3Zm4.5 13.5C60 64.5 69.75 72 64.5 78c-6 4.5-10.5-8.25-10.5-8.25Z"
|
||||
/>
|
||||
</G>
|
||||
return (
|
||||
<Svg viewBox="0 0 400 650" width={300} height={487.5} {...props}>
|
||||
{/* Arka Plan */}
|
||||
<Path fill="#252c36" d="M0 0h400v650H0z" />
|
||||
|
||||
{/* Sağ Üst Kahve İkonu */}
|
||||
<G transform="translate(340 52)">
|
||||
<Circle r={32} fill="#eadcc7" stroke="#3a2312" strokeWidth={1.2} />
|
||||
<Circle
|
||||
r={26}
|
||||
{/* Ana Kart */}
|
||||
<Rect
|
||||
width={360}
|
||||
height={610}
|
||||
x={20}
|
||||
y={20}
|
||||
fill="#f6efe2"
|
||||
stroke="#3a2312"
|
||||
strokeWidth={1.5}
|
||||
rx={20}
|
||||
/>
|
||||
<Rect
|
||||
width={344}
|
||||
height={594}
|
||||
x={28}
|
||||
y={28}
|
||||
fill="none"
|
||||
stroke="#8c6239"
|
||||
strokeDasharray="2 2"
|
||||
strokeWidth={0.8}
|
||||
strokeOpacity={0.4}
|
||||
rx={14}
|
||||
/>
|
||||
<Circle r={21} fill="#7a4b26" stroke="#3a2312" strokeWidth={1.4} />
|
||||
<Path fill="#f6efe2" d="M0 10C-8 4-4-6 0-12 4-6 8 4 0 10" />
|
||||
<Path fill="#7a4b26" d="M0 4C-5 0-2-5 0-8 2-5 5 0 0 4" />
|
||||
<Circle cy={-14} r={1.8} fill="#f6efe2" />
|
||||
</G>
|
||||
|
||||
{/* Sol Orta Kahve Bardağı */}
|
||||
<G transform="translate(48 250)">
|
||||
<Circle r={26} fill="#eadcc7" stroke="#3a2312" />
|
||||
<Circle r={17} fill="#6a3b18" stroke="#3a2312" strokeWidth={1.2} />
|
||||
<Path fill="#f6efe2" d="M-5-3c-3-4 5-7 5-1 0-6 8-3 5 1L0 7z" />
|
||||
<Path fill="none" stroke="#3a2312" strokeWidth={1.5} d="M17-4c6 0 6 8 0 8" />
|
||||
</G>
|
||||
|
||||
{/* Sağ Dal */}
|
||||
<G fill="none" stroke="#3a2312" strokeWidth={0.91}>
|
||||
<Path d="M352 230c-7 21-10.5 49-3.5 77" />
|
||||
<Path
|
||||
fill="#eadcc7"
|
||||
d="M349.2 247.5c8.4-7 15.4 2.1 5.6 7.7-5.6 0-5.6-7.7-5.6-7.7Zm-2.8 24.5c-9.8-8.4-15.4 1.4-7 7 7 0 7-7 7-7Zm2.1 19.6c9.1-7 13.3 2.8 4.9 8.4-4.9 0-4.9-8.4-4.9-8.4Z"
|
||||
<Rect
|
||||
width={336}
|
||||
height={586}
|
||||
x={32}
|
||||
y={32}
|
||||
fill="none"
|
||||
stroke="#8c6239"
|
||||
strokeOpacity={0.25}
|
||||
strokeWidth={0.5}
|
||||
rx={10}
|
||||
/>
|
||||
</G>
|
||||
|
||||
{/* Dekoratif Çizgi */}
|
||||
<Path
|
||||
fill="none"
|
||||
stroke="#8c6239"
|
||||
strokeLinecap="round"
|
||||
strokeWidth={1.2}
|
||||
d="M142 66c6-2 12 2 18 0m80 0c6 2 12-2 18 0"
|
||||
/>
|
||||
|
||||
{/* Sol Alt Dal */}
|
||||
<G fill="none" stroke="#3a2312" strokeWidth={0.91}>
|
||||
<Path d="M42 601.5c13-26 9.75-52 0-71.5" />
|
||||
<Path
|
||||
fill="#eadcc7"
|
||||
d="M47.2 549.5c10.4-9.75 17.55 0 6.5 7.8Zm2.6 26c11.7-9.75 18.2 1.3 5.2 9.1Z"
|
||||
/>
|
||||
</G>
|
||||
|
||||
{/* Kahve Çekirdekleri */}
|
||||
<G stroke="#3a2312" strokeWidth={1.2} transform="rotate(-20 1741.206 -8.75) scale(.8)">
|
||||
<Ellipse fill="#cbb296" rx={9} ry={6.5} />
|
||||
<Path fill="none" d="M-7 0q7 3 7 0t7 0" />
|
||||
</G>
|
||||
<G stroke="#3a2312" strokeWidth={1.2} transform="rotate(35 -862.106 494.982) scale(.8)">
|
||||
<Ellipse fill="#cbb296" rx={9} ry={6.5} />
|
||||
<Path fill="none" d="M-7 0q7 3 7 0t7 0" />
|
||||
</G>
|
||||
<G stroke="#3a2312" strokeWidth={1.2} transform="rotate(-45 602.558 -225.588) scale(.7)">
|
||||
<Ellipse fill="#cbb296" rx={9} ry={6.5} />
|
||||
<Path fill="none" d="M-7 0q7 3 7 0t7 0" />
|
||||
</G>
|
||||
|
||||
{/* Sağ Alt Fincan */}
|
||||
<G transform="translate(325 590)">
|
||||
<Ellipse cy={18} fill="#eadcc7" stroke="#3a2312" strokeWidth={1.2} rx={28} ry={7} />
|
||||
<Path fill="#f6efe2" stroke="#3a2312" strokeWidth={1.4} d="M-18 2c0 14 36 14 36 0Z" />
|
||||
<Ellipse cy={2} fill="#6a3b18" stroke="#3a2312" strokeWidth={1.2} rx={18} ry={4} />
|
||||
<Path fill="none" stroke="#3a2312" strokeWidth={1.3} d="M16 4c8 0 8 8 0 10" />
|
||||
<Path fill="none" stroke="#8c6239" strokeLinecap="round" d="M-6-4c-2-5 2-8 0-13M2-5c-2-5 2-8 0-14" />
|
||||
</G>
|
||||
|
||||
{/* QR Köşe Çerçeveleri */}
|
||||
<Path
|
||||
fill="none"
|
||||
stroke="#3a2312"
|
||||
strokeLinecap="round"
|
||||
strokeWidth={2}
|
||||
d="M80 205c0-10 0-10 10-10m230 10c0-10 0-10-10-10M80 445c0 10 0 10 10 10m230-10c0 10 0 10-10 10"
|
||||
/>
|
||||
<Path stroke="#8c6239" strokeWidth={0.8} d="M145 608h30m50 0h30" />
|
||||
|
||||
{/* QR Placeholder / Gerçek QR */}
|
||||
<G transform="translate(90 215)">
|
||||
<Rect width={220} height={220} fill="#fbf8f2" stroke="#d8c7b0" strokeWidth={1.5} rx={20} />
|
||||
{qrBase64 ? (
|
||||
<Image
|
||||
href={`data:image/png;base64,${qrBase64}`}
|
||||
x={10}
|
||||
y={10}
|
||||
width={200}
|
||||
height={200}
|
||||
{/* Sol Üst Botanik Dal */}
|
||||
<G fill="none" stroke="#3a2312" strokeLinecap="round" strokeWidth={1.05}>
|
||||
<Path d="M36 36c11.25 11.25 18.75 26.25 22.5 48.75" />
|
||||
<Path
|
||||
fill="#eadcc7"
|
||||
d="M43.5 45c-3.75-7.5 7.5-10.5 9-3 0 7.5-9 3-9 3Zm6 11.25C45 51 57 46.5 60 53.25c0 6.75-10.5 3-10.5 3Zm4.5 13.5C60 64.5 69.75 72 64.5 78c-6 4.5-10.5-8.25-10.5-8.25Z"
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
<Rect
|
||||
width={200}
|
||||
height={200}
|
||||
</G>
|
||||
|
||||
{/* Sağ Üst Kahve İkonu */}
|
||||
<G transform="translate(340 52)">
|
||||
<Circle r={32} fill="#eadcc7" stroke="#3a2312" strokeWidth={1.2} />
|
||||
<Circle
|
||||
r={26}
|
||||
fill="#f6efe2"
|
||||
stroke="#8c6239"
|
||||
strokeDasharray="2 2"
|
||||
strokeWidth={0.8}
|
||||
/>
|
||||
<Circle r={21} fill="#7a4b26" stroke="#3a2312" strokeWidth={1.4} />
|
||||
<Path fill="#f6efe2" d="M0 10C-8 4-4-6 0-12 4-6 8 4 0 10" />
|
||||
<Path fill="#7a4b26" d="M0 4C-5 0-2-5 0-8 2-5 5 0 0 4" />
|
||||
<Circle cy={-14} r={1.8} fill="#f6efe2" />
|
||||
</G>
|
||||
|
||||
{/* Sol Orta Kahve Bardağı */}
|
||||
<G transform="translate(48 250)">
|
||||
<Circle r={26} fill="#eadcc7" stroke="#3a2312" />
|
||||
<Circle r={17} fill="#6a3b18" stroke="#3a2312" strokeWidth={1.2} />
|
||||
<Path fill="#f6efe2" d="M-5-3c-3-4 5-7 5-1 0-6 8-3 5 1L0 7z" />
|
||||
<Path fill="none" stroke="#3a2312" strokeWidth={1.5} d="M17-4c6 0 6 8 0 8" />
|
||||
</G>
|
||||
|
||||
{/* Sağ Dal */}
|
||||
<G fill="none" stroke="#3a2312" strokeWidth={0.91}>
|
||||
<Path d="M352 230c-7 21-10.5 49-3.5 77" />
|
||||
<Path
|
||||
fill="#eadcc7"
|
||||
d="M349.2 247.5c8.4-7 15.4 2.1 5.6 7.7-5.6 0-5.6-7.7-5.6-7.7Zm-2.8 24.5c-9.8-8.4-15.4 1.4-7 7 7 0 7-7 7-7Zm2.1 19.6c9.1-7 13.3 2.8 4.9 8.4-4.9 0-4.9-8.4-4.9-8.4Z"
|
||||
/>
|
||||
</G>
|
||||
|
||||
{/* Dekoratif Çizgi */}
|
||||
<Path
|
||||
fill="none"
|
||||
stroke="#8c6239"
|
||||
strokeLinecap="round"
|
||||
strokeWidth={1.2}
|
||||
d="M142 66c6-2 12 2 18 0m80 0c6 2 12-2 18 0"
|
||||
/>
|
||||
|
||||
{/* Sol Alt Dal */}
|
||||
<G fill="none" stroke="#3a2312" strokeWidth={0.91}>
|
||||
<Path d="M42 601.5c13-26 9.75-52 0-71.5" />
|
||||
<Path
|
||||
fill="#eadcc7"
|
||||
d="M47.2 549.5c10.4-9.75 17.55 0 6.5 7.8Zm2.6 26c11.7-9.75 18.2 1.3 5.2 9.1Z"
|
||||
/>
|
||||
</G>
|
||||
|
||||
{/* Kahve Çekirdekleri */}
|
||||
<G stroke="#3a2312" strokeWidth={1.2} transform="rotate(-20 1741.206 -8.75) scale(.8)">
|
||||
<Ellipse fill="#cbb296" rx={9} ry={6.5} />
|
||||
<Path fill="none" d="M-7 0q7 3 7 0t7 0" />
|
||||
</G>
|
||||
<G stroke="#3a2312" strokeWidth={1.2} transform="rotate(35 -862.106 494.982) scale(.8)">
|
||||
<Ellipse fill="#cbb296" rx={9} ry={6.5} />
|
||||
<Path fill="none" d="M-7 0q7 3 7 0t7 0" />
|
||||
</G>
|
||||
<G stroke="#3a2312" strokeWidth={1.2} transform="rotate(-45 602.558 -225.588) scale(.7)">
|
||||
<Ellipse fill="#cbb296" rx={9} ry={6.5} />
|
||||
<Path fill="none" d="M-7 0q7 3 7 0t7 0" />
|
||||
</G>
|
||||
|
||||
{/* Sağ Alt Fincan */}
|
||||
<G transform="translate(325 590)">
|
||||
<Ellipse cy={18} fill="#eadcc7" stroke="#3a2312" strokeWidth={1.2} rx={28} ry={7} />
|
||||
<Path fill="#f6efe2" stroke="#3a2312" strokeWidth={1.4} d="M-18 2c0 14 36 14 36 0Z" />
|
||||
<Ellipse cy={2} fill="#6a3b18" stroke="#3a2312" strokeWidth={1.2} rx={18} ry={4} />
|
||||
<Path fill="none" stroke="#3a2312" strokeWidth={1.3} d="M16 4c8 0 8 8 0 10" />
|
||||
<Path fill="none" stroke="#8c6239" strokeLinecap="round" d="M-6-4c-2-5 2-8 0-13M2-5c-2-5 2-8 0-14" />
|
||||
</G>
|
||||
|
||||
{/* QR Köşe Çerçeveleri */}
|
||||
<Path
|
||||
fill="none"
|
||||
stroke="#3a2312"
|
||||
strokeLinecap="round"
|
||||
strokeWidth={2}
|
||||
d="M80 205c0-10 0-10 10-10m230 10c0-10 0-10-10-10M80 445c0 10 0 10 10 10m230-10c0 10 0 10-10 10"
|
||||
/>
|
||||
<Path stroke="#8c6239" strokeWidth={0.8} d="M145 608h30m50 0h30" />
|
||||
|
||||
{/* QR Placeholder / Gerçek QR */}
|
||||
<G transform="translate(90 215)">
|
||||
<Rect width={220} height={220} fill="#fbf8f2" stroke="#d8c7b0" strokeWidth={1.5} rx={20} />
|
||||
{qrBase64 ? (
|
||||
<Image
|
||||
href={`data:image/png;base64,${qrBase64}`}
|
||||
x={10}
|
||||
y={10}
|
||||
fill="#f5efe6"
|
||||
stroke="#d8c7b0"
|
||||
strokeDasharray="4 3"
|
||||
rx={14}
|
||||
width={200}
|
||||
height={200}
|
||||
/>
|
||||
<Circle cx={110} cy={98} r={18} fill="#fbf8f2" stroke="#8c6239" />
|
||||
<G fill="#3a2312" transform="matrix(.65 0 0 .65 110 98)">
|
||||
<Ellipse cx={-5} cy={2} rx={7} ry={5} transform="rotate(-30)" />
|
||||
<Ellipse cx={5} rx={7} ry={5} transform="rotate(40)" />
|
||||
</G>
|
||||
<Text
|
||||
x={110}
|
||||
y={132}
|
||||
fill="#8c6239"
|
||||
fontFamily="Inter, Arial, sans-serif"
|
||||
fontSize={11}
|
||||
fontWeight={700}
|
||||
letterSpacing={1}
|
||||
textAnchor="middle"
|
||||
>
|
||||
{"QR KOD ALANI"}
|
||||
</Text>
|
||||
</>
|
||||
)}
|
||||
</G>
|
||||
) : (
|
||||
<>
|
||||
<Rect
|
||||
width={200}
|
||||
height={200}
|
||||
x={10}
|
||||
y={10}
|
||||
fill="#f5efe6"
|
||||
stroke="#d8c7b0"
|
||||
strokeDasharray="4 3"
|
||||
rx={14}
|
||||
/>
|
||||
<Circle cx={110} cy={98} r={18} fill="#fbf8f2" stroke="#8c6239" />
|
||||
<G fill="#3a2312" transform="matrix(.65 0 0 .65 110 98)">
|
||||
<Ellipse cx={-5} cy={2} rx={7} ry={5} transform="rotate(-30)" />
|
||||
<Ellipse cx={5} rx={7} ry={5} transform="rotate(40)" />
|
||||
</G>
|
||||
<Text
|
||||
x={110}
|
||||
y={132}
|
||||
fill="#8c6239"
|
||||
fontFamily="System, sans-serif"
|
||||
fontSize={11}
|
||||
fontWeight={700}
|
||||
letterSpacing={1}
|
||||
textAnchor="middle"
|
||||
>
|
||||
{"QR KOD ALANI"}
|
||||
</Text>
|
||||
</>
|
||||
)}
|
||||
</G>
|
||||
|
||||
{/* Metinler */}
|
||||
<G textAnchor="middle">
|
||||
{/* Üst Tag / Takı */}
|
||||
<Text
|
||||
x={200}
|
||||
y={70}
|
||||
fill="#3a2312"
|
||||
fontFamily={fontFamily}
|
||||
fontSize={14}
|
||||
fontStyle="italic"
|
||||
fontWeight={700}
|
||||
letterSpacing={4}
|
||||
>
|
||||
{"THE"}
|
||||
</Text>
|
||||
|
||||
{/* Restoran Adı */}
|
||||
{restaurantName ? (
|
||||
{/* Metinler (Çok satırlı destekli) */}
|
||||
<G textAnchor="middle">
|
||||
<Text
|
||||
x={200}
|
||||
y={114}
|
||||
fill="#2c1a0e"
|
||||
fontFamily={fontFamily}
|
||||
fontSize={30}
|
||||
fontWeight={800}
|
||||
letterSpacing={0.5}
|
||||
>
|
||||
{restaurantName}
|
||||
</Text>
|
||||
) : null}
|
||||
|
||||
{/* Slogan */}
|
||||
{showSubtitle && subtitle ? (
|
||||
<Text
|
||||
x={200}
|
||||
y={146}
|
||||
y={68}
|
||||
fill="#3a2312"
|
||||
fontFamily="Inter, Arial, sans-serif"
|
||||
fontSize={12}
|
||||
fontFamily={rNameFont}
|
||||
fontSize={14}
|
||||
fontStyle="italic"
|
||||
fontWeight={700}
|
||||
letterSpacing={2.5}
|
||||
letterSpacing={4}
|
||||
>
|
||||
{subtitle}
|
||||
{"THE"}
|
||||
</Text>
|
||||
) : null}
|
||||
|
||||
{/* CTA */}
|
||||
{showCta && ctaText ? (
|
||||
{/* Restoran Adı */}
|
||||
{rName?.visible !== false &&
|
||||
renderSvgLines({
|
||||
text: rName?.text || "The Daily Grind",
|
||||
x: 200,
|
||||
y: 110,
|
||||
fill: "#2c1a0e",
|
||||
fontFamily: rNameFont,
|
||||
fontSize: rName?.fontSize || 28,
|
||||
fontWeight: "bold",
|
||||
letterSpacing: 0.5,
|
||||
})}
|
||||
|
||||
{/* Slogan */}
|
||||
{sub?.visible !== false &&
|
||||
renderSvgLines({
|
||||
text: sub?.text || "COFFEE & KITCHEN",
|
||||
x: 200,
|
||||
y: 144,
|
||||
fill: "#3a2312",
|
||||
fontFamily: subFont,
|
||||
fontSize: sub?.fontSize || 12,
|
||||
fontWeight: 700,
|
||||
letterSpacing: 2.5,
|
||||
})}
|
||||
|
||||
{/* CTA */}
|
||||
{cta?.visible !== false &&
|
||||
renderSvgLines({
|
||||
text: cta?.text || "MENÜYÜ GÖRMEK İÇİN OKUTUN",
|
||||
x: 200,
|
||||
y: 486,
|
||||
fill: "#2c1a0e",
|
||||
fontFamily: ctaFont,
|
||||
fontSize: cta?.fontSize || 15,
|
||||
fontWeight: "bold",
|
||||
letterSpacing: 1.2,
|
||||
})}
|
||||
|
||||
{/* WiFi */}
|
||||
{wifi?.visible !== false &&
|
||||
renderSvgLines({
|
||||
text: wifi?.text || "WiFi: DailyGrind | Şifre: coffee2026",
|
||||
x: 200,
|
||||
y: 520,
|
||||
fill: "#3a2312",
|
||||
fontFamily: infoFont,
|
||||
fontSize: wifi?.fontSize || 10.5,
|
||||
fontWeight: 700,
|
||||
letterSpacing: 0.5,
|
||||
})}
|
||||
|
||||
{/* Masa No & Sosyal */}
|
||||
{(table?.visible !== false || social?.visible !== false) &&
|
||||
renderSvgLines({
|
||||
text: [
|
||||
table?.visible !== false && table?.text ? table.text : "",
|
||||
social?.visible !== false && social?.text ? social.text : "",
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(" • "),
|
||||
x: 200,
|
||||
y: 544,
|
||||
fill: "#8c6239",
|
||||
fontFamily: infoFont,
|
||||
fontSize: table?.fontSize || social?.fontSize || 10,
|
||||
fontWeight: 600,
|
||||
letterSpacing: 1,
|
||||
})}
|
||||
|
||||
<Text
|
||||
x={200}
|
||||
y={488}
|
||||
fill="#2c1a0e"
|
||||
fontFamily={fontFamily}
|
||||
fontSize={16}
|
||||
fontWeight={800}
|
||||
letterSpacing={1.2}
|
||||
>
|
||||
{ctaText}
|
||||
</Text>
|
||||
) : null}
|
||||
|
||||
{/* WiFi */}
|
||||
{showWifi && wifiText ? (
|
||||
<Text
|
||||
x={200}
|
||||
y={520}
|
||||
y={611}
|
||||
fill="#3a2312"
|
||||
fontFamily="Inter, Arial, sans-serif"
|
||||
fontSize={10.5}
|
||||
fontFamily={rNameFont}
|
||||
fontSize={11}
|
||||
fontStyle="italic"
|
||||
fontWeight={700}
|
||||
letterSpacing={0.5}
|
||||
letterSpacing={2}
|
||||
>
|
||||
{wifiText}
|
||||
{"EST. 2026"}
|
||||
</Text>
|
||||
) : null}
|
||||
|
||||
{/* Masa No & Sosyal */}
|
||||
{showTableNo || showSocial ? (
|
||||
<Text
|
||||
x={200}
|
||||
y={544}
|
||||
fill="#8c6239"
|
||||
fontFamily="Inter, Arial, sans-serif"
|
||||
fontSize={10}
|
||||
fontWeight={600}
|
||||
letterSpacing={1}
|
||||
>
|
||||
{[
|
||||
showTableNo && tableNo ? tableNo : "",
|
||||
showSocial && socialText ? socialText : "",
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(" • ")}
|
||||
</Text>
|
||||
) : null}
|
||||
|
||||
<Text
|
||||
x={200}
|
||||
y={611}
|
||||
fill="#3a2312"
|
||||
fontFamily={fontFamily}
|
||||
fontSize={11}
|
||||
fontStyle="italic"
|
||||
fontWeight={700}
|
||||
letterSpacing={2}
|
||||
>
|
||||
{"EST. 2026"}
|
||||
</Text>
|
||||
</G>
|
||||
</Svg>
|
||||
);
|
||||
</G>
|
||||
</Svg>
|
||||
);
|
||||
};
|
||||
|
||||
export default QrTemplate2;
|
||||
|
||||
@@ -12,356 +12,336 @@ import Svg, {
|
||||
Text,
|
||||
Image,
|
||||
} from "react-native-svg";
|
||||
import type { QrTemplateProps } from "./index";
|
||||
import { type QrTemplateProps, getFontFamily, renderSvgLines } from "./index";
|
||||
|
||||
const QrTemplate3 = ({
|
||||
qrBase64,
|
||||
restaurantName = "BELLA NAPOLI",
|
||||
subtitle = "AUTENTICA CUCINA ITALIANA",
|
||||
tableNo = "MASA NO: 01",
|
||||
ctaText = "MENÜYÜ GÖRMEK İÇİN OKUTUN",
|
||||
wifiText = "WiFi: GourmetBistro | Şifre: lezzetli01",
|
||||
socialText = "@gourmetbistro",
|
||||
fontFamily = "'Playfair Display', Georgia, serif",
|
||||
showTableNo = true,
|
||||
showSubtitle = true,
|
||||
showCta = true,
|
||||
showWifi = true,
|
||||
showSocial = true,
|
||||
fields,
|
||||
...props
|
||||
}: QrTemplateProps) => (
|
||||
<Svg
|
||||
viewBox="0 0 400 650"
|
||||
width={300}
|
||||
height={487.5}
|
||||
{...props}
|
||||
>
|
||||
<Defs>
|
||||
<LinearGradient id="card-grad-3" x1="0%" x2="0%" y1="0%" y2="100%">
|
||||
<Stop offset="0%" stopColor="#fdfbf5" />
|
||||
<Stop offset="50%" stopColor="#faf4e6" />
|
||||
<Stop offset="100%" stopColor="#f7eed8" />
|
||||
</LinearGradient>
|
||||
<LinearGradient id="oven-fire-3" x1="0%" x2="0%" y1="100%" y2="0%">
|
||||
<Stop offset="0%" stopColor="#c0392b" />
|
||||
<Stop offset="50%" stopColor="#e67e22" />
|
||||
<Stop offset="100%" stopColor="#f1c40f" />
|
||||
</LinearGradient>
|
||||
<LinearGradient id="wine-grad-3" x1="0%" x2="0%" y1="0%" y2="100%">
|
||||
<Stop offset="0%" stopColor="#7b1123" />
|
||||
<Stop offset="100%" stopColor="#4a0512" />
|
||||
</LinearGradient>
|
||||
<Pattern
|
||||
id="checkered-border-3"
|
||||
width={20}
|
||||
height={20}
|
||||
patternUnits="userSpaceOnUse"
|
||||
>
|
||||
<Path fill="#b92b27" d="M0 0h20v20H0z" />
|
||||
<Path fill="#fdf8ee" d="M0 0h10v10H0zm10 10h10v10H10z" />
|
||||
</Pattern>
|
||||
</Defs>
|
||||
}: 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;
|
||||
|
||||
{/* Arka Plan */}
|
||||
<Path fill="url(#checkered-border-3)" d="M0 0h400v650H0z" />
|
||||
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");
|
||||
|
||||
{/* Kart */}
|
||||
<G id="layer-card">
|
||||
<Rect
|
||||
width={356}
|
||||
height={606}
|
||||
x={22}
|
||||
y={22}
|
||||
fill="url(#card-grad-3)"
|
||||
stroke="#b92b27"
|
||||
strokeWidth={2}
|
||||
rx={20}
|
||||
/>
|
||||
<Rect
|
||||
width={344}
|
||||
height={594}
|
||||
x={28}
|
||||
y={28}
|
||||
fill="none"
|
||||
stroke="#8c6239"
|
||||
strokeOpacity={0.5}
|
||||
strokeWidth={0.8}
|
||||
rx={15}
|
||||
/>
|
||||
{showTableNo && tableNo ? (
|
||||
return (
|
||||
<Svg viewBox="0 0 400 650" width={300} height={487.5} {...props}>
|
||||
<Defs>
|
||||
<LinearGradient id="card-grad-3" x1="0%" x2="0%" y1="0%" y2="100%">
|
||||
<Stop offset="0%" stopColor="#fdfbf5" />
|
||||
<Stop offset="50%" stopColor="#faf4e6" />
|
||||
<Stop offset="100%" stopColor="#f7eed8" />
|
||||
</LinearGradient>
|
||||
<LinearGradient id="oven-fire-3" x1="0%" x2="0%" y1="100%" y2="0%">
|
||||
<Stop offset="0%" stopColor="#c0392b" />
|
||||
<Stop offset="50%" stopColor="#e67e22" />
|
||||
<Stop offset="100%" stopColor="#f1c40f" />
|
||||
</LinearGradient>
|
||||
<LinearGradient id="wine-grad-3" x1="0%" x2="0%" y1="0%" y2="100%">
|
||||
<Stop offset="0%" stopColor="#7b1123" />
|
||||
<Stop offset="100%" stopColor="#4a0512" />
|
||||
</LinearGradient>
|
||||
<Pattern
|
||||
id="checkered-border-3"
|
||||
width={20}
|
||||
height={20}
|
||||
patternUnits="userSpaceOnUse"
|
||||
>
|
||||
<Path fill="#b92b27" d="M0 0h20v20H0z" />
|
||||
<Path fill="#fdf8ee" d="M0 0h10v10H0zm10 10h10v10H10z" />
|
||||
</Pattern>
|
||||
</Defs>
|
||||
|
||||
{/* Arka Plan */}
|
||||
<Path fill="url(#checkered-border-3)" d="M0 0h400v650H0z" />
|
||||
|
||||
{/* Kart */}
|
||||
<G id="layer-card">
|
||||
<Rect
|
||||
width={140}
|
||||
height={24}
|
||||
x={130}
|
||||
y={34}
|
||||
fill="#faf4e6"
|
||||
width={356}
|
||||
height={606}
|
||||
x={22}
|
||||
y={22}
|
||||
fill="url(#card-grad-3)"
|
||||
stroke="#b92b27"
|
||||
strokeWidth={2}
|
||||
rx={20}
|
||||
/>
|
||||
<Rect
|
||||
width={344}
|
||||
height={594}
|
||||
x={28}
|
||||
y={28}
|
||||
fill="none"
|
||||
stroke="#8c6239"
|
||||
strokeWidth={1.2}
|
||||
rx={12}
|
||||
/>
|
||||
) : null}
|
||||
</G>
|
||||
|
||||
{/* İkonlar */}
|
||||
<G id="layer-icons">
|
||||
<Path
|
||||
fill="none"
|
||||
stroke="#c5a880"
|
||||
strokeLinecap="round"
|
||||
strokeWidth={1.5}
|
||||
d="M68 88q12-13 28-2 6 5 10 2m226 0q-12-13-28-2-6 5-10 2"
|
||||
/>
|
||||
{/* Pizza Fırını */}
|
||||
<G id="pizza-oven" transform="translate(200 192)">
|
||||
<Rect
|
||||
width={88}
|
||||
height={6}
|
||||
x={-44}
|
||||
fill="#d7ccc8"
|
||||
stroke="#5d4037"
|
||||
rx={2}
|
||||
/>
|
||||
<Path
|
||||
fill="#d7ccc8"
|
||||
stroke="#5d4037"
|
||||
strokeWidth={1.5}
|
||||
d="M-40 0a40 38 0 0 1 80 0Z"
|
||||
/>
|
||||
<Path stroke="#8d6e63" d="m-30-25 7 6m6-15 4 8M0-38v9m17-5-4 8m17 1-7 6" />
|
||||
<Path fill="#3e2723" stroke="#271c19" d="M-28 0a28 26 0 0 1 56 0Z" />
|
||||
<Path fill="url(#oven-fire-3)" d="M-18 0q3-16 12-10 6-12 12-2 9-6 12 12Z" />
|
||||
<Path fill="#fff9c4" d="M-10 0q5-10 10-6 5-6 10 6Z" />
|
||||
</G>
|
||||
{/* Sol Malzemeler */}
|
||||
<G id="left-ingredients" transform="translate(108 185)">
|
||||
<Ellipse
|
||||
cx={-16}
|
||||
cy={6}
|
||||
fill="#d32f2f"
|
||||
stroke="#8e0000"
|
||||
strokeOpacity={0.5}
|
||||
strokeWidth={0.8}
|
||||
rx={14}
|
||||
ry={10}
|
||||
transform="rotate(-25 -16 6)"
|
||||
rx={15}
|
||||
/>
|
||||
<Ellipse
|
||||
cx={-16}
|
||||
cy={6}
|
||||
fill="#e53935"
|
||||
rx={10}
|
||||
ry={6.5}
|
||||
transform="rotate(-25 -16 6)"
|
||||
/>
|
||||
<Ellipse
|
||||
cx={2}
|
||||
cy={7}
|
||||
fill="#c62828"
|
||||
stroke="#8e0000"
|
||||
strokeWidth={0.8}
|
||||
rx={13}
|
||||
ry={9}
|
||||
transform="rotate(-10 2 7)"
|
||||
/>
|
||||
<Ellipse cx={2} cy={7} fill="#e53935" rx={9} ry={5.5} transform="rotate(-10 2 7)" />
|
||||
<Circle cx={2} cy={7} r={1.5} fill="#fdd835" />
|
||||
<Circle cx={16} cy={-2} r={14} fill="#e53935" stroke="#b71c1c" strokeWidth={0.8} />
|
||||
<Ellipse cx={12} cy={-6} fill="#ff8a80" opacity={0.6} rx={4} ry={2} />
|
||||
<Path
|
||||
stroke="#2e7d32"
|
||||
strokeLinecap="round"
|
||||
strokeWidth={1.5}
|
||||
d="M16-16v3m0 0-5 2m5-2 5 2m-5-2-3-2m3 2 3-2"
|
||||
/>
|
||||
</G>
|
||||
{/* Sağ Malzemeler */}
|
||||
<G id="right-ingredients" transform="translate(290 182)">
|
||||
<Circle cx={-14} cy={2} r={15} fill="#e53935" stroke="#b71c1c" strokeWidth={0.8} />
|
||||
<Ellipse cx={-18} cy={-3} fill="#ff8a80" opacity={0.6} rx={4} ry={2} />
|
||||
<Path
|
||||
stroke="#2e7d32"
|
||||
strokeLinecap="round"
|
||||
strokeWidth={1.5}
|
||||
d="M-14-13v3m0 0-4 2m4-2 4 2"
|
||||
/>
|
||||
<Path fill="#2e7d32" stroke="#1b5e20" strokeWidth={0.8} d="M-2 0C8-16 26-12 24 2 22 14 6 10-2 0Z" />
|
||||
<Path fill="none" stroke="#4caf50" strokeWidth={0.7} d="M-2 0q14-4 26 2" />
|
||||
<Path fill="#388e3c" stroke="#1b5e20" strokeWidth={0.8} d="M8 6c10-6 24 4 18 16-8 6-18-4-18-16Z" />
|
||||
<Path fill="none" stroke="#81c784" strokeWidth={0.7} d="M8 6q12 6 18 16" />
|
||||
</G>
|
||||
{/* Alt Pizza Dilimi */}
|
||||
<G id="footer-pizza-slice" transform="rotate(-10 3278.565 44.969)">
|
||||
<Path fill="#deac68" stroke="#8d6e63" strokeWidth={1.2} d="m0 0 46-18c4 8 6 32 0 40Z" />
|
||||
<Path fill="#fbc02d" d="m2 0 40-15c3 7 5 25 0 33Z" />
|
||||
<Circle cx={28} cy={-5} r={5} fill="#c62828" stroke="#8e0000" strokeWidth={0.8} />
|
||||
<Circle cx={32} cy={8} r={4.5} fill="#c62828" stroke="#8e0000" strokeWidth={0.8} />
|
||||
<Circle cx={16} r={3.5} fill="#c62828" stroke="#8e0000" strokeWidth={0.8} />
|
||||
<Ellipse cx={23} cy={4} fill="#2e7d32" rx={2} ry={4} transform="rotate(30 23 4)" />
|
||||
<Ellipse cx={34} cy={-11} fill="#2e7d32" rx={2} ry={3} transform="rotate(-40 34 -11)" />
|
||||
</G>
|
||||
{/* Şarap Kadehi */}
|
||||
<G id="footer-wine-glass" transform="translate(345 562)">
|
||||
<Path fill="none" stroke="#71717a" strokeWidth={1.2} d="M-14-24C-15-8-11 4 0 6 11 4 15-8 14-24Z" />
|
||||
<Path fill="url(#wine-grad-3)" d="M-13-12C-11 0-7 4 0 5.5 7 4 11 0 13-12Z" />
|
||||
<Ellipse cy={-12} fill="#991b1b" rx={13} ry={2} />
|
||||
<Path stroke="#71717a" strokeWidth={1.4} d="M0 6v22" />
|
||||
<Ellipse cy={28} fill="#e4e4e7" stroke="#71717a" strokeWidth={1.2} rx={11} ry={2} />
|
||||
<Path fill="none" stroke="#fff" strokeLinecap="round" d="M-10-20c-2 8 1 18 6 23" opacity={0.6} />
|
||||
</G>
|
||||
{/* QR Köşe Aksanları */}
|
||||
<G id="qr-corner-accents">
|
||||
<Path fill="none" stroke="#2e7d32" strokeLinecap="round" strokeWidth={3} d="M78 227v-22h22" />
|
||||
<Path fill="none" stroke="#b92b27" strokeLinecap="round" strokeWidth={3} d="M322 227v-22h-22M78 423v22h22" />
|
||||
<Path fill="none" stroke="#2e7d32" strokeLinecap="round" strokeWidth={3} d="M322 423v22h-22" />
|
||||
</G>
|
||||
</G>
|
||||
|
||||
{/* QR Placeholder / Gerçek QR */}
|
||||
<G id="qr-placeholder" transform="translate(90 215)">
|
||||
<Rect width={220} height={220} fill="#fff" stroke="#e4e4e7" strokeWidth={2} rx={20} />
|
||||
{qrBase64 ? (
|
||||
<Image
|
||||
href={`data:image/png;base64,${qrBase64}`}
|
||||
x={10}
|
||||
y={10}
|
||||
width={200}
|
||||
height={200}
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
{table?.visible !== false && table?.text ? (
|
||||
<Rect
|
||||
width={196}
|
||||
height={196}
|
||||
x={12}
|
||||
y={12}
|
||||
fill="#fafafa"
|
||||
stroke="#e4e4e7"
|
||||
strokeDasharray="4 3"
|
||||
rx={14}
|
||||
width={140}
|
||||
height={24}
|
||||
x={130}
|
||||
y={34}
|
||||
fill="#faf4e6"
|
||||
stroke="#8c6239"
|
||||
strokeWidth={1.2}
|
||||
rx={12}
|
||||
/>
|
||||
<Text
|
||||
x={110}
|
||||
y={115}
|
||||
fill="#71717a"
|
||||
fontFamily="Inter, Arial, sans-serif"
|
||||
fontSize={12}
|
||||
fontWeight={700}
|
||||
textAnchor="middle"
|
||||
>
|
||||
{"QR KOD ALANI"}
|
||||
</Text>
|
||||
</>
|
||||
)}
|
||||
</G>
|
||||
) : null}
|
||||
</G>
|
||||
|
||||
{/* İkonlar */}
|
||||
<G id="layer-icons">
|
||||
<Path
|
||||
fill="none"
|
||||
stroke="#c5a880"
|
||||
strokeLinecap="round"
|
||||
strokeWidth={1.5}
|
||||
d="M68 88q12-13 28-2 6 5 10 2m226 0q-12-13-28-2-6 5-10 2"
|
||||
/>
|
||||
{/* Pizza Fırını */}
|
||||
<G id="pizza-oven" transform="translate(200 192)">
|
||||
<Rect
|
||||
width={88}
|
||||
height={6}
|
||||
x={-44}
|
||||
fill="#d7ccc8"
|
||||
stroke="#5d4037"
|
||||
rx={2}
|
||||
/>
|
||||
<Path
|
||||
fill="#d7ccc8"
|
||||
stroke="#5d4037"
|
||||
strokeWidth={1.5}
|
||||
d="M-40 0a40 38 0 0 1 80 0Z"
|
||||
/>
|
||||
<Path stroke="#8d6e63" d="m-30-25 7 6m6-15 4 8M0-38v9m17-5-4 8m17 1-7 6" />
|
||||
<Path fill="#3e2723" stroke="#271c19" d="M-28 0a28 26 0 0 1 56 0Z" />
|
||||
<Path fill="url(#oven-fire-3)" d="M-18 0q3-16 12-10 6-12 12-2 9-6 12 12Z" />
|
||||
<Path fill="#fff9c4" d="M-10 0q5-10 10-6 5-6 10 6Z" />
|
||||
</G>
|
||||
{/* Sol Malzemeler */}
|
||||
<G id="left-ingredients" transform="translate(108 185)">
|
||||
<Ellipse
|
||||
cx={-16}
|
||||
cy={6}
|
||||
fill="#d32f2f"
|
||||
stroke="#8e0000"
|
||||
strokeWidth={0.8}
|
||||
rx={14}
|
||||
ry={10}
|
||||
transform="rotate(-25 -16 6)"
|
||||
/>
|
||||
<Ellipse
|
||||
cx={-16}
|
||||
cy={6}
|
||||
fill="#e53935"
|
||||
rx={10}
|
||||
ry={6.5}
|
||||
transform="rotate(-25 -16 6)"
|
||||
/>
|
||||
<Ellipse
|
||||
cx={2}
|
||||
cy={7}
|
||||
fill="#c62828"
|
||||
stroke="#8e0000"
|
||||
strokeWidth={0.8}
|
||||
rx={13}
|
||||
ry={9}
|
||||
transform="rotate(-10 2 7)"
|
||||
/>
|
||||
<Ellipse cx={2} cy={7} fill="#e53935" rx={9} ry={5.5} transform="rotate(-10 2 7)" />
|
||||
<Circle cx={2} cy={7} r={1.5} fill="#fdd835" />
|
||||
<Circle cx={16} cy={-2} r={14} fill="#e53935" stroke="#b71c1c" strokeWidth={0.8} />
|
||||
<Ellipse cx={12} cy={-6} fill="#ff8a80" opacity={0.6} rx={4} ry={2} />
|
||||
<Path
|
||||
stroke="#2e7d32"
|
||||
strokeLinecap="round"
|
||||
strokeWidth={1.5}
|
||||
d="M16-16v3m0 0-5 2m5-2 5 2m-5-2-3-2m3 2 3-2"
|
||||
/>
|
||||
</G>
|
||||
{/* Sağ Malzemeler */}
|
||||
<G id="right-ingredients" transform="translate(290 182)">
|
||||
<Circle cx={-14} cy={2} r={15} fill="#e53935" stroke="#b71c1c" strokeWidth={0.8} />
|
||||
<Ellipse cx={-18} cy={-3} fill="#ff8a80" opacity={0.6} rx={4} ry={2} />
|
||||
<Path
|
||||
stroke="#2e7d32"
|
||||
strokeLinecap="round"
|
||||
strokeWidth={1.5}
|
||||
d="M-14-13v3m0 0-4 2m4-2 4 2"
|
||||
/>
|
||||
<Path fill="#2e7d32" stroke="#1b5e20" strokeWidth={0.8} d="M-2 0C8-16 26-12 24 2 22 14 6 10-2 0Z" />
|
||||
<Path fill="none" stroke="#4caf50" strokeWidth={0.7} d="M-2 0q14-4 26 2" />
|
||||
<Path fill="#388e3c" stroke="#1b5e20" strokeWidth={0.8} d="M8 6c10-6 24 4 18 16-8 6-18-4-18-16Z" />
|
||||
<Path fill="none" stroke="#81c784" strokeWidth={0.7} d="M8 6q12 6 18 16" />
|
||||
</G>
|
||||
{/* Alt Pizza Dilimi */}
|
||||
<G id="footer-pizza-slice" transform="rotate(-10 3278.565 44.969)">
|
||||
<Path fill="#deac68" stroke="#8d6e63" strokeWidth={1.2} d="m0 0 46-18c4 8 6 32 0 40Z" />
|
||||
<Path fill="#fbc02d" d="m2 0 40-15c3 7 5 25 0 33Z" />
|
||||
<Circle cx={28} cy={-5} r={5} fill="#c62828" stroke="#8e0000" strokeWidth={0.8} />
|
||||
<Circle cx={32} cy={8} r={4.5} fill="#c62828" stroke="#8e0000" strokeWidth={0.8} />
|
||||
<Circle cx={16} r={3.5} fill="#c62828" stroke="#8e0000" strokeWidth={0.8} />
|
||||
<Ellipse cx={23} cy={4} fill="#2e7d32" rx={2} ry={4} transform="rotate(30 23 4)" />
|
||||
<Ellipse cx={34} cy={-11} fill="#2e7d32" rx={2} ry={3} transform="rotate(-40 34 -11)" />
|
||||
</G>
|
||||
{/* Şarap Kadehi */}
|
||||
<G id="footer-wine-glass" transform="translate(345 562)">
|
||||
<Path fill="none" stroke="#71717a" strokeWidth={1.2} d="M-14-24C-15-8-11 4 0 6 11 4 15-8 14-24Z" />
|
||||
<Path fill="url(#wine-grad-3)" d="M-13-12C-11 0-7 4 0 5.5 7 4 11 0 13-12Z" />
|
||||
<Ellipse cy={-12} fill="#991b1b" rx={13} ry={2} />
|
||||
<Path stroke="#71717a" strokeWidth={1.4} d="M0 6v22" />
|
||||
<Ellipse cy={28} fill="#e4e4e7" stroke="#71717a" strokeWidth={1.2} rx={11} ry={2} />
|
||||
<Path fill="none" stroke="#fff" strokeLinecap="round" d="M-10-20c-2 8 1 18 6 23" opacity={0.6} />
|
||||
</G>
|
||||
{/* QR Köşe Aksanları */}
|
||||
<G id="qr-corner-accents">
|
||||
<Path fill="none" stroke="#2e7d32" strokeLinecap="round" strokeWidth={3} d="M78 227v-22h22" />
|
||||
<Path fill="none" stroke="#b92b27" strokeLinecap="round" strokeWidth={3} d="M322 227v-22h-22M78 423v22h22" />
|
||||
<Path fill="none" stroke="#2e7d32" strokeLinecap="round" strokeWidth={3} d="M322 423v22h-22" />
|
||||
</G>
|
||||
</G>
|
||||
|
||||
{/* QR Placeholder / Gerçek QR */}
|
||||
<G id="qr-placeholder" transform="translate(90 215)">
|
||||
<Rect width={220} height={220} fill="#fff" stroke="#e4e4e7" strokeWidth={2} rx={20} />
|
||||
{qrBase64 ? (
|
||||
<Image
|
||||
href={`data:image/png;base64,${qrBase64}`}
|
||||
x={10}
|
||||
y={10}
|
||||
width={200}
|
||||
height={200}
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
<Rect
|
||||
width={196}
|
||||
height={196}
|
||||
x={12}
|
||||
y={12}
|
||||
fill="#fafafa"
|
||||
stroke="#e4e4e7"
|
||||
strokeDasharray="4 3"
|
||||
rx={14}
|
||||
/>
|
||||
<Text
|
||||
x={110}
|
||||
y={115}
|
||||
fill="#71717a"
|
||||
fontFamily="System, sans-serif"
|
||||
fontSize={12}
|
||||
fontWeight={700}
|
||||
textAnchor="middle"
|
||||
>
|
||||
{"QR KOD ALANI"}
|
||||
</Text>
|
||||
</>
|
||||
)}
|
||||
</G>
|
||||
|
||||
{/* Metinler (Çok satırlı destekli) */}
|
||||
<G id="layer-texts">
|
||||
{/* Masa No */}
|
||||
{table?.visible !== false &&
|
||||
renderSvgLines({
|
||||
text: table?.text || "MASA NO: 01",
|
||||
x: 200,
|
||||
y: 50,
|
||||
fill: "#18181b",
|
||||
fontFamily: infoFont,
|
||||
fontSize: table?.fontSize || 11,
|
||||
fontWeight: "bold",
|
||||
letterSpacing: 1.2,
|
||||
})}
|
||||
|
||||
{/* Metinler */}
|
||||
<G id="layer-texts">
|
||||
{/* Masa No */}
|
||||
{showTableNo && tableNo ? (
|
||||
<Text
|
||||
x={200}
|
||||
y={50}
|
||||
fill="#18181b"
|
||||
fontFamily="Inter, Arial, sans-serif"
|
||||
fontSize={11}
|
||||
fontWeight={800}
|
||||
letterSpacing={1.2}
|
||||
textAnchor="middle"
|
||||
>
|
||||
{tableNo}
|
||||
</Text>
|
||||
) : null}
|
||||
|
||||
<Text
|
||||
x={200}
|
||||
y={96}
|
||||
fill="#3e2723"
|
||||
fontFamily={fontFamily}
|
||||
fontSize={24}
|
||||
textAnchor="middle"
|
||||
>
|
||||
{"PIZZERIA"}
|
||||
</Text>
|
||||
|
||||
{/* Restoran Adı */}
|
||||
{restaurantName ? (
|
||||
<Text
|
||||
x={200}
|
||||
y={132}
|
||||
fill="#18181b"
|
||||
fontFamily={fontFamily}
|
||||
fontSize={28}
|
||||
fontWeight={700}
|
||||
letterSpacing={1}
|
||||
textAnchor="middle"
|
||||
>
|
||||
{restaurantName}
|
||||
</Text>
|
||||
) : null}
|
||||
|
||||
{/* Slogan */}
|
||||
{showSubtitle && subtitle ? (
|
||||
<Text
|
||||
x={200}
|
||||
y={222}
|
||||
fill="#2e7d32"
|
||||
fontFamily="Inter, Arial, sans-serif"
|
||||
fontSize={11.5}
|
||||
fontWeight={800}
|
||||
letterSpacing={1.8}
|
||||
textAnchor="middle"
|
||||
>
|
||||
{subtitle}
|
||||
</Text>
|
||||
) : null}
|
||||
|
||||
{/* CTA */}
|
||||
{showCta && ctaText ? (
|
||||
<Text
|
||||
x={200}
|
||||
y={474}
|
||||
fill="#b92b27"
|
||||
fontFamily={fontFamily}
|
||||
fontSize={14}
|
||||
fontWeight={700}
|
||||
letterSpacing={1.2}
|
||||
textAnchor="middle"
|
||||
>
|
||||
{ctaText}
|
||||
</Text>
|
||||
) : null}
|
||||
|
||||
{/* WiFi */}
|
||||
{showWifi && wifiText ? (
|
||||
<Text
|
||||
x={200}
|
||||
y={546}
|
||||
y={96}
|
||||
fill="#3e2723"
|
||||
fontFamily="Inter, Arial, sans-serif"
|
||||
fontSize={10.5}
|
||||
fontWeight={700}
|
||||
fontFamily={rNameFont}
|
||||
fontSize={24}
|
||||
textAnchor="middle"
|
||||
>
|
||||
{wifiText}
|
||||
{"PIZZERIA"}
|
||||
</Text>
|
||||
) : null}
|
||||
|
||||
{/* Sosyal Medya */}
|
||||
{showSocial && socialText ? (
|
||||
<Text
|
||||
x={200}
|
||||
y={570}
|
||||
fill="#b92b27"
|
||||
fontFamily="Inter, Arial, sans-serif"
|
||||
fontSize={10.5}
|
||||
fontWeight={700}
|
||||
letterSpacing={0.5}
|
||||
textAnchor="middle"
|
||||
>
|
||||
{socialText}
|
||||
</Text>
|
||||
) : null}
|
||||
</G>
|
||||
</Svg>
|
||||
);
|
||||
{/* Restoran Adı */}
|
||||
{rName?.visible !== false &&
|
||||
renderSvgLines({
|
||||
text: rName?.text || "BELLA NAPOLI",
|
||||
x: 200,
|
||||
y: 130,
|
||||
fill: "#18181b",
|
||||
fontFamily: rNameFont,
|
||||
fontSize: rName?.fontSize || 26,
|
||||
fontWeight: "bold",
|
||||
letterSpacing: 1,
|
||||
})}
|
||||
|
||||
{/* Slogan (Enter ile çok satır olabilir) */}
|
||||
{sub?.visible !== false &&
|
||||
renderSvgLines({
|
||||
text: sub?.text || "AUTENTICA CUCINA ITALIANA",
|
||||
x: 200,
|
||||
y: 222,
|
||||
fill: "#2e7d32",
|
||||
fontFamily: subFont,
|
||||
fontSize: sub?.fontSize || 11.5,
|
||||
fontWeight: "bold",
|
||||
letterSpacing: 1.8,
|
||||
})}
|
||||
|
||||
{/* CTA */}
|
||||
{cta?.visible !== false &&
|
||||
renderSvgLines({
|
||||
text: cta?.text || "MENÜYÜ GÖRMEK İÇİN OKUTUN",
|
||||
x: 200,
|
||||
y: 474,
|
||||
fill: "#b92b27",
|
||||
fontFamily: ctaFont,
|
||||
fontSize: cta?.fontSize || 13,
|
||||
fontWeight: "bold",
|
||||
letterSpacing: 1.2,
|
||||
})}
|
||||
|
||||
{/* WiFi */}
|
||||
{wifi?.visible !== false &&
|
||||
renderSvgLines({
|
||||
text: wifi?.text || "WiFi: GourmetBistro | Şifre: lezzetli01",
|
||||
x: 200,
|
||||
y: 546,
|
||||
fill: "#3e2723",
|
||||
fontFamily: infoFont,
|
||||
fontSize: wifi?.fontSize || 10.5,
|
||||
fontWeight: "bold",
|
||||
})}
|
||||
|
||||
{/* Sosyal Medya */}
|
||||
{social?.visible !== false &&
|
||||
renderSvgLines({
|
||||
text: social?.text || "BİZİ TAKİP EDİN | @gourmetbistro",
|
||||
x: 200,
|
||||
y: 570,
|
||||
fill: "#b92b27",
|
||||
fontFamily: infoFont,
|
||||
fontSize: social?.fontSize || 10.5,
|
||||
fontWeight: "bold",
|
||||
letterSpacing: 0.5,
|
||||
})}
|
||||
</G>
|
||||
</Svg>
|
||||
);
|
||||
};
|
||||
|
||||
export default QrTemplate3;
|
||||
|
||||
@@ -9,271 +9,262 @@ import Svg, {
|
||||
Text,
|
||||
Image,
|
||||
} from "react-native-svg";
|
||||
import type { QrTemplateProps } from "./index";
|
||||
import { type QrTemplateProps, getFontFamily, renderSvgLines } from "./index";
|
||||
|
||||
const QrTemplate4 = ({
|
||||
qrBase64,
|
||||
restaurantName = "THE CRIMSON PETAL",
|
||||
subtitle = "FINE DINING EXPERIENCE",
|
||||
tableNo = "MASA NO: 01",
|
||||
ctaText = "MENÜYÜ GÖRMEK İÇİN OKUTUN",
|
||||
wifiText = "WiFi: CrimsonGuest | Şifre: petal2026",
|
||||
socialText = "@thecrimsonpetal",
|
||||
fontFamily = "Georgia, 'Times New Roman', serif",
|
||||
showTableNo = true,
|
||||
showSubtitle = true,
|
||||
showCta = true,
|
||||
showWifi = true,
|
||||
showSocial = true,
|
||||
fields,
|
||||
...props
|
||||
}: QrTemplateProps) => (
|
||||
<Svg width={300} height={435} viewBox="0 0 400 580" {...props}>
|
||||
<Defs>
|
||||
<G id="b4">
|
||||
<Path
|
||||
fill="none"
|
||||
stroke="#c59b4b"
|
||||
strokeWidth={1.3}
|
||||
d="M0-22c22-8 36 6 38 22-2 16-16 30-38 22Z"
|
||||
/>
|
||||
<Path
|
||||
fill="none"
|
||||
stroke="#c59b4b"
|
||||
strokeWidth={0.9}
|
||||
d="M0-12c14-6 24 2 26 12-2 10-12 18-26 12Z"
|
||||
/>
|
||||
<Path stroke="#c59b4b" strokeWidth={0.8} d="M0 0h26" />
|
||||
<Path
|
||||
fill="none"
|
||||
stroke="#c59b4b"
|
||||
strokeWidth={1.2}
|
||||
d="M0-8c16-28 34-32 46-18C36-12 20-4 0-8ZM0 8c16 28 34 32 46 18C36 12 20 4 0 8Z"
|
||||
/>
|
||||
<Circle cx={48} cy={-28} r={1.5} fill="#c59b4b" />
|
||||
<Circle cx={48} cy={28} r={1.5} fill="#c59b4b" />
|
||||
<Path
|
||||
fill="none"
|
||||
stroke="#c59b4b"
|
||||
strokeWidth={1.1}
|
||||
d="M0-35c24-21 52-15 56-1-14 6-32 12-56 1Zm0 70c24 21 52 15 56 1-14-6-32-12-56-1Z"
|
||||
/>
|
||||
<Path
|
||||
fill="none"
|
||||
stroke="#c59b4b"
|
||||
d="M28-44c14-20 36-10 30 2-10 6-20 4-30-2Zm0 88c14 20 36 10 30-2-10-6-20-4-30 2Z"
|
||||
/>
|
||||
<Circle cx={60} cy={-44} r={1.2} fill="#c59b4b" />
|
||||
<Circle cx={60} cy={44} r={1.2} fill="#c59b4b" />
|
||||
<Circle cx={34} cy={-58} r={1.2} fill="#c59b4b" />
|
||||
<Circle cx={34} cy={58} r={1.2} fill="#c59b4b" />
|
||||
<Path
|
||||
fill="none"
|
||||
stroke="#c59b4b"
|
||||
strokeLinecap="round"
|
||||
d="M0-60c22-15 36-35 32-55-6 15-16 30-32 55M0 60c22 15 36 35 32 55-6-15-16-30-32-55"
|
||||
/>
|
||||
<Path
|
||||
fill="none"
|
||||
stroke="#c59b4b"
|
||||
strokeWidth={0.9}
|
||||
d="M14-78c8-6 12 2 6 6-4 0-6-4-6-6Zm0 156c8 6 12-2 6-6-4 0-6 4-6 6Z"
|
||||
/>
|
||||
<Circle cx={32} cy={-116} r={1.5} fill="#c59b4b" />
|
||||
<Circle cx={32} cy={116} r={1.5} fill="#c59b4b" />
|
||||
</G>
|
||||
<G id="a4">
|
||||
<Path
|
||||
fill="none"
|
||||
stroke="#c59b4b"
|
||||
strokeWidth={1.3}
|
||||
d="M18 64c0-28 18-46 46-46"
|
||||
/>
|
||||
<Path
|
||||
fill="none"
|
||||
stroke="#c59b4b"
|
||||
strokeWidth={0.8}
|
||||
d="M24 52c0-16 12-28 28-28"
|
||||
/>
|
||||
<Path
|
||||
fill="none"
|
||||
stroke="#c59b4b"
|
||||
strokeLinecap="round"
|
||||
strokeWidth={0.9}
|
||||
d="M28 32c4-6 10-4 8 2-2 4-8 2-6-4s10-6 14-2"
|
||||
/>
|
||||
<Circle cx={28} cy={28} r={1.8} fill="#c59b4b" />
|
||||
<Circle cx={48} cy={18} r={1.4} fill="#c59b4b" />
|
||||
<Circle cx={18} cy={48} r={1.4} fill="#c59b4b" />
|
||||
</G>
|
||||
</Defs>
|
||||
<Path fill="#fdfdfd" d="M0 0h400v580H0z" />
|
||||
<Path
|
||||
fill="none"
|
||||
stroke="#c59b4b"
|
||||
strokeWidth={1.2}
|
||||
d="M20 14h360v552H20z"
|
||||
/>
|
||||
<Use href="#a4" />
|
||||
<Use href="#a4" transform="matrix(-1 0 0 1 400 0)" />
|
||||
<Use href="#a4" transform="matrix(1 0 0 -1 0 580)" />
|
||||
<Use href="#a4" transform="rotate(180 200 290)" />
|
||||
<Path
|
||||
fill="none"
|
||||
stroke="#c59b4b"
|
||||
strokeLinecap="round"
|
||||
strokeWidth={1.2}
|
||||
d="M132 62c8-4 16 2 24-2 4-2 2-6-2-4m114 6c-8-4-16 2-24-2-4-2-2-6 2-4"
|
||||
/>
|
||||
<Use href="#b4" transform="translate(0 310)" />
|
||||
<Use href="#b4" transform="matrix(-1 0 0 1 400 310)" />
|
||||
<Path
|
||||
fill="none"
|
||||
stroke="#c59b4b"
|
||||
strokeLinecap="square"
|
||||
strokeWidth={2.2}
|
||||
d="M114 278v-58h54m118 58v-58h-54M114 342v58h54m118-58v58h-54"
|
||||
/>
|
||||
}: 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;
|
||||
|
||||
{/* QR Placeholder / Live QR */}
|
||||
<G transform="translate(125 230)">
|
||||
<Rect
|
||||
width={150}
|
||||
height={150}
|
||||
fill="#fff"
|
||||
stroke="#eae5d9"
|
||||
strokeWidth={1.5}
|
||||
rx={12}
|
||||
const rNameFont = getFontFamily(rName?.fontId, "Georgia, 'Times New Roman', serif");
|
||||
const subFont = getFontFamily(sub?.fontId, "System, -apple-system, Roboto, sans-serif");
|
||||
const ctaFont = getFontFamily(cta?.fontId, "Georgia, 'Times New Roman', serif");
|
||||
const infoFont = getFontFamily(wifi?.fontId, "System, -apple-system, Roboto, sans-serif");
|
||||
|
||||
return (
|
||||
<Svg width={300} height={435} viewBox="0 0 400 580" {...props}>
|
||||
<Defs>
|
||||
<G id="b4">
|
||||
<Path
|
||||
fill="none"
|
||||
stroke="#c59b4b"
|
||||
strokeWidth={1.3}
|
||||
d="M0-22c22-8 36 6 38 22-2 16-16 30-38 22Z"
|
||||
/>
|
||||
<Path
|
||||
fill="none"
|
||||
stroke="#c59b4b"
|
||||
strokeWidth={0.9}
|
||||
d="M0-12c14-6 24 2 26 12-2 10-12 18-26 12Z"
|
||||
/>
|
||||
<Path stroke="#c59b4b" strokeWidth={0.8} d="M0 0h26" />
|
||||
<Path
|
||||
fill="none"
|
||||
stroke="#c59b4b"
|
||||
strokeWidth={1.2}
|
||||
d="M0-8c16-28 34-32 46-18C36-12 20-4 0-8ZM0 8c16 28 34 32 46 18C36 12 20 4 0 8Z"
|
||||
/>
|
||||
<Circle cx={48} cy={-28} r={1.5} fill="#c59b4b" />
|
||||
<Circle cx={48} cy={28} r={1.5} fill="#c59b4b" />
|
||||
<Path
|
||||
fill="none"
|
||||
stroke="#c59b4b"
|
||||
strokeWidth={1.1}
|
||||
d="M0-35c24-21 52-15 56-1-14 6-32 12-56 1Zm0 70c24 21 52 15 56 1-14-6-32-12-56-1Z"
|
||||
/>
|
||||
<Path
|
||||
fill="none"
|
||||
stroke="#c59b4b"
|
||||
d="M28-44c14-20 36-10 30 2-10 6-20 4-30-2Zm0 88c14 20 36 10 30-2-10-6-20-4-30 2Z"
|
||||
/>
|
||||
<Circle cx={60} cy={-44} r={1.2} fill="#c59b4b" />
|
||||
<Circle cx={60} cy={44} r={1.2} fill="#c59b4b" />
|
||||
<Circle cx={34} cy={-58} r={1.2} fill="#c59b4b" />
|
||||
<Circle cx={34} cy={58} r={1.2} fill="#c59b4b" />
|
||||
<Path
|
||||
fill="none"
|
||||
stroke="#c59b4b"
|
||||
strokeLinecap="round"
|
||||
d="M0-60c22-15 36-35 32-55-6 15-16 30-32 55M0 60c22 15 36 35 32 55-6-15-16-30-32-55"
|
||||
/>
|
||||
<Path
|
||||
fill="none"
|
||||
stroke="#c59b4b"
|
||||
strokeWidth={0.9}
|
||||
d="M14-78c8-6 12 2 6 6-4 0-6-4-6-6Zm0 156c8 6 12-2 6-6-4 0-6 4-6 6Z"
|
||||
/>
|
||||
<Circle cx={32} cy={-116} r={1.5} fill="#c59b4b" />
|
||||
<Circle cx={32} cy={116} r={1.5} fill="#c59b4b" />
|
||||
</G>
|
||||
<G id="a4">
|
||||
<Path
|
||||
fill="none"
|
||||
stroke="#c59b4b"
|
||||
strokeWidth={1.3}
|
||||
d="M18 64c0-28 18-46 46-46"
|
||||
/>
|
||||
<Path
|
||||
fill="none"
|
||||
stroke="#c59b4b"
|
||||
strokeWidth={0.8}
|
||||
d="M24 52c0-16 12-28 28-28"
|
||||
/>
|
||||
<Path
|
||||
fill="none"
|
||||
stroke="#c59b4b"
|
||||
strokeLinecap="round"
|
||||
strokeWidth={0.9}
|
||||
d="M28 32c4-6 10-4 8 2-2 4-8 2-6-4s10-6 14-2"
|
||||
/>
|
||||
<Circle cx={28} cy={28} r={1.8} fill="#c59b4b" />
|
||||
<Circle cx={48} cy={18} r={1.4} fill="#c59b4b" />
|
||||
<Circle cx={18} cy={48} r={1.4} fill="#c59b4b" />
|
||||
</G>
|
||||
</Defs>
|
||||
<Path fill="#fdfdfd" d="M0 0h400v580H0z" />
|
||||
<Path
|
||||
fill="none"
|
||||
stroke="#c59b4b"
|
||||
strokeWidth={1.2}
|
||||
d="M20 14h360v552H20z"
|
||||
/>
|
||||
{qrBase64 ? (
|
||||
<Image
|
||||
href={`data:image/png;base64,${qrBase64}`}
|
||||
x={8}
|
||||
y={8}
|
||||
width={134}
|
||||
height={134}
|
||||
<Use href="#a4" />
|
||||
<Use href="#a4" transform="matrix(-1 0 0 1 400 0)" />
|
||||
<Use href="#a4" transform="matrix(1 0 0 -1 0 580)" />
|
||||
<Use href="#a4" transform="rotate(180 200 290)" />
|
||||
<Path
|
||||
fill="none"
|
||||
stroke="#c59b4b"
|
||||
strokeLinecap="round"
|
||||
strokeWidth={1.2}
|
||||
d="M132 62c8-4 16 2 24-2 4-2 2-6-2-4m114 6c-8-4-16 2-24-2-4-2-2-6 2-4"
|
||||
/>
|
||||
<Use href="#b4" transform="translate(0 310)" />
|
||||
<Use href="#b4" transform="matrix(-1 0 0 1 400 310)" />
|
||||
<Path
|
||||
fill="none"
|
||||
stroke="#c59b4b"
|
||||
strokeLinecap="square"
|
||||
strokeWidth={2.2}
|
||||
d="M114 278v-58h54m118 58v-58h-54M114 342v58h54m118-58v58h-54"
|
||||
/>
|
||||
|
||||
{/* QR Placeholder / Live QR */}
|
||||
<G transform="translate(125 230)">
|
||||
<Rect
|
||||
width={150}
|
||||
height={150}
|
||||
fill="#fff"
|
||||
stroke="#eae5d9"
|
||||
strokeWidth={1.5}
|
||||
rx={12}
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
<Rect
|
||||
width={134}
|
||||
height={134}
|
||||
{qrBase64 ? (
|
||||
<Image
|
||||
href={`data:image/png;base64,${qrBase64}`}
|
||||
x={8}
|
||||
y={8}
|
||||
fill="#fafaf8"
|
||||
stroke="#c59b4b"
|
||||
strokeDasharray="4 3"
|
||||
strokeOpacity={0.35}
|
||||
rx={8}
|
||||
width={134}
|
||||
height={134}
|
||||
/>
|
||||
<Text
|
||||
x={75}
|
||||
y={79}
|
||||
fill="#c59b4b"
|
||||
fontFamily="Inter, Arial, sans-serif"
|
||||
fontSize={10}
|
||||
fontWeight={700}
|
||||
letterSpacing={1}
|
||||
textAnchor="middle"
|
||||
>
|
||||
{"QR KOD ALANI"}
|
||||
</Text>
|
||||
</>
|
||||
)}
|
||||
</G>
|
||||
) : (
|
||||
<>
|
||||
<Rect
|
||||
width={134}
|
||||
height={134}
|
||||
x={8}
|
||||
y={8}
|
||||
fill="#fafaf8"
|
||||
stroke="#c59b4b"
|
||||
strokeDasharray="4 3"
|
||||
strokeOpacity={0.35}
|
||||
rx={8}
|
||||
/>
|
||||
<Text
|
||||
x={75}
|
||||
y={79}
|
||||
fill="#c59b4b"
|
||||
fontFamily="System, sans-serif"
|
||||
fontSize={10}
|
||||
fontWeight={700}
|
||||
letterSpacing={1}
|
||||
textAnchor="middle"
|
||||
>
|
||||
{"QR KOD ALANI"}
|
||||
</Text>
|
||||
</>
|
||||
)}
|
||||
</G>
|
||||
|
||||
{/* Metinler */}
|
||||
<G fill="#111" textAnchor="middle">
|
||||
{/* Masa No */}
|
||||
{showTableNo && tableNo ? (
|
||||
<Text
|
||||
x={200}
|
||||
y={56}
|
||||
fill="#c59b4b"
|
||||
fontFamily={fontFamily}
|
||||
fontSize={11}
|
||||
fontWeight={700}
|
||||
letterSpacing={1.5}
|
||||
>
|
||||
{tableNo}
|
||||
</Text>
|
||||
) : null}
|
||||
{/* Metinler */}
|
||||
<G fill="#111" textAnchor="middle">
|
||||
{/* Masa No */}
|
||||
{table?.visible !== false &&
|
||||
renderSvgLines({
|
||||
text: table?.text || "MASA NO: 01",
|
||||
x: 200,
|
||||
y: 56,
|
||||
fill: "#c59b4b",
|
||||
fontFamily: infoFont,
|
||||
fontSize: table?.fontSize || 11,
|
||||
fontWeight: "bold",
|
||||
letterSpacing: 1.5,
|
||||
})}
|
||||
|
||||
{/* Restoran Başlığı */}
|
||||
{restaurantName ? (
|
||||
<Text
|
||||
x={200}
|
||||
y={116}
|
||||
fill="#111111"
|
||||
fontFamily={fontFamily}
|
||||
fontSize={26}
|
||||
fontWeight={700}
|
||||
letterSpacing={2}
|
||||
>
|
||||
{restaurantName}
|
||||
</Text>
|
||||
) : null}
|
||||
{/* Restoran Başlığı (Enter ile alt satıra geçebilir) */}
|
||||
{rName?.visible !== false &&
|
||||
renderSvgLines({
|
||||
text: rName?.text || "THE CRIMSON PETAL",
|
||||
x: 200,
|
||||
y: 114,
|
||||
fill: "#111111",
|
||||
fontFamily: rNameFont,
|
||||
fontSize: rName?.fontSize || 24,
|
||||
fontWeight: "bold",
|
||||
letterSpacing: 1.5,
|
||||
})}
|
||||
|
||||
{/* Slogan */}
|
||||
{showSubtitle && subtitle ? (
|
||||
<Text
|
||||
x={200}
|
||||
y={154}
|
||||
fill="#71717a"
|
||||
fontFamily={fontFamily}
|
||||
fontSize={11}
|
||||
fontWeight={600}
|
||||
letterSpacing={1.8}
|
||||
>
|
||||
{subtitle}
|
||||
</Text>
|
||||
) : null}
|
||||
{/* Slogan */}
|
||||
{sub?.visible !== false &&
|
||||
renderSvgLines({
|
||||
text: sub?.text || "FINE DINING EXPERIENCE",
|
||||
x: 200,
|
||||
y: 154,
|
||||
fill: "#71717a",
|
||||
fontFamily: subFont,
|
||||
fontSize: sub?.fontSize || 11,
|
||||
fontWeight: 600,
|
||||
letterSpacing: 1.8,
|
||||
})}
|
||||
|
||||
{/* CTA Metni */}
|
||||
{showCta && ctaText ? (
|
||||
<Text
|
||||
x={200}
|
||||
y={440}
|
||||
fill="#111111"
|
||||
fontFamily={fontFamily}
|
||||
fontSize={15}
|
||||
fontWeight={700}
|
||||
letterSpacing={1}
|
||||
>
|
||||
{ctaText}
|
||||
</Text>
|
||||
) : null}
|
||||
{/* CTA Metni */}
|
||||
{cta?.visible !== false &&
|
||||
renderSvgLines({
|
||||
text: cta?.text || "MENÜYÜ GÖRMEK İÇİN OKUTUN",
|
||||
x: 200,
|
||||
y: 440,
|
||||
fill: "#111111",
|
||||
fontFamily: ctaFont,
|
||||
fontSize: cta?.fontSize || 15,
|
||||
fontWeight: "bold",
|
||||
letterSpacing: 1,
|
||||
})}
|
||||
|
||||
{/* WiFi Bilgisi */}
|
||||
{showWifi && wifiText ? (
|
||||
<Text
|
||||
x={200}
|
||||
y={488}
|
||||
fill="#71717a"
|
||||
fontFamily="System, -apple-system, Roboto, sans-serif"
|
||||
fontSize={10.5}
|
||||
fontWeight={600}
|
||||
letterSpacing={0.5}
|
||||
>
|
||||
{wifiText}
|
||||
</Text>
|
||||
) : null}
|
||||
{/* WiFi Bilgisi */}
|
||||
{wifi?.visible !== false &&
|
||||
renderSvgLines({
|
||||
text: wifi?.text || "WiFi: CrimsonGuest | Şifre: petal2026",
|
||||
x: 200,
|
||||
y: 488,
|
||||
fill: "#71717a",
|
||||
fontFamily: infoFont,
|
||||
fontSize: wifi?.fontSize || 10.5,
|
||||
fontWeight: 600,
|
||||
letterSpacing: 0.5,
|
||||
})}
|
||||
|
||||
{/* Sosyal Medya */}
|
||||
{showSocial && socialText ? (
|
||||
<Text
|
||||
x={200}
|
||||
y={514}
|
||||
fill="#c59b4b"
|
||||
fontFamily="System, -apple-system, Roboto, sans-serif"
|
||||
fontSize={10.5}
|
||||
fontWeight={600}
|
||||
letterSpacing={0.5}
|
||||
>
|
||||
{socialText}
|
||||
</Text>
|
||||
) : null}
|
||||
</G>
|
||||
</Svg>
|
||||
);
|
||||
{/* Sosyal Medya */}
|
||||
{social?.visible !== false &&
|
||||
renderSvgLines({
|
||||
text: social?.text || "@thecrimsonpetal",
|
||||
x: 200,
|
||||
y: 514,
|
||||
fill: "#c59b4b",
|
||||
fontFamily: infoFont,
|
||||
fontSize: social?.fontSize || 10.5,
|
||||
fontWeight: 600,
|
||||
letterSpacing: 0.5,
|
||||
})}
|
||||
</G>
|
||||
</Svg>
|
||||
);
|
||||
};
|
||||
|
||||
export default QrTemplate4;
|
||||
|
||||
@@ -6,183 +6,174 @@ import Svg, {
|
||||
Path,
|
||||
Text,
|
||||
} from "react-native-svg";
|
||||
import type { QrTemplateProps } from "./index";
|
||||
import { type QrTemplateProps, getFontFamily, renderSvgLines } from "./index";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
const bgImage = require("../../../assets/templates/5.png");
|
||||
|
||||
const QrTemplate5 = ({
|
||||
qrBase64,
|
||||
restaurantName = "THE URBAN FORK",
|
||||
subtitle = "FRESH FLAVORS DAILY",
|
||||
tableNo = "MASA NO: 01",
|
||||
ctaText = "DİJİTAL MENÜYÜ GÖRÜNTÜLE",
|
||||
wifiText = "WiFi: UrbanFork | Şifre: urban2026",
|
||||
socialText = "@theurbanfork",
|
||||
fontFamily = "System, -apple-system, Roboto, Arial, sans-serif",
|
||||
showTableNo = true,
|
||||
showSubtitle = true,
|
||||
showCta = true,
|
||||
showWifi = true,
|
||||
showSocial = true,
|
||||
fields,
|
||||
...props
|
||||
}: QrTemplateProps) => (
|
||||
<Svg width={300} height={394.7} viewBox="0 0 380 500" {...props}>
|
||||
{/* PNG Arka Plan */}
|
||||
<Image
|
||||
width={380}
|
||||
height={500}
|
||||
href={bgImage}
|
||||
preserveAspectRatio="none"
|
||||
/>
|
||||
}: 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;
|
||||
|
||||
{/* QR Placeholder / Live QR */}
|
||||
<G transform="translate(108 206)">
|
||||
<Rect
|
||||
width={164}
|
||||
height={164}
|
||||
fill="#fff"
|
||||
stroke="#dce5ea"
|
||||
strokeWidth={1.2}
|
||||
rx={16}
|
||||
const rNameFont = getFontFamily(rName?.fontId, "System, -apple-system, Roboto, sans-serif");
|
||||
const subFont = getFontFamily(sub?.fontId, "System, -apple-system, Roboto, sans-serif");
|
||||
const ctaFont = getFontFamily(cta?.fontId, "System, -apple-system, Roboto, sans-serif");
|
||||
const infoFont = getFontFamily(wifi?.fontId, "System, -apple-system, Roboto, sans-serif");
|
||||
|
||||
return (
|
||||
<Svg width={300} height={394.7} viewBox="0 0 380 500" {...props}>
|
||||
{/* PNG Arka Plan */}
|
||||
<Image
|
||||
width={380}
|
||||
height={500}
|
||||
href={bgImage}
|
||||
preserveAspectRatio="none"
|
||||
/>
|
||||
<Path
|
||||
fill="none"
|
||||
stroke="#003554"
|
||||
strokeLinecap="round"
|
||||
strokeWidth={3}
|
||||
d="M6 30V12a6 6 0 0 1 6-6h18m128 24V12a6 6 0 0 0-6-6h-18M6 134v18a6 6 0 0 0 6 6h18m128-24v18a6 6 0 0 1-6 6h-18"
|
||||
/>
|
||||
{qrBase64 ? (
|
||||
<Image
|
||||
href={`data:image/png;base64,${qrBase64}`}
|
||||
x={12}
|
||||
y={12}
|
||||
width={140}
|
||||
height={140}
|
||||
|
||||
{/* QR Placeholder / Live QR */}
|
||||
<G transform="translate(108 206)">
|
||||
<Rect
|
||||
width={164}
|
||||
height={164}
|
||||
fill="#fff"
|
||||
stroke="#dce5ea"
|
||||
strokeWidth={1.2}
|
||||
rx={16}
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
<Rect
|
||||
width={140}
|
||||
height={140}
|
||||
<Path
|
||||
fill="none"
|
||||
stroke="#003554"
|
||||
strokeLinecap="round"
|
||||
strokeWidth={3}
|
||||
d="M6 30V12a6 6 0 0 1 6-6h18m128 24V12a6 6 0 0 0-6-6h-18M6 134v18a6 6 0 0 0 6 6h18m128-24v18a6 6 0 0 1-6 6h-18"
|
||||
/>
|
||||
{qrBase64 ? (
|
||||
<Image
|
||||
href={`data:image/png;base64,${qrBase64}`}
|
||||
x={12}
|
||||
y={12}
|
||||
fill="#fafcfd"
|
||||
stroke="#003554"
|
||||
strokeDasharray="4 3"
|
||||
strokeOpacity={0.2}
|
||||
rx={10}
|
||||
width={140}
|
||||
height={140}
|
||||
/>
|
||||
<Text
|
||||
x={82}
|
||||
y={87}
|
||||
fill="#003554"
|
||||
fontFamily="Inter, Arial, sans-serif"
|
||||
fontSize={11}
|
||||
fontWeight={700}
|
||||
letterSpacing={1}
|
||||
textAnchor="middle"
|
||||
>
|
||||
{"QR KOD ALANI"}
|
||||
</Text>
|
||||
</>
|
||||
)}
|
||||
</G>
|
||||
) : (
|
||||
<>
|
||||
<Rect
|
||||
width={140}
|
||||
height={140}
|
||||
x={12}
|
||||
y={12}
|
||||
fill="#fafcfd"
|
||||
stroke="#003554"
|
||||
strokeDasharray="4 3"
|
||||
strokeOpacity={0.2}
|
||||
rx={10}
|
||||
/>
|
||||
<Text
|
||||
x={82}
|
||||
y={87}
|
||||
fill="#003554"
|
||||
fontFamily="System, sans-serif"
|
||||
fontSize={11}
|
||||
fontWeight={700}
|
||||
letterSpacing={1}
|
||||
textAnchor="middle"
|
||||
>
|
||||
{"QR KOD ALANI"}
|
||||
</Text>
|
||||
</>
|
||||
)}
|
||||
</G>
|
||||
|
||||
{/* Metinler */}
|
||||
<G fill="#003554" textAnchor="middle">
|
||||
{/* Masa Numarası */}
|
||||
{showTableNo && tableNo ? (
|
||||
<Text
|
||||
x={190}
|
||||
y={40}
|
||||
fill="#003554"
|
||||
fontFamily={fontFamily}
|
||||
fontSize={11}
|
||||
fontWeight={800}
|
||||
letterSpacing={1.5}
|
||||
>
|
||||
{tableNo}
|
||||
</Text>
|
||||
) : null}
|
||||
{/* Metinler */}
|
||||
<G fill="#003554" textAnchor="middle">
|
||||
{/* Masa Numarası */}
|
||||
{table?.visible !== false &&
|
||||
renderSvgLines({
|
||||
text: table?.text || "MASA NO: 01",
|
||||
x: 190,
|
||||
y: 40,
|
||||
fill: "#003554",
|
||||
fontFamily: infoFont,
|
||||
fontSize: table?.fontSize || 11,
|
||||
fontWeight: "bold",
|
||||
letterSpacing: 1.5,
|
||||
})}
|
||||
|
||||
{/* Restoran Başlığı */}
|
||||
{restaurantName ? (
|
||||
<Text
|
||||
x={190}
|
||||
y={86}
|
||||
fill="#003554"
|
||||
fontFamily={fontFamily}
|
||||
fontSize={24}
|
||||
fontWeight={900}
|
||||
letterSpacing={1}
|
||||
>
|
||||
{restaurantName}
|
||||
</Text>
|
||||
) : null}
|
||||
{/* Restoran Başlığı */}
|
||||
{rName?.visible !== false &&
|
||||
renderSvgLines({
|
||||
text: rName?.text || "THE URBAN FORK",
|
||||
x: 190,
|
||||
y: 86,
|
||||
fill: "#003554",
|
||||
fontFamily: rNameFont,
|
||||
fontSize: rName?.fontSize || 24,
|
||||
fontWeight: "bold",
|
||||
letterSpacing: 1,
|
||||
})}
|
||||
|
||||
{/* Yönlendirme (CTA) */}
|
||||
{showCta && ctaText ? (
|
||||
<Text
|
||||
x={190}
|
||||
y={160}
|
||||
fill="#003554"
|
||||
fontFamily={fontFamily}
|
||||
fontSize={13}
|
||||
fontWeight={800}
|
||||
letterSpacing={0.5}
|
||||
>
|
||||
{ctaText}
|
||||
</Text>
|
||||
) : null}
|
||||
{/* Yönlendirme (CTA) */}
|
||||
{cta?.visible !== false &&
|
||||
renderSvgLines({
|
||||
text: cta?.text || "DİJİTAL MENÜYÜ GÖRÜNTÜLE",
|
||||
x: 190,
|
||||
y: 160,
|
||||
fill: "#003554",
|
||||
fontFamily: ctaFont,
|
||||
fontSize: cta?.fontSize || 13,
|
||||
fontWeight: "bold",
|
||||
letterSpacing: 0.5,
|
||||
})}
|
||||
|
||||
{/* Slogan */}
|
||||
{showSubtitle && subtitle ? (
|
||||
<Text
|
||||
x={190}
|
||||
y={402}
|
||||
fill="#003554"
|
||||
fontFamily={fontFamily}
|
||||
fontSize={14}
|
||||
fontWeight={900}
|
||||
letterSpacing={0.8}
|
||||
>
|
||||
{subtitle}
|
||||
</Text>
|
||||
) : null}
|
||||
{/* Slogan (Enter ile çok satır olabilir) */}
|
||||
{sub?.visible !== false &&
|
||||
renderSvgLines({
|
||||
text: sub?.text || "FRESH FLAVORS DAILY",
|
||||
x: 190,
|
||||
y: 402,
|
||||
fill: "#003554",
|
||||
fontFamily: subFont,
|
||||
fontSize: sub?.fontSize || 13,
|
||||
fontWeight: "bold",
|
||||
letterSpacing: 0.8,
|
||||
})}
|
||||
|
||||
{/* WiFi */}
|
||||
{showWifi && wifiText ? (
|
||||
<Text
|
||||
x={190}
|
||||
y={430}
|
||||
fill="#003554"
|
||||
fontFamily="System, -apple-system, Roboto, sans-serif"
|
||||
fontSize={10}
|
||||
fontWeight={700}
|
||||
letterSpacing={0.2}
|
||||
>
|
||||
{wifiText}
|
||||
</Text>
|
||||
) : null}
|
||||
{/* WiFi */}
|
||||
{wifi?.visible !== false &&
|
||||
renderSvgLines({
|
||||
text: wifi?.text || "WiFi: UrbanFork | Şifre: urban2026",
|
||||
x: 190,
|
||||
y: 430,
|
||||
fill: "#003554",
|
||||
fontFamily: infoFont,
|
||||
fontSize: wifi?.fontSize || 10,
|
||||
fontWeight: 700,
|
||||
letterSpacing: 0.2,
|
||||
})}
|
||||
|
||||
{/* Sosyal Medya */}
|
||||
{showSocial && socialText ? (
|
||||
<Text
|
||||
x={190}
|
||||
y={454}
|
||||
fill="#003554"
|
||||
fontFamily="System, -apple-system, Roboto, sans-serif"
|
||||
fontSize={10}
|
||||
fontWeight={700}
|
||||
letterSpacing={0.2}
|
||||
>
|
||||
{socialText}
|
||||
</Text>
|
||||
) : null}
|
||||
</G>
|
||||
</Svg>
|
||||
);
|
||||
{/* Sosyal Medya */}
|
||||
{social?.visible !== false &&
|
||||
renderSvgLines({
|
||||
text: social?.text || "@theurbanfork",
|
||||
x: 190,
|
||||
y: 454,
|
||||
fill: "#003554",
|
||||
fontFamily: infoFont,
|
||||
fontSize: social?.fontSize || 10,
|
||||
fontWeight: 700,
|
||||
letterSpacing: 0.2,
|
||||
})}
|
||||
</G>
|
||||
</Svg>
|
||||
);
|
||||
};
|
||||
|
||||
export default QrTemplate5;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
import type React from "react";
|
||||
import type { SvgProps } from "react-native-svg";
|
||||
import QrTemplate1 from "./QrTemplateLumiere";
|
||||
import QrTemplate2 from "./QrTemplate2";
|
||||
import QrTemplate3 from "./QrTemplate3";
|
||||
import QrTemplate4 from "./QrTemplate4";
|
||||
import QrTemplate5 from "./QrTemplate5";
|
||||
|
||||
export interface QrCustomTextConfig {
|
||||
restaurantName?: string;
|
||||
subtitle?: string;
|
||||
tableNo?: string;
|
||||
ctaText?: string;
|
||||
wifiText?: string;
|
||||
socialText?: string;
|
||||
fontFamily?: string;
|
||||
// Görünürlük anahtarları
|
||||
showTableNo?: boolean;
|
||||
showSubtitle?: boolean;
|
||||
showCta?: boolean;
|
||||
showWifi?: boolean;
|
||||
showSocial?: boolean;
|
||||
}
|
||||
|
||||
export interface QrTemplateProps extends SvgProps, QrCustomTextConfig {
|
||||
qrBase64?: string;
|
||||
}
|
||||
|
||||
// Türkçe karakterleri (İ, ı, Ş, ş, Ğ, ğ, Ü, ü, Ö, ö, Ç, ç) eksiksiz destekleyen sistem fontları
|
||||
export const FONT_OPTIONS = [
|
||||
{
|
||||
id: "sans",
|
||||
label: "Modern Sans (Sistem)",
|
||||
fontFamily: "System, -apple-system, Roboto, 'Helvetica Neue', Arial, sans-serif",
|
||||
},
|
||||
{
|
||||
id: "serif",
|
||||
label: "Zarif Serif (Georgia)",
|
||||
fontFamily: "Georgia, 'Times New Roman', serif",
|
||||
},
|
||||
{
|
||||
id: "times",
|
||||
label: "Klasik (Times New Roman)",
|
||||
fontFamily: "'Times New Roman', Times, Georgia, serif",
|
||||
},
|
||||
{
|
||||
id: "palatino",
|
||||
label: "Lüks Palatino",
|
||||
fontFamily: "Palatino, 'Palatino Linotype', Georgia, serif",
|
||||
},
|
||||
{
|
||||
id: "trebuchet",
|
||||
label: "Dinamik (Trebuchet)",
|
||||
fontFamily: "'Trebuchet MS', 'Segoe UI', Arial, sans-serif",
|
||||
},
|
||||
];
|
||||
|
||||
// Yeni component eklemek için buraya import edip COMPONENT_TEMPLATES'e kaydet
|
||||
export const COMPONENT_TEMPLATES: Record<
|
||||
string,
|
||||
React.FC<QrTemplateProps>
|
||||
> = {
|
||||
"qr-1": QrTemplate1,
|
||||
"qr-2": QrTemplate2,
|
||||
"qr-3": QrTemplate3,
|
||||
"qr-4": QrTemplate4,
|
||||
"qr-5": QrTemplate5,
|
||||
};
|
||||
|
||||
// Her template'in aspect ratio'su (width/height)
|
||||
export const TEMPLATE_ASPECT_RATIOS: Record<string, number> = {
|
||||
"qr-1": 1, // 600x600 = 1:1
|
||||
"qr-2": 400 / 650, // 400x650 = standart kart
|
||||
"qr-3": 400 / 650, // 400x650 = standart kart
|
||||
"qr-4": 400 / 580, // 400x580 = zarif altın çerçeve
|
||||
"qr-5": 380 / 500, // 380x500 = PNG arka planlı modern kart
|
||||
};
|
||||
@@ -0,0 +1,133 @@
|
||||
import React from "react";
|
||||
import { Text as SvgText, type SvgProps } from "react-native-svg";
|
||||
import QrTemplate1 from "./QrTemplateLumiere";
|
||||
import QrTemplate2 from "./QrTemplate2";
|
||||
import QrTemplate3 from "./QrTemplate3";
|
||||
import QrTemplate4 from "./QrTemplate4";
|
||||
import QrTemplate5 from "./QrTemplate5";
|
||||
|
||||
export interface TextItemConfig {
|
||||
text: string;
|
||||
fontSize?: number;
|
||||
fontId?: string;
|
||||
visible?: boolean;
|
||||
}
|
||||
|
||||
export interface QrCustomFields {
|
||||
restaurantName: TextItemConfig;
|
||||
subtitle: TextItemConfig;
|
||||
tableNo: TextItemConfig;
|
||||
ctaText: TextItemConfig;
|
||||
wifiText: TextItemConfig;
|
||||
socialText: TextItemConfig;
|
||||
}
|
||||
|
||||
export interface QrTemplateProps extends SvgProps {
|
||||
qrBase64?: string;
|
||||
fields?: Partial<QrCustomFields>;
|
||||
}
|
||||
|
||||
// Türkçe karakterleri (İ, ı, Ş, ş, Ğ, ğ, Ü, ü, Ö, ö, Ç, ç) eksiksiz destekleyen sistem fontları
|
||||
export const FONT_OPTIONS = [
|
||||
{
|
||||
id: "sans",
|
||||
label: "Modern Sans",
|
||||
fontFamily: "System, -apple-system, Roboto, 'Helvetica Neue', Arial, sans-serif",
|
||||
},
|
||||
{
|
||||
id: "serif",
|
||||
label: "Zarif Serif",
|
||||
fontFamily: "Georgia, 'Times New Roman', serif",
|
||||
},
|
||||
{
|
||||
id: "times",
|
||||
label: "Klasik (Times)",
|
||||
fontFamily: "'Times New Roman', Times, Georgia, serif",
|
||||
},
|
||||
{
|
||||
id: "palatino",
|
||||
label: "Lüks Palatino",
|
||||
fontFamily: "Palatino, 'Palatino Linotype', Georgia, serif",
|
||||
},
|
||||
{
|
||||
id: "trebuchet",
|
||||
label: "Dinamik",
|
||||
fontFamily: "'Trebuchet MS', 'Segoe UI', Arial, sans-serif",
|
||||
},
|
||||
];
|
||||
|
||||
export function getFontFamily(fontId?: string, defaultFamily = "Georgia, serif"): string {
|
||||
if (!fontId) return defaultFamily;
|
||||
const found = FONT_OPTIONS.find((f) => f.id === fontId);
|
||||
return found ? found.fontFamily : defaultFamily;
|
||||
}
|
||||
|
||||
// Çok satırlı (Enter / \n) metinleri SVG içinde alt alta kusursuz render eden yardımcı fonksiyon
|
||||
export function renderSvgLines({
|
||||
text,
|
||||
x,
|
||||
y,
|
||||
lineHeight,
|
||||
fill,
|
||||
fontFamily,
|
||||
fontSize,
|
||||
fontWeight = "normal",
|
||||
letterSpacing,
|
||||
textAnchor = "middle",
|
||||
}: {
|
||||
text?: string;
|
||||
x: number;
|
||||
y: number;
|
||||
lineHeight?: number;
|
||||
fill?: string;
|
||||
fontFamily?: string;
|
||||
fontSize?: number;
|
||||
fontWeight?: string | number;
|
||||
letterSpacing?: number;
|
||||
textAnchor?: "middle" | "start" | "end";
|
||||
}) {
|
||||
if (!text) return null;
|
||||
const lines = text.split("\n");
|
||||
const computedLineHeight = lineHeight || (fontSize ? fontSize * 1.25 : 18);
|
||||
|
||||
return (
|
||||
<>
|
||||
{lines.map((line, idx) => (
|
||||
<SvgText
|
||||
key={idx}
|
||||
x={x}
|
||||
y={y + idx * computedLineHeight}
|
||||
fill={fill}
|
||||
fontFamily={fontFamily}
|
||||
fontSize={fontSize}
|
||||
fontWeight={fontWeight}
|
||||
letterSpacing={letterSpacing}
|
||||
textAnchor={textAnchor}
|
||||
>
|
||||
{line}
|
||||
</SvgText>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
// Yeni component eklemek için buraya import edip COMPONENT_TEMPLATES'e kaydet
|
||||
export const COMPONENT_TEMPLATES: Record<
|
||||
string,
|
||||
React.FC<QrTemplateProps>
|
||||
> = {
|
||||
"qr-1": QrTemplate1,
|
||||
"qr-2": QrTemplate2,
|
||||
"qr-3": QrTemplate3,
|
||||
"qr-4": QrTemplate4,
|
||||
"qr-5": QrTemplate5,
|
||||
};
|
||||
|
||||
// Her template'in aspect ratio'su (width/height)
|
||||
export const TEMPLATE_ASPECT_RATIOS: Record<string, number> = {
|
||||
"qr-1": 1, // 600x600 = 1:1
|
||||
"qr-2": 400 / 650, // 400x650 = standart kart
|
||||
"qr-3": 400 / 650, // 400x650 = standart kart
|
||||
"qr-4": 400 / 580, // 400x580 = zarif altın çerçeve
|
||||
"qr-5": 380 / 500, // 380x500 = PNG arka planlı modern kart
|
||||
};
|
||||
Reference in New Issue
Block a user