From ccc1059598bb5fe7d570b5d13eba2ae7de4fe8d1 Mon Sep 17 00:00:00 2001 From: mike Date: Fri, 29 Aug 2025 00:49:04 -0500 Subject: [PATCH] feat: refactor cart and product models to use attributeValueId, update related functions and components --- src/lib/cart.ts | 11 +++--- src/models/cart.model.ts | 2 +- src/models/product.model.ts | 1 + src/routes/cart/add-item/index.tsx | 4 +-- src/routes/cart/index.tsx | 12 +++---- src/routes/checkout/index.tsx | 2 +- src/routes/product/index.tsx | 58 ++++++++++++++++++++++-------- src/services/cart.service.ts | 8 ++--- 8 files changed, 65 insertions(+), 33 deletions(-) diff --git a/src/lib/cart.ts b/src/lib/cart.ts index e0308df..537a129 100644 --- a/src/lib/cart.ts +++ b/src/lib/cart.ts @@ -1,5 +1,6 @@ import type { CartItem, CartItemInput } from "@/models/cart.model"; -import { type Product } from "@/models/product.model"; +// import { type Product } from "@/models/product.model"; +import { type VariantAttributeValue } from "@/models/variant-attribute.model"; import { alterQuantityCartItem, deleteRemoteCartItem, @@ -18,14 +19,14 @@ export async function getCart(userId?: number, sessionCartId?: string) { export async function addToCart( userId: number | undefined, sessionCartId: string | undefined, - productId: Product["id"], + attributeValueId: VariantAttributeValue["id"], quantity: number = 1 ) { try { const updatedCart = await alterQuantityCartItem( userId, sessionCartId, - productId, + attributeValueId, quantity ); return updatedCart; @@ -62,10 +63,10 @@ export function calculateTotal(items: CartItem[] | CartItemInput[]): number { // Type guard to determine which type we're working with if ("product" in item) { // CartItem - has a product property - return total + item.product.price * item.quantity; + return total + Number(item.product.price) * item.quantity; } else { // CartItemInput - has price directly - return total + item.price * item.quantity; + return total + Number(item.price) * item.quantity; } }, 0); } diff --git a/src/models/cart.model.ts b/src/models/cart.model.ts index 8550190..53333ce 100644 --- a/src/models/cart.model.ts +++ b/src/models/cart.model.ts @@ -33,7 +33,7 @@ export type CartProductInfo = Pick< export type CartItemWithProduct = { product: CartProductInfo; quantity: number; - attributeId: number; + attributeValueId: number; }; // Tipo para el carrito con items y productos incluidos diff --git a/src/models/product.model.ts b/src/models/product.model.ts index 489125f..47259f5 100644 --- a/src/models/product.model.ts +++ b/src/models/product.model.ts @@ -5,6 +5,7 @@ export type Product = PrismaProduct & { price?: number | null; minPrice?: number | null; maxPrice?: number | null; + variantAttributeValues?: VariantAttributeValue[]; }; export type ProductVariantValue = PrismaProduct & { diff --git a/src/routes/cart/add-item/index.tsx b/src/routes/cart/add-item/index.tsx index ac49758..06745d1 100644 --- a/src/routes/cart/add-item/index.tsx +++ b/src/routes/cart/add-item/index.tsx @@ -7,14 +7,14 @@ import type { Route } from "../+types"; export async function action({ request }: Route.ActionArgs) { const formData = await request.formData(); - const productId = Number(formData.get("productId")); + const attributeValueId = Number(formData.get("attributeValueId")); const quantity = Number(formData.get("quantity")) || 1; const redirectTo = formData.get("redirectTo") as string | null; const session = await getSession(request.headers.get("Cookie")); const sessionCartId = session.get("sessionCartId"); const userId = session.get("userId"); - await addToCart(userId, sessionCartId, productId, quantity); + await addToCart(userId, sessionCartId, attributeValueId, quantity); return redirect(redirectTo || "/cart"); } diff --git a/src/routes/cart/index.tsx b/src/routes/cart/index.tsx index d330cef..e80a88b 100644 --- a/src/routes/cart/index.tsx +++ b/src/routes/cart/index.tsx @@ -30,7 +30,7 @@ export default function Cart({ loaderData }: Route.ComponentProps) { Carrito de compras
- {cart?.items?.map(({ product, quantity, id }) => ( + {cart?.items?.map(({ product, quantity, id, attributeValueId }) => (

- ${product.price.toFixed(2)} + ${product.price!.toFixed(2)}

diff --git a/src/routes/checkout/index.tsx b/src/routes/checkout/index.tsx index 5bfbbde..8b23f33 100644 --- a/src/routes/checkout/index.tsx +++ b/src/routes/checkout/index.tsx @@ -266,7 +266,7 @@ export default function Checkout({

{quantity}

-

S/{product.price.toFixed(2)}

+

S/{product.price!.toFixed(2)}

diff --git a/src/routes/product/index.tsx b/src/routes/product/index.tsx index da547f3..545544c 100644 --- a/src/routes/product/index.tsx +++ b/src/routes/product/index.tsx @@ -1,9 +1,12 @@ -import { Form, useNavigation } from "react-router"; import { useState } from "react"; +import { Form, useNavigation } from "react-router"; + import { Button, Container, Separator } from "@/components/ui"; import { type Product } from "@/models/product.model"; import { getProductById } from "@/services/product.service"; + import NotFound from "../not-found"; + import type { Route } from "./+types"; export async function loader({ params }: Route.LoaderArgs) { @@ -26,7 +29,18 @@ export default function Product({ loaderData }: Route.ComponentProps) { } const showSizeSelector = product.categoryId === 1 || product.categoryId === 3; - + + const getAttributeValueId = () => { // AQUI TRAER EL AttributeValueId con el cambio de SEBAS + if ( + !product.variantAttributeValues || + product.variantAttributeValues.length === 0 + ) { + return undefined; + } + // Devuelve el attributeId de la posición 0 + return product.variantAttributeValues[0].id; + }; + const getSizeOptions = () => { if (product.categoryId === 3) { return { @@ -34,8 +48,8 @@ export default function Product({ loaderData }: Route.ComponentProps) { options: [ { value: "Small", label: "3x3 cm" }, { value: "Medium", label: "5x5 cm" }, - { value: "Large", label: "10x10 cm" } - ] + { value: "Large", label: "10x10 cm" }, + ], }; } else { return { @@ -43,8 +57,8 @@ export default function Product({ loaderData }: Route.ComponentProps) { options: [ { value: "Small", label: "Small" }, { value: "Medium", label: "Medium" }, - { value: "Large", label: "Large" } - ] + { value: "Large", label: "Large" }, + ], }; } }; @@ -67,7 +81,14 @@ export default function Product({ loaderData }: Route.ComponentProps) { {product.title} {showSizeSelector && ( - {" "}({sizeOptions.options.find(option => option.value === selectedSize)?.label}) + {" "} + ( + { + sizeOptions.options.find( + (option) => option.value === selectedSize + )?.label + } + ) )} @@ -78,12 +99,16 @@ export default function Product({ loaderData }: Route.ComponentProps) { {showSizeSelector && (
-

{sizeOptions.label}

+

+ {sizeOptions.label} +

{sizeOptions.options.map((option) => ( - + - +

Características @@ -129,4 +159,4 @@ export default function Product({ loaderData }: Route.ComponentProps) { ); -} \ No newline at end of file +} diff --git a/src/services/cart.service.ts b/src/services/cart.service.ts index af05fa3..417bcbb 100644 --- a/src/services/cart.service.ts +++ b/src/services/cart.service.ts @@ -138,7 +138,7 @@ export async function createRemoteItems( await prisma.cartItem.createMany({ data: items.map((item) => ({ cartId: cart.id, - attributeValueId: item.attributeId, // modificar + attributeValueId: item.attributeValueId, quantity: item.quantity, })), }); @@ -154,13 +154,13 @@ export async function createRemoteItems( export async function alterQuantityCartItem( userId: User["id"] | undefined, sessionCartId: string | undefined, - attributeId: number, + attributeValueId: number, quantity: number = 1 ): Promise { const cart = await getOrCreateCart(userId, sessionCartId); const existingItem = cart.items.find( - (item) => item.attributeValueId === attributeId + (item) => item.attributeValueId === attributeValueId ); if (existingItem) { @@ -180,7 +180,7 @@ export async function alterQuantityCartItem( await prisma.cartItem.create({ data: { cartId: cart.id, - attributeValueId: attributeId, + attributeValueId: attributeValueId, quantity, }, });