first commit
This commit is contained in:
@@ -0,0 +1,226 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { router } from "expo-router";
|
||||
import {
|
||||
ActivityIndicator,
|
||||
Image,
|
||||
Pressable,
|
||||
ScrollView,
|
||||
Share,
|
||||
Text,
|
||||
View,
|
||||
} from "react-native";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import * as Clipboard from "expo-clipboard";
|
||||
import { api } from "@/lib/api";
|
||||
import { getActiveRestaurant, type ActiveRestaurant } from "@/lib/active-restaurant";
|
||||
|
||||
interface QrResponse {
|
||||
id: string;
|
||||
redirectUrl: string;
|
||||
targetUrl: string;
|
||||
pngBase64: string;
|
||||
}
|
||||
|
||||
export default function QrScreen() {
|
||||
const [active, setActive] = useState<ActiveRestaurant | null>(null);
|
||||
const [qr, setQr] = useState<QrResponse | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [copied, setCopied] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
const activeRest = await getActiveRestaurant();
|
||||
if (!activeRest) return;
|
||||
setActive(activeRest);
|
||||
|
||||
try {
|
||||
const data = await api.post<QrResponse>(`/restaurants/${activeRest.restaurantId}/qr`);
|
||||
setQr(data);
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : "QR oluşturulamadı");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
})();
|
||||
}, []);
|
||||
|
||||
async function handleCopy() {
|
||||
if (!qr?.targetUrl) return;
|
||||
await Clipboard.setStringAsync(qr.targetUrl);
|
||||
setCopied(true);
|
||||
setTimeout(() => setCopied(false), 2000);
|
||||
}
|
||||
|
||||
async function handleShare() {
|
||||
if (!qr?.targetUrl) return;
|
||||
await Share.share({
|
||||
title: "Dijital QR Menü",
|
||||
message: `${qr.targetUrl}\nMenümüzü incelemek için QR kodu taratın veya linke tıklayın.`,
|
||||
url: qr.targetUrl,
|
||||
});
|
||||
}
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<View style={{ flex: 1, backgroundColor: "#FAF8F5", alignItems: "center", justifyContent: "center" }}>
|
||||
<ActivityIndicator size="large" color="#C8A96B" />
|
||||
<Text style={{ marginTop: 12, color: "#78716C", fontSize: 14 }}>QR Kod Hazırlanıyor...</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
if (error || !qr) {
|
||||
return (
|
||||
<View style={{ flex: 1, backgroundColor: "#FAF8F5", alignItems: "center", justifyContent: "center", padding: 24 }}>
|
||||
<Ionicons name="alert-circle-outline" size={48} color="#DC2626" style={{ marginBottom: 12 }} />
|
||||
<Text style={{ color: "#DC2626", fontSize: 16, fontWeight: "600", textAlign: "center" }}>
|
||||
{error ?? "QR kod yüklenemedi"}
|
||||
</Text>
|
||||
<Pressable
|
||||
onPress={() => router.back()}
|
||||
style={{ marginTop: 20, backgroundColor: "#1C1917", paddingHorizontal: 20, paddingVertical: 10, borderRadius: 8 }}
|
||||
>
|
||||
<Text style={{ color: "#FFF", fontWeight: "600" }}>Geri Dön</Text>
|
||||
</Pressable>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<ScrollView contentContainerStyle={{ flexGrow: 1, backgroundColor: "#FAF8F5", padding: 24, justifyContent: "center" }}>
|
||||
<View style={{ maxWidth: 440, width: "100%", alignSelf: "center", alignItems: "center" }}>
|
||||
{/* Header Badge */}
|
||||
<View
|
||||
style={{
|
||||
backgroundColor: "#F3EDE2",
|
||||
paddingHorizontal: 14,
|
||||
paddingVertical: 6,
|
||||
borderRadius: 99,
|
||||
marginBottom: 16,
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
gap: 6,
|
||||
}}
|
||||
>
|
||||
<Ionicons name="qr-code-outline" size={15} color="#926E27" />
|
||||
<Text style={{ color: "#926E27", fontSize: 12, fontWeight: "700" }}>
|
||||
DİJİTAL RESTORAN QR KODU
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<Text style={{ fontSize: 26, fontWeight: "800", color: "#1C1917", marginBottom: 6, textAlign: "center" }}>
|
||||
Masanıza Özel QR Kod
|
||||
</Text>
|
||||
<Text style={{ fontSize: 14, color: "#78716C", textAlign: "center", marginBottom: 28, lineHeight: 20 }}>
|
||||
Müşterileriniz bu QR kodu telefon kameralarıyla taratarak saniyeler içinde menünüzü inceleyebilir.
|
||||
</Text>
|
||||
|
||||
{/* QR Code Container Card */}
|
||||
<View
|
||||
style={{
|
||||
backgroundColor: "#FFFFFF",
|
||||
borderRadius: 24,
|
||||
padding: 24,
|
||||
alignItems: "center",
|
||||
shadowColor: "#000",
|
||||
shadowOffset: { width: 0, height: 8 },
|
||||
shadowOpacity: 0.08,
|
||||
shadowRadius: 24,
|
||||
elevation: 8,
|
||||
borderWidth: 1,
|
||||
borderColor: "rgba(200, 169, 107, 0.25)",
|
||||
marginBottom: 24,
|
||||
}}
|
||||
>
|
||||
<Image
|
||||
source={{ uri: `data:image/png;base64,${qr.pngBase64}` }}
|
||||
style={{ width: 220, height: 220, borderRadius: 12 }}
|
||||
resizeMode="contain"
|
||||
/>
|
||||
|
||||
<View
|
||||
style={{
|
||||
marginTop: 16,
|
||||
paddingVertical: 6,
|
||||
paddingHorizontal: 14,
|
||||
backgroundColor: "#FAF8F5",
|
||||
borderRadius: 8,
|
||||
borderWidth: 1,
|
||||
borderColor: "#E7E5E4",
|
||||
}}
|
||||
>
|
||||
<Text style={{ fontSize: 13, fontWeight: "600", color: "#1C1917" }}>
|
||||
{qr.targetUrl}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* Action Buttons */}
|
||||
<View style={{ width: "100%", gap: 12 }}>
|
||||
{/* Share Button */}
|
||||
<Pressable
|
||||
onPress={handleShare}
|
||||
style={({ pressed }) => ({
|
||||
backgroundColor: "#1C1917",
|
||||
borderRadius: 14,
|
||||
padding: 16,
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
gap: 10,
|
||||
opacity: pressed ? 0.9 : 1,
|
||||
shadowColor: "#000",
|
||||
shadowOffset: { width: 0, height: 4 },
|
||||
shadowOpacity: 0.1,
|
||||
shadowRadius: 10,
|
||||
elevation: 4,
|
||||
})}
|
||||
>
|
||||
<Ionicons name="share-social-outline" size={18} color="#FFFFFF" />
|
||||
<Text style={{ color: "#FFFFFF", fontSize: 15, fontWeight: "700" }}>
|
||||
QR Kodu ve Linki Paylaş
|
||||
</Text>
|
||||
</Pressable>
|
||||
|
||||
{/* Copy Link Button */}
|
||||
<Pressable
|
||||
onPress={handleCopy}
|
||||
style={({ pressed }) => ({
|
||||
backgroundColor: "#FFFFFF",
|
||||
borderWidth: 1.5,
|
||||
borderColor: "#E7E5E4",
|
||||
borderRadius: 14,
|
||||
padding: 15,
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
gap: 8,
|
||||
opacity: pressed ? 0.85 : 1,
|
||||
})}
|
||||
>
|
||||
<Ionicons
|
||||
name={copied ? "checkmark-circle-outline" : "copy-outline"}
|
||||
size={18}
|
||||
color={copied ? "#10B981" : "#1C1917"}
|
||||
/>
|
||||
<Text style={{ color: copied ? "#10B981" : "#1C1917", fontSize: 14, fontWeight: "600" }}>
|
||||
{copied ? "Link Kopyalandı!" : "Menü Linkini Kopyala"}
|
||||
</Text>
|
||||
</Pressable>
|
||||
|
||||
{/* Back to Menu Editor */}
|
||||
<Pressable
|
||||
onPress={() => router.back()}
|
||||
style={{ padding: 12, alignItems: "center", flexDirection: "row", justifyContent: "center", gap: 6 }}
|
||||
>
|
||||
<Ionicons name="arrow-back" size={16} color="#78716C" />
|
||||
<Text style={{ color: "#78716C", fontSize: 14, fontWeight: "600" }}>
|
||||
Menü Editörüne Dön
|
||||
</Text>
|
||||
</Pressable>
|
||||
</View>
|
||||
</View>
|
||||
</ScrollView>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user