Files
webmailserver/app/[lang]/dashboard/settings/page.tsx
2026-05-14 22:47:00 +03:00

197 lines
7.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import { useState, useEffect } from "react";
import { useDictionary } from "@/components/DictionaryContext";
import { useSession } from "next-auth/react";
export default function SettingsPage() {
const { data: session } = useSession();
const [profile, setProfile] = useState<any>(null);
const [waStatus, setWaStatus] = useState<any>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const [saving, setSaving] = useState(false);
const [fetchingQr, setFetchingQr] = useState(false);
const dict = useDictionary();
useEffect(() => {
fetchProfile();
fetchWaStatus();
const interval = setInterval(() => {
fetchWaStatus();
}, 5000);
return () => clearInterval(interval);
}, []);
const fetchProfile = async () => {
try {
const res = await fetch("/api/users/profile");
const data = await res.json();
if (data && data.error) setError(data.error);
else if (!data) setError("Kullanıcı profili bulunamadı.");
else setProfile(data);
} catch (e: any) {
setError(e.message);
} finally {
setLoading(false);
}
};
const fetchWaStatus = async () => {
try {
const res = await fetch("/api/whatsapp/status");
const data = await res.json();
setWaStatus(data);
} catch (e) {
console.error(e);
}
};
const handleConnectWa = async () => {
setFetchingQr(true);
try {
const res = await fetch("/api/whatsapp/qr");
const data = await res.json();
setWaStatus(data);
} catch (e) {
console.error(e);
} finally {
setFetchingQr(false);
}
};
const handleSave = async (e: React.FormEvent) => {
e.preventDefault();
setSaving(true);
try {
const res = await fetch("/api/users/profile", {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(profile)
});
if (res.ok) alert("Ayarlar kaydedildi!");
else {
const data = await res.json();
alert("Hata: " + (data?.error || "Bilinmeyen bir hata oluştu."));
}
} catch (e: any) {
alert("Hata: " + e.message);
} finally {
setSaving(false);
}
};
if (loading) return <div className="page-body"><span className="spinner" /></div>;
if (error) return <div className="page-body"><div className="card" style={{ color: "var(--error)" }}>Hata: {error}</div></div>;
if (!profile) return <div className="page-body">Profil yüklenemedi.</div>;
return (
<>
<div className="page-header">
<div>
<h1 className="page-title">Bildirim Ayarları</h1>
<p className="page-subtitle">Telegram ve WhatsApp bildirimlerinizi buradan yönetin.</p>
</div>
</div>
<div className="page-body" style={{ maxWidth: 800 }}>
<form onSubmit={handleSave} className="form-group">
<div className="card">
<h3 style={{ marginBottom: 20, display: "flex", alignItems: "center", gap: 10 }}>
<TelegramIcon /> Telegram Bildirimleri
</h3>
<div style={{ display: "flex", alignItems: "center", gap: 10, marginBottom: 20 }}>
<input
type="checkbox"
id="tg-enabled"
checked={profile.telegramEnabled}
onChange={e => setProfile({...profile, telegramEnabled: e.target.checked})}
/>
<label htmlFor="tg-enabled">Telegram bildirimlerini aktif et</label>
</div>
<div>
<label className="label">Telegram ID</label>
<input
className="input"
value={profile.telegramId || ""}
onChange={e => setProfile({...profile, telegramId: e.target.value})}
placeholder="Örn: 5009005027"
/>
</div>
</div>
<div className="card" style={{ marginTop: 24 }}>
<h3 style={{ marginBottom: 20, display: "flex", alignItems: "center", gap: 10 }}>
<WhatsAppIcon /> WhatsApp Bildirimleri
</h3>
<div style={{ display: "flex", alignItems: "center", gap: 10, marginBottom: 20 }}>
<input
type="checkbox"
id="wa-enabled"
checked={profile.whatsappEnabled}
onChange={e => setProfile({...profile, whatsappEnabled: e.target.checked})}
/>
<label htmlFor="wa-enabled">WhatsApp bildirimlerini aktif et</label>
</div>
<div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 24 }}>
<div>
<label className="label">Telefon Numarası</label>
<input
className="input"
value={profile.whatsappNumber || ""}
onChange={e => setProfile({...profile, whatsappNumber: e.target.value})}
placeholder="90554XXXXXXX"
/>
</div>
<div style={{ borderLeft: "1px solid var(--border)", paddingLeft: 24 }}>
<label className="label">Bağlantı Durumu</label>
{waStatus?.status === 'connected' ? (
<div style={{ color: "#10b981", fontWeight: 600, display: "flex", alignItems: "center", gap: 8 }}>
<div style={{ width: 8, height: 8, borderRadius: "50%", background: "#10b981" }} />
Bağlı
</div>
) : (
<div>
<div style={{ color: "#ef4444", fontWeight: 600, display: "flex", alignItems: "center", gap: 8, marginBottom: 12 }}>
<div style={{ width: 8, height: 8, borderRadius: "50%", background: "#ef4444" }} />
Bağlı Değil
</div>
{waStatus?.qr ? (
<div style={{ background: "#fff", padding: 10, borderRadius: 8, width: "fit-content" }}>
<img src={waStatus.qr} alt="QR Code" style={{ width: 150, height: 150 }} />
<p style={{ fontSize: 11, color: "#000", textAlign: "center", marginTop: 5 }}>WhatsApp'tan okutun</p>
</div>
) : (
<button
type="button"
className="btn btn-secondary btn-sm"
onClick={handleConnectWa}
disabled={fetchingQr}
>
{fetchingQr ? "QR Oluşturuluyor..." : "Bağlantı Kur (QR)"}
</button>
)}
</div>
)}
</div>
</div>
</div>
<div style={{ marginTop: 24, display: "flex", justifyContent: "flex-end" }}>
<button type="submit" className="btn btn-primary" disabled={saving}>
{saving ? <span className="spinner" /> : "Değişiklikleri Kaydet"}
</button>
</div>
</form>
</div>
</>
);
}
function TelegramIcon() { return <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="m22 2-7 20-4-9-9-4Z"/><path d="M22 2 11 13"/></svg>; }
function WhatsAppIcon() { return <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5Z"/></svg>; }