From fc592f4dfcda72ae0903e30584210abc96115123 Mon Sep 17 00:00:00 2001 From: Jeffcar1993 Date: Tue, 26 Aug 2025 20:21:45 -0500 Subject: [PATCH] Refactor: To add information about as availability variables on grid category of polos and stickers, and link variants since url to product component --- .../components/product-card/index.tsx | 51 +++++++++++++++++-- src/routes/category/index.tsx | 6 ++- src/routes/product/index.tsx | 44 ++++++++++++---- 3 files changed, 87 insertions(+), 14 deletions(-) diff --git a/src/routes/category/components/product-card/index.tsx b/src/routes/category/components/product-card/index.tsx index a6abe33..6b83d98 100644 --- a/src/routes/category/components/product-card/index.tsx +++ b/src/routes/category/components/product-card/index.tsx @@ -1,12 +1,42 @@ -import { Link } from "react-router"; +import { Link, useNavigate } from "react-router"; import type { Product } from "@/models/product.model"; +import { Button } from "@/components/ui"; interface ProductCardProps { product: Product; + categorySlug: string; } -export function ProductCard({ product }: ProductCardProps) { +export function ProductCard({ product, categorySlug }: ProductCardProps) { + const navigate = useNavigate(); + let variantTitle: string | null = null; + let variants: string[] = []; + let variantParamName: "size" | "measure" | null = null; + + if (categorySlug === "polos") { + variantTitle = "Elige la talla"; + variants = ["Small", "Medium", "Large"]; + variantParamName = "size"; + } else if (categorySlug === "stickers") { + variantTitle = "Elige la medida"; + variants = ["3*3", "5*5", "10*10"]; + variantParamName = "measure"; + } + + const handleVariantClick = ( + e: React.MouseEvent, + variant: string + ) => { + e.preventDefault(); + e.stopPropagation(); + if (variantParamName) { + const paramValue = + variantParamName === "size" ? variant.toLowerCase() : variant; + navigate(`/products/${product.id}?${variantParamName}=${paramValue}`); + } + }; + return (
-
+
{product.title} + {variantTitle && ( +
+

{variantTitle}

+
+ {variants.map((variant) => ( + + ))} +
+
+ )}

{product.title}

diff --git a/src/routes/category/index.tsx b/src/routes/category/index.tsx index 7c0aef5..a165661 100644 --- a/src/routes/category/index.tsx +++ b/src/routes/category/index.tsx @@ -82,7 +82,11 @@ export default function Category({ loaderData }: Route.ComponentProps) { />
{products.map((product) => ( - + ))}
diff --git a/src/routes/product/index.tsx b/src/routes/product/index.tsx index 88bbffd..106efe2 100644 --- a/src/routes/product/index.tsx +++ b/src/routes/product/index.tsx @@ -1,5 +1,5 @@ -import { useState } from "react"; -import { Form, useNavigation } from "react-router"; +import { useEffect, useState } from "react"; +import { Form, useNavigation, useSearchParams } from "react-router"; import { VariantSelector } from "@/components/product/VariantSelector"; import { Button, Container, Separator } from "@/components/ui"; @@ -22,17 +22,41 @@ export async function loader({ params }: Route.LoaderArgs) { export default function Product({ loaderData }: Route.ComponentProps) { const { product } = loaderData; const navigation = useNavigation(); + const [searchParams] = useSearchParams(); const cartLoading = navigation.state === "submitting"; - // Si el producto tiene variantes, selecciona la primera por defecto - const [selectedSize, setSelectedSize] = useState( - product?.variants?.[0]?.size ?? "" - ); + const getInitialSize = () => { + const isValidSize = (size: string | null) => { + return size === "small" || size === "medium" || size === "large"; + }; + const sizeFromUrl = searchParams.get("size"); + const availableSizes = product?.variants?.map((v) => v.size) || []; + if (isValidSize(sizeFromUrl) && availableSizes.includes(sizeFromUrl)) { + return sizeFromUrl; + } + return product?.variants?.[0]?.size ?? ""; + }; - // Si el producto tiene variantes de stickers, selecciona la primera por defecto - const [selectedMeasure, setSelectedMeasure] = useState( - product?.stickersVariants?.[0]?.measure ?? "" - ); + const getInitialMeasure = () => { + const isValidMeasure = (measure: string | null) => { + return measure === "3*3" || measure === "5*5" || measure === "10*10"; + }; + const measureFromUrl = searchParams.get("measure"); + const availableMeasures = + product?.stickersVariants?.map((v) => v.measure) || []; + if (isValidMeasure(measureFromUrl) && availableMeasures.includes(measureFromUrl)) { + return measureFromUrl; + } + return product?.stickersVariants?.[0]?.measure ?? ""; + }; + + const [selectedSize, setSelectedSize] = useState(getInitialSize); + const [selectedMeasure, setSelectedMeasure] = useState(getInitialMeasure); + + useEffect(() => { + setSelectedSize(getInitialSize); + setSelectedMeasure(getInitialMeasure); + }, [searchParams, product?.id]); if (!product) { return ;