import InteractiveMakerMapClient from "./InteractiveMakerMapClient"; import { MapHomeMakerList, type MapHomeMakerListItem } from "./MapHomeMakerList"; import { serverFetch } from "../lib/api"; type PublicMaker = { id: string; slug: string; business_name: string; description: string; province: string; city: string; main_image_url: string | null; avg_rating: number | string; review_count: number; service_count: number; work_count: number; public_latitude: number | null; public_longitude: number | null; public_locations?: Array<{ id: string; label?: string | null; city?: string | null; province?: string | null; latitude: number | null; longitude: number | null; }>; categories?: string[]; }; type SearchParams = Record; type HomeCategory = "all" | "print-3d" | "design-3d" | "resin" | "fdm"; const quickCategories: Array<{ id: HomeCategory; label: string }> = [ { id: "print-3d", label: "Impresion 3D" }, { id: "design-3d", label: "Diseno 3D" }, { id: "resin", label: "Resina" }, { id: "fdm", label: "FDM" } ]; const preferredOrder = [ "MakerLab 3D", "PrintCraft", "3D Ideas", "ImpresionAR", "ProtoWorks", "Resin Forge" ]; const distanceLabels = ["1,2 km", "1,8 km", "2,1 km", "2,4 km", "2,6 km", "2,9 km", "3,2 km"]; function getMakerImage(maker: PublicMaker) { return maker.main_image_url || "/demo/maker-hero-1.svg"; } function readParam(value: string | string[] | undefined) { return typeof value === "string" ? value : ""; } function getRating(value: number | string) { const parsed = typeof value === "number" ? value : Number(value); return Number.isFinite(parsed) ? parsed : 0; } function getSatisfaction(value: number | string) { const rating = getRating(value); return `${Math.max(92, Math.round(rating * 20))}% satisfaccion`; } function normalizeCategory(value: string): HomeCategory { if (value === "print-3d" || value === "design-3d" || value === "resin" || value === "fdm") { return value; } return "all"; } function hasCategory(maker: PublicMaker, expected: string) { return (maker.categories || []).some((category) => category.toLowerCase() === expected.toLowerCase()); } function filterByCategory(makers: PublicMaker[], category: HomeCategory) { if (category === "all") { return makers; } if (category === "print-3d") { return makers.filter((maker) => hasCategory(maker, "Impresion FDM") || hasCategory(maker, "Impresion Resina") || hasCategory(maker, "Prototipado")); } if (category === "design-3d") { return makers.filter((maker) => hasCategory(maker, "Diseno 3D")); } if (category === "resin") { return makers.filter((maker) => hasCategory(maker, "Impresion Resina")); } return makers.filter((maker) => hasCategory(maker, "Impresion FDM")); } function orderMakers(makers: PublicMaker[]) { return [...makers].sort((left, right) => { const leftIndex = preferredOrder.indexOf(left.business_name); const rightIndex = preferredOrder.indexOf(right.business_name); if (leftIndex !== -1 || rightIndex !== -1) { return (leftIndex === -1 ? 999 : leftIndex) - (rightIndex === -1 ? 999 : rightIndex); } return getRating(right.avg_rating) - getRating(left.avg_rating); }); } function getMakerTags(maker: PublicMaker) { const tags = new Set(); for (const category of maker.categories || []) { if (category === "Impresion FDM") { tags.add("FDM"); } if (category === "Impresion Resina") { tags.add("Resina"); } if (category === "Diseno 3D") { tags.add("Diseno 3D"); } if (category === "Prototipado") { tags.add("Prototipos"); } } if (tags.size === 0) { tags.add("Impresion 3D"); } return Array.from(tags).slice(0, 3); } function buildHomeHref(query: string, category: HomeCategory) { const params = new URLSearchParams(); if (query) { params.set("q", query); } if (category !== "all") { params.set("category", category); } const serialized = params.toString(); return serialized ? `/?${serialized}` : "/"; } function buildDiscoverHref(query: string, category: HomeCategory) { const params = new URLSearchParams(); if (query) { params.set("q", query); } if (category === "design-3d") { params.set("serviceCategory", "Diseno 3D"); } if (category === "resin") { params.set("serviceCategory", "Impresion Resina"); } if (category === "fdm") { params.set("serviceCategory", "Impresion FDM"); } const serialized = params.toString(); return serialized ? `/discover?${serialized}` : "/discover"; } export async function MapHomeScreen({ searchParams = {} }: { searchParams?: SearchParams }) { const query = readParam(searchParams.q); const activeCategory = normalizeCategory(readParam(searchParams.category)); const requestParams = new URLSearchParams(); if (query) { requestParams.set("q", query); } const data = await serverFetch<{ makers: PublicMaker[] }>(`/makers?${requestParams.toString()}`); const makers = orderMakers(filterByCategory(data.makers, activeCategory)); const visibleMakers = makers.slice(0, 10); const makerListItems: MapHomeMakerListItem[] = visibleMakers.map((maker, index) => ({ id: maker.id, slug: maker.slug, name: maker.business_name, city: maker.city, province: maker.province, imageUrl: getMakerImage(maker), distance: distanceLabels[index % distanceLabels.length], rating: getRating(maker.avg_rating).toFixed(1), reviewCount: Math.max(maker.review_count * 32, 12), satisfaction: getSatisfaction(maker.avg_rating), tags: getMakerTags(maker) })); const discoverHref = buildDiscoverHref(query, activeCategory); const mapMarkers = makers .flatMap((maker) => { const publicLocations = (maker.public_locations || []).filter((location) => location.latitude !== null && location.longitude !== null); const locations = publicLocations.length ? publicLocations : maker.public_latitude !== null && maker.public_longitude !== null ? [{ id: maker.id, city: maker.city, province: maker.province, latitude: maker.public_latitude, longitude: maker.public_longitude }] : []; return locations.map((location, index) => ({ id: `${maker.id}:${location.id || index}`, slug: maker.slug, businessName: maker.business_name, city: location.city || maker.city, province: location.province || maker.province, latitude: location.latitude as number, longitude: location.longitude as number })); }); return (
{activeCategory !== "all" ? : null}
Filtros {quickCategories.map((category) => ( {category.label} ))}
Makers cerca de ti Cordoba, Argentina | 1,2 km
Ver todos
); }