Skip to content

Commit 00a60c7

Browse files
authored
Merge pull request #274 from codeableorg/grupo-3-mike-5
feat: update variant attribute values and improve product pricing logic
2 parents 35dddc6 + 9b3b553 commit 00a60c7

File tree

11 files changed

+193
-197
lines changed

11 files changed

+193
-197
lines changed

.react-router/types/+register.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,5 @@ type Params = {
2929
"/account/orders": {};
3030
"/not-found": {};
3131
"/verify-email": {};
32+
"/chat": {};
3233
};

prisma/initial_data.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,7 @@ export const variantAttributeValues = [
424424

425425
{ attributeId: 2, productId: 17, value: "3x3 cm", price: 2.99 },
426426
{ attributeId: 2, productId: 17, value: "5x5 cm", price: 3.99 },
427-
{ attributeId: 2, productId: 17, value: "10x10 cm", price: 4.99 },
427+
{ attributeId: 2, productId: 17, value: "10x10 cm", price: .99 },
428428

429429
// --- TAZAS (no aplica: Único) ---
430430
{ attributeId: 3, productId: 18, value: "Único", price: 14.99 },

src/models/cart.model.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ import { type Product } from "./product.model";
33
import type {
44
Cart as PrismaCart,
55
CartItem as PrismaCartItem,
6+
VariantAttributeValue
67
} from "@/../generated/prisma/client";
78

89
export type CartItem = PrismaCartItem & {
910
product: Pick<
1011
Product,
1112
"id" | "title" | "imgSrc" | "alt" | "price" | "isOnSale"
1213
>;
14+
variantAttributeValue?: VariantAttributeValue;
1315
};
1416

1517
export type Cart = PrismaCart;
@@ -34,6 +36,7 @@ export type CartItemWithProduct = {
3436
product: CartProductInfo;
3537
quantity: number;
3638
attributeValueId: number;
39+
variantAttributeValue?: VariantAttributeValue;
3740
};
3841

3942
// Tipo para el carrito con items y productos incluidos
Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
1-
import type { VariantAttributeValue as PrismaVariantAttributeValue } from "@/../generated/prisma/client";
2-
export type VariantAttributeValue= PrismaVariantAttributeValue
1+
import type { VariantAttributeValue as PrismaVariantAttributeValue, VariantAttribute } from "@/../generated/prisma/client";
2+
3+
export type VariantAttributeValue = PrismaVariantAttributeValue & {
4+
variantAttribute?: VariantAttribute;
5+
};

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ export async function action({ request }: Route.ActionArgs) {
1313
const session = await getSession(request.headers.get("Cookie"));
1414
const sessionCartId = session.get("sessionCartId");
1515
const userId = session.get("userId");
16-
1716
await addToCart(userId, sessionCartId, attributeValueId, quantity);
18-
1917
return redirect(redirectTo || "/cart");
2018
}
Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import { Form } from "react-router";
1+
import { useSubmit } from "react-router";
22

33
import { Button, Input } from "@/components/ui";
44
import { cn } from "@/lib/utils";
55

66
interface PriceFilterProps {
7-
minPrice: string;
8-
maxPrice: string;
7+
minPrice?: number;
8+
maxPrice?: number;
99
className?: string;
1010
}
1111

@@ -14,15 +14,24 @@ export function PriceFilter({
1414
maxPrice,
1515
className,
1616
}: PriceFilterProps) {
17+
const submit = useSubmit()
18+
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
19+
e.preventDefault()
20+
const formData = new FormData(e.currentTarget)
21+
const minPrice = formData.get("minPrice")
22+
const maxPrice = formData.get("maxPrice")
23+
if (!minPrice && !maxPrice) return
24+
if (maxPrice && minPrice && maxPrice < minPrice) return
25+
submit(formData, { method: 'get', action: window.location.pathname })
26+
}
1727
return (
18-
<Form className={cn("flex flex-col gap-6", className)}>
28+
<form onSubmit={handleSubmit} className={cn("flex flex-col gap-6", className)}>
1929
<fieldset>
2030
<legend className="text-base font-medium mb-4">Precio</legend>
2131
<div className="flex gap-6">
2232
<div className="flex flex-col gap-2">
2333
<label className="text-sm font-medium">Min</label>
2434
<Input
25-
type="number"
2635
name="minPrice"
2736
defaultValue={minPrice}
2837
min="0"
@@ -31,7 +40,6 @@ export function PriceFilter({
3140
<div className="flex flex-col gap-2">
3241
<label className="text-sm font-medium">Max</label>
3342
<Input
34-
type="number"
3543
name="maxPrice"
3644
defaultValue={maxPrice}
3745
min="0"
@@ -42,6 +50,6 @@ export function PriceFilter({
4250
<Button type="submit" size="xl" variant="secondary" className="w-full">
4351
Filtrar Productos
4452
</Button>
45-
</Form>
53+
</form>
4654
);
4755
}

src/routes/category/components/product-card/index.tsx

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -31,25 +31,23 @@ export function ProductCard({ product }: ProductCardProps) {
3131
<div className="flex grow flex-col gap-2 p-4">
3232
<h2 className="text-sm font-medium">{product.title}</h2>
3333
<p className="text-sm text-muted-foreground">{product.description}</p>
34-
{product.categoryId === 3 ? (
35-
<div className="text-xs text-muted-foreground">
36-
<p className="text-base font-semibold text-accent-foreground">
37-
Desde
38-
</p>
39-
<p className="font-medium text-foreground text-base">
40-
S/{product.minPrice} - S/{product.maxPrice}
41-
</p>
42-
</div>
34+
{isSticker ? (
35+
<div className="text-xs text-muted-foreground">
36+
<p className="text-base font-semibold text-accent-foreground">
37+
Entre
38+
</p>
39+
<p className="font-medium text-foreground text-base">
40+
S/{product.minPrice} - S/{product.maxPrice}
41+
</p>
42+
</div>
4343
) : (
44-
<div className="text-xs text-muted-foreground">
45-
<p className="text-base font-semibold text-accent-foreground">
46-
Precio
47-
</p>
48-
<p className="font-medium text-foreground text-base">
49-
S/{product.price}
50-
</p>
51-
</div>
52-
)}
44+
<div className="text-xs text-muted-foreground">
45+
<p className="text-base font-semibold text-accent-foreground">
46+
Precio
47+
</p>
48+
<p className="mt-auto text-base font-medium">S/{product.price}</p>
49+
</div>
50+
)}
5351
</div>
5452
{product.isOnSale && (
5553
<span className="absolute top-0 right-0 rounded-bl-xl bg-primary px-2 py-1 text-sm font-medium text-primary-foreground">

src/routes/category/index.tsx

Lines changed: 13 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@ import { redirect } from "react-router";
22

33
import { Container } from "@/components/ui";
44
import { isValidCategorySlug, type Category } from "@/models/category.model";
5-
import type { Product } from "@/models/product.model";
65
import { getCategoryBySlug } from "@/services/category.service";
7-
import { getProductsByCategorySlug } from "@/services/product.service";
6+
import { filterByMinMaxPrice } from "@/services/product.service";
87

98
import { PriceFilter } from "./components/price-filter";
109
import { ProductCard } from "./components/product-card";
@@ -19,54 +18,25 @@ export async function loader({ params, request }: Route.LoaderArgs) {
1918
}
2019

2120
const url = new URL(request.url);
22-
const minPrice = url.searchParams.get("minPrice") || "";
23-
const maxPrice = url.searchParams.get("maxPrice") || "";
21+
const minPrice = url.searchParams.get("minPrice");
22+
const minValue = minPrice ? parseFloat(minPrice) : undefined;
23+
const maxPrice = url.searchParams.get("maxPrice");
24+
const maxValue = maxPrice ? parseFloat(maxPrice) : undefined;
25+
2426

2527
try {
26-
const [category, products] = await Promise.all([
28+
const [category] = await Promise.all([
2729
getCategoryBySlug(categorySlug),
28-
getProductsByCategorySlug(categorySlug),
2930
]);
30-
31-
const filterProductsByPrice = (
32-
products: Product[],
33-
minPrice: string,
34-
maxPrice: string
35-
) => {
36-
const min = minPrice ? parseFloat(minPrice) : 0;
37-
const max = maxPrice ? parseFloat(maxPrice) : Infinity;
38-
return products.filter(
39-
(product) => {
40-
const minProductPrice = product.minPrice||0
41-
const maxProductPrice = product.maxPrice ||0
42-
const productPrice = product.price || 0
43-
44-
if (min && max) {
45-
return ((productPrice||minProductPrice) >= min) && ((productPrice||maxProductPrice) <= max)
46-
}
47-
48-
if (min) {
49-
return (productPrice||minProductPrice) >= min
50-
}
51-
52-
if (max) {
53-
return (productPrice||maxProductPrice) <= max
54-
}
55-
return true
56-
});
57-
};
58-
59-
const filteredProducts = filterProductsByPrice(
60-
products,
61-
minPrice,
62-
maxPrice
63-
);
31+
console.log({categorySlug, minValue, maxValue})
32+
const finalProducts = await filterByMinMaxPrice(categorySlug, minValue, maxValue);
6433

6534
return {
6635
category,
67-
products: filteredProducts,
68-
minPrice,
69-
maxPrice,
36+
products: finalProducts,
37+
minPrice: minValue,
38+
maxPrice: maxValue,
39+
finalProducts
7040
};
7141
} catch (e) {
7242
throw new Response("Error loading category: " + e, { status: 500 });

0 commit comments

Comments
 (0)