From b09d189d36989f2eaa37917537e5e38f9760fb6a Mon Sep 17 00:00:00 2001 From: Kellyarias02 Date: Wed, 27 Aug 2025 20:23:46 -0500 Subject: [PATCH] Refactor: to add interactivity hover category stickers and to improve the user experiencie. --- .../components/product-card/index.tsx | 33 ++++++++++++++- src/routes/category/index.tsx | 4 +- src/services/product.service.ts | 40 +++++++++++++------ 3 files changed, 60 insertions(+), 17 deletions(-) diff --git a/src/routes/category/components/product-card/index.tsx b/src/routes/category/components/product-card/index.tsx index 6b83d98..58b40a2 100644 --- a/src/routes/category/components/product-card/index.tsx +++ b/src/routes/category/components/product-card/index.tsx @@ -1,4 +1,5 @@ import { Link, useNavigate } from "react-router"; +import { useState } from "react"; import type { Product } from "@/models/product.model"; import { Button } from "@/components/ui"; @@ -10,17 +11,24 @@ interface ProductCardProps { export function ProductCard({ product, categorySlug }: ProductCardProps) { const navigate = useNavigate(); + const [hoveredPrice, setHoveredPrice] = useState(null); let variantTitle: string | null = null; let variants: string[] = []; let variantParamName: "size" | "measure" | null = null; + const variantMap: Record = { + "3*3": "3*3", + "5*5": "5*5", + "10*10": "10*10" + }; + 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"]; + variants = ["3*3", "5*5", "10*10"]; variantParamName = "measure"; } @@ -37,6 +45,23 @@ export function ProductCard({ product, categorySlug }: ProductCardProps) { } }; + const hoverVariantClick = (variant: string) => { + if (variantParamName === "measure") { + if (product.stickersVariants && product.stickersVariants.length > 0) { + const variantPrice = product.stickersVariants.find( + (v) => v.measure === variant + )?.price; + setHoveredPrice(variantPrice || null); + } else { + setHoveredPrice(null); + } + } + }; + + const handleMouseLeave = () => { + setHoveredPrice(null); + }; + return ( handleVariantClick(e, variant)} + onMouseEnter={() => hoverVariantClick(variant)} + onMouseLeave={handleMouseLeave} > {variant} @@ -70,7 +97,9 @@ export function ProductCard({ product, categorySlug }: ProductCardProps) {

{product.title}

{product.description}

-

S/{product.price}

+

+ S/{hoveredPrice !== null ? hoveredPrice : product.price} +

{product.isOnSale && ( diff --git a/src/routes/category/index.tsx b/src/routes/category/index.tsx index a165661..b6b36b8 100644 --- a/src/routes/category/index.tsx +++ b/src/routes/category/index.tsx @@ -92,6 +92,6 @@ export default function Category({ loaderData }: Route.ComponentProps) { - - ); +     +  ); } diff --git a/src/services/product.service.ts b/src/services/product.service.ts index 65f729c..a7a35ca 100644 --- a/src/services/product.service.ts +++ b/src/services/product.service.ts @@ -4,19 +4,6 @@ import type { Product } from "@/models/product.model"; import { getCategoryBySlug } from "./category.service"; -export async function getProductsByCategorySlug( - categorySlug: Category["slug"] -): Promise { - const category = await getCategoryBySlug(categorySlug); - const products = await prisma.product.findMany({ - where: { categoryId: category.id }, - }); - - return products.map((product) => ({ - ...product, - price: product.price.toNumber(), - })); -} export async function getProductById(id: number): Promise { const product = await prisma.product.findUnique({ @@ -48,3 +35,30 @@ export async function getAllProducts(): Promise { price: p.price.toNumber(), })); } + +export async function getProductsByCategorySlug( + categorySlug: Category["slug"] +): Promise { + const category = await getCategoryBySlug(categorySlug); + const products = await prisma.product.findMany({ + where: { categoryId: category.id }, + include: { + stickersVariants: true, + variants: true + }, + }); + + return products.map((product) => ({ + ...product, + price: product.price.toNumber(), + variants: product.variants?.map(v => ({ + id: v.id, + size: v.size as "small" | "medium" | "large", + })), + stickersVariants: product.stickersVariants?.map(s => ({ + id: s.id, + measure: s.measure as "3*3" | "5*5" | "10*10", + price: s.price.toNumber(), + })), + })); +}