diff --git a/src/App.js b/src/App.js index 3784575..7f48141 100644 --- a/src/App.js +++ b/src/App.js @@ -1,23 +1,174 @@ -import logo from './logo.svg'; -import './App.css'; +import "./App.css"; + +// Iteration 1–13 Components +import IdCard from "./components/IdCard/IdCard"; +import Greetings from "./components/Greetings/Greetings"; +import Random from "./components/Random/Random"; +import BoxColor from "./components/BoxColor/BoxColor"; +import CreditCard from "./components/CreditCard/CreditCard"; +import Rating from "./components/Rating/Rating"; +import DriverCard from "./components/DriverCard/DriverCard"; +import LikeButton from "./components/LikeButton/LikeButton"; +import ClickablePicture from "./components/ClickablePicture/ClickablePicture"; +import Dice from "./components/Dice/Dice"; +import Carousel from "./components/Carousel/Carousel"; +import NumbersTable from "./components/NumbersTable/NumbersTable"; +import RGBColorPicker from "./components/RGBColorPicker/RGBColorPicker"; function App() { return (
-
- logo -

- Edit src/App.js and save to reload. -

- - Learn React - -
+ + {/* -------------------------------------------------- */} + {/* ITERATION 1: ID CARD */} + {/* -------------------------------------------------- */} + + + + + {/* -------------------------------------------------- */} + {/* ITERATION 2: GREETINGS */} + {/* -------------------------------------------------- */} + Ludwig + François + + {/* -------------------------------------------------- */} + {/* ITERATION 3: RANDOM */} + {/* -------------------------------------------------- */} + + + + {/* -------------------------------------------------- */} + {/* ITERATION 4: BOX COLOR */} + {/* -------------------------------------------------- */} + + + + {/* -------------------------------------------------- */} + {/* ITERATION 5: CREDIT CARD */} + {/* -------------------------------------------------- */} +
+ + + + + +
+ + {/* -------------------------------------------------- */} + {/* ITERATION 6: RATING */} + {/* -------------------------------------------------- */} + 0 + 1.49 + 1.5 + 3 + 4 + 5 + + {/* -------------------------------------------------- */} + {/* ITERATION 7: DRIVER CARD */} + {/* -------------------------------------------------- */} + + + + + {/* -------------------------------------------------- */} + {/* ITERATION 8: LIKE BUTTON */} + {/* -------------------------------------------------- */} + + + + {/* -------------------------------------------------- */} + {/* ITERATION 9: CLICKABLE PICTURE */} + {/* -------------------------------------------------- */} + + + {/* -------------------------------------------------- */} + {/* ITERATION 10: DICE */} + {/* -------------------------------------------------- */} + + + {/* -------------------------------------------------- */} + {/* ITERATION 11: CAROUSEL */} + {/* -------------------------------------------------- */} + + + {/* -------------------------------------------------- */} + {/* ITERATION 12: NUMBERS TABLE */} + {/* -------------------------------------------------- */} + + + {/* -------------------------------------------------- */} + {/* ITERATION 13: RGB COLOR PICKER */} + {/* -------------------------------------------------- */} +
); } diff --git a/src/components/BoxColor/BoxColor.css b/src/components/BoxColor/BoxColor.css new file mode 100644 index 0000000..bfaa4a5 --- /dev/null +++ b/src/components/BoxColor/BoxColor.css @@ -0,0 +1,6 @@ +.BoxColor { + padding: 20px; + border: 1px solid black; + margin: 15px 0; + text-align: center; +} diff --git a/src/components/BoxColor/BoxColor.js b/src/components/BoxColor/BoxColor.js new file mode 100644 index 0000000..84279ba --- /dev/null +++ b/src/components/BoxColor/BoxColor.js @@ -0,0 +1,17 @@ +import './BoxColor.css'; + +function BoxColor({ r, g, b }) { + const rgb = `rgb(${r}, ${g}, ${b})`; + const hex = "#" + [r, g, b] + .map((v) => v.toString(16).padStart(2, "0")) + .join(""); + + return ( +
+

{rgb}

+

{hex}

+
+ ); +} + +export default BoxColor; diff --git a/src/components/Carousel/Carousel.css b/src/components/Carousel/Carousel.css new file mode 100644 index 0000000..5ca6aa9 --- /dev/null +++ b/src/components/Carousel/Carousel.css @@ -0,0 +1,15 @@ +.carousel { + display: flex; + align-items: center; + margin: 10px 0; +} + +.carousel img { + width: 150px; + margin: 0 10px; +} + +.carousel button { + padding: 5px 10px; + cursor: pointer; +} diff --git a/src/components/Carousel/Carousel.js b/src/components/Carousel/Carousel.js new file mode 100644 index 0000000..1a45662 --- /dev/null +++ b/src/components/Carousel/Carousel.js @@ -0,0 +1,19 @@ +import { useState } from "react"; +import "./Carousel.css"; + +function Carousel({ images }) { + const [index, setIndex] = useState(0); + + const prev = () => setIndex((index - 1 + images.length) % images.length); + const next = () => setIndex((index + 1) % images.length); + + return ( +
+ + carousel + +
+ ); +} + +export default Carousel; diff --git a/src/components/ClickablePicture/ClickablePicture.css b/src/components/ClickablePicture/ClickablePicture.css new file mode 100644 index 0000000..30a27e0 --- /dev/null +++ b/src/components/ClickablePicture/ClickablePicture.css @@ -0,0 +1,5 @@ +.clickable-picture { + cursor: pointer; + width: 200px; + margin: 10px 0; +} diff --git a/src/components/ClickablePicture/ClickablePicture.js b/src/components/ClickablePicture/ClickablePicture.js new file mode 100644 index 0000000..9d8b744 --- /dev/null +++ b/src/components/ClickablePicture/ClickablePicture.js @@ -0,0 +1,17 @@ +import "./ClickablePicture.css"; +import { useState } from "react"; + +function ClickablePicture({ img, imgClicked }) { + const [clicked, setClicked] = useState(false); + + return ( + clickable setClicked(!clicked)} + /> + ); +} + +export default ClickablePicture; diff --git a/src/components/CreditCard/CreditCard.css b/src/components/CreditCard/CreditCard.css new file mode 100644 index 0000000..01837f0 --- /dev/null +++ b/src/components/CreditCard/CreditCard.css @@ -0,0 +1,27 @@ +.credit-card { + width: 300px; + border-radius: 10px; + padding: 20px; + margin: 12px; + display: flex; + flex-direction: column; +} + +.card-logo { + width: 60px; + align-self: flex-end; +} + +.card-number { + font-size: 1.5rem; + margin: 20px 0; +} + +.exp-bank { + display: flex; + justify-content: space-between; +} + +.owner { + margin-top: 10px; +} diff --git a/src/components/CreditCard/CreditCard.js b/src/components/CreditCard/CreditCard.js new file mode 100644 index 0000000..d1f2f6f --- /dev/null +++ b/src/components/CreditCard/CreditCard.js @@ -0,0 +1,39 @@ +import "./CreditCard.css"; + +function CreditCard({ + type, + number, + expirationMonth, + expirationYear, + bank, + owner, + bgColor, + color, +}) { + const cardTypeImg = + type === "Visa" + ? "/assets/images/visa.png" + : "/assets/images/master-card.svg"; + + const maskedNumber = "•••• •••• •••• " + number.slice(-4); + + return ( +
+ {type} + +
{maskedNumber}
+ +
+ + Expires {String(expirationMonth).padStart(2, "0")}/ + {String(expirationYear).slice(-2)} + + {bank} +
+ +
{owner}
+
+ ); +} + +export default CreditCard; diff --git a/src/components/Dice/Dice.css b/src/components/Dice/Dice.css new file mode 100644 index 0000000..1aa84ef --- /dev/null +++ b/src/components/Dice/Dice.css @@ -0,0 +1,5 @@ +.dice { + width: 100px; + cursor: pointer; + margin: 10px 0; +} diff --git a/src/components/Dice/Dice.js b/src/components/Dice/Dice.js new file mode 100644 index 0000000..7cc2fad --- /dev/null +++ b/src/components/Dice/Dice.js @@ -0,0 +1,35 @@ +import { useState } from "react"; +import "./Dice.css"; + +const diceImages = [ + "/assets/images/dice1.png", + "/assets/images/dice2.png", + "/assets/images/dice3.png", + "/assets/images/dice4.png", + "/assets/images/dice5.png", + "/assets/images/dice6.png", +]; + +function Dice() { + const [dice, setDice] = useState(diceImages[0]); + + const rollDice = () => { + setDice("/assets/images/dice-empty.png"); + + setTimeout(() => { + const random = Math.floor(Math.random() * 6); + setDice(diceImages[random]); + }, 1000); + }; + + return ( + dice + ); +} + +export default Dice; diff --git a/src/components/DriverCard/DriverCard.css b/src/components/DriverCard/DriverCard.css new file mode 100644 index 0000000..635e18d --- /dev/null +++ b/src/components/DriverCard/DriverCard.css @@ -0,0 +1,15 @@ +.driver-card { + background-color: #455eb5; + color: white; + border-radius: 10px; + padding: 20px; + display: flex; + align-items: center; + margin: 10px 0; +} + +.driver-card img { + width: 120px; + border-radius: 50%; + margin-right: 20px; +} diff --git a/src/components/DriverCard/DriverCard.js b/src/components/DriverCard/DriverCard.js new file mode 100644 index 0000000..18ad367 --- /dev/null +++ b/src/components/DriverCard/DriverCard.js @@ -0,0 +1,19 @@ +import "./DriverCard.css"; +import Rating from "../Rating/Rating"; + +function DriverCard({ name, rating, img, car }) { + return ( +
+ {name} +
+

{name}

+ {rating} +

+ {car.model} – {car.licensePlate} +

+
+
+ ); +} + +export default DriverCard; diff --git a/src/components/Greetings/Greetings.css b/src/components/Greetings/Greetings.css new file mode 100644 index 0000000..86fa2af --- /dev/null +++ b/src/components/Greetings/Greetings.css @@ -0,0 +1,5 @@ +.Greetings { + border: 1px solid black; + padding: 12px; + margin: 15px 0; +} diff --git a/src/components/Greetings/Greetings.js b/src/components/Greetings/Greetings.js new file mode 100644 index 0000000..89f0293 --- /dev/null +++ b/src/components/Greetings/Greetings.js @@ -0,0 +1,18 @@ +import './Greetings.css'; + +function Greetings({ lang, children }) { + const text = { + de: "Hallo", + en: "Hello", + es: "Hola", + fr: "Bonjour", + }; + + return ( +
+ {text[lang]} {children} +
+ ); +} + +export default Greetings; diff --git a/src/components/IdCard/IdCard.css b/src/components/IdCard/IdCard.css new file mode 100644 index 0000000..8338b09 --- /dev/null +++ b/src/components/IdCard/IdCard.css @@ -0,0 +1,15 @@ +.IdCard { + display: flex; + border: 1px solid #ccc; + padding: 16px; + margin: 15px 0; +} + +.IdCard img { + width: 120px; + margin-right: 20px; +} + +.IdCard-info p { + margin: 4px 0; +} diff --git a/src/components/IdCard/IdCard.js b/src/components/IdCard/IdCard.js new file mode 100644 index 0000000..ed3aef4 --- /dev/null +++ b/src/components/IdCard/IdCard.js @@ -0,0 +1,19 @@ +import './IdCard.css'; + +function IdCard({ lastName, firstName, gender, height, birth, picture }) { + return ( +
+ {firstName} + +
+

Last name: {lastName}

+

First name: {firstName}

+

Gender: {gender}

+

Height: {height / 100}m

+

Birth: {birth.toDateString()}

+
+
+ ); +} + +export default IdCard; diff --git a/src/components/LikeButton/LikeButton.css b/src/components/LikeButton/LikeButton.css new file mode 100644 index 0000000..f1e8633 --- /dev/null +++ b/src/components/LikeButton/LikeButton.css @@ -0,0 +1,9 @@ +.like-button { + padding: 10px 20px; + margin: 10px; + border: none; + color: white; + cursor: pointer; + border-radius: 6px; + font-size: 1rem; +} diff --git a/src/components/LikeButton/LikeButton.js b/src/components/LikeButton/LikeButton.js new file mode 100644 index 0000000..c523f2f --- /dev/null +++ b/src/components/LikeButton/LikeButton.js @@ -0,0 +1,22 @@ +import { useState } from "react"; +import "./LikeButton.css"; + +const colors = ["purple", "blue", "green", "yellow", "orange", "red"]; + +function LikeButton() { + const [count, setCount] = useState(0); + + const color = colors[count % colors.length]; + + return ( + + ); +} + +export default LikeButton; diff --git a/src/components/NumbersTable/NumbersTable.css b/src/components/NumbersTable/NumbersTable.css new file mode 100644 index 0000000..1717ca5 --- /dev/null +++ b/src/components/NumbersTable/NumbersTable.css @@ -0,0 +1,15 @@ +.numbers-table { + display: flex; + flex-wrap: wrap; + margin: 10px 0; +} + +.number { + width: 50px; + height: 50px; + display: flex; + justify-content: center; + align-items: center; + border: 1px solid #000; + margin: 2px; +} diff --git a/src/components/NumbersTable/NumbersTable.js b/src/components/NumbersTable/NumbersTable.js new file mode 100644 index 0000000..198c583 --- /dev/null +++ b/src/components/NumbersTable/NumbersTable.js @@ -0,0 +1,21 @@ +import "./NumbersTable.css"; + +function NumbersTable({ limit }) { + const numbers = Array.from({ length: limit }, (_, i) => i + 1); + + return ( +
+ {numbers.map((n) => ( +
+ {n} +
+ ))} +
+ ); +} + +export default NumbersTable; diff --git a/src/components/RGBColorPicker/RGBColorPicker.css b/src/components/RGBColorPicker/RGBColorPicker.css new file mode 100644 index 0000000..977f394 --- /dev/null +++ b/src/components/RGBColorPicker/RGBColorPicker.css @@ -0,0 +1,15 @@ +.rgb-color-picker { + margin: 10px 0; +} + +.combined-color-box { + width: 150px; + height: 50px; + margin-top: 10px; + display: flex; + justify-content: center; + align-items: center; + border: 1px solid #000; + font-weight: bold; + color: #000; +} diff --git a/src/components/RGBColorPicker/RGBColorPicker.js b/src/components/RGBColorPicker/RGBColorPicker.js new file mode 100644 index 0000000..9c85f29 --- /dev/null +++ b/src/components/RGBColorPicker/RGBColorPicker.js @@ -0,0 +1,26 @@ +import { useState } from "react"; +import SingleColorPicker from "../SingleColorPicker/SingleColorPicker"; +import "./RGBColorPicker.css"; + +function RGBColorPicker() { + const [r, setR] = useState(0); + const [g, setG] = useState(0); + const [b, setB] = useState(0); + + return ( +
+ + + + +
+ rgb({r},{g},{b}) +
+
+ ); +} + +export default RGBColorPicker; diff --git a/src/components/Random/Random.css b/src/components/Random/Random.css new file mode 100644 index 0000000..57b0851 --- /dev/null +++ b/src/components/Random/Random.css @@ -0,0 +1,5 @@ +.Random { + border: 1px solid black; + padding: 12px; + margin: 15px 0; +} diff --git a/src/components/Random/Random.js b/src/components/Random/Random.js new file mode 100644 index 0000000..d053ea8 --- /dev/null +++ b/src/components/Random/Random.js @@ -0,0 +1,13 @@ +import './Random.css'; + +function Random({ min, max }) { + const randomNum = Math.floor(Math.random() * (max - min + 1)) + min; + + return ( +
+ Random value between {min} and {max} => {randomNum} +
+ ); +} + +export default Random; diff --git a/src/components/Rating/Rating.css b/src/components/Rating/Rating.css new file mode 100644 index 0000000..6b15990 --- /dev/null +++ b/src/components/Rating/Rating.css @@ -0,0 +1,4 @@ +.Rating { + font-size: 2rem; + margin: 10px 0; +} diff --git a/src/components/Rating/Rating.js b/src/components/Rating/Rating.js new file mode 100644 index 0000000..4ac28d3 --- /dev/null +++ b/src/components/Rating/Rating.js @@ -0,0 +1,10 @@ +import "./Rating.css"; + +function Rating({ children }) { + const value = Math.round(Number(children)); + const stars = "★★★★★☆☆☆☆☆".slice(5 - value, 10 - value); + + return
{stars}
; +} + +export default Rating; diff --git a/src/components/SingleColorPicker/SingleColorPicker.css b/src/components/SingleColorPicker/SingleColorPicker.css new file mode 100644 index 0000000..d4c5eb6 --- /dev/null +++ b/src/components/SingleColorPicker/SingleColorPicker.css @@ -0,0 +1,17 @@ +.single-color-picker { + display: flex; + align-items: center; + margin: 5px 0; +} + +.single-color-picker input { + width: 60px; + margin-left: 5px; + margin-right: 10px; +} + +.color-box { + width: 50px; + height: 30px; + border: 1px solid #000; +} diff --git a/src/components/SingleColorPicker/SingleColorPicker.js b/src/components/SingleColorPicker/SingleColorPicker.js new file mode 100644 index 0000000..359e7c8 --- /dev/null +++ b/src/components/SingleColorPicker/SingleColorPicker.js @@ -0,0 +1,29 @@ +import "./SingleColorPicker.css"; + +function SingleColorPicker({ color, value, onChange }) { + return ( +
+ + onChange(Number(e.target.value))} + /> +
+
+ ); +} + +export default SingleColorPicker;