diff --git a/src/App.css b/src/App.css index 74b5e05..7069533 100644 --- a/src/App.css +++ b/src/App.css @@ -7,6 +7,15 @@ pointer-events: none; } +.card-container { + display: flex; + flex-wrap: wrap; + gap: 20px; + justify-content: center; + padding: 20px; +} + + @media (prefers-reduced-motion: no-preference) { .App-logo { animation: App-logo-spin infinite 20s linear; diff --git a/src/App.js b/src/App.js index 3784575..e5e3777 100644 --- a/src/App.js +++ b/src/App.js @@ -1,23 +1,104 @@ -import logo from './logo.svg'; -import './App.css'; +import IdCard from "./components/IdCard"; +import Greetings from "./components/Greetings"; +import Random from "./components/Randoms"; +import BoxColor from "./components/BoxColor"; +import CreditCard from "./components/CreditCard"; +import Rating from "./components/Rating"; +import DriverCard from "./components/DriverCard"; +import LikeButton from "./components/LikeButton"; +import ClickablePicture from "./components/ClickablePicture"; +import picture from '../src/assets/images/maxence.png' +import picture2 from '../src/assets/images/maxence-glasses.png' +import "./App.css"; function App() { return (
-
- logo -

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

- - Learn React - -
+ + + Ludwig + François + John + Carlos + + + + +
+ + + +
+ 0 + 1.49 + 1.5 + 3 + 4 + 5 + + + +
); } diff --git a/src/components/BoxColor.js b/src/components/BoxColor.js new file mode 100644 index 0000000..2f6a635 --- /dev/null +++ b/src/components/BoxColor.js @@ -0,0 +1,22 @@ +export default function BoxColor(props) { + const { r, g, b } = props; + const isValidColor = (value) => value >= 0 && value <= 255; + const validatedR = isValidColor(r) ? r : 0; + const validatedG = isValidColor(g) ? g : 0; + const validatedB = isValidColor(b) ? b : 0; + + const style = { + backgroundColor: `rgb(${validatedR}, ${validatedG}, ${validatedB})`, + color: (validatedR + validatedG + validatedB) > 382 ? 'black' : 'white', + padding: '20px', + borderRadius: '8px', + textAlign: 'center', + marginBottom: '10px', + }; + + return ( +
+ rgb({validatedR}, {validatedG}, {validatedB}) +
+ ); +} \ No newline at end of file diff --git a/src/components/ClickablePicture.js b/src/components/ClickablePicture.js new file mode 100644 index 0000000..695a61f --- /dev/null +++ b/src/components/ClickablePicture.js @@ -0,0 +1,17 @@ +import { useState } from 'react'; +export default function ClickablePicture({ img, imgClicked }) { + const [isClicked, setIsClicked] = useState(false); + + const handleClick = () => { + setIsClicked(!isClicked); + }; + + return ( + Clickable + ); +} diff --git a/src/components/CreditCard.js b/src/components/CreditCard.js new file mode 100644 index 0000000..1a770f0 --- /dev/null +++ b/src/components/CreditCard.js @@ -0,0 +1,66 @@ +export default function CreditCard(props) { + const { + type, + number, + expirationMonth, + expirationYear, + bank, + owner, + bgColor, + color + } = props; + + const lastFourDigits = number.slice(-4); + + const formattedMonth = expirationMonth.toString().padStart(2, '0'); + const formattedYear = expirationYear.toString().slice(-2); + + const cardStyle = { + backgroundColor: bgColor, + color: color, + width: '300px', + height: '180px', + borderRadius: '10px', + padding: '20px', + display: 'flex', + flexDirection: 'column', + justifyContent: 'space-between', + fontFamily: 'Arial, sans-serif', + color: color, + position: 'relative' + }; + + const logoStyle = { + position: 'absolute', + top: '10px', + right: '10px', + fontSize: '24px' + }; + + const cardNumberStyle = { + fontSize: '24px', + letterSpacing: '2px' + }; + + const infoStyle = { + display: 'flex', + justifyContent: 'space-between', + fontSize: '14px' + }; + + return ( +
+
+ {type === 'Visa' ? 'V' : 'M'} +
+
+ **** **** **** {lastFourDigits} +
+
+
{bank}
+
{formattedMonth}/{formattedYear}
+
+
{owner}
+
+ ); +} \ No newline at end of file diff --git a/src/components/DriverCard.js b/src/components/DriverCard.js new file mode 100644 index 0000000..4d49057 --- /dev/null +++ b/src/components/DriverCard.js @@ -0,0 +1,59 @@ +export default function DriverCard({ name, rating, img, car }) { + // Ensure rating is between 0 and 5 + const validatedRating = Math.max(0, Math.min(5, parseFloat(rating))); + + // Format the rating to one decimal place + const formattedRating = validatedRating.toFixed(1); + + // Card styles + const cardStyle = { + display: "flex", + alignItems: "center", + backgroundColor: "#f8f9fa", + borderRadius: "10px", + padding: "20px", + boxShadow: "0 4px 8px rgba(0, 0, 0, 0.1)", + width: "400px", + margin: "20px 0", + }; + + const imgStyle = { + borderRadius: "50%", + width: "80px", + height: "80px", + marginRight: "20px", + }; + + const textStyle = { + display: "flex", + flexDirection: "column", + justifyContent: "center", + }; + + const nameStyle = { + fontSize: "18px", + fontWeight: "bold", + }; + + const ratingStyle = { + color: "#f39c12", + }; + + const carStyle = { + fontSize: "14px", + color: "#333", + }; + + return ( +
+ {`${name}`} +
+
{name}
+
{formattedRating} ★
+
+ {car.model} - {car.licensePlate} +
+
+
+ ); +} diff --git a/src/components/Greetings.js b/src/components/Greetings.js new file mode 100644 index 0000000..2ee0a81 --- /dev/null +++ b/src/components/Greetings.js @@ -0,0 +1,16 @@ +const greetings = { + de: 'Hallo', + en: 'Hello', + es: 'Hola', + fr: 'Bonjour' +}; +export default function Greetings(props) { + const { lang, children } = props; + const greeting = greetings[lang] || 'Hello'; + + return ( +
+ {greeting}, {children}! +
+ ); +} \ No newline at end of file diff --git a/src/components/IdCard.css b/src/components/IdCard.css new file mode 100644 index 0000000..cd0d6b3 --- /dev/null +++ b/src/components/IdCard.css @@ -0,0 +1,20 @@ +.id-card { + display: flex; + align-items: center; + border: 1px solid #ccc; + border-radius: 8px; + padding: 16px; + margin-bottom: 16px; + background-color: #f9f9f9; +} + +.id-card-picture { + border-radius: 50%; + width: 100px; + height: 100px; + margin-right: 16px; +} + +.id-card-info p { + margin: 4px 0; +} diff --git a/src/components/IdCard.js b/src/components/IdCard.js new file mode 100644 index 0000000..2c5abe1 --- /dev/null +++ b/src/components/IdCard.js @@ -0,0 +1,30 @@ +import './IdCard.css'; +export default function IdCard(props) { + const { lastName, firstName, gender, height, birth, picture } = props; + return ( +
+ {`${firstName} +
+

+ First Name: {firstName} +

+

+ Last Name: {lastName} +

+

+ Gender: {gender} +

+

+ Height: {height} cm +

+

+ Birth: {birth.toDateString()} +

+
+
+ ); +} diff --git a/src/components/LikeButton.js b/src/components/LikeButton.js new file mode 100644 index 0000000..c79e81f --- /dev/null +++ b/src/components/LikeButton.js @@ -0,0 +1,29 @@ +import { useState } from "react"; + +const colors = ["purple", "blue", "green", "yellow", "orange", "red"]; +export default function LikeButton() { + const [likes, setLikes] = useState(0); + const [colorIndex, setColorIndex] = useState(0); + + const handleClick = () => { + setLikes(likes + 1); + setColorIndex((colorIndex + 1) % colors.length); + }; + + return ( + + ); +} diff --git a/src/components/Randoms.js b/src/components/Randoms.js new file mode 100644 index 0000000..4277f48 --- /dev/null +++ b/src/components/Randoms.js @@ -0,0 +1,11 @@ +export default function Random(props) { + const { min, max } = props; + + const randomNumber = Math.floor(Math.random() * (max - min + 1)) + min; + + return ( +
+ Random value between {min} and {max} is {randomNumber} +
+ ); +} \ No newline at end of file diff --git a/src/components/Rating.js b/src/components/Rating.js new file mode 100644 index 0000000..0ea6942 --- /dev/null +++ b/src/components/Rating.js @@ -0,0 +1,15 @@ +export default function Rating({ children }) { + const value = Math.max(0, Math.min(5, parseFloat(children))); + + const roundedValue = Math.round(value); + + const stars = Array.from({ length: 5 }, (_, index) => + index < roundedValue ? '★' : '☆' + ); + + return ( +
+ {stars.join(' ')} +
+ ); +} \ No newline at end of file