202 lines
6.5 KiB
TypeScript
202 lines
6.5 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useState } from "react";
|
|
import { useSession } from "next-auth/react";
|
|
import { updateCustomer } from "@/lib/api";
|
|
|
|
export default function ProfilePage() {
|
|
const { data: session } = useSession();
|
|
const userName = session?.user?.name || "";
|
|
const userEmail = session?.user?.email || "";
|
|
const [customer, setCustomer] = useState<Record<string, unknown> | null>(null);
|
|
const [customerName, setCustomerName] = useState("");
|
|
const [saving, setSaving] = useState(false);
|
|
const [saved, setSaved] = useState(false);
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
useEffect(() => {
|
|
fetch("/api/customer/me")
|
|
.then((res) => (res.ok ? res.json() : null))
|
|
.then((res) => {
|
|
if (res?.data) {
|
|
setCustomer(res.data);
|
|
setCustomerName(String(res.data.name || ""));
|
|
}
|
|
})
|
|
.catch(() => {})
|
|
.finally(() => setLoading(false));
|
|
}, []);
|
|
|
|
async function handleSave(e: React.FormEvent<HTMLFormElement>) {
|
|
e.preventDefault();
|
|
setSaving(true);
|
|
setSaved(false);
|
|
const form = new FormData(e.currentTarget);
|
|
|
|
try {
|
|
await updateCustomer(customerName, {
|
|
customer_name: form.get("company") as string,
|
|
tax_id: form.get("tax_id") as string,
|
|
});
|
|
setSaved(true);
|
|
} catch {
|
|
alert("Eroare la salvare");
|
|
} finally {
|
|
setSaving(false);
|
|
}
|
|
}
|
|
|
|
if (loading) {
|
|
return (
|
|
<div>
|
|
<h1 className="text-2xl font-bold text-gray-900">Profil</h1>
|
|
<p className="mt-4 text-gray-500">Se incarca...</p>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div>
|
|
<h1 className="text-2xl font-bold text-gray-900">Profil</h1>
|
|
<p className="mt-1 text-sm text-gray-500">Gestioneaza datele tale personale.</p>
|
|
|
|
<form onSubmit={handleSave} className="mt-6 max-w-lg space-y-4">
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700">Nume</label>
|
|
<input
|
|
type="text"
|
|
defaultValue={userName}
|
|
disabled
|
|
className="mt-1 block w-full rounded-lg border border-gray-200 bg-gray-50 px-4 py-2.5 text-sm text-gray-500"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700">Email</label>
|
|
<input
|
|
type="email"
|
|
defaultValue={userEmail}
|
|
disabled
|
|
className="mt-1 block w-full rounded-lg border border-gray-200 bg-gray-50 px-4 py-2.5 text-sm text-gray-500"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700">Companie</label>
|
|
<input
|
|
name="company"
|
|
type="text"
|
|
defaultValue={String(customer?.customer_name || "")}
|
|
className="mt-1 block w-full rounded-lg border border-gray-300 px-4 py-2.5 text-sm"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700">CUI</label>
|
|
<input
|
|
name="tax_id"
|
|
type="text"
|
|
defaultValue={String(customer?.tax_id || "")}
|
|
className="mt-1 block w-full rounded-lg border border-gray-300 px-4 py-2.5 text-sm"
|
|
/>
|
|
</div>
|
|
<div className="flex items-center gap-3">
|
|
<button
|
|
type="submit"
|
|
disabled={saving}
|
|
className="rounded-lg bg-teal-600 px-6 py-2.5 text-sm font-semibold text-white hover:bg-teal-700 disabled:opacity-50"
|
|
>
|
|
{saving ? "Se salveaza..." : "Salveaza"}
|
|
</button>
|
|
{saved && <span className="text-sm text-green-600">Salvat!</span>}
|
|
</div>
|
|
</form>
|
|
|
|
{/* GDPR section */}
|
|
<GdprActions />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function GdprActions() {
|
|
const [busy, setBusy] = useState<string | null>(null);
|
|
const [msg, setMsg] = useState<string | null>(null);
|
|
|
|
function exportData() {
|
|
setBusy("export");
|
|
setMsg(null);
|
|
// Open download in new tab — server returns Content-Disposition: attachment
|
|
window.open("/api/gdpr/export", "_blank");
|
|
setTimeout(() => {
|
|
setBusy(null);
|
|
setMsg("Datele tale au fost descarcate ca fisier JSON.");
|
|
}, 1500);
|
|
}
|
|
|
|
async function requestDelete() {
|
|
const ok = confirm(
|
|
"Esti SIGUR ca vrei sa stergi contul?\n\n" +
|
|
"- Analizele si rapoartele tale vor fi anonimizate\n" +
|
|
"- Facturile fiscale raman in arhiva 10 ani (cerinta legala RO)\n" +
|
|
"- Datele personale vor fi sterse in 30 zile\n" +
|
|
"- Actiunea este IREVERSIBILA dupa 30 zile\n\n" +
|
|
"Continui?"
|
|
);
|
|
if (!ok) return;
|
|
setBusy("delete");
|
|
setMsg(null);
|
|
try {
|
|
const res = await fetch("/api/gdpr/delete", {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ confirm: true, reason: "Solicitare self-service din dashboard" }),
|
|
});
|
|
const data = await res.json();
|
|
if (res.ok) {
|
|
setMsg(data.message || "Cererea a fost inregistrata.");
|
|
} else {
|
|
setMsg(`Eroare: ${data.error}`);
|
|
}
|
|
} catch (e) {
|
|
setMsg(`Eroare: ${e instanceof Error ? e.message : "necunoscuta"}`);
|
|
} finally {
|
|
setBusy(null);
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div className="mt-10 border-t pt-8">
|
|
<h2 className="text-lg font-semibold text-gray-900">Protectia datelor (GDPR)</h2>
|
|
<p className="mt-2 text-sm text-gray-500">
|
|
Exercita-ti drepturile conform Regulamentului (UE) 2016/679 (GDPR).
|
|
</p>
|
|
|
|
<div className="mt-4 grid gap-3 sm:grid-cols-2">
|
|
<button
|
|
disabled={!!busy}
|
|
onClick={exportData}
|
|
className="rounded-lg border p-4 text-left text-sm hover:bg-gray-50 disabled:opacity-50"
|
|
>
|
|
<div className="font-semibold text-gray-900">Exporta datele mele</div>
|
|
<div className="mt-1 text-xs text-gray-500">
|
|
Art. 20 GDPR — portabilitate. Descarca toate datele tale (profil, facturi, plati, analize) in format JSON.
|
|
</div>
|
|
</button>
|
|
|
|
<button
|
|
disabled={!!busy}
|
|
onClick={requestDelete}
|
|
className="rounded-lg border border-red-200 p-4 text-left text-sm hover:bg-red-50 disabled:opacity-50"
|
|
>
|
|
<div className="font-semibold text-red-700">Solicita stergerea contului</div>
|
|
<div className="mt-1 text-xs text-red-600">
|
|
Art. 17 GDPR — dreptul la stergere. Cererea va fi procesata in 30 zile.
|
|
</div>
|
|
</button>
|
|
</div>
|
|
|
|
{msg && (
|
|
<p className={`mt-4 text-sm ${msg.startsWith("Eroare") ? "text-red-600" : "text-green-700"}`}>
|
|
{msg}
|
|
</p>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|