Sistema de Notificaciones y Baja One-Click
This commit is contained in:
@@ -2,6 +2,10 @@ import { useState, useEffect } from "react";
|
||||
import { ProfileService } from "../services/profile.service";
|
||||
import { useAuth } from "../context/AuthContext";
|
||||
import { AuthService } from "../services/auth.service";
|
||||
import {
|
||||
NotificationPreferencesService,
|
||||
type NotificationPreferences,
|
||||
} from "../services/notification-preferences.service";
|
||||
|
||||
export default function PerfilPage() {
|
||||
const { user, refreshSession } = useAuth();
|
||||
@@ -19,10 +23,46 @@ export default function PerfilPage() {
|
||||
phoneNumber: "",
|
||||
});
|
||||
|
||||
// Estado de preferencias de notificación
|
||||
const [notifPrefs, setNotifPrefs] = useState<NotificationPreferences>({
|
||||
sistema: true,
|
||||
marketing: true,
|
||||
rendimiento: true,
|
||||
mensajes: true,
|
||||
});
|
||||
const [savingPrefs, setSavingPrefs] = useState(false);
|
||||
const [prefsSaved, setPrefsSaved] = useState(false);
|
||||
const [loadingPrefs, setLoadingPrefs] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
loadProfile();
|
||||
loadNotifPrefs();
|
||||
}, []);
|
||||
|
||||
const loadNotifPrefs = async () => {
|
||||
try {
|
||||
const data = await NotificationPreferencesService.getPreferences();
|
||||
setNotifPrefs(data);
|
||||
} catch (err) {
|
||||
console.error("Error cargando preferencias de notificación", err);
|
||||
} finally {
|
||||
setLoadingPrefs(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSaveNotifPrefs = async () => {
|
||||
setSavingPrefs(true);
|
||||
try {
|
||||
await NotificationPreferencesService.updatePreferences(notifPrefs);
|
||||
setPrefsSaved(true);
|
||||
setTimeout(() => setPrefsSaved(false), 3000);
|
||||
} catch (err) {
|
||||
alert("Error al guardar las preferencias de notificación.");
|
||||
} finally {
|
||||
setSavingPrefs(false);
|
||||
}
|
||||
};
|
||||
|
||||
const loadProfile = async () => {
|
||||
try {
|
||||
const data = await ProfileService.getProfile();
|
||||
@@ -97,7 +137,7 @@ export default function PerfilPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Edit Form */}
|
||||
{/* Formulario de datos personales */}
|
||||
<div className="lg:col-span-2">
|
||||
<form
|
||||
onSubmit={handleSubmit}
|
||||
@@ -189,6 +229,118 @@ export default function PerfilPage() {
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{/* ─── Preferencias de Notificación ─── */}
|
||||
<div className="mt-8 glass p-8 rounded-[2.5rem] border border-white/5">
|
||||
<div className="flex items-center gap-3 mb-6">
|
||||
<div className="w-10 h-10 bg-blue-600/15 rounded-2xl flex items-center justify-center text-xl border border-blue-500/20">
|
||||
🔔
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-sm font-black uppercase tracking-widest text-white">
|
||||
Preferencias de Notificación
|
||||
</h3>
|
||||
<p className="text-[10px] text-gray-500 font-medium mt-0.5">
|
||||
Elegir qué correos querés recibir
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{loadingPrefs ? (
|
||||
<div className="flex items-center gap-3 py-4 text-gray-500 text-xs">
|
||||
<div className="w-5 h-5 border-2 border-blue-500/40 border-t-blue-500 rounded-full animate-spin" />
|
||||
Cargando preferencias...
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-4">
|
||||
{([
|
||||
{
|
||||
key: "sistema" as const,
|
||||
label: "Avisos del Sistema",
|
||||
desc: "Vencimiento de avisos, renovaciones y alertas importantes.",
|
||||
icon: "⚙️",
|
||||
},
|
||||
{
|
||||
key: "marketing" as const,
|
||||
label: "Promociones y Marketing",
|
||||
desc: "Ofertas especiales, recordatorio de carrito abandonado.",
|
||||
icon: "🎁",
|
||||
},
|
||||
{
|
||||
key: "rendimiento" as const,
|
||||
label: "Resumen Semanal",
|
||||
desc: "Visitas y favoritos de tus avisos publicados.",
|
||||
icon: "📊",
|
||||
},
|
||||
{
|
||||
key: "mensajes" as const,
|
||||
label: "Recordatorio de Mensajes",
|
||||
desc: "Aviso cuando tenés mensajes sin leer por más de 4 horas.",
|
||||
icon: "💬",
|
||||
},
|
||||
] as const).map(({ key, label, desc, icon }) => (
|
||||
<label
|
||||
key={key}
|
||||
className="flex items-center justify-between gap-4 p-4 rounded-2xl bg-white/3
|
||||
border border-white/5 hover:bg-white/5 transition-all cursor-pointer group"
|
||||
>
|
||||
<div className="flex items-center gap-3">
|
||||
<span className="text-xl">{icon}</span>
|
||||
<div>
|
||||
<p className="text-xs font-black text-white uppercase tracking-wider">
|
||||
{label}
|
||||
</p>
|
||||
<p className="text-[10px] text-gray-500 font-medium mt-0.5">{desc}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Toggle switch */}
|
||||
<div className="relative flex-shrink-0">
|
||||
<input
|
||||
type="checkbox"
|
||||
className="sr-only"
|
||||
checked={notifPrefs[key]}
|
||||
onChange={(e) =>
|
||||
setNotifPrefs((prev) => ({ ...prev, [key]: e.target.checked }))
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className={`w-12 h-6 rounded-full transition-all duration-300 cursor-pointer
|
||||
${notifPrefs[key]
|
||||
? 'bg-blue-600 shadow-lg shadow-blue-600/30'
|
||||
: 'bg-white/10'}`}
|
||||
>
|
||||
<div
|
||||
className={`absolute top-1 w-4 h-4 bg-white rounded-full shadow transition-all duration-300
|
||||
${notifPrefs[key] ? 'left-7' : 'left-1'}`}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
))}
|
||||
|
||||
<div className="pt-4 border-t border-white/5 flex items-center gap-4">
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleSaveNotifPrefs}
|
||||
disabled={savingPrefs}
|
||||
className="bg-blue-600 hover:bg-blue-500 text-white py-3.5 px-10 rounded-2xl
|
||||
text-[10px] font-black uppercase tracking-widest transition-all
|
||||
shadow-lg shadow-blue-600/20 active:scale-95 disabled:opacity-50"
|
||||
>
|
||||
{savingPrefs ? "Guardando..." : "Guardar Preferencias"}
|
||||
</button>
|
||||
|
||||
{prefsSaved && (
|
||||
<span className="text-green-400 text-[10px] font-black uppercase tracking-widest
|
||||
animate-pulse">
|
||||
✓ Preferencias guardadas
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{showEmailModal && (
|
||||
|
||||
Reference in New Issue
Block a user