Skip to content

Commit b2cfcc8

Browse files
committed
finished the challenge
1 parent 8f149dd commit b2cfcc8

File tree

4 files changed

+272
-103
lines changed

4 files changed

+272
-103
lines changed
Lines changed: 146 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,112 @@
11
/**
22
* Exercise 01: The Retro Movie Store
33
* Implement a shopping cart with the next features for the Movie Store that is selling retro dvds:
4-
* 1. Add a movie to the cart
5-
* 2. Increment or decrement the quantity of movie copies. If quantity is equal to 0, the movie must be removed from the cart
6-
* 3. Calculate and show the total cost of your cart. Ex: Total: $150
4+
* 1. Add a movie to the cart [done]
5+
* 2. Increment or decrement the quantity of movie copies. If quantity is equal to 0, the movie must be removed from the cart [done]
6+
* 3. Calculate and show the total cost of your cart. Ex: Total: $150 [done]
77
* 4. Apply discount rules. You have an array of offers with discounts depending of the combination of movie you have in your cart.
88
* You have to apply all discounts in the rules array (discountRules).
9-
* Ex: If m: [1, 2, 3], it means the discount will be applied to the total when the cart has all that products in only.
9+
* Ex: If m: [1, 2, 3], it means the discount will be applied to the total when the cart has all that products in only.[done]
1010
*
1111
* You can modify all the code, this component isn't well designed intentionally. You can redesign it as you need.
1212
*/
1313

1414
import './assets/styles.css'
15-
import { useState } from 'react'
15+
import { useState, createContext, useContext } from 'react'
1616

17-
export default function Exercise01 () {
17+
const Context = createContext()
18+
19+
const SingleMovie = (props) => {
20+
const { movieInfo } = props
21+
const { setCart, cart } = useContext(Context)
22+
const handleAddToCart = () => {
23+
24+
const cartIdExist = () => {
25+
let exist = false
26+
for (let i = 0; i < cart.length; i++) {
27+
const item = cart[i];
28+
if (item.id === movieInfo.id) {
29+
exist = true
30+
break
31+
}
32+
}
33+
return exist
34+
}
35+
if (cartIdExist()) {
36+
return
37+
}
38+
movieInfo.quantity = 1
39+
const cartCopy = [...cart]
40+
cartCopy.push(movieInfo)
41+
setCart(cartCopy)
42+
}
43+
return (
44+
<li className="movies__list-card">
45+
<ul>
46+
<li>
47+
ID: {movieInfo.id}
48+
</li>
49+
<li>
50+
Name: {movieInfo.name}
51+
</li>
52+
<li>
53+
Price: ${movieInfo.price}
54+
</li>
55+
</ul>
56+
<button onClick={handleAddToCart}>
57+
Add to cart
58+
</button>
59+
</li>
60+
)
61+
}
62+
63+
const SingleCartItem = ({ cartItem }) => {
64+
const { cart, setCart } = useContext(Context)
65+
const handleCount = (increment) => {
66+
const cartCopy = [...cart]
67+
for (let i = 0; i < cart.length; i++) {
68+
const item = cart[i];
69+
if (item.id === cartItem.id) {
70+
if (increment) {
71+
item.quantity++
72+
} else {
73+
item.quantity--
74+
}
75+
if (item.quantity === 0) {
76+
cartCopy.splice(i, 1)
77+
}
78+
break
79+
}
80+
}
81+
setCart(cartCopy)
82+
}
83+
return <li className="movies__cart-card">
84+
<ul>
85+
<li>
86+
ID: {cartItem.id}
87+
</li>
88+
<li>
89+
Name: {cartItem.name}
90+
</li>
91+
<li>
92+
Price: ${cartItem.price}
93+
</li>
94+
</ul>
95+
<div className="movies__cart-card-quantity">
96+
<button onClick={() => handleCount(false)}>
97+
-
98+
</button>
99+
<span>
100+
{cartItem.quantity}
101+
</span>
102+
<button onClick={() => handleCount(true)}>
103+
+
104+
</button>
105+
</div>
106+
</li>
107+
}
108+
109+
export default function Exercise01() {
18110
const movies = [
19111
{
20112
id: 1,
@@ -50,77 +142,59 @@ export default function Exercise01 () {
50142
{
51143
m: [4, 2],
52144
discount: 0.1
53-
}
145+
}
54146
]
55147

56-
const [cart, setCart] = useState([
57-
{
58-
id: 1,
59-
name: 'Star Wars',
60-
price: 20,
61-
quantity: 2
148+
const [cart, setCart] = useState([])
149+
150+
const getTotal = () => {
151+
let total = 0
152+
for (let i = 0; i < cart.length; i++) {
153+
const cartItem = cart[i];
154+
total += cartItem.price * cartItem.quantity
62155
}
63-
])
64156

65-
const getTotal = () => 0 // TODO: Implement this
157+
const checkForDiscount = () => {
158+
for (let i = 0; i < discountRules.length; i++) {
159+
const rule = discountRules[i];
160+
if (rule.m.length !== cart.length) continue
161+
const ruleMatch = rule.m.every((id) => {
162+
return cart.some((cartItem) => {
163+
return cartItem.id === id
164+
})
165+
})
166+
if (ruleMatch) {
167+
return rule.discount
168+
}
169+
}
170+
}
171+
const discount = checkForDiscount()
172+
return { total, discount }
173+
}
66174

175+
const { total, discount } = getTotal()
67176
return (
68-
<section className="exercise01">
69-
<div className="movies__list">
70-
<ul>
71-
{movies.map(o => (
72-
<li className="movies__list-card">
73-
<ul>
74-
<li>
75-
ID: {o.id}
76-
</li>
77-
<li>
78-
Name: {o.name}
79-
</li>
80-
<li>
81-
Price: ${o.price}
82-
</li>
83-
</ul>
84-
<button onClick={() => console.log('Add to cart', o)}>
85-
Add to cart
86-
</button>
87-
</li>
88-
))}
89-
</ul>
90-
</div>
91-
<div className="movies__cart">
92-
<ul>
93-
{cart.map(x => (
94-
<li className="movies__cart-card">
95-
<ul>
96-
<li>
97-
ID: {x.id}
98-
</li>
99-
<li>
100-
Name: {x.name}
101-
</li>
102-
<li>
103-
Price: ${x.price}
104-
</li>
105-
</ul>
106-
<div className="movies__cart-card-quantity">
107-
<button onClick={() => console.log('Decrement quantity', x)}>
108-
-
109-
</button>
110-
<span>
111-
{x.quantity}
112-
</span>
113-
<button onClick={() => console.log('Increment quantity', x)}>
114-
+
115-
</button>
116-
</div>
117-
</li>
118-
))}
119-
</ul>
120-
<div className="movies__cart-total">
121-
<p>Total: ${getTotal()}</p>
177+
<Context.Provider value={{ cart, setCart }}>
178+
<section className="exercise01">
179+
<div className="movies__list">
180+
<ul>
181+
{movies.map((o, idx) => {
182+
return (<SingleMovie movieInfo={o} key={idx} />)
183+
})}
184+
</ul>
185+
</div>
186+
<div className="movies__cart">
187+
<ul>
188+
{cart.length === 0 && <p>Cart is empty add at least one item</p>}
189+
{cart.map((cartItem, idx) => (
190+
<SingleCartItem cartItem={cartItem} key={idx} />
191+
))}
192+
</ul>
193+
<div className="movies__cart-total">
194+
<p>Total: {discount && <>From ${total} to </>}${(total && discount) ? (total - (total * (discount / 100))) : total} {discount && <>With a discount of {discount * 100}% applied</>}</p>
195+
</div>
122196
</div>
123-
</div>
124-
</section>
197+
</section>
198+
</Context.Provider>
125199
)
126-
}
200+
}

src/components/pages/Exercise02/assets/styles.css

Lines changed: 76 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,61 @@
33
color: var(--white);
44
min-height: 100vh;
55
padding: 2em;
6+
background: url("./mountains.jpeg"), linear-gradient(180deg, #1B1B1B00 0%, #1B1B1B 30%, #1B1B1B 100%);
7+
background-position: top;
8+
background-position-y: 100%;
9+
background-repeat: no-repeat;
10+
background-blend-mode: overlay;
11+
background-attachment: fixed;
12+
background-size: cover;
613
}
714

815
.movie-library__title {
916
font-size: 2em;
1017
margin-bottom: 1em;
18+
font-weight: 900;
1119
}
1220

1321
.movie-library__actions {
1422
display: flex;
1523
margin-bottom: 1em;
24+
border: var(--ms-green) solid 2px;
25+
border-radius: 5px;
26+
min-height: 41px;
27+
}
28+
29+
.movie-library__actions * {
30+
font-family: var(--poppins);
31+
font-size: 0.875em;
32+
line-height: 1;
33+
font-weight: 500;
1634
}
1735

1836
.movie-library__actions select {
1937
width: 100%;
2038
padding: .25em;
39+
text-decoration: none;
40+
border: none;
41+
color: var(--black);
42+
background-color: var(--white);
43+
outline: none;
44+
}
45+
46+
.movie-library__actions select:focus {
47+
outline: none;
2148
}
2249

2350
.movie-library__actions button {
2451
white-space: nowrap;
52+
text-decoration: none;
53+
border: none;
54+
color: var(--black);
55+
background-color: var(--ms-green);
56+
outline: none;
57+
}
58+
59+
.movie-library__actions button:focus {
60+
outline: none;
2561
}
2662

2763
.movie-library__loading {
@@ -34,24 +70,57 @@
3470

3571
.movie-library__list {
3672
padding: 1em;
37-
background-color: #222222;
73+
display: grid;
74+
grid-template-columns: repeat(auto-fill, minmax(15em, 1fr));
75+
gap: 2.5em;
76+
padding-left: 0px;
77+
padding-right: 0px;
78+
margin-top: 3.625em;
3879
}
3980

4081
.movie-library__card {
4182
background-color: #333333;
42-
margin-bottom: 1em;
43-
display: flex;
83+
display: grid;
84+
grid-template-columns: 1fr;
4485
align-items: center;
86+
position: relative;
87+
border-radius: 8px;
88+
max-width: 100%;
4589
}
4690

4791
.movie-library__card img {
48-
width: 10em;
92+
width: 100%;
4993
}
5094

5195
.movie-library__card ul {
52-
padding: 1em;
96+
position: absolute;
97+
height: 100%;
98+
width: 100%;
99+
display: flex;
100+
flex-direction: column;
101+
justify-content: flex-end;
102+
border-radius: 8px;
103+
background: linear-gradient(0deg, #96d501 0%, rgba(150, 214, 1, 0.51) 24.27%, rgba(151, 215, 0, 0) 100%);
53104
}
54105

55-
.movie-library__card li {
56-
line-height: 120%;
106+
.movie-library .content {
107+
padding-left: 1em;
108+
padding-right: 1em;
109+
padding-bottom: 1em;
57110
}
111+
112+
113+
.movie-library__card ul .title {
114+
font-family: var(--poppins);
115+
font-weight: 900;
116+
font-size: 1.2em;
117+
line-height: 1;
118+
margin-bottom: 8px;
119+
}
120+
121+
.movie-library__card ul .sub-title{
122+
font-weight: 500;
123+
font-size: 0.75em;
124+
font-family: var(--poppins);
125+
margin-bottom: 4px;
126+
}

0 commit comments

Comments
 (0)