diff --git a/src/App.js b/src/App.js index 3784575..6a81dda 100644 --- a/src/App.js +++ b/src/App.js @@ -1,23 +1,138 @@ -import logo from './logo.svg'; + import './App.css'; +import BoxColor from './component/BoxColor'; +import Greetings from './component/Greetings'; +import IdCard from './component/IdCard'; +import Random from './component/Random'; +import CreditCard from './component/CreditCard'; +import Ratings from './component/Ratings'; +import DriverCard from './component/DriverCard'; +import LikeButton from './component/LikeButton'; +import ClickablePicture from './component/ClickablePicture'; +import fir from './assets/images/maxence.png' +import Sfir from './assets/images/maxence-glasses.png' +import Dice from './component/Dice'; +import Carousel from './component/Carousal'; +import NumbersTable from './component/NumbersTable'; +import RGBColorPicker from './component/RGBColorPicker'; function App() { return (
-
- logo -

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

- - Learn React - -
+ + + + + Ludwig + + François + + + + + + + + + + + + + + 0 + + 1.49 + + 1.5 + + 3 + + 4 + + 5 + + + + + + +
+ +
+
+ + + + + + +
+ +
); } diff --git a/src/assets/images/MasterCard.png b/src/assets/images/MasterCard.png new file mode 100644 index 0000000..6d76d32 Binary files /dev/null and b/src/assets/images/MasterCard.png differ diff --git a/src/component/BoxColor.css b/src/component/BoxColor.css new file mode 100644 index 0000000..f4df5fe --- /dev/null +++ b/src/component/BoxColor.css @@ -0,0 +1,19 @@ +.box-color { + width: 80%; + height: 150px; + display: flex; + align-items: center; + flex-direction: column; + justify-content: center; + color: white; + font-family: Arial, sans-serif; + border: 2px solid black; + margin-bottom: 20px; + margin-left: 10px; + } + + .box-color p { + margin: 0; + font-size: 30px; + line-height: 1.5; + } \ No newline at end of file diff --git a/src/component/BoxColor.js b/src/component/BoxColor.js new file mode 100644 index 0000000..bb80303 --- /dev/null +++ b/src/component/BoxColor.js @@ -0,0 +1,36 @@ +import React from "react"; +import "./BoxColor.css"; + +const rgbToHex = (r, g, b) => { + const toHex = (num) => { + const hex = num.toString(16); + return hex.length === 1 ? "0" + hex : hex; + }; + return `#${toHex(r)}${toHex(g)}${toHex(b)}`.toLowerCase(); +}; + +const BoxColor = ({ r, g, b }) => { + + const clampedR = Math.max(0, Math.min(255, r)); + const clampedG = Math.max(0, Math.min(255, g)); + const clampedB = Math.max(0, Math.min(255, b)); + + + const rgbColor = `rgb(${clampedR}, ${clampedG}, ${clampedB})`; + + + const hexColor = rgbToHex(clampedR, clampedG, clampedB); + + + const textColor = + clampedR === 128 && clampedG === 255 && clampedB === 0 ? "black" : "white"; + + return ( +
+

{rgbColor}

+

{hexColor}

+
+ ); +}; + +export default BoxColor; diff --git a/src/component/Carousal.css b/src/component/Carousal.css new file mode 100644 index 0000000..17e3593 --- /dev/null +++ b/src/component/Carousal.css @@ -0,0 +1,27 @@ +.carousel { + display: flex; + align-items: center; + justify-content: center; + position: relative; + } + + .carousel-image { + width: 300px; + height: 200px; + object-fit: cover; + margin: 0 10px; + } + + .carousel-button { + background-color: rgb(5, 172, 172); + border-radius: 11px; + color: white; + border: none; + padding: 10px; + cursor: pointer; + } + + .carousel-button:hover { + background-color: rgb(2, 95, 95); + } + \ No newline at end of file diff --git a/src/component/Carousal.js b/src/component/Carousal.js new file mode 100644 index 0000000..e94571c --- /dev/null +++ b/src/component/Carousal.js @@ -0,0 +1,34 @@ +import React, { useState } from "react"; +import './Carousal.css' + +const Carousel = ({ images }) => { + const [currentIndex, setCurrentIndex] = useState(0); + + const goToPrevious = () => { + setCurrentIndex( + (prevIndex) => (prevIndex - 1 + images.length) % images.length + ); + }; + + const goToNext = () => { + setCurrentIndex((prevIndex) => (prevIndex + 1) % images.length); + }; + + return ( +
+ + carousel + +
+ ); +}; + +export default Carousel; diff --git a/src/component/ClickablePicture.js b/src/component/ClickablePicture.js new file mode 100644 index 0000000..ba287a3 --- /dev/null +++ b/src/component/ClickablePicture.js @@ -0,0 +1,20 @@ +import React, { useState } from 'react'; + +const ClickablePicture = ({ img, imgClicked }) => { + const [isClicked, setIsClicked] = useState(false); + + const handleClick = () => { + setIsClicked(!isClicked); + }; + + return ( + Clickable + ); +}; + +export default ClickablePicture; \ No newline at end of file diff --git a/src/component/CreditCard.css b/src/component/CreditCard.css new file mode 100644 index 0000000..5467358 --- /dev/null +++ b/src/component/CreditCard.css @@ -0,0 +1,44 @@ +.credit-card { + width: 300px; + height: 130px; + border-radius: 10px; + padding: 20px; + display: flex; + flex-direction: column; + justify-content: space-between; + font-family: Arial, sans-serif; + margin: 20px; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); +} + +.card-logo { + display: flex; + justify-content: flex-end; +} + +.card-logo img { + margin-top: -15px; + width: 50px; + height: auto; +} + +.card-number { + font-size: 30px; + letter-spacing: 2px; + margin-top: -28px; +} + +.card-info { + font-size: 14px; + text-align: left; +} + +.bank { + margin-left: 30px; +} + +.owner { + display: flex; + margin-top: 20px; /* Optional: Adjust the spacing above the owner text */ + font-size: 14px; +} \ No newline at end of file diff --git a/src/component/CreditCard.js b/src/component/CreditCard.js new file mode 100644 index 0000000..166d5e1 --- /dev/null +++ b/src/component/CreditCard.js @@ -0,0 +1,51 @@ +import React from 'react'; +import './CreditCard.css'; +import mCard from '../assets/images/MasterCard.png' +import visa from '../assets/images/visa.png'; + + +const CreditCard = ({ + type, + number, + expirationMonth, + expirationYear, + bank, + owner, + bgColor, + color, +}) => { + + const lastFourDigits = number.slice(-4); + + const formattedMonth = expirationMonth.toString().padStart(2, "0"); + + const cardLogo = type === "Visa" ? visa : mCard; + + return ( +
+
+
+ {`${type} +
+
+

•••• •••• •••• {lastFourDigits}

+
+
+ + Expires {formattedMonth}/{expirationYear} + + {bank} + +
+ {owner} +
+
+
+
+ ); +}; + +export default CreditCard \ No newline at end of file diff --git a/src/component/Dice.js b/src/component/Dice.js new file mode 100644 index 0000000..0891e96 --- /dev/null +++ b/src/component/Dice.js @@ -0,0 +1,31 @@ +import React, { useState } from "react"; + + +const Dice = () => { + // State to keep track of the current dice image + const imagePath = require('../assets/images/dice3.png'); + const [diceImage, setDiceImage] = useState(imagePath); + + const rollDice = () => { + const emptyImage = require('../assets/images/dice-empty.png') + setDiceImage(emptyImage); + + // After 1 second, change the image to a random dice image + setTimeout(() => { + const randomDiceValue = Math.floor(Math.random() * 6) + 1; + const randomImage = require(`../assets/images/dice${randomDiceValue}.png`); + setDiceImage(randomImage); + }, 1000); + }; + + return ( + dice + ); +}; + +export default Dice; diff --git a/src/component/DriverCard.css b/src/component/DriverCard.css new file mode 100644 index 0000000..2b7c564 --- /dev/null +++ b/src/component/DriverCard.css @@ -0,0 +1,42 @@ +.driver-card { + display: flex; + align-items: center; + justify-content: flex-start; + background-color: #455eb5; + color: white; + border-radius: 10px; + padding: 20px; + width: 700px; + margin: 20px auto; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + padding-left: 400px; + } + + .driver-img { + width: 100px; + height: 100px; + border-radius: 50%; + object-fit: cover; + margin-right: 20px; + } + + .driver-info { + flex-grow: 1; + display: flex; + flex-direction: column; + justify-content: center; + } + + .driver-info h2 { + margin: 0; + font-size: 24px; + text-align: left; + } + + .driver-info p { + margin: -5px 0 0; + font-size: 16px; + text-align: left; + } + + \ No newline at end of file diff --git a/src/component/DriverCard.js b/src/component/DriverCard.js new file mode 100644 index 0000000..fbb6115 --- /dev/null +++ b/src/component/DriverCard.js @@ -0,0 +1,20 @@ +import React from "react"; +import "./DriverCard.css"; +import Ratings from "./Ratings"; + +const DriverCard = ({ name, rating, img, car }) => { + return ( +
+ {name} +
+

{name}

+ {rating} +

+ {car.model} - {car.licensePlate} +

+
+
+ ); +}; + +export default DriverCard; diff --git a/src/component/Greetings.css b/src/component/Greetings.css new file mode 100644 index 0000000..ee9ffaf --- /dev/null +++ b/src/component/Greetings.css @@ -0,0 +1,7 @@ +.greetings{ + font-size: 31px; + text-align: left; + border: 2px solid black; + margin: 10px 10px; + padding: 6px 4px; +} \ No newline at end of file diff --git a/src/component/Greetings.js b/src/component/Greetings.js new file mode 100644 index 0000000..aeeb0b0 --- /dev/null +++ b/src/component/Greetings.js @@ -0,0 +1,23 @@ +import React from 'react' +import './Greetings.css' + +function Greetings(props) { + const { lang, children } = props; + + const greetings = { + de: 'Hallo', + en: 'Hello', + es: 'Hola', + fr: 'Bonjour', + } + + const greetingText = greetings[lang] || 'Hello'; + + return ( +
+ {greetingText} {children} +
+ ) +} + +export default Greetings \ No newline at end of file diff --git a/src/component/IdCard.css b/src/component/IdCard.css new file mode 100644 index 0000000..5821070 --- /dev/null +++ b/src/component/IdCard.css @@ -0,0 +1,24 @@ +.id-card { + display: flex; + align-items: center; + border: 2px solid black; + padding: 3px 7px; + margin: 10px 10px; +} + +.id-card img { + margin-right: 20px; + padding-top: 5px; + padding-bottom: 5px; +} + +.id-card-details { + margin-top: -30px; +} + +.id-card-details p { + margin-left: -15px; + text-align: left; + line-height: 5px; + font-weight:500 +} \ No newline at end of file diff --git a/src/component/IdCard.js b/src/component/IdCard.js new file mode 100644 index 0000000..69e4368 --- /dev/null +++ b/src/component/IdCard.js @@ -0,0 +1,33 @@ +import React from 'react' +import './IdCard.css' + + +function IdCard(props) { + const { lastName, firstName, gender, height, birth, picture } = props; + + let formattedBirthDate = birth.toDateString().replace(/,/g, ""); + return ( +
+ {`${firstName} +
+

+ First name: {firstName} +

+

+ Last name: {lastName} +

+

+ Gender: {gender} +

+

+ Height: {(height / 100).toFixed(2)}m +

+

+ Birth: {formattedBirthDate} +

+
+
+ ); +} + +export default IdCard \ No newline at end of file diff --git a/src/component/LikeButton.css b/src/component/LikeButton.css new file mode 100644 index 0000000..b211b54 --- /dev/null +++ b/src/component/LikeButton.css @@ -0,0 +1,13 @@ +.like-button { + padding: 10px 20px; + margin-right: 10px; + font-size: 18px; + color: white; + border: none; + cursor: pointer; + transition: background-color 0.3s ease; + } + + .like-button:hover { + opacity: 0.8; + } \ No newline at end of file diff --git a/src/component/LikeButton.js b/src/component/LikeButton.js new file mode 100644 index 0000000..ae91ee4 --- /dev/null +++ b/src/component/LikeButton.js @@ -0,0 +1,24 @@ +import { useState } from "react"; +import './LikeButton.css' + +import React from 'react' + +const LikeButton = () => { + const [likes, setLikes] = useState(0) + + const [colorIndex, setColorIndex] = useState(0) + + const colors = ["purple", "blue", "green", "yellow", "orange", "red"]; + + const handleClick = () =>{ + setLikes(likes + 1) + setColorIndex((colorIndex + 1) % colors.length) + } + return ( +
+ +
+ ) +} + +export default LikeButton \ No newline at end of file diff --git a/src/component/NumbersTable.css b/src/component/NumbersTable.css new file mode 100644 index 0000000..18297f7 --- /dev/null +++ b/src/component/NumbersTable.css @@ -0,0 +1,28 @@ + +.numbers-table { + margin-top: 21px; + justify-content: center; + display: grid; + grid-template-columns: repeat(5, 52px); + grid-template-rows: repeat(3, 52px); + gap: 0px; +} + +.number { + width: 50px; + height: 50px; + display: flex; + align-items: center; + justify-content: center; + border: 2px solid black; + font-size: 18px; + font-weight: 500; +} + +.even { + background-color: red; +} + +.odd { + color: black; +} \ No newline at end of file diff --git a/src/component/NumbersTable.js b/src/component/NumbersTable.js new file mode 100644 index 0000000..dbaebfd --- /dev/null +++ b/src/component/NumbersTable.js @@ -0,0 +1,21 @@ +import React from "react"; +import "./NumbersTable.css"; + +const NumbersTable = ({ limit }) => { + const numbers = Array.from({ length: limit }, (_, i) => i + 1); + + return ( +
+ {numbers.map((number) => ( +
+ {number} +
+ ))} +
+ ); +}; + +export default NumbersTable; diff --git a/src/component/RGBColorPicker.js b/src/component/RGBColorPicker.js new file mode 100644 index 0000000..8038f5e --- /dev/null +++ b/src/component/RGBColorPicker.js @@ -0,0 +1,73 @@ +import React, { useState } from "react"; +import SingleColorPicker from "./SingleColorPicker"; + +const RGBColorPicker = () => { + const [rValue, setRValue] = useState(0); + const [gValue, setGValue] = useState(0); + const [bValue, setBValue] = useState(0); + + return ( +
+
+ setRValue(Number(value))} + /> + setGValue(Number(value))} + /> + setBValue(Number(value))} + /> +
+ +
+
+
+ rgb({rValue},{gValue},{bValue}) +
+
+
+ ); +}; + +const styles = { + container: { + display: "flex", + flexDirection: "column", + alignItems: "center", + justifyContent: "center", + paddingTop: "100px", + }, + pickersContainer: { + display: "flex", + flexDirection: "column", + alignItems: "center", + marginBottom: "20px", + }, + colorAndText: { + display: "flex", + alignItems: "center", + }, +}; + +export default RGBColorPicker; diff --git a/src/component/Random.css b/src/component/Random.css new file mode 100644 index 0000000..1e88427 --- /dev/null +++ b/src/component/Random.css @@ -0,0 +1,7 @@ +.random{ + font-size: 31px; + text-align: left; + border: 2px solid black; + margin: 10px 10px; + padding: 6px 4px; +} \ No newline at end of file diff --git a/src/component/Random.js b/src/component/Random.js new file mode 100644 index 0000000..afa1a63 --- /dev/null +++ b/src/component/Random.js @@ -0,0 +1,12 @@ +import React from 'react' +import './Random.css' + +function Random(props) { + + const {min, max} = props; + + const r = Math.floor(Math.random()*max + min); + return
Random Value between {min} and {max} → {r}
; +} + +export default Random \ No newline at end of file diff --git a/src/component/Rating.css b/src/component/Rating.css new file mode 100644 index 0000000..4b18d21 --- /dev/null +++ b/src/component/Rating.css @@ -0,0 +1,4 @@ +.rating{ + font-size: 24px; + color: black; +} \ No newline at end of file diff --git a/src/component/Ratings.js b/src/component/Ratings.js new file mode 100644 index 0000000..0e21c2c --- /dev/null +++ b/src/component/Ratings.js @@ -0,0 +1,13 @@ +import React from 'react' +import './Rating.css' + +const Ratings = ({ children, isDriverCard }) => { + const roundedRating = Math.round(children); + const stars = "★".repeat(roundedRating) + "☆".repeat(5 - roundedRating); + + const textColor = isDriverCard ? "white" : "black"; + const textAlign = isDriverCard ? "left" : "center"; + return
{stars}
; +} + +export default Ratings \ No newline at end of file diff --git a/src/component/SingleColorPicker.js b/src/component/SingleColorPicker.js new file mode 100644 index 0000000..6303736 --- /dev/null +++ b/src/component/SingleColorPicker.js @@ -0,0 +1,46 @@ +import React from 'react'; + +const SingleColorPicker = ({ color, value, onChange }) => { + const handleInputChange = (e) => { + onChange(e.target.value); + }; + + const getColorLabel = (color) => { + switch (color) { + case 'r': + return 'R:'; + case 'g': + return 'G:'; + case 'b': + return 'B:'; + default: + return ''; + } + }; + + return ( +
+
+ + +
+ ); +}; + +export default SingleColorPicker; \ No newline at end of file