"use client"; import { useEffect, useRef, useState } from "react"; import Image from "next/image"; import { Blocks, Brain, Building2, ImageIcon, Key, Monitor, Moon, Palette, Save, Shield, Sun, Trash2, Upload, User, } from "lucide-react"; import { loadSettings, removeWorkspaceLogo, saveAiSettings, saveColorMode, saveWorkspaceBranding, updatePassword, updateProfile, } from "./actions"; import { Button, Card, CardContent, Input, Label, RadioGroup, RadioGroupItem, } from "poyraz-ui/atoms"; import { toast } from "poyraz-ui/molecules"; import { applyColorMode } from "@/components/theme/color-mode-sync"; import { isColorMode, type ColorMode } from "@/lib/color-mode"; type AiProvider = "groq" | "ollama" | "openai" | "gemini"; const colorModeOptions = [ { value: "light", label: "Açık", description: "Her zaman aydınlık renk paletini kullanır.", icon: Sun, }, { value: "dark", label: "Koyu", description: "Her zaman koyu renk paletini kullanır.", icon: Moon, }, { value: "system", label: "Sistem", description: "Cihazınızın görünüm tercihini otomatik takip eder.", icon: Monitor, }, ] satisfies Array<{ value: ColorMode; label: string; description: string; icon: typeof Sun; }>; export default function SettingsPage() { const [activeTab, setActiveTab] = useState("Workspace"); // Profile States const [firstName, setFirstName] = useState(""); const [lastName, setLastName] = useState(""); const [avatarUrl, setAvatarUrl] = useState(""); // Security States const formRef = useRef(null); // AI States const [aiProvider, setAiProvider] = useState("gemini"); const [apiKey, setApiKey] = useState(""); const [hasApiKey, setHasApiKey] = useState(false); const [colorMode, setColorMode] = useState("system"); const [isSavingColorMode, setIsSavingColorMode] = useState(false); const [workspaceName, setWorkspaceName] = useState("Neta"); const [primaryColor, setPrimaryColor] = useState("#C81E1E"); const [logoUrl, setLogoUrl] = useState(""); const [pendingLogoUrl, setPendingLogoUrl] = useState(""); const [hasCustomLogo, setHasCustomLogo] = useState(false); const [isSavingBranding, setIsSavingBranding] = useState(false); const logoObjectUrlRef = useRef(null); const tabs = [ { name: "Workspace", icon: Building2 }, { name: "Profile & Account", icon: User }, { name: "Görünüm", icon: Palette }, { name: "AI Preferences", icon: Brain }, { name: "Security", icon: Shield }, ]; useEffect(() => { let isActive = true; const fetchData = async () => { const settings = await loadSettings(); if (!isActive) return; setFirstName(settings.firstName); setLastName(settings.lastName); setAvatarUrl(settings.avatarUrl); setAiProvider(settings.aiProvider); setHasApiKey(settings.hasApiKey); setColorMode(settings.colorMode); setWorkspaceName(settings.workspaceName); setPrimaryColor(settings.primaryColor); setLogoUrl(settings.logoUrl); setHasCustomLogo(settings.hasCustomLogo); }; void fetchData(); return () => { isActive = false; }; }, []); useEffect(() => { return () => { if (logoObjectUrlRef.current) URL.revokeObjectURL(logoObjectUrlRef.current); }; }, []); const handleProfileAction = async (formData: FormData) => { const response = await updateProfile(formData); if (response?.error) { toast.error(`Hata: ${response.error}`); } else { toast.success("Profil güncellendi!"); const avatar = formData.get("avatar"); if (avatar instanceof File && avatar.size > 0) window.location.reload(); } }; const handlePasswordAction = async (formData: FormData) => { const response = await updatePassword(formData); if (response?.error) { toast.error(`Hata: ${response.error}`); } else { toast.success("Şifre güncellendi!"); formRef.current?.reset(); } }; const handleSaveAI = async () => { const response = await saveAiSettings(aiProvider, apiKey); if (response.error) { toast.error(response.error); return; } setHasApiKey(Boolean(response.hasApiKey)); setApiKey(""); toast.success("Yapay Zeka ayarları kaydedildi!"); }; const handleColorModeChange = async (value: string) => { if (!isColorMode(value) || value === colorMode || isSavingColorMode) return; const previousColorMode = colorMode; setColorMode(value); applyColorMode(value); setIsSavingColorMode(true); try { const response = await saveColorMode(value); if (response.error) { setColorMode(previousColorMode); applyColorMode(previousColorMode); toast.error(response.error); return; } toast.success("Görünüm tercihi kaydedildi."); } finally { setIsSavingColorMode(false); } }; const handleLogoChange = (event: React.ChangeEvent) => { if (logoObjectUrlRef.current) URL.revokeObjectURL(logoObjectUrlRef.current); const file = event.target.files?.[0]; const objectUrl = file ? URL.createObjectURL(file) : ""; logoObjectUrlRef.current = objectUrl || null; setPendingLogoUrl(objectUrl); }; const handleWorkspaceBrandingAction = async (formData: FormData) => { setIsSavingBranding(true); try { const response = await saveWorkspaceBranding(formData); if (response.error) { toast.error(response.error); return; } toast.success("Workspace görünümü güncellendi."); window.location.reload(); } finally { setIsSavingBranding(false); } }; const handleRemoveWorkspaceLogo = async () => { setIsSavingBranding(true); try { const response = await removeWorkspaceLogo(); if (response.error) { toast.error(response.error); return; } setLogoUrl(""); setPendingLogoUrl(""); setHasCustomLogo(false); toast.success("Workspace logosu kaldırıldı."); window.location.reload(); } finally { setIsSavingBranding(false); } }; return (

Ayarlar

Workspace markanızı, profilinizi, görünümü ve sistem tercihlerinizi yönetin.

{/* Settings Sidebar */}
{tabs.map((tab) => { const Icon = tab.icon; return ( ) })}
{/* Settings Content Area */}
{activeTab === "Workspace" && (

Workspace görünümü

Müşterilerinizin ve sizin gördüğünüz workspace adını, logoyu ve ana rengi yönetin.

Firma, freelance marka veya çalışma alanı adınız.

setWorkspaceName(event.target.value)} minLength={1} maxLength={80} required />

PNG, JPEG, WebP veya GIF; en fazla 5 MB. Şeffaf arka planlı yatay logo önerilir.

{hasCustomLogo ? ( ) : null}
{pendingLogoUrl || logoUrl ? ( Workspace logo önizlemesi ) : (
)}

Bir renk seçin; vurgu, focus ve yumuşak yüzey tonları otomatik türetilir.

setPrimaryColor(event.target.value.toUpperCase())} aria-label="Ana renk seçici" className="h-11 w-16 shrink-0 cursor-pointer p-1" /> setPrimaryColor(event.target.value.toUpperCase())} pattern="^#[0-9A-Fa-f]{6}$" maxLength={7} placeholder="#C81E1E" required className="font-mono uppercase" />
)} {activeTab === "Profile & Account" && (

Kullanıcı Profili

{avatarUrl ? ( Avatar ) : (
)}
setFirstName(e.target.value)} />
setLastName(e.target.value)} />
)} {activeTab === "Security" && (

Şifre İşlemleri

)} {activeTab === "Görünüm" && (

Tema görünümü

Neta arayüzünün açık, koyu veya cihazınızla uyumlu görünmesini seçin.

{colorModeOptions.map((option) => { const Icon = option.icon; const selected = colorMode === option.value; return ( ); })}

{isSavingColorMode ? "Görünüm tercihi kaydediliyor…" : "Değişiklik tüm Neta sayfalarına anında uygulanır."}

)} {activeTab === "AI Preferences" && (

AI Asistan Konfigürasyonu

Model ve Sağlayıcı Seçimi

{aiProvider !== "ollama" && (

API Keys

setApiKey(e.target.value)} placeholder={hasApiKey ? "Kayıtlı anahtarı korumak için boş bırakın" : "sk-..."} />
)}
)} {["Integrations", "Notifications", "Billing & Plans"].includes(activeTab) && (

{activeTab}

Bu bölüm şu an geliştirme aşamasındadır.

)}
); }