diff --git a/prisma/migrations/20250822015032_update_table_cart_with_attribute_id/migration.sql b/prisma/migrations/20250822015032_update_table_cart_with_attribute_id/migration.sql
new file mode 100644
index 0000000..aab9f1b
--- /dev/null
+++ b/prisma/migrations/20250822015032_update_table_cart_with_attribute_id/migration.sql
@@ -0,0 +1,23 @@
+/*
+ Warnings:
+
+ - You are about to drop the column `product_id` on the `cart_items` table. All the data in the column will be lost.
+ - A unique constraint covering the columns `[cart_id,attribute_value_id]` on the table `cart_items` will be added. If there are existing duplicate values, this will fail.
+ - Added the required column `attribute_value_id` to the `cart_items` table without a default value. This is not possible if the table is not empty.
+
+*/
+-- DropForeignKey
+ALTER TABLE "cart_items" DROP CONSTRAINT "cart_items_product_id_fkey";
+
+-- DropIndex
+DROP INDEX "cart_items_cart_id_product_id_key";
+
+-- AlterTable
+ALTER TABLE "cart_items" DROP COLUMN "product_id",
+ADD COLUMN "attribute_value_id" INTEGER NOT NULL;
+
+-- CreateIndex
+CREATE UNIQUE INDEX "cart_items_cart_id_attribute_value_id_key" ON "cart_items"("cart_id", "attribute_value_id");
+
+-- AddForeignKey
+ALTER TABLE "cart_items" ADD CONSTRAINT "cart_items_attribute_value_id_fkey" FOREIGN KEY ("attribute_value_id") REFERENCES "variants_attributes_values"("id") ON DELETE CASCADE ON UPDATE CASCADE;
diff --git a/prisma/schema.prisma b/prisma/schema.prisma
index d251f4a..b8df94a 100644
--- a/prisma/schema.prisma
+++ b/prisma/schema.prisma
@@ -63,7 +63,7 @@ model Product {
updatedAt DateTime @default(now()) @map("updated_at") @db.Timestamp(0)
category Category? @relation(fields: [categoryId], references: [id], onDelete: SetNull)
- cartItems CartItem[]
+
orderItems OrderItem[]
variantAttributeValues VariantAttributeValue[]
@@ -92,6 +92,8 @@ model VariantAttributeValue {
variantAttribute VariantAttribute @relation(fields: [attributeId], references: [id])
product Product @relation(fields: [productId], references: [id])
+
+ CartItem CartItem[]
@@unique([attributeId, productId, value], name: "unique_attribute_product_value")
@@map("variants_attributes_values")
@@ -113,15 +115,15 @@ model Cart {
model CartItem {
id Int @id @default(autoincrement())
cartId Int @map("cart_id")
- productId Int @map("product_id")
+ attributeValueId Int @map("attribute_value_id")
quantity Int
createdAt DateTime @default(now()) @map("created_at") @db.Timestamp(0)
updatedAt DateTime @default(now()) @map("updated_at") @db.Timestamp(0)
cart Cart @relation(fields: [cartId], references: [id], onDelete: Cascade)
- product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
+ variantAttributeValue VariantAttributeValue @relation(fields: [attributeValueId], references: [id], onDelete: Cascade)
- @@unique([cartId, productId], name: "unique_cart_item")
+ @@unique([cartId, attributeValueId], name: "unique_cart_item")
@@map("cart_items")
}
diff --git a/src/models/cart.model.ts b/src/models/cart.model.ts
index ad4206a..8550190 100644
--- a/src/models/cart.model.ts
+++ b/src/models/cart.model.ts
@@ -33,6 +33,7 @@ export type CartProductInfo = Pick<
export type CartItemWithProduct = {
product: CartProductInfo;
quantity: number;
+ attributeId: number;
};
// Tipo para el carrito con items y productos incluidos
diff --git a/src/routes/category/components/product-card/index.tsx b/src/routes/category/components/product-card/index.tsx
index 05d36bd..23c402b 100644
--- a/src/routes/category/components/product-card/index.tsx
+++ b/src/routes/category/components/product-card/index.tsx
@@ -1,16 +1,17 @@
import { Link } from "react-router";
+
import type { Product } from "@/models/product.model";
interface ProductCardProps {
product: Product;
}
-const stickerCategoryId = 3;
+const stickerCategoryId = 3; // ID de la categorÃa "Stickers"
export function ProductCard({ product }: ProductCardProps) {
-
- const isSticker = stickerCategoryId;
-
+
+ const isSticker = product.categoryId === stickerCategoryId;
+
return (
<>
= min
}
+
if (max) {
return (productPrice||maxProductPrice) <= max
-
}
return true
});
diff --git a/src/services/cart.service.ts b/src/services/cart.service.ts
index 74cbdfc..af05fa3 100644
--- a/src/services/cart.service.ts
+++ b/src/services/cart.service.ts
@@ -18,52 +18,46 @@ async function getCart(
: undefined;
if (!whereCondition) return null;
- try {
- const data = await prisma.cart.findFirst({
- where: whereCondition,
- include: {
- items: {
- include: {
- product: {
- select: {
- id: true,
- title: true,
- imgSrc: true,
- alt: true,
- price: true,
- isOnSale: true,
+ const data = await prisma.cart.findFirst({
+ where: whereCondition,
+ include: {
+ items: {
+ include: {
+ variantAttributeValue: {
+ include: {
+ product: {
+ select: {
+ id: true,
+ title: true,
+ imgSrc: true,
+ alt: true,
+ isOnSale: true,
+ },
},
},
},
- orderBy: {
- id: "asc",
- },
},
- },
- });
-
- if (!data) return null;
-
- return {
- ...data,
- items: data.items.map((item) => ({
- ...item,
- product: {
- ...item.product,
- price: item.product.price.toNumber(),
+ orderBy: {
+ id: "asc",
},
- })),
- };
- }catch(e) {
- console.log(e)
- return {
- error: true,
- status: 500,
- message: "Error al obtener el carrito. Verifica el modelo Product.",
- };
- }
+ },
+ },
+ });
+ if (!data) return null;
+
+ return {
+ ...data,
+ items: data.items.map((item) => ({
+ ...item,
+ product: {
+ ...item.variantAttributeValue.product,
+ price: item.variantAttributeValue.price.toNumber(),
+ },
+ variantAttributeValue: item.variantAttributeValue,
+ })),
+ };
}
export async function getRemoteCart(
@@ -92,14 +86,17 @@ export async function getOrCreateCart(
include: {
items: {
include: {
- product: {
- select: {
- id: true,
- title: true,
- imgSrc: true,
- alt: true,
- price: true,
- isOnSale: true,
+ variantAttributeValue: {
+ include: {
+ product: {
+ select: {
+ id: true,
+ title: true,
+ imgSrc: true,
+ alt: true,
+ isOnSale: true,
+ },
+ },
},
},
},
@@ -114,9 +111,10 @@ export async function getOrCreateCart(
items: newCart.items.map((item) => ({
...item,
product: {
- ...item.product,
- price: item.product.price.toNumber(),
+ ...item.variantAttributeValue.product,
+ price: item.variantAttributeValue.price.toNumber(),
},
+ variantAttributeValue: item.variantAttributeValue,
})),
};
}
@@ -140,7 +138,7 @@ export async function createRemoteItems(
await prisma.cartItem.createMany({
data: items.map((item) => ({
cartId: cart.id,
- productId: item.product.id,
+ attributeValueId: item.attributeId, // modificar
quantity: item.quantity,
})),
});
@@ -156,12 +154,14 @@ export async function createRemoteItems(
export async function alterQuantityCartItem(
userId: User["id"] | undefined,
sessionCartId: string | undefined,
- productId: number,
+ attributeId: number,
quantity: number = 1
): Promise {
const cart = await getOrCreateCart(userId, sessionCartId);
- const existingItem = cart.items.find((item) => item.product.id === productId);
+ const existingItem = cart.items.find(
+ (item) => item.attributeValueId === attributeId
+ );
if (existingItem) {
const newQuantity = existingItem.quantity + quantity;
@@ -180,7 +180,7 @@ export async function alterQuantityCartItem(
await prisma.cartItem.create({
data: {
cartId: cart.id,
- productId,
+ attributeValueId: attributeId,
quantity,
},
});
@@ -246,14 +246,17 @@ export async function linkCartToUser(
include: {
items: {
include: {
- product: {
- select: {
- id: true,
- title: true,
- imgSrc: true,
- alt: true,
- price: true,
- isOnSale: true,
+ variantAttributeValue: {
+ include: {
+ product: {
+ select: {
+ id: true,
+ title: true,
+ imgSrc: true,
+ alt: true,
+ isOnSale: true,
+ },
+ },
},
},
},
@@ -268,9 +271,10 @@ export async function linkCartToUser(
items: updatedCart.items.map((item) => ({
...item,
product: {
- ...item.product,
- price: item.product.price.toNumber(),
+ ...item.variantAttributeValue.product,
+ price: item.variantAttributeValue.price.toNumber(),
},
+ variantAttributeValue: item.variantAttributeValue,
})),
};
}
@@ -295,41 +299,48 @@ export async function mergeGuestCartWithUserCart(
include: {
items: {
include: {
- product: {
- select: {
- id: true,
- title: true,
- imgSrc: true,
- alt: true,
- price: true,
- isOnSale: true,
+ variantAttributeValue: {
+ include: {
+ product: {
+ select: {
+ id: true,
+ title: true,
+ imgSrc: true,
+ alt: true,
+ isOnSale: true,
+ },
+ },
},
},
},
},
},
});
+
return {
...updatedCart,
items: updatedCart.items.map((item) => ({
...item,
product: {
- ...item.product,
- price: item.product.price.toNumber(),
+ ...item.variantAttributeValue.product,
+ price: item.variantAttributeValue.price.toNumber(),
},
+ variantAttributeValue: item.variantAttributeValue,
})),
};
}
// Obtener productos duplicados para eliminarlos del carrito del usuario
- const guestProductIds = guestCart.items.map((item) => item.productId);
+ const guestAttributeValueIds = guestCart.items.map(
+ (item) => item.attributeValueId
+ );
// Eliminar productos del carrito usuario que también existan en el carrito invitado
await prisma.cartItem.deleteMany({
where: {
cartId: userCart.id,
- productId: {
- in: guestProductIds,
+ attributeValueId: {
+ in: guestAttributeValueIds,
},
},
});
@@ -338,7 +349,7 @@ export async function mergeGuestCartWithUserCart(
await prisma.cartItem.createMany({
data: guestCart.items.map((item) => ({
cartId: userCart.id,
- productId: item.productId,
+ attributeValueId: item.attributeValueId,
quantity: item.quantity,
})),
});
@@ -351,3 +362,4 @@ export async function mergeGuestCartWithUserCart(
// Devolver el carrito actualizado del usuario
return await getCart(userId);
}
+