feat: admin auth, web menu template studio, live text editing & Ayris Tech footer backlink

This commit is contained in:
AyrisAI
2026-08-23 01:45:00 +03:00
parent e7ba6c7807
commit 1f8195ff67
48 changed files with 5588 additions and 402 deletions
@@ -3,6 +3,7 @@ import {
Pressable,
ScrollView,
Text,
TextInput,
View,
} from "react-native";
import { Ionicons } from "@expo/vector-icons";
@@ -14,6 +15,7 @@ import { InstagramTextEditorModal } from "./InstagramTextEditorModal";
import {
type CanvasTextLayer,
type CanvasQrConfig,
CANVAS_FONT_OPTIONS,
QR_SIZE_PRESETS,
QR_RADIUS_PRESETS,
getDefaultLayersForTemplate,
@@ -537,7 +539,79 @@ export const QrCanvasStudio: React.FC<QrCanvasStudioProps> = ({
</View>
</View>
{/* Alt Sıra: Hızlı Döndürme Açısı Hapları */}
{/* Hızlı Metin Değiştirme Girdisi */}
<View
style={{
flexDirection: "row",
alignItems: "center",
gap: 8,
backgroundColor: "#0C0C0E",
borderRadius: 12,
paddingHorizontal: 10,
paddingVertical: 6,
borderWidth: 1,
borderColor: "rgba(212, 175, 55, 0.4)",
}}
>
<Ionicons name="text-outline" size={14} color="#D4AF37" />
<TextInput
value={selectedLayer.text}
onChangeText={(newText: string) => {
onLayersChange((prev) =>
prev.map((l) => (l.id === selectedLayer.id ? { ...l, text: newText } : l))
);
}}
placeholder="Metin yazın..."
placeholderTextColor="#71717A"
style={{
flex: 1,
color: "#FFFFFF",
fontSize: 13,
fontWeight: "700",
padding: 0,
}}
/>
</View>
{/* Alt Sıra 1: Font Stili Seçici */}
<View style={{ flexDirection: "row", alignItems: "center", gap: 6 }}>
<Text style={{ color: "#71717A", fontSize: 10, fontWeight: "700" }}>FONT:</Text>
<ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={{ gap: 6 }}>
{CANVAS_FONT_OPTIONS.map((f) => {
const isActive = (selectedLayer.fontId || "sans") === f.id;
return (
<Pressable
key={f.id}
onPress={() => {
try { Haptics.selectionAsync(); } catch {}
onLayersChange((prev) =>
prev.map((l) => (l.id === selectedLayer.id ? { ...l, fontId: f.id } : l))
);
}}
style={{
paddingHorizontal: 10,
paddingVertical: 4,
borderRadius: 10,
backgroundColor: isActive ? "#D4AF37" : "#242429",
}}
>
<Text
style={{
color: isActive ? "#0C0C0E" : "#FFFFFF",
fontSize: 10.5,
fontWeight: isActive ? "900" : "700",
fontFamily: f.fontFamily,
}}
>
{f.label}
</Text>
</Pressable>
);
})}
</ScrollView>
</View>
{/* Alt Sıra 2: Hızlı Döndürme Açısı Hapları */}
<View style={{ flexDirection: "row", alignItems: "center", gap: 6 }}>
<Text style={{ color: "#71717A", fontSize: 10, fontWeight: "700" }}>EĞİM:</Text>
<ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={{ gap: 6 }}>
@@ -573,6 +647,94 @@ export const QrCanvasStudio: React.FC<QrCanvasStudioProps> = ({
})}
</ScrollView>
</View>
{/* Alt Sıra 3: Kavis (Eğri Yazı) Stepper & Preset Hapları */}
<View style={{ flexDirection: "row", alignItems: "center", gap: 6 }}>
<Text style={{ color: "#71717A", fontSize: 10, fontWeight: "700" }}>KAVİS:</Text>
{/* Stepper Butonları (- / +) */}
<View style={{ flexDirection: "row", alignItems: "center", backgroundColor: "#242429", borderRadius: 10, paddingHorizontal: 4, paddingVertical: 2, gap: 4 }}>
<Pressable
onPress={() => {
try { Haptics.selectionAsync(); } catch {}
onLayersChange((prev) =>
prev.map((l) =>
l.id === selectedLayer.id
? { ...l, curveDegree: Math.max(-100, (l.curveDegree || 0) - 5) }
: l
)
);
}}
hitSlop={{ top: 6, bottom: 6, left: 6, right: 6 }}
style={{ width: 22, height: 22, borderRadius: 11, backgroundColor: "rgba(255,255,255,0.12)", alignItems: "center", justifyContent: "center" }}
>
<Ionicons name="remove" size={13} color="#FFFFFF" />
</Pressable>
<Text style={{ color: "#D4AF37", fontSize: 11, fontWeight: "900", minWidth: 30, textAlign: "center" }}>
{(selectedLayer.curveDegree || 0)}°
</Text>
<Pressable
onPress={() => {
try { Haptics.selectionAsync(); } catch {}
onLayersChange((prev) =>
prev.map((l) =>
l.id === selectedLayer.id
? { ...l, curveDegree: Math.min(100, (l.curveDegree || 0) + 5) }
: l
)
);
}}
hitSlop={{ top: 6, bottom: 6, left: 6, right: 6 }}
style={{ width: 22, height: 22, borderRadius: 11, backgroundColor: "rgba(255,255,255,0.12)", alignItems: "center", justifyContent: "center" }}
>
<Ionicons name="add" size={13} color="#FFFFFF" />
</Pressable>
</View>
{/* Hazır Kavis Presetleri */}
<ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={{ gap: 6 }}>
{[
{ label: "0° (Düz)", deg: 0 },
{ label: "20° ◠", deg: 20 },
{ label: "35° ◠", deg: 35 },
{ label: "50° ◠", deg: 50 },
{ label: "70° ◠", deg: 70 },
{ label: "-35° ◡", deg: -35 },
{ label: "-50° ◡", deg: -50 },
].map((item) => {
const isActive = (selectedLayer.curveDegree || 0) === item.deg;
return (
<Pressable
key={item.deg}
onPress={() => {
try { Haptics.selectionAsync(); } catch {}
onLayersChange((prev) =>
prev.map((l) => (l.id === selectedLayer.id ? { ...l, curveDegree: item.deg } : l))
);
}}
style={{
paddingHorizontal: 9,
paddingVertical: 4,
borderRadius: 10,
backgroundColor: isActive ? "#D4AF37" : "#242429",
}}
>
<Text
style={{
color: isActive ? "#0C0C0E" : "#FFFFFF",
fontSize: 10.5,
fontWeight: isActive ? "800" : "600",
}}
>
{item.label}
</Text>
</Pressable>
);
})}
</ScrollView>
</View>
</View>
)}