Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 16 additions & 16 deletions prisma/initial_data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -395,36 +395,36 @@ export const variantAttributeValues = [

// --- STICKERS (dimensiones: 3x3, 6x6, 9x9) ---
{ attributeId: 2, productId: 10, value: "3x3", price: 2.99 },
{ attributeId: 2, productId: 10, value: "6x6", price: 3.99 },
{ attributeId: 2, productId: 10, value: "9x9", price: 4.99 },
{ attributeId: 2, productId: 10, value: "5x5", price: 3.99 },
{ attributeId: 2, productId: 10, value: "10x10", price: 4.99 },

{ attributeId: 2, productId: 11, value: "3x3", price: 2.49 },
{ attributeId: 2, productId: 11, value: "6x6", price: 3.49 },
{ attributeId: 2, productId: 11, value: "9x9", price: 4.49 },
{ attributeId: 2, productId: 11, value: "5x5", price: 3.49 },
{ attributeId: 2, productId: 11, value: "10x10", price: 4.49 },

{ attributeId: 2, productId: 12, value: "3x3", price: 3.99 },
{ attributeId: 2, productId: 12, value: "6x6", price: 4.99 },
{ attributeId: 2, productId: 12, value: "9x9", price: 5.99 },
{ attributeId: 2, productId: 12, value: "5x5", price: 4.99 },
{ attributeId: 2, productId: 12, value: "10x10", price: 5.99 },

{ attributeId: 2, productId: 13, value: "3x3", price: 2.99 },
{ attributeId: 2, productId: 13, value: "6x6", price: 3.99 },
{ attributeId: 2, productId: 13, value: "9x9", price: 4.99 },
{ attributeId: 2, productId: 13, value: "5x5", price: 3.99 },
{ attributeId: 2, productId: 13, value: "10x10", price: 4.99 },

{ attributeId: 2, productId: 14, value: "3x3", price: 2.49 },
{ attributeId: 2, productId: 14, value: "6x6", price: 3.49 },
{ attributeId: 2, productId: 14, value: "9x9", price: 4.49 },
{ attributeId: 2, productId: 14, value: "5x5", price: 3.49 },
{ attributeId: 2, productId: 14, value: "10x10", price: 4.49 },

{ attributeId: 2, productId: 15, value: "3x3", price: 2.49 },
{ attributeId: 2, productId: 15, value: "6x6", price: 3.49 },
{ attributeId: 2, productId: 15, value: "9x9", price: 4.49 },
{ attributeId: 2, productId: 15, value: "5x5", price: 3.49 },
{ attributeId: 2, productId: 15, value: "10x10", price: 4.49 },

{ attributeId: 2, productId: 16, value: "3x3", price: 2.99 },
{ attributeId: 2, productId: 16, value: "6x6", price: 3.99 },
{ attributeId: 2, productId: 16, value: "9x9", price: 4.99 },
{ attributeId: 2, productId: 16, value: "5x5", price: 3.99 },
{ attributeId: 2, productId: 16, value: "10x10", price: 4.99 },

{ attributeId: 2, productId: 17, value: "3x3", price: 2.99 },
{ attributeId: 2, productId: 17, value: "6x6", price: 3.99 },
{ attributeId: 2, productId: 17, value: "9x9", price: .99 },
{ attributeId: 2, productId: 17, value: "5x5", price: 3.99 },
{ attributeId: 2, productId: 17, value: "10x10", price: .99 },

// --- TAZAS (no aplica: Único) ---
{ attributeId: 3, productId: 18, value: "Único", price: 14.99 },
Expand Down
11 changes: 9 additions & 2 deletions src/models/product.model.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import type { VariantAttributeValue } from "./variant-attribute.model";
import type { Product as PrismaProduct } from "@/../generated/prisma/client";

export type Product = Omit<PrismaProduct, "price"> & {
price: number;
export type Product = PrismaProduct & {
price?: number | null;
minPrice?: number | null;
maxPrice?: number | null;
};

export type ProductVariantValue = PrismaProduct & {
variantAttributeValues: VariantAttributeValue[];
}
2 changes: 2 additions & 0 deletions src/models/variant-attribute.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import type { VariantAttributeValue as PrismaVariantAttributeValue } from "@/../generated/prisma/client";
export type VariantAttributeValue= PrismaVariantAttributeValue
9 changes: 9 additions & 0 deletions src/routes/category/components/product-card/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ interface ProductCardProps {

export function ProductCard({ product }: ProductCardProps) {
return (
<>
<Link
to={`/products/${product.id}`}
className="block"
Expand All @@ -25,7 +26,14 @@ export function ProductCard({ product }: ProductCardProps) {
<div className="flex grow flex-col gap-2 p-4">
<h2 className="text-sm font-medium">{product.title}</h2>
<p className="text-sm text-muted-foreground">{product.description}</p>
{
product?.price &&
<p className="mt-auto text-base font-medium">S/{product.price}</p>
}
{
product?.minPrice &&
<p className="mt-auto text-base font-medium">Entre S/{product.minPrice} - {product.maxPrice}</p>
}
</div>
{product.isOnSale && (
<span className="absolute top-0 right-0 rounded-bl-xl bg-primary px-2 py-1 text-sm font-medium text-primary-foreground">
Expand All @@ -34,5 +42,6 @@ export function ProductCard({ product }: ProductCardProps) {
)}
</div>
</Link>
</>
);
}
20 changes: 18 additions & 2 deletions src/routes/category/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,24 @@ export async function loader({ params, request }: Route.LoaderArgs) {
const min = minPrice ? parseFloat(minPrice) : 0;
const max = maxPrice ? parseFloat(maxPrice) : Infinity;
return products.filter(
(product) => product.price >= min && product.price <= max
);
(product) => {
const minProductPrice = product.minPrice||0
const maxProductPrice = product.maxPrice ||0
const productPrice = product.price || 0

if (min && max) {
return ((productPrice||minProductPrice) >= min) && ((productPrice||maxProductPrice) <= max)
}

if (min) {
return (productPrice||minProductPrice) >= min
}
if (max) {
return (productPrice||maxProductPrice) <= max

}
return true
});
};

const filteredProducts = filterProductsByPrice(
Expand Down
2 changes: 1 addition & 1 deletion src/routes/root/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export async function loader({ request }: Route.LoaderArgs) {
}

const totalItems =
cart?.items.reduce((total, item) => total + item.quantity, 0) || 0;
cart?.items?.reduce((total, item) => total + item.quantity, 0) || 0;

// Preparar datos de respuesta según estado de autenticación
const responseData = user ? { user, totalItems } : { totalItems };
Expand Down
70 changes: 40 additions & 30 deletions src/services/cart.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,42 +18,52 @@ 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: {
product: {
select: {
id: true,
title: true,
imgSrc: true,
alt: true,
price: true,
isOnSale: true,
},
},
},
},
orderBy: {
id: "asc",
orderBy: {
id: "asc",
},
},
},
},
});

if (!data) return null;
});

if (!data) return null;

return {
...data,
items: data.items.map((item) => ({
...item,
product: {
...item.product,
price: item.product.price.toNumber(),
},
})),
};
}catch(e) {
console.log(e)
return {
error: true,
status: 500,
message: "Error al obtener el carrito. Verifica el modelo Product.",
};
}

return {
...data,
items: data.items.map((item) => ({
...item,
product: {
...item.product,
price: item.product.price.toNumber(),
},
})),
};
}

export async function getRemoteCart(
Expand Down
48 changes: 38 additions & 10 deletions src/services/product.service.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,66 @@
import { prisma } from "@/db/prisma";
import type { Category } from "@/models/category.model";
import type { Product } from "@/models/product.model";
import type { Product, ProductVariantValue } from "@/models/product.model";
import type { VariantAttributeValue } from "@/models/variant-attribute.model";

import { getCategoryBySlug } from "./category.service";

const formattedProduct = (product: ProductVariantValue) => {
const {variantAttributeValues, ...rest} = product
const prices = variantAttributeValues.map((v: VariantAttributeValue) => Number(v.price))
const minPrice = Math.min(...prices)
const maxPrice = Math.max(...prices)
if (minPrice === maxPrice) {
return {
...rest,
price: minPrice
}
}
return {
...rest,
minPrice,
maxPrice
}
}

export async function getProductsByCategorySlug(
categorySlug: Category["slug"]
): Promise<Product[]> {
const category = await getCategoryBySlug(categorySlug);
const products = await prisma.product.findMany({
where: { categoryId: category.id },
include: {
variantAttributeValues: true
}
});

return products.map((product) => ({
...product,
price: product.price.toNumber(),
}));
return products.map(formattedProduct)
}

export async function getProductById(id: number): Promise<Product> {
const product = await prisma.product.findUnique({
where: { id },
include: {
variantAttributeValues: true
}
});

if (!product) {
throw new Error("Product not found");
}
const variants = product.variantAttributeValues.map((variant)=> ({
...variant,
price: Number(variant.price)
}))

return { ...product, price: product.price.toNumber() };
return {...product, variantAttributeValues: variants } as Product
}

export async function getAllProducts(): Promise<Product[]> {
return (await prisma.product.findMany()).map((p) => ({
...p,
price: p.price.toNumber(),
}));
const products = await prisma.product.findMany({
include: {
variantAttributeValues: true
}
});
return products.map(formattedProduct)
}