Skip to content

Commit e80ed14

Browse files
committed
refactor: add functions to add variants for category polos
1 parent d8699c5 commit e80ed14

File tree

6 files changed

+65
-26
lines changed

6 files changed

+65
-26
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/*
2+
Warnings:
3+
4+
- A unique constraint covering the columns `[cartId,productId,productVariantId]` on the table `cart_items` will be added. If there are existing duplicate values, this will fail.
5+
6+
*/
7+
-- DropIndex
8+
DROP INDEX "cart_items_cartId_productId_key";
9+
10+
-- CreateIndex
11+
CREATE UNIQUE INDEX "cart_items_cartId_productId_productVariantId_key" ON "cart_items"("cartId", "productId", "productVariantId");

prisma/schema.prisma

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ model CartItem {
106106
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
107107
productVariant ProductVariant? @relation("CartItemToProductVariant", fields: [productVariantId], references: [id])
108108
109-
@@unique([cartId, productId], name: "unique_cart_item")
109+
@@unique([cartId, productId, productVariantId], name: "unique_cart_item")
110110
@@map("cart_items")
111111
}
112112

src/models/cart.model.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@ import type {
66
} from "@/../generated/prisma/client";
77

88
export type CartItem = PrismaCartItem & {
9-
product: Pick<
10-
Product,
11-
"id" | "title" | "imgSrc" | "alt" | "price" | "isOnSale"
12-
>;
9+
product: Pick<Product, "id" | "title" | "imgSrc" | "alt" | "price" | "isOnSale">;
10+
productVariant?: {
11+
id: number;
12+
size: "small" | "medium" | "large";
13+
} | null;
1314
};
1415

1516
export type Cart = PrismaCart;

src/routes/cart/index.tsx

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { type Cart } from "@/models/cart.model";
77
import { getSession } from "@/session.server";
88

99
import type { Route } from "./+types";
10+
import { productVariant } from "prisma/initial_data";
1011

1112
export async function loader({ request }: Route.LoaderArgs) {
1213
const session = await getSession(request.headers.get("Cookie"));
@@ -30,8 +31,8 @@ export default function Cart({ loaderData }: Route.ComponentProps) {
3031
Carrito de compras
3132
</h1>
3233
<div className="border-solid border rounded-xl flex flex-col">
33-
{cart?.items?.map(({ product, quantity, id }) => (
34-
<div key={product.id} className="flex gap-7 p-6 border-b">
34+
{cart?.items?.map(({ product, quantity, id, productVariant }) => (
35+
<div key={id} className="flex gap-7 p-6 border-b">
3536
<div className="w-20 rounded-xl bg-muted">
3637
<img
3738
src={product.imgSrc}
@@ -41,7 +42,14 @@ export default function Cart({ loaderData }: Route.ComponentProps) {
4142
</div>
4243
<div className="flex grow flex-col justify-between">
4344
<div className="flex gap-4 justify-between items-center">
44-
<h2 className="text-sm">{product.title}</h2>
45+
<h2 className="text-sm">
46+
{product.title}
47+
{productVariant && (
48+
<span className="ml-2 text-xs text-muted-foreground">
49+
({productVariant.size})
50+
</span>
51+
)}
52+
</h2>
4553
<Form method="post" action="/cart/remove-item">
4654
<Button
4755
size="sm-icon"
@@ -60,6 +68,10 @@ export default function Cart({ loaderData }: Route.ComponentProps) {
6068
<div className="flex gap-4 items-center">
6169
<Form method="post" action="/cart/add-item">
6270
<input type="hidden" name="quantity" value="-1" />
71+
{productVariant && (
72+
<input type="hidden" name="size" value={productVariant.size} />
73+
)}
74+
<input type="hidden" name="productId" value={product.id} />
6375
<Button
6476
name="productId"
6577
value={product.id}
@@ -74,6 +86,10 @@ export default function Cart({ loaderData }: Route.ComponentProps) {
7486
{quantity}
7587
</span>
7688
<Form method="post" action="/cart/add-item">
89+
{productVariant && (
90+
<input type="hidden" name="size" value={productVariant.size} />
91+
)}
92+
<input type="hidden" name="productId" value={product.id} />
7793
<Button
7894
variant="outline"
7995
size="sm-icon"

src/routes/checkout/index.tsx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ export async function action({ request }: Route.ActionArgs) {
109109
title: item.product.title,
110110
price: item.product.price,
111111
imgSrc: item.product.imgSrc,
112+
productVariantTitle: item.productVariant?.size || null,
112113
}));
113114

114115
const { id: orderId } = await createOrder(
@@ -249,9 +250,9 @@ export default function Checkout({
249250
<div className="flex-grow">
250251
<h2 className="text-lg font-medium mb-4">Resumen de la orden</h2>
251252
<div className="border border-border rounded-xl bg-background flex flex-col">
252-
{cart?.items?.map(({ product, quantity }) => (
253+
{cart?.items?.map(({ product, quantity, id, productVariant }) => (
253254
<div
254-
key={product.id}
255+
key={id}
255256
className="flex gap-6 p-6 border-b border-border"
256257
>
257258
<div className="w-20 rounded-xl bg-muted">
@@ -262,7 +263,14 @@ export default function Checkout({
262263
/>
263264
</div>
264265
<div className="flex flex-col justify-between flex-grow">
265-
<h3 className="text-sm leading-5">{product.title}</h3>
266+
<h2 className="text-sm">
267+
{product.title}
268+
{productVariant && (
269+
<span className="ml-2 text-xs text-muted-foreground">
270+
({productVariant.size})
271+
</span>
272+
)}
273+
</h2>
266274
<div className="flex text-sm font-medium gap-4 items-center self-end">
267275
<p>{quantity}</p>
268276
<X className="w-4 h-4" />

src/services/cart.service.ts

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,20 @@ async function getCart(
3838

3939
return {
4040
...data,
41-
items: data.items.map((item) => ({
41+
items: data.items.map((item: any) => ({
4242
...item,
4343
product: {
4444
...item.product,
4545
price: typeof item.product.price === "object"
4646
? item.product.price.toNumber()
4747
: item.product.price,
4848
},
49-
productVariant: item.productVariant ?? null,
49+
productVariant: item.productVariant
50+
? {
51+
id: item.productVariant.id,
52+
size: item.productVariant.size as "small" | "medium" | "large",
53+
}
54+
: null,
5055
productVariantId: item.productVariantId ?? null,
5156
})),
5257
};
@@ -94,15 +99,15 @@ export async function getOrCreateCart(
9499

95100
return {
96101
...newCart,
97-
items: newCart.items.map((item) => ({
102+
items: newCart.items.map((item: any) => ({
98103
...item,
99104
product: {
100105
...item.product,
101106
price: typeof item.product.price === "object"
102107
? item.product.price.toNumber()
103108
: item.product.price,
104-
},
105-
productVariant: item.productVariant ?? null,
109+
} as any, // Cast to any to resolve type issues
110+
productVariant: item.productVariant ?? null, // Ensure productVariant is null if undefined
106111
productVariantId: item.productVariantId ?? null,
107112
})),
108113
};
@@ -153,10 +158,8 @@ export async function alterQuantityCartItem(
153158
// Busca por productId y productVariantId (si existe)
154159
const existingItem = cart.items.find(
155160
(item) =>
156-
item.product.id === productId &&
157-
(productVariantId
158-
? item.productVariantId === productVariantId
159-
: !item.productVariantId)
161+
item.productId === productId &&
162+
item.productVariantId === (productVariantId ?? null)
160163
);
161164

162165
if (existingItem) {
@@ -254,15 +257,15 @@ export async function linkCartToUser(
254257

255258
return {
256259
...updatedCart,
257-
items: updatedCart.items.map((item) => ({
260+
items: updatedCart.items.map((item: any) => ({
258261
...item,
259262
product: {
260263
...item.product,
261264
price: typeof item.product.price === "object"
262265
? item.product.price.toNumber()
263266
: item.product.price,
264-
},
265-
productVariant: item.productVariant ?? null,
267+
} as any, // Cast to any to resolve type issues
268+
productVariant: item.productVariant ?? null, // Ensure productVariant is null if undefined
266269
productVariantId: item.productVariantId ?? null,
267270
})),
268271
};
@@ -295,15 +298,15 @@ export async function mergeGuestCartWithUserCart(
295298
},
296299
});
297300
return {
298-
...updatedCart,
299-
items: updatedCart.items.map((item) => ({
301+
...updatedCart, // Spread the updatedCart object
302+
items: updatedCart.items.map((item: any) => ({ // Map over items, casting item to any
300303
...item,
301304
product: {
302305
...item.product,
303306
price: typeof item.product.price === "object"
304307
? item.product.price.toNumber()
305308
: item.product.price,
306-
},
309+
} as any, // Cast product to any to resolve type issues
307310
productVariant: item.productVariant ?? null,
308311
productVariantId: item.productVariantId ?? null,
309312
})),

0 commit comments

Comments
 (0)