2026-02-13 11:23:16 -03:00
|
|
|
import { useState, useEffect } from "react";
|
|
|
|
|
import { useSearchParams, useNavigate } from "react-router-dom";
|
|
|
|
|
import { AvisosService } from "../services/avisos.service";
|
|
|
|
|
import { AdsV2Service } from "../services/ads.v2.service";
|
|
|
|
|
import { AuthService, type UserSession } from "../services/auth.service";
|
|
|
|
|
import type { DatosAvisoDto } from "../types/aviso.types";
|
|
|
|
|
import FormularioAviso from "../components/FormularioAviso";
|
|
|
|
|
import LoginModal from "../components/LoginModal";
|
2026-01-29 13:43:44 -03:00
|
|
|
|
|
|
|
|
const TAREAS_DISPONIBLES = [
|
2026-02-13 11:23:16 -03:00
|
|
|
{
|
|
|
|
|
id: "EAUTOS",
|
|
|
|
|
label: "Automóviles",
|
|
|
|
|
icon: "🚗",
|
|
|
|
|
description: "Venta de Autos, Camionetas y Utilitarios",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: "EMOTOS",
|
|
|
|
|
label: "Motos",
|
|
|
|
|
icon: "🏍️",
|
|
|
|
|
description: "Venta de Motos, Cuatriciclos y Náutica",
|
|
|
|
|
},
|
2026-01-29 13:43:44 -03:00
|
|
|
];
|
|
|
|
|
|
|
|
|
|
export default function PublicarAvisoPage() {
|
|
|
|
|
const [searchParams] = useSearchParams();
|
|
|
|
|
const navigate = useNavigate(); // Hook de navegación
|
2026-02-13 11:23:16 -03:00
|
|
|
const editId = searchParams.get("edit");
|
2026-01-29 13:43:44 -03:00
|
|
|
|
2026-02-13 11:23:16 -03:00
|
|
|
const [categorySelection, setCategorySelection] = useState<string>("");
|
2026-01-29 13:43:44 -03:00
|
|
|
const [tarifas, setTarifas] = useState<DatosAvisoDto[]>([]);
|
|
|
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
|
const [error, setError] = useState<string | null>(null);
|
2026-02-13 11:23:16 -03:00
|
|
|
const [planSeleccionado, setPlanSeleccionado] =
|
|
|
|
|
useState<DatosAvisoDto | null>(null);
|
2026-01-29 13:43:44 -03:00
|
|
|
const [fixedCategory, setFixedCategory] = useState<string | null>(null);
|
2026-02-13 11:23:16 -03:00
|
|
|
const [user, setUser] = useState<UserSession | null>(
|
|
|
|
|
AuthService.getCurrentUser(),
|
|
|
|
|
);
|
2026-01-29 13:43:44 -03:00
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (editId) {
|
|
|
|
|
cargarAvisoParaEdicion(parseInt(editId));
|
|
|
|
|
}
|
|
|
|
|
}, [editId]);
|
|
|
|
|
|
2026-02-13 11:23:16 -03:00
|
|
|
useEffect(() => {
|
|
|
|
|
if (planSeleccionado) {
|
|
|
|
|
window.scrollTo({ top: 0, behavior: "instant" });
|
|
|
|
|
}
|
|
|
|
|
}, [planSeleccionado]);
|
|
|
|
|
|
2026-01-29 13:43:44 -03:00
|
|
|
const cargarAvisoParaEdicion = async (id: number) => {
|
|
|
|
|
setLoading(true);
|
|
|
|
|
try {
|
|
|
|
|
const ad = await AdsV2Service.getById(id);
|
|
|
|
|
|
|
|
|
|
// Determinamos la categoría para cargar las tarifas correspondientes
|
2026-02-13 11:23:16 -03:00
|
|
|
const categoryCode = ad.vehicleTypeID === 1 ? "EAUTOS" : "EMOTOS";
|
2026-01-29 13:43:44 -03:00
|
|
|
|
|
|
|
|
setCategorySelection(categoryCode);
|
|
|
|
|
|
2026-02-13 11:23:16 -03:00
|
|
|
// Bloquear el cambio de categoría
|
2026-01-29 13:43:44 -03:00
|
|
|
setFixedCategory(categoryCode);
|
|
|
|
|
} catch (err) {
|
|
|
|
|
console.error(err);
|
|
|
|
|
setError("Error al cargar el aviso.");
|
|
|
|
|
} finally {
|
|
|
|
|
setLoading(false);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (!categorySelection) return;
|
|
|
|
|
|
|
|
|
|
const cargarTarifas = async () => {
|
|
|
|
|
setLoading(true);
|
|
|
|
|
setError(null);
|
|
|
|
|
try {
|
|
|
|
|
const [simple, destacado] = await Promise.all([
|
2026-02-13 11:23:16 -03:00
|
|
|
AvisosService.obtenerConfiguracion("EMOTORES", 0),
|
|
|
|
|
AvisosService.obtenerConfiguracion("EMOTORES", 1),
|
2026-01-29 13:43:44 -03:00
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
const planes = [...simple, ...destacado];
|
|
|
|
|
planes.sort((a, b) => a.importeTotsiniva - b.importeTotsiniva);
|
|
|
|
|
|
|
|
|
|
setTarifas(planes);
|
|
|
|
|
} catch (err) {
|
|
|
|
|
setError("Error al cargar tarifas.");
|
|
|
|
|
console.error(err);
|
|
|
|
|
} finally {
|
|
|
|
|
setLoading(false);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
cargarTarifas();
|
|
|
|
|
}, [categorySelection]);
|
|
|
|
|
|
|
|
|
|
const handleSelectPlan = (plan: DatosAvisoDto) => {
|
2026-02-13 11:23:16 -03:00
|
|
|
const vehicleTypeId = categorySelection === "EAUTOS" ? 1 : 2;
|
|
|
|
|
const nombrePlanAmigable =
|
|
|
|
|
plan.paquete === 1 ? "PLAN DESTACADO" : "PLAN ESTÁNDAR";
|
2026-01-29 13:43:44 -03:00
|
|
|
|
|
|
|
|
setPlanSeleccionado({
|
|
|
|
|
...plan,
|
|
|
|
|
idRubro: vehicleTypeId,
|
2026-02-13 11:23:16 -03:00
|
|
|
nomavi: nombrePlanAmigable,
|
2026-01-29 13:43:44 -03:00
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Manejador centralizado de éxito
|
|
|
|
|
const handleSuccess = (adId: number, isAdminAction: boolean = false) => {
|
2026-02-13 11:23:16 -03:00
|
|
|
const status = isAdminAction ? "admin_created" : "approved";
|
2026-01-29 13:43:44 -03:00
|
|
|
navigate(`/pago-confirmado?status=${status}&adId=${adId}`);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (!user) {
|
|
|
|
|
return (
|
|
|
|
|
<div className="flex justify-center items-center py-20 min-h-[60vh]">
|
2026-02-13 11:23:16 -03:00
|
|
|
<LoginModal
|
|
|
|
|
onSuccess={(u) => setUser(u)}
|
|
|
|
|
onClose={() => navigate("/")}
|
|
|
|
|
/>
|
2026-01-29 13:43:44 -03:00
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ELIMINADO: Bloque if (publicacionExitosa) { return ... }
|
|
|
|
|
|
|
|
|
|
if (planSeleccionado) {
|
|
|
|
|
return (
|
|
|
|
|
<div className="max-w-6xl mx-auto py-8 px-6">
|
|
|
|
|
<header className="flex justify-between items-center mb-10">
|
2026-02-13 11:23:16 -03:00
|
|
|
<button
|
|
|
|
|
onClick={() => setPlanSeleccionado(null)}
|
|
|
|
|
className="text-gray-500 hover:text-white uppercase text-[10px] font-black tracking-widest flex items-center gap-2 transition-colors"
|
|
|
|
|
>
|
2026-01-29 13:43:44 -03:00
|
|
|
← Volver a Planes
|
|
|
|
|
</button>
|
|
|
|
|
<div className="glass px-4 py-2 rounded-xl text-xs border border-white/5">
|
2026-02-13 11:23:16 -03:00
|
|
|
Publicando como:{" "}
|
|
|
|
|
<span className="text-blue-400 font-bold">{user.username}</span>
|
2026-01-29 13:43:44 -03:00
|
|
|
</div>
|
|
|
|
|
</header>
|
|
|
|
|
<FormularioAviso
|
|
|
|
|
plan={planSeleccionado}
|
|
|
|
|
onCancel={() => setPlanSeleccionado(null)}
|
|
|
|
|
onSuccess={handleSuccess} // Usamos la redirección
|
|
|
|
|
editId={editId ? parseInt(editId) : null}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className="max-w-6xl mx-auto px-4 md:px-6 py-8 md:py-12">
|
|
|
|
|
<header className="mb-8 md:mb-16 text-center md:text-left">
|
2026-02-13 11:23:16 -03:00
|
|
|
<h2 className="text-3xl md:text-6xl font-black tracking-tighter uppercase mb-2">
|
|
|
|
|
Comienza a <span className="text-gradient">Vender</span>
|
|
|
|
|
</h2>
|
|
|
|
|
<p className="text-gray-500 text-sm md:text-lg italic">
|
|
|
|
|
Selecciona una categoría para ver los planes de publicación.
|
|
|
|
|
</p>
|
2026-01-29 13:43:44 -03:00
|
|
|
</header>
|
|
|
|
|
|
|
|
|
|
{/* SECCIÓN DE CATEGORÍA */}
|
|
|
|
|
<section className="grid grid-cols-1 md:grid-cols-2 gap-4 md:gap-8 mb-10 md:mb-20 text-white">
|
2026-02-13 11:23:16 -03:00
|
|
|
{TAREAS_DISPONIBLES.map((t) => {
|
2026-01-29 13:43:44 -03:00
|
|
|
// Lógica de bloqueo
|
|
|
|
|
const isDisabled = fixedCategory && fixedCategory !== t.id;
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<button
|
|
|
|
|
key={t.id}
|
|
|
|
|
onClick={() => !isDisabled && setCategorySelection(t.id)}
|
|
|
|
|
disabled={!!isDisabled} // Deshabilitar botón
|
|
|
|
|
className={`
|
|
|
|
|
glass-card p-6 md:p-10 rounded-[2rem] md:rounded-[2.5rem] flex items-center justify-between group transition-all text-left
|
2026-02-13 11:23:16 -03:00
|
|
|
${categorySelection === t.id ? "border-blue-500 scale-[1.02] shadow-2xl shadow-blue-600/10 bg-white/5" : "hover:bg-white/5"}
|
|
|
|
|
${isDisabled ? "opacity-30 cursor-not-allowed grayscale" : "cursor-pointer"}
|
2026-01-29 13:43:44 -03:00
|
|
|
`}
|
|
|
|
|
>
|
|
|
|
|
<div>
|
2026-02-13 11:23:16 -03:00
|
|
|
<span className="text-[10px] md:text-xs font-black uppercase tracking-widest text-blue-400 mb-1 md:mb-2 block">
|
|
|
|
|
Categoría
|
|
|
|
|
</span>
|
|
|
|
|
<h3 className="text-2xl md:text-4xl font-bold mb-1 md:mb-2 uppercase tracking-tight">
|
|
|
|
|
{t.label}
|
|
|
|
|
</h3>
|
|
|
|
|
<p className="text-gray-500 font-light text-xs md:text-sm">
|
|
|
|
|
{t.description}
|
|
|
|
|
</p>
|
2026-01-29 13:43:44 -03:00
|
|
|
</div>
|
2026-02-13 11:23:16 -03:00
|
|
|
<span className="text-4xl md:text-6xl group-hover:scale-110 transition-transform duration-300">
|
|
|
|
|
{t.icon}
|
|
|
|
|
</span>
|
2026-01-29 13:43:44 -03:00
|
|
|
</button>
|
|
|
|
|
);
|
|
|
|
|
})}
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
{/* LISTA DE PLANES */}
|
|
|
|
|
{categorySelection && (
|
|
|
|
|
<section className="animate-fade-in-up">
|
|
|
|
|
<div className="flex justify-between items-end mb-10 border-b border-white/5 pb-4">
|
|
|
|
|
<div>
|
2026-02-13 11:23:16 -03:00
|
|
|
<h3 className="text-3xl font-black uppercase tracking-tighter">
|
|
|
|
|
Planes <span className="text-blue-400">Disponibles</span>
|
|
|
|
|
</h3>
|
|
|
|
|
<p className="text-gray-500 text-xs mt-1 uppercase tracking-widest">
|
|
|
|
|
Para {categorySelection === "EAUTOS" ? "Automóviles" : "Motos"}
|
|
|
|
|
</p>
|
2026-01-29 13:43:44 -03:00
|
|
|
</div>
|
2026-02-13 11:23:16 -03:00
|
|
|
<span className="text-gray-600 text-[10px] font-bold uppercase tracking-widest">
|
|
|
|
|
Precios finales (IVA Incluido)
|
|
|
|
|
</span>
|
2026-01-29 13:43:44 -03:00
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{error && (
|
|
|
|
|
<div className="bg-red-500/10 text-red-400 p-6 rounded-[2rem] border border-red-500/20 mb-10 text-center">
|
2026-02-13 11:23:16 -03:00
|
|
|
<p className="font-bold uppercase tracking-widest text-xs mb-2">
|
|
|
|
|
Error de Conexión
|
|
|
|
|
</p>
|
2026-01-29 13:43:44 -03:00
|
|
|
<p className="italic text-sm">{error}</p>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
{loading ? (
|
2026-02-13 11:23:16 -03:00
|
|
|
<div className="flex justify-center p-20">
|
|
|
|
|
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-500"></div>
|
|
|
|
|
</div>
|
2026-01-29 13:43:44 -03:00
|
|
|
) : (
|
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 max-w-4xl mx-auto">
|
|
|
|
|
{tarifas.map((tarifa, idx) => {
|
2026-02-13 11:23:16 -03:00
|
|
|
const precioRaw =
|
|
|
|
|
tarifa.importeTotsiniva > 0
|
|
|
|
|
? tarifa.importeTotsiniva * 1.105
|
|
|
|
|
: tarifa.importeSiniva * 1.105;
|
2026-01-29 13:43:44 -03:00
|
|
|
const precioFinal = Math.round(precioRaw);
|
|
|
|
|
const esDestacado = tarifa.paquete === 1;
|
|
|
|
|
const tituloPlan = esDestacado ? "DESTACADO" : "ESTÁNDAR";
|
|
|
|
|
const descripcionPlan = esDestacado
|
|
|
|
|
? "Máxima visibilidad. Tu aviso aparecerá en el carrusel de inicio y primeros lugares de búsqueda."
|
|
|
|
|
: "Presencia esencial. Tu aviso aparecerá en el listado general de búsqueda.";
|
|
|
|
|
|
|
|
|
|
return (
|
2026-02-13 11:23:16 -03:00
|
|
|
<div
|
|
|
|
|
key={idx}
|
|
|
|
|
onClick={() => handleSelectPlan(tarifa)}
|
|
|
|
|
className={`glass-card p-8 rounded-[2.5rem] flex flex-col group cursor-pointer relative overflow-hidden transition-all hover:-translate-y-2 hover:shadow-2xl ${esDestacado ? "border-blue-500/30 hover:border-blue-500 hover:shadow-blue-900/20" : "hover:border-white/30"}`}
|
|
|
|
|
>
|
|
|
|
|
<div
|
|
|
|
|
className={`absolute top-0 right-0 text-white text-[9px] font-black px-6 py-2 rounded-bl-3xl uppercase tracking-widest shadow-lg ${esDestacado ? "bg-gradient-to-bl from-blue-600 to-cyan-500 animate-glow" : "bg-white/10 text-gray-400"}`}
|
|
|
|
|
>
|
|
|
|
|
{esDestacado ? "RECOMENDADO" : "BÁSICO"}
|
2026-01-29 13:43:44 -03:00
|
|
|
</div>
|
|
|
|
|
|
2026-02-13 11:23:16 -03:00
|
|
|
<h4
|
|
|
|
|
className={`text-3xl font-black uppercase tracking-tighter mb-4 mt-4 ${esDestacado ? "text-blue-400" : "text-white"}`}
|
|
|
|
|
>
|
2026-01-29 13:43:44 -03:00
|
|
|
{tituloPlan}
|
|
|
|
|
</h4>
|
|
|
|
|
|
|
|
|
|
<div className="space-y-4 mb-10 flex-1">
|
|
|
|
|
<p className="text-gray-400 text-sm leading-relaxed border-b border-white/5 pb-4 min-h-[60px]">
|
|
|
|
|
{descripcionPlan}
|
|
|
|
|
</p>
|
|
|
|
|
|
|
|
|
|
<ul className="space-y-3">
|
|
|
|
|
<li className="flex justify-between text-xs text-gray-300 items-center">
|
2026-02-13 11:23:16 -03:00
|
|
|
<span className="text-gray-500 uppercase tracking-wider font-bold text-[10px]">
|
|
|
|
|
Plataforma
|
|
|
|
|
</span>
|
|
|
|
|
<span className="font-bold bg-white/5 px-2 py-1 rounded text-[10px]">
|
|
|
|
|
SOLO WEB
|
|
|
|
|
</span>
|
2026-01-29 13:43:44 -03:00
|
|
|
</li>
|
|
|
|
|
<li className="flex justify-between text-xs text-gray-300 items-center">
|
2026-02-13 11:23:16 -03:00
|
|
|
<span className="text-gray-500 uppercase tracking-wider font-bold text-[10px]">
|
|
|
|
|
Duración
|
|
|
|
|
</span>
|
|
|
|
|
<span className="font-bold">
|
|
|
|
|
{tarifa.cantidadDias} Días
|
|
|
|
|
</span>
|
2026-01-29 13:43:44 -03:00
|
|
|
</li>
|
|
|
|
|
<li className="flex justify-between text-xs text-gray-300 items-center">
|
2026-02-13 11:23:16 -03:00
|
|
|
<span className="text-gray-500 uppercase tracking-wider font-bold text-[10px]">
|
|
|
|
|
Fotos
|
|
|
|
|
</span>
|
|
|
|
|
<span className="font-bold text-green-400">
|
|
|
|
|
Hasta 5
|
|
|
|
|
</span>
|
2026-01-29 13:43:44 -03:00
|
|
|
</li>
|
|
|
|
|
<li className="flex justify-between text-xs text-gray-300 items-center">
|
2026-02-13 11:23:16 -03:00
|
|
|
<span className="text-gray-500 uppercase tracking-wider font-bold text-[10px]">
|
|
|
|
|
Visibilidad
|
|
|
|
|
</span>
|
|
|
|
|
<span
|
|
|
|
|
className={`font-bold ${esDestacado ? "text-blue-400" : "text-gray-300"}`}
|
|
|
|
|
>
|
|
|
|
|
{esDestacado ? "ALTA ⭐" : "NORMAL"}
|
|
|
|
|
</span>
|
2026-01-29 13:43:44 -03:00
|
|
|
</li>
|
|
|
|
|
</ul>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="mt-auto pt-6 border-t border-white/5">
|
2026-02-13 11:23:16 -03:00
|
|
|
<span className="text-gray-500 text-[10px] font-black uppercase tracking-widest block mb-1">
|
|
|
|
|
Precio Final
|
|
|
|
|
</span>
|
2026-01-29 13:43:44 -03:00
|
|
|
<div className="flex items-baseline gap-1">
|
|
|
|
|
<span className="text-4xl font-black tracking-tighter text-white">
|
2026-02-13 11:23:16 -03:00
|
|
|
$
|
|
|
|
|
{precioFinal.toLocaleString("es-AR", {
|
|
|
|
|
minimumFractionDigits: 0,
|
|
|
|
|
maximumFractionDigits: 0,
|
|
|
|
|
})}
|
|
|
|
|
</span>
|
|
|
|
|
<span className="text-xs font-bold text-gray-500">
|
|
|
|
|
ARS
|
2026-01-29 13:43:44 -03:00
|
|
|
</span>
|
|
|
|
|
</div>
|
2026-02-13 11:23:16 -03:00
|
|
|
<button
|
|
|
|
|
className={`w-full mt-6 text-white py-4 rounded-xl font-bold uppercase text-xs tracking-widest transition-all shadow-lg ${esDestacado ? "bg-blue-600 hover:bg-blue-500 shadow-blue-600/20" : "bg-white/5 hover:bg-white/10"}`}
|
|
|
|
|
>
|
2026-01-29 13:43:44 -03:00
|
|
|
Seleccionar
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
})}
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</section>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
2026-02-13 11:23:16 -03:00
|
|
|
}
|