diff --git a/apps/mobile/src/app/account/index.tsx b/apps/mobile/src/app/account/index.tsx index 76eb751..238ab92 100644 --- a/apps/mobile/src/app/account/index.tsx +++ b/apps/mobile/src/app/account/index.tsx @@ -28,8 +28,17 @@ interface RestaurantDetail { logo_url: string | null; phone: string | null; address: string | null; + enabled_languages?: string[]; } +const SUPPORTED_LANGUAGES: { code: string; label: string; flag: string }[] = [ + { code: "en", label: "İngilizce", flag: "🇬🇧" }, + { code: "de", label: "Almanca", flag: "🇩🇪" }, + { code: "ar", label: "Arapça", flag: "🇸🇦" }, + { code: "ru", label: "Rusça", flag: "🇷🇺" }, + { code: "fr", label: "Fransızca", flag: "🇫🇷" }, +]; + export interface TxtRecord { name: string; value: string; @@ -87,6 +96,10 @@ export default function AccountScreen() { const [selectedTheme, setSelectedTheme] = useState("elegant"); const [savingTheme, setSavingTheme] = useState(false); + // Language / AI Translation state + const [enabledLanguages, setEnabledLanguages] = useState(["tr"]); + const [updatingLanguage, setUpdatingLanguage] = useState(null); + // Custom Domain state const [domains, setDomains] = useState([]); const [newDomainInput, setNewDomainInput] = useState(""); @@ -118,6 +131,7 @@ export default function AccountScreen() { setAddress(rest.address ?? ""); setLogoUrl(rest.logo_url ?? null); setSlug(rest.slug); + setEnabledLanguages(rest.enabled_languages ?? ["tr"]); // Fetch theme const themeRes = await api.get<{ themeKey: string }>(`/restaurants/${cached.restaurantId}/theme`).catch(() => ({ themeKey: "elegant" })); @@ -214,6 +228,54 @@ export default function AccountScreen() { } } + async function handleAddLanguage(code: string, label: string) { + if (!active || updatingLanguage) return; + setUpdatingLanguage(code); + Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium).catch(() => {}); + try { + const res = await api.post<{ enabledLanguages: string[] }>( + `/restaurants/${active.restaurantId}/languages`, + { code }, + ); + setEnabledLanguages(res.enabledLanguages); + Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success).catch(() => {}); + Alert.alert("Menü Çevrildi 🎉", `Menünüz yapay zeka ile ${label} diline çevrildi.`); + } catch (err) { + Alert.alert("Hata", err instanceof Error ? err.message : "Dil eklenemedi."); + } finally { + setUpdatingLanguage(null); + } + } + + async function handleRemoveLanguage(code: string, label: string) { + if (!active || updatingLanguage) return; + Alert.alert( + `${label} Dilini Kaldır`, + "Bu dil menüde artık gösterilmeyecek. Çeviriler saklanacağı için dili tekrar eklerseniz yeniden çevrilmesi gerekmez.", + [ + { text: "Vazgeç", style: "cancel" }, + { + text: "Kaldır", + style: "destructive", + onPress: async () => { + setUpdatingLanguage(code); + try { + const res = await api.delete<{ enabledLanguages: string[] }>( + `/restaurants/${active.restaurantId}/languages/${code}`, + ); + setEnabledLanguages(res.enabledLanguages); + Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success).catch(() => {}); + } catch (err) { + Alert.alert("Hata", err instanceof Error ? err.message : "Dil kaldırılamadı."); + } finally { + setUpdatingLanguage(null); + } + }, + }, + ], + ); + } + async function handleAddCustomDomain() { if (!active || !newDomainInput.trim()) { Alert.alert("Eksik Bilgi", "Lütfen bağlamak istediğiniz alan adını girin (Örn: menu.kebapciahmet.com)"); @@ -605,6 +667,94 @@ export default function AccountScreen() { + {/* Language / AI Translation Section */} + + + + + Diller (Yapay Zeka Çevirisi) + + + + Menünüzü yapay zeka ile otomatik olarak çevirin. Müşterileriniz menüde istedikleri dili seçebilir. + + + + {/* Turkish — always on, base language */} + + 🇹🇷 + Türkçe + + + {SUPPORTED_LANGUAGES.map((lang) => { + const isEnabled = enabledLanguages.includes(lang.code); + const isUpdating = updatingLanguage === lang.code; + return ( + + isEnabled + ? handleRemoveLanguage(lang.code, lang.label) + : handleAddLanguage(lang.code, lang.label) + } + disabled={isUpdating} + style={{ + flexDirection: "row", + alignItems: "center", + gap: 6, + backgroundColor: isEnabled ? "#FDF8F0" : "#FAF8F5", + borderWidth: 1.5, + borderColor: isEnabled ? "#C8A96B" : "#E7E5E4", + paddingHorizontal: 12, + paddingVertical: 8, + borderRadius: 10, + opacity: isUpdating ? 0.6 : 1, + }} + > + {isUpdating ? ( + + ) : ( + {lang.flag} + )} + + {lang.label} + + {isEnabled ? ( + + ) : ( + + )} + + ); + })} + + + {/* Custom Domain Section */}