Skip to content

Commit 4d4f2cc

Browse files
committed
pagina de tienda actualizada con filtro para diferentes generos
1 parent 81df4cd commit 4d4f2cc

File tree

7 files changed

+232
-131
lines changed

7 files changed

+232
-131
lines changed

backend/models/productModel.js

+56-56
Original file line numberDiff line numberDiff line change
@@ -2,65 +2,65 @@ const mongoose = require("mongoose");
22
const { Schema } = mongoose;
33

44
const productSchema = new Schema(
5-
{
6-
productName: {
7-
type: String,
8-
required: true,
9-
trim: true,
10-
},
11-
price: {
12-
type: Number,
13-
required: true,
14-
get: (v) => (v / 100).toFixed(2),
15-
set: (v) => v * 100,
16-
},
17-
image: {
18-
type: String,
19-
required: true,
20-
},
21-
description: {
22-
type: String,
23-
trim: true,
24-
},
25-
genre: {
26-
type: String,
27-
required: true,
28-
trim: true,
29-
},
30-
types: {
31-
type: Array,
32-
default: [
33-
{
34-
type1: "Collar",
35-
type2: "Pendiente suelto",
36-
type3: "Par de pendientes",
37-
type4: "Llavero",
38-
type5: "Chocker",
39-
type6: "Imán",
40-
type7: "Pinza para el pelo",
41-
type8: "Broche",
42-
}
43-
]
44-
},
45-
discount: {
46-
type: Number
47-
},
48-
rating: {
49-
type: Number,
50-
default: 0,
51-
},
52-
reviews: [{
53-
userId: {
54-
type: Schema.Types.ObjectId,
55-
ref: "User",
5+
{
6+
productName: {
7+
type: String,
8+
required: true,
9+
trim: true,
10+
},
11+
price: {
12+
type: Number,
13+
required: true,
14+
get: (v) => (v / 100).toFixed(2),
15+
set: (v) => v * 100,
5616
},
57-
review: {
17+
image: {
5818
type: String,
19+
required: true,
20+
},
21+
description: {
22+
type: String,
23+
trim: true,
24+
},
25+
genre: {
26+
type: String,
27+
required: true,
5928
trim: true,
60-
}
61-
}]
62-
},
63-
{ toJSON: { getters: true }, timestamps: true }
29+
},
30+
types: {
31+
type: Array,
32+
default: [
33+
"Collar",
34+
"Pendiente suelto",
35+
"Par de pendientes",
36+
"Llavero",
37+
"Chocker",
38+
"Imán",
39+
"Pinza para el pelo",
40+
"Broche",
41+
]
42+
43+
44+
},
45+
discount: {
46+
type: Number
47+
},
48+
rating: {
49+
type: Number,
50+
default: 0,
51+
},
52+
reviews: [{
53+
userId: {
54+
type: Schema.Types.ObjectId,
55+
ref: "User",
56+
},
57+
review: {
58+
type: String,
59+
trim: true,
60+
}
61+
}]
62+
},
63+
{ toJSON: { getters: true }, timestamps: true }
6464
);
6565

6666
const ProductModel = mongoose.model("Product", productSchema);

frontend/src/App.jsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ export default function App() {
4747
<Route path="/about" element={<About />} />
4848
<Route path="/contact" element={<Contact />} />
4949
<Route path="/news" element={<News />} />
50-
<Route path="/store" element={<Store />} />
51-
<Route path="/store/:productName" element={<Product />} />
50+
<Route path="/store/:genre" element={<Store />} />
51+
<Route path="/store/:genre/:productName" element={<Product />} />
5252
<Route path="/users/:id/verify/:token" element={<EmailVerification />} />
5353
<Route path="/admin-dashboard" element={<AdminDashboard />} />
5454
<Route path="/admin-dashboard/products" element={<AdminProducts />} />

frontend/src/components/NavbarLoggedIn.jsx

+26-7
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,28 @@
11
import { Link } from "react-router-dom";
2-
import { useContext } from "react";
2+
import { useContext, useState, useEffect } from "react";
33
import { UserContext } from "../context/userContext";
44
import axios from "axios";
55
import { useNavigate } from "react-router-dom";
66
import toast from "react-hot-toast";
77
import TextBoxWithTextOnTop from "./TextBoxWithTextOnTop";
88

9-
export default function NavbarLoggedIn() {
9+
export default function NavbarLoggedIn({ props }) {
1010
const navigate = useNavigate();
1111
const { user, setUser } = useContext(UserContext);
12+
const [genres, setGenres] = useState([]);
13+
14+
useEffect(() => {
15+
const getGenres = async () => {
16+
try {
17+
const response = await axios.get("/get-products");
18+
const uniqueGenres = [...new Set(response.data.map(product => product.genre))];
19+
setGenres(uniqueGenres);
20+
} catch (error) {
21+
console.error("Error recogiendo los productos:", error);
22+
}
23+
};
24+
getGenres();
25+
}, []);
1226

1327
const logoutUser = async () => {
1428
try {
@@ -31,13 +45,17 @@ export default function NavbarLoggedIn() {
3145
<summary className={`btn btn-ghost ${padding}`}>Tienda</summary>
3246
<ul className="p-2 bg-accent rounded-t-none">
3347
<li>
34-
<Link to="/store" className="btn btn-ghost">
35-
catálogo
48+
<Link to="/store/all" className="btn btn-ghost">
49+
Catálogo
3650
</Link>
3751
</li>
38-
<li>
39-
<a>Link 2</a>
40-
</li>
52+
{genres.map((genre, index) => (
53+
<li key={index}>
54+
<Link to={`/store/${genre}`} className="btn btn-ghost">
55+
{genre}
56+
</Link>
57+
</li>
58+
))}
4159
</ul>
4260
</details>
4361
</li>
@@ -123,6 +141,7 @@ export default function NavbarLoggedIn() {
123141
{user.role !== 1 ? (
124142
<>
125143
<div>{navList}</div>
144+
126145
{/** Carrito de compra */}
127146
<div className="mr-1 dropdown dropdown-end">
128147
<div
+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import React from 'react'
2+
3+
export default function StarRating({ rating }) {
4+
const starsRating = () => {
5+
switch (rating) {
6+
case 0: return (
7+
<div className="rating">
8+
<input type="radio" name="rating-1" className="rating-hidden" checked disabled />
9+
<input type="radio" name="rating-1" className="mask mask-star" disabled />
10+
<input type="radio" name="rating-1" className="mask mask-star" disabled />
11+
<input type="radio" name="rating-1" className="mask mask-star" disabled />
12+
<input type="radio" name="rating-1" className="mask mask-star" disabled />
13+
<input type="radio" name="rating-1" className="mask mask-star" disabled />
14+
</div>
15+
);
16+
case 1: return (
17+
<div className="rating">
18+
<input type="radio" name="rating-1" className="mask mask-star" checked disabled />
19+
<input type="radio" name="rating-1" className="mask mask-star" disabled />
20+
<input type="radio" name="rating-1" className="mask mask-star" disabled />
21+
<input type="radio" name="rating-1" className="mask mask-star" disabled />
22+
<input type="radio" name="rating-1" className="mask mask-star" disabled />
23+
</div>
24+
);
25+
case 2: return (
26+
<div className="rating">
27+
<input type="radio" name="rating-1" className="mask mask-star" disabled />
28+
<input type="radio" name="rating-1" className="mask mask-star" checked disabled />
29+
<input type="radio" name="rating-1" className="mask mask-star" disabled />
30+
<input type="radio" name="rating-1" className="mask mask-star" disabled />
31+
<input type="radio" name="rating-1" className="mask mask-star" disabled />
32+
</div>
33+
);
34+
case 3: return (
35+
<div className="rating">
36+
<input type="radio" name="rating-1" className="mask mask-star" disabled />
37+
<input type="radio" name="rating-1" className="mask mask-star" disabled />
38+
<input type="radio" name="rating-1" className="mask mask-star" checked disabled />
39+
<input type="radio" name="rating-1" className="mask mask-star" disabled />
40+
<input type="radio" name="rating-1" className="mask mask-star" disabled />
41+
</div>
42+
);
43+
case 4: return (
44+
<div className="rating">
45+
<input type="radio" name="rating-1" className="mask mask-star" disabled />
46+
<input type="radio" name="rating-1" className="mask mask-star" disabled />
47+
<input type="radio" name="rating-1" className="mask mask-star" disabled />
48+
<input type="radio" name="rating-1" className="mask mask-star" checked disabled />
49+
<input type="radio" name="rating-1" className="mask mask-star" disabled />
50+
</div>
51+
);
52+
case 5: return (
53+
<div className="rating">
54+
<input type="radio" name="rating-1" className="mask mask-star" disabled />
55+
<input type="radio" name="rating-1" className="mask mask-star" disabled />
56+
<input type="radio" name="rating-1" className="mask mask-star" disabled />
57+
<input type="radio" name="rating-1" className="mask mask-star" disabled />
58+
<input type="radio" name="rating-1" className="mask mask-star" checked disabled />
59+
</div>
60+
);
61+
default: return null;
62+
}
63+
}
64+
65+
return (
66+
<>
67+
{starsRating()}
68+
</>
69+
)
70+
}

frontend/src/pages/Product.jsx

+7-2
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,17 @@ import { toast } from "react-hot-toast";
55
import axios from "axios";
66
import Error from "./error/Error";
77
import { Link } from "react-router-dom";
8+
import StarRating from "../components/StarRating";
89

910
export default function Product() {
1011
const { user } = useContext(UserContext);
1112
const location = useLocation();
1213
const product = location.state.product;
1314

15+
const addToCart = (product) => {
16+
17+
}
18+
1419
return (
1520
<>
1621
{product ? (
@@ -31,7 +36,7 @@ export default function Product() {
3136
</h1>
3237
<div className="flex items-center gap-4">
3338
<div className="flex items-center gap-0.5">
34-
{product.rating}
39+
<StarRating rating={product.rating} />
3540
</div>
3641
</div>
3742
<div className="text-4xl font-bold">{product.price}</div>
@@ -41,7 +46,7 @@ export default function Product() {
4146
<div className="flex flex-col gap-2 min-[400px]:flex-row">
4247
{user ? (
4348
<>
44-
<button className="btn btn-accent">
49+
<button className="btn btn-accent" onClick={() => addToCart(product)}>
4550
Añadir al carrito
4651
</button>
4752
<button className="btn btn-primary w-[10%]">

0 commit comments

Comments
 (0)