Skip to content

Commit 8cf348c

Browse files
authored
Merge pull request #258 from codeableorg/branch-Jeff2
Branch jeff2
2 parents 88f5c16 + 2c65377 commit 8cf348c

File tree

15 files changed

+367
-61
lines changed

15 files changed

+367
-61
lines changed

prisma/initial_data.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,17 @@ export const productVariant = [
4242
{ productTitle: "Polo It Works On My Machine", sizes: ["small", "medium", "large"] },
4343
];
4444

45+
export const stickersVariant = [
46+
{ productTitle: "Sticker JavaScript", measure: ["3*3", "5*5", "10*10"] },
47+
{ productTitle: "Sticker React", measure: ["3*3", "5*5", "10*10"] },
48+
{ productTitle: "Sticker Git", measure: ["3*3", "5*5", "10*10"] },
49+
{ productTitle: "Sticker Docker", measure: ["3*3", "5*5", "10*10"] },
50+
{ productTitle: "Sticker Linux", measure: ["3*3", "5*5", "10*10"] },
51+
{ productTitle: "Sticker VS Code", measure: ["3*3", "5*5", "10*10"] },
52+
{ productTitle: "Sticker GitHub", measure: ["3*3", "5*5", "10*10"] },
53+
{ productTitle: "Sticker HTML", measure: ["3*3", "5*5", "10*10"] },
54+
];
55+
4556
export const products = [
4657
{
4758
title: "Polo React",
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
Warnings:
3+
4+
- A unique constraint covering the columns `[cartId,productId,productVariantId,stickersVariantId]` 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_productVariantId_key";
9+
10+
-- AlterTable
11+
ALTER TABLE "cart_items" ADD COLUMN "stickersVariantId" INTEGER;
12+
13+
-- CreateTable
14+
CREATE TABLE "stickersVariant" (
15+
"id" SERIAL NOT NULL,
16+
"productId" INTEGER NOT NULL,
17+
"measure" TEXT NOT NULL,
18+
19+
CONSTRAINT "stickersVariant_pkey" PRIMARY KEY ("id")
20+
);
21+
22+
-- CreateIndex
23+
CREATE UNIQUE INDEX "cart_items_cartId_productId_productVariantId_stickersVarian_key" ON "cart_items"("cartId", "productId", "productVariantId", "stickersVariantId");
24+
25+
-- AddForeignKey
26+
ALTER TABLE "stickersVariant" ADD CONSTRAINT "stickersVariant_productId_fkey" FOREIGN KEY ("productId") REFERENCES "products"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
27+
28+
-- AddForeignKey
29+
ALTER TABLE "cart_items" ADD CONSTRAINT "cart_items_stickersVariantId_fkey" FOREIGN KEY ("stickersVariantId") REFERENCES "stickersVariant"("id") ON DELETE SET NULL ON UPDATE CASCADE;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/*
2+
Warnings:
3+
4+
- Added the required column `price` to the `cart_items` table without a default value. This is not possible if the table is not empty.
5+
- Added the required column `price` to the `stickersVariant` table without a default value. This is not possible if the table is not empty.
6+
7+
*/
8+
-- AlterTable
9+
ALTER TABLE "cart_items" ADD COLUMN "price" DECIMAL(10,2) NOT NULL;
10+
11+
-- AlterTable
12+
ALTER TABLE "stickersVariant" ADD COLUMN "price" DECIMAL(10,2) NOT NULL;

prisma/schema.prisma

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ model Product {
6363
createdAt DateTime @default(now()) @map("created_at") @db.Timestamp(0)
6464
updatedAt DateTime @default(now()) @map("updated_at") @db.Timestamp(0)
6565
variants ProductVariant[]
66+
stickersVariants stickersVariant[]
6667
6768
category Category? @relation(fields: [categoryId], references: [id], onDelete: SetNull)
6869
cartItems CartItem[]
@@ -80,6 +81,16 @@ model ProductVariant {
8081
cartItems CartItem[] @relation("CartItemToProductVariant")
8182
}
8283

84+
model stickersVariant {
85+
id Int @id @default(autoincrement())
86+
product Product @relation(fields: [productId], references: [id])
87+
productId Int
88+
measure String // '3*3', '5*5', '10*10'
89+
price Decimal @db.Decimal(10, 2)
90+
91+
cartItems CartItem[] @relation("CartItemTostickersVariant")
92+
}
93+
8394
model Cart {
8495
id Int @id @default(autoincrement())
8596
sessionCartId String @unique @default(dbgenerated("gen_random_uuid()")) @map("session_cart_id") @db.Uuid
@@ -98,15 +109,18 @@ model CartItem {
98109
cartId Int
99110
productId Int
100111
productVariantId Int?
112+
stickersVariantId Int?
113+
price Decimal @db.Decimal(10, 2)
101114
quantity Int
102115
createdAt DateTime @default(now()) @map("created_at") @db.Timestamp(0)
103116
updatedAt DateTime @default(now()) @map("updated_at") @db.Timestamp(0)
104117
105118
cart Cart @relation(fields: [cartId], references: [id], onDelete: Cascade)
106119
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
107120
productVariant ProductVariant? @relation("CartItemToProductVariant", fields: [productVariantId], references: [id])
121+
stickersVariant stickersVariant? @relation("CartItemTostickersVariant", fields: [stickersVariantId], references: [id])
108122
109-
@@unique([cartId, productId, productVariantId], name: "unique_cart_item")
123+
@@unique([cartId, productId, productVariantId, stickersVariantId], name: "unique_cart_item")
110124
@@map("cart_items")
111125
}
112126

prisma/seed.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@ const prisma = new PrismaClient();
55

66
// Define las tallas para los productos tipo "Polo"
77
const poloSizes = ["small", "medium", "large"] as const;
8+
// Define el tamaño para los productos tipo "Stickers"
9+
const stickerMeasures = ["3*3", "5*5", "10*10"] as const;
810

911
async function seedDb() {
1012
// Limpia las tablas para evitar duplicados
1113
await prisma.productVariant.deleteMany();
14+
await prisma.stickersVariant.deleteMany();
1215
await prisma.product.deleteMany();
1316
await prisma.category.deleteMany();
1417

@@ -46,6 +49,35 @@ async function seedDb() {
4649
}
4750
console.log("3. Polo variants successfully inserted");
4851
}
52+
53+
// Obtiene los productos tipo "Stickers" para agregar variantes
54+
const stickersCategory = await prisma.category.findUnique({
55+
where: { slug: "stickers" },
56+
});
57+
if (stickersCategory) {
58+
const stickers = await prisma.product.findMany({
59+
where: { categoryId: stickersCategory.id },
60+
});
61+
62+
const stickerPrices: Record<typeof stickerMeasures[number], number> = {
63+
"3*3": 2.99,
64+
"5*5": 5.99,
65+
"10*10": 8.99,
66+
};
67+
68+
for (const sticker of stickers) {
69+
for (const measure of stickerMeasures) {
70+
await prisma.stickersVariant.create({
71+
data: {
72+
productId: sticker.id,
73+
measure,
74+
price: stickerPrices[measure], // Asigna el precio según la medida
75+
},
76+
});
77+
}
78+
}
79+
console.log("4. Stickers variants successfully inserted");
80+
}
4981
}
5082

5183
seedDb()
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
type VariantOption = {
2+
id: number | string;
3+
label: string;
4+
value: string;
5+
};
6+
7+
type VariantSelectorProps = {
8+
label: string;
9+
name: string;
10+
options: VariantOption[];
11+
selectedValue: string;
12+
onSelect: (value: string) => void;
13+
};
14+
15+
export function VariantSelector({
16+
label,
17+
name,
18+
options,
19+
selectedValue,
20+
onSelect,
21+
}: VariantSelectorProps) {
22+
return (
23+
<div className="mb-4">
24+
<label className="block mb-2 font-medium">{label}</label>
25+
<div className="flex flex-wrap gap-2">
26+
{options.map(option => (
27+
<button
28+
type="button"
29+
key={option.id}
30+
className={`px-4 py-2 rounded border transition-colors ${
31+
selectedValue === option.value
32+
? "bg-primary text-primary-foreground border-primary"
33+
: "bg-background text-foreground border-border hover:bg-accent"
34+
}`}
35+
onClick={() => onSelect(option.value)}
36+
>
37+
{option.label}
38+
</button>
39+
))}
40+
</div>
41+
{/* input oculto para enviar la opción seleccionada */}
42+
<input type="hidden" name={name} value={selectedValue} />
43+
</div>
44+
);
45+
}
46+

src/lib/cart.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,17 @@ export async function addToCart(
2020
sessionCartId: string | undefined,
2121
productId: Product["id"],
2222
quantity: number = 1,
23-
productVariantId?: number
23+
productVariantId?: number,
24+
stickersVariantId?: number
2425
) {
2526
try {
2627
const updatedCart = await alterQuantityCartItem(
2728
userId,
2829
sessionCartId,
2930
productId,
3031
quantity,
31-
productVariantId
32+
productVariantId,
33+
stickersVariantId
3234
);
3335
return updatedCart;
3436
} catch (error) {

src/models/cart.model.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ export type CartItem = PrismaCartItem & {
1111
id: number;
1212
size: "small" | "medium" | "large";
1313
} | null;
14+
stickersVariant?: {
15+
id: number;
16+
measure: "3*3" | "5*5" | "10*10";
17+
} | null;
1418
};
1519

1620
export type Cart = PrismaCart;
@@ -35,6 +39,8 @@ export type CartItemWithProduct = {
3539
product: CartProductInfo;
3640
quantity: number;
3741
productVariantId: number | null;
42+
stickersVariantId: number | null;
43+
price: number;
3844
};
3945

4046
// Tipo para el carrito con items y productos incluidos

src/models/product.model.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@ import type { Product as PrismaProduct } from "@/../generated/prisma/client";
33
export type Product = Omit<PrismaProduct, "price"> & {
44
price: number;
55
variants?: ProductVariant[];
6+
stickersVariants?: StickersVariant[];
7+
};
8+
9+
export type StickersVariant = {
10+
id: number;
11+
measure: "3*3" | "5*5" | "10*10";
12+
price: number;
613
};
714
export interface ProductVariant {
815
id: number;

src/routes/cart/add-item/index.tsx

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,14 @@ export async function action({ request }: Route.ActionArgs) {
1010
const productId = Number(formData.get("productId"));
1111
const quantity = Number(formData.get("quantity")) || 1;
1212
const size = formData.get("size") as string | undefined;
13+
const measure = formData.get("measure") as string | undefined;
1314
const redirectTo = formData.get("redirectTo") as string | null;
1415
const session = await getSession(request.headers.get("Cookie"));
1516
const sessionCartId = session.get("sessionCartId");
1617
const userId = session.get("userId");
1718

1819
let productVariantId: number | undefined = undefined;
20+
let stickersVariantId: number | undefined = undefined;
1921

2022
// Si hay talla, busca el variant correspondiente
2123
if (size) {
@@ -34,7 +36,24 @@ export async function action({ request }: Route.ActionArgs) {
3436
productVariantId = variant.id;
3537
}
3638

37-
await addToCart(userId, sessionCartId, productId, quantity, productVariantId);
39+
// Si hay medida, busca el variant correspondiente
40+
if (measure) {
41+
const variantMeasure = await prisma.stickersVariant.findFirst({
42+
where: {
43+
productId,
44+
measure,
45+
},
46+
});
47+
if (!variantMeasure) {
48+
return new Response(
49+
JSON.stringify({ error: "No se encontró la variante de stickers seleccionada." }),
50+
{ status: 400, headers: { "Content-Type": "application/json" } }
51+
);
52+
}
53+
stickersVariantId = variantMeasure.id;
54+
}
55+
56+
await addToCart(userId, sessionCartId, productId, quantity, productVariantId, stickersVariantId);
3857

3958
return redirect(redirectTo || "/cart");
4059
}

0 commit comments

Comments
 (0)