Skip to content
Open
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
5 changes: 0 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,3 @@ Instead, it will copy all the configuration files and the transitive dependencie

You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.

## Learn More

You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).

To learn React, check out the [React documentation](https://reactjs.org/).
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"@types/react-dom": "^17.0.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-router-dom": "^5.3.0",
"react-router-dom": "^6.7.0",
"react-scripts": "4.0.3",
"typescript": "^4.1.2",
"web-vitals": "^1.0.1"
Expand Down
Binary file added public/coffee-mug.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/02-component-patterns/assets/no-image.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions src/02-component-patterns/components/ProductButtons.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { useContext } from "react";

import { ProductCardContext } from "./ProductCard";
import { ProductCardButtons } from "../interfaces/interfaces";

import styles from "../styles/styles.module.css";

export const ProductButtons = () => {
const { counter, increaseBy }: ProductCardButtons = useContext(ProductCardContext);

return (
<div className={styles.buttonsContainer}>
<button className={styles.buttonMinus} onClick={() => increaseBy(-1)}> - </button>

<div className={styles.countLabel}> {counter} </div>

<button className={styles.buttonAdd} onClick={() => increaseBy(1)}> + </button>
</div>
)
};
36 changes: 36 additions & 0 deletions src/02-component-patterns/components/ProductCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { createContext } from "react";

import { IProductCardContext, IProductCardProps } from "../interfaces/interfaces";
// import { ProductButtons, ProductImage, ProductTitle } from "./";

import useProducts from "../hooks/useProducts";

import styles from "../styles/styles.module.css";

export const ProductCardContext = createContext({} as IProductCardContext);

export const ProductCard = ({ product, children }: IProductCardProps) => {
const { counter, increaseBy } = useProducts();

return (
<ProductCardContext.Provider
value={{
product,
counter,
increaseBy
}}>
<div className={styles.productCard}>
{children}
</div>
</ProductCardContext.Provider>
)
};

/*
Se puede asignar componentes a otro componente de este modo
cuando los componentes a añadir se encuentran en el mismo archivo.
*/

// ProductCard.Title = ProductTitle;
// ProductCard.Image = ProductImage;
// ProductCard.Buttons = ProductButtons;
23 changes: 23 additions & 0 deletions src/02-component-patterns/components/ProductImage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { useContext } from "react";

import styles from "../styles/styles.module.css";
import noImage from "../assets/no-image.jpg";
import { ProductCardContext } from "./ProductCard";

export const ProductImage = ({ image = "" }) => {
let imgToShow: string;

const { product } = useContext(ProductCardContext);

if (image) {
imgToShow = image
} else if (product.img) {
imgToShow = product.img
} else {
imgToShow = noImage
}

return (
<img className={styles.productImg} src={imgToShow} alt="Product img" />
)
};
15 changes: 15 additions & 0 deletions src/02-component-patterns/components/ProductTitle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { useContext } from "react";

import { ProductCardContext } from "./ProductCard";

import styles from "../styles/styles.module.css";

export const ProductTitle = ({ title }: { title?: string }) => {
const { product } = useContext(ProductCardContext);

return (
<span className={styles.productDescription}>
{ title ? title : product.title }
</span>
)
};
18 changes: 18 additions & 0 deletions src/02-component-patterns/components/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { ProductButtons } from "./ProductButtons";
import { ProductCard as ProductCardHOC} from "./ProductCard";
import { ProductImage } from "./ProductImage";
import { ProductTitle } from "./ProductTitle";

import { IProductCardHOC } from "../interfaces/interfaces";

export { ProductImage } from "./ProductImage";
export { ProductTitle } from "./ProductTitle";
export { ProductButtons } from "./ProductButtons";

export const ProductCard: IProductCardHOC = Object.assign( ProductCardHOC, {
Image: ProductImage,
Title: ProductTitle,
Buttons: ProductButtons
});


14 changes: 14 additions & 0 deletions src/02-component-patterns/hooks/useProducts.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { useState } from 'react'

const useProducts = () => {

const [counter, setCounter] = useState(0)

const increaseBy = (value: number) => {
setCounter(prev => Math.max(prev + value, 0));
}

return { counter, increaseBy }
}

export default useProducts
30 changes: 30 additions & 0 deletions src/02-component-patterns/interfaces/interfaces.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { ReactElement } from "react";

export interface IProductCardContext {
product: Product;
counter: number;
increaseBy: (value: number) => void;
}

export interface IProductCardProps {
product: Product;
children?: ReactElement | ReactElement[];
}

interface Product {
id: number;
title?: string;
img?: string;
}

export interface ProductCardButtons {
counter: number;
increaseBy: (value: number) => void;
}

export interface IProductCardHOC {
({ product, children }: IProductCardProps): JSX.Element;
Image: ({ image }: { image?: string }) => JSX.Element;
Title: ({ title }: { title?: string }) => JSX.Element;
Buttons: () => JSX.Element;
}
7 changes: 7 additions & 0 deletions src/02-component-patterns/pages/About.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const About = () => {
return (
<div>About Page</div>
)
}

export default About;
7 changes: 7 additions & 0 deletions src/02-component-patterns/pages/Home.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const Home = () => {
return (
<div>Home page</div>
)
}

export default Home;
40 changes: 40 additions & 0 deletions src/02-component-patterns/pages/Shopping.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { ProductButtons, ProductCard, ProductImage, ProductTitle } from '../components';

/* Compound component pattern */

const product = {
id: 1,
title: "Coffee Mug",
img: "./coffee-mug.png"
}

const product2 = {
id: 1,
title: "Coffee Mug",
}

const Shopping = () => {
return (
<>
<h1>Shopping Store</h1>

<hr style={{ width: "100%" }} />

<div className="shopping-div">
<ProductCard product={product}>
<ProductCard.Image />
<ProductCard.Title />
<ProductCard.Buttons />
</ProductCard>

<ProductCard product={product2}>
<ProductImage />
<ProductTitle title='No Product' />
<ProductButtons />
</ProductCard>
</div>
</>
)
}

export default Shopping;
7 changes: 7 additions & 0 deletions src/02-component-patterns/pages/Users.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const Users = () => {
return (
<div>Users Page</div>
)
}

export default Users;
61 changes: 61 additions & 0 deletions src/02-component-patterns/styles/styles.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@

.productCard {
background-color: white;
border-radius: 15px;
color: black;
padding-bottom: 5px;
width: 250px;
margin-right: 5px;
margin-top: 5px;
}

.productImg {
border-radius: 15px 15px 0px 0px;
width: 100%;
}

.productDescription {
margin: 10px;
}

.buttonsContainer {
margin: 10px;
display: flex;
flex-direction: row;
}

.buttonMinus {
cursor: pointer;
background-color: transparent;
border: 1px solid black;
border-radius: 5px 0px 0px 5px;
font-size: 20px;
width: 30px;
}

.buttonMinus:hover {
background-color: rgba(0, 0, 0, 0.1);
}

.countLabel {
border-bottom: 1px solid black;
border-top: 1px solid black;
font-size: 16px;
height: 25px;
padding-top: 5px;
text-align: center;
width: 30px;
}

.buttonAdd {
cursor: pointer;
background-color: transparent;
border: 1px solid black;
border-radius: 0px 5px 5px 0px;
font-size: 20px;
width: 30px;
}

.buttonAdd:hover {
background-color: rgba(0, 0, 0, 0.1);
}
13 changes: 12 additions & 1 deletion src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,22 @@ code {
flex-direction: row;
}

.page-layout {
width: auto;
display: flex;
flex-direction: column;
}

.shopping-div {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}

nav {
background-color: #363a45;
height: 100vh;
margin-right: 15px;
overflow-y: scroll;
text-align: center;
width: 250px;
}
Expand Down
Loading