Files

188 lines
6.8 KiB
TypeScript

"use client";
import Link from "next/link";
import { useEffect, useState } from "react";
import { browserFetch } from "../lib/api";
type FavoriteMaker = {
id: string;
slug: string;
business_name: string;
city: string | null;
province: string | null;
main_image_url: string | null;
availability: string | null;
avg_rating: number | string;
review_count: number;
};
type FavoriteWork = {
id: string;
slug: string;
title: string;
summary: string;
technology: string;
material: string;
image_url: string;
maker_slug: string;
maker_name: string;
};
type FavoritesResponse = {
makers: FavoriteMaker[];
works: FavoriteWork[];
};
function rating(value: number | string) {
const parsed = typeof value === "number" ? value : Number(value);
return Number.isFinite(parsed) ? parsed.toFixed(1) : "0.0";
}
export default function FavoritesClient() {
const [activeTab, setActiveTab] = useState<"makers" | "works">("makers");
const [favorites, setFavorites] = useState<FavoritesResponse>({ makers: [], works: [] });
const [loading, setLoading] = useState(true);
const [needsLogin, setNeedsLogin] = useState(false);
const [status, setStatus] = useState("");
async function loadFavorites() {
setStatus("");
try {
const response = await browserFetch<FavoritesResponse>("/favorites");
setFavorites(response);
setNeedsLogin(false);
} catch (error) {
const message = error instanceof Error ? error.message : "";
if (message.includes("Authentication")) {
setNeedsLogin(true);
return;
}
setStatus("No se pudieron cargar tus favoritos.");
} finally {
setLoading(false);
}
}
useEffect(() => {
void loadFavorites();
}, []);
async function removeFavorite(type: "maker" | "work", id: string) {
const endpoint = type === "maker" ? `/favorites/makers/${id}` : `/favorites/works/${id}`;
await browserFetch(endpoint, { method: "DELETE" });
await loadFavorites();
}
if (loading) {
return (
<section className="favorites-shell">
<div className="profile-account-card stack">
<span className="eyebrow">Favoritos</span>
<h1 className="section-title">Cargando guardados</h1>
<p className="muted">Estamos preparando tus makers y trabajos favoritos.</p>
</div>
</section>
);
}
if (needsLogin) {
return (
<section className="favorites-shell">
<div className="profile-account-card stack">
<span className="eyebrow">Favoritos</span>
<h1 className="section-title">Inicia sesion para guardar favoritos</h1>
<p className="muted">Tus makers y trabajos guardados quedan asociados a tu cuenta para recuperarlos desde cualquier pestana.</p>
<Link href="/login?returnTo=%2Ffavorites" className="button button-primary">Entrar</Link>
</div>
</section>
);
}
const visibleMakers = activeTab === "makers";
const empty = visibleMakers ? favorites.makers.length === 0 : favorites.works.length === 0;
return (
<section className="favorites-shell">
<div className="favorites-header">
<div>
<span className="eyebrow">Favoritos</span>
<h1 className="section-title">Guardados para volver rapido</h1>
<p className="muted">Separados por makers y trabajos para que puedas comparar proveedores o ejemplos concretos.</p>
</div>
<div className="favorites-counts">
<span>{favorites.makers.length} makers</span>
<span>{favorites.works.length} trabajos</span>
</div>
</div>
<div className="favorites-tabs" role="tablist" aria-label="Secciones de favoritos">
<button className={activeTab === "makers" ? "is-active" : ""} type="button" onClick={() => setActiveTab("makers")}>
Makers
</button>
<button className={activeTab === "works" ? "is-active" : ""} type="button" onClick={() => setActiveTab("works")}>
Trabajos
</button>
</div>
{status ? <p className="messages-status">{status}</p> : null}
{empty ? (
<div className="profile-account-card stack">
<h2 className="section-title">{visibleMakers ? "Todavia no guardaste makers" : "Todavia no guardaste trabajos"}</h2>
<p className="muted">Usa el boton Guardar desde un perfil de maker o desde el detalle de un trabajo.</p>
<Link href="/discover" className="button button-primary">Descubrir makers</Link>
</div>
) : null}
{visibleMakers ? (
<div className="favorites-grid">
{favorites.makers.map((maker) => (
<article key={maker.id} className="favorite-card">
<img className="thumb" src={maker.main_image_url || "/demo/maker-hero-1.svg"} alt={maker.business_name} />
<div className="favorite-card-body">
<div>
<strong>{maker.business_name}</strong>
<span className="mini-note">{maker.city || "Cordoba"}, {maker.province || "Argentina"}</span>
</div>
<div className="badges">
<span className="badge">Rating {rating(maker.avg_rating)}</span>
<span className="badge">{maker.review_count} resenas</span>
<span className="badge">{maker.availability || "available"}</span>
</div>
<div className="favorite-card-actions">
<Link href={`/makers/${maker.slug}`} className="button button-primary">Ver perfil</Link>
<button className="button button-secondary" type="button" onClick={() => removeFavorite("maker", maker.id)}>Quitar</button>
</div>
</div>
</article>
))}
</div>
) : (
<div className="favorites-grid">
{favorites.works.map((work) => (
<article key={work.id} className="favorite-card">
<img className="thumb" src={work.image_url || "/demo/work-custom.svg"} alt={work.title} />
<div className="favorite-card-body">
<div>
<strong>{work.title}</strong>
<span className="mini-note">{work.maker_name}</span>
</div>
<p className="muted">{work.summary}</p>
<div className="badges">
<span className="badge">{work.technology}</span>
<span className="badge">{work.material}</span>
</div>
<div className="favorite-card-actions">
<Link href={`/works/${work.slug}`} className="button button-primary">Ver trabajo</Link>
<button className="button button-secondary" type="button" onClick={() => removeFavorite("work", work.id)}>Quitar</button>
</div>
</div>
</article>
))}
</div>
)}
</section>
);
}