From 42bb1bce8b6d233649b1cc403cc7e2a9bf22590a Mon Sep 17 00:00:00 2001 From: Gowtham Jangiti Date: Sun, 13 Oct 2024 16:04:01 +0530 Subject: [PATCH 1/2] Initial Setup --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 894799c..d6df92d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,3 @@ - From fcd607029ed2374c122cc614f0ecfd35c3f41ffc Mon Sep 17 00:00:00 2001 From: Gowtham Jangiti Date: Sun, 13 Oct 2024 16:17:50 +0530 Subject: [PATCH 2/2] Completed --- README.md | 864 ---------------------------- src/App.js | 137 ++++- src/App.test.js | 8 - src/components/BoxColor.js | 25 + src/components/Carousal.js | 27 + src/components/ClickablePicture.js | 20 + src/components/CreditCard.js | 40 ++ src/components/DiceComponent.js | 32 ++ src/components/DriverCard.js | 40 ++ src/components/Greetings.js | 29 + src/components/Idcard.js | 46 ++ src/components/LikeButton.js | 30 + src/components/NumbersTable.js | 28 + src/components/RGBColorPicker.js | 34 ++ src/components/Random.js | 13 + src/components/Rating.js | 10 + src/components/SingleColorPicker.js | 19 + src/setupTests.js | 5 - 18 files changed, 516 insertions(+), 891 deletions(-) delete mode 100644 README.md delete mode 100644 src/App.test.js create mode 100644 src/components/BoxColor.js create mode 100644 src/components/Carousal.js create mode 100644 src/components/ClickablePicture.js create mode 100644 src/components/CreditCard.js create mode 100644 src/components/DiceComponent.js create mode 100644 src/components/DriverCard.js create mode 100644 src/components/Greetings.js create mode 100644 src/components/Idcard.js create mode 100644 src/components/LikeButton.js create mode 100644 src/components/NumbersTable.js create mode 100644 src/components/RGBColorPicker.js create mode 100644 src/components/Random.js create mode 100644 src/components/Rating.js create mode 100644 src/components/SingleColorPicker.js delete mode 100644 src/setupTests.js diff --git a/README.md b/README.md deleted file mode 100644 index d6df92d..0000000 --- a/README.md +++ /dev/null @@ -1,864 +0,0 @@ - - - -# LAB | React Training - - - -## Introduction - - - -The purpose of this exercise is to practice the core React concepts such as: creating components, passing data through props, working with state, rendering lists, and working with forms (controlled components). - - - -To see the expected result for each iteration, refer to the solution example: [**React Training - solution**](https://5c6c2a0de07b084ce35373ee--determined-aryabhata-a8a833.netlify.com/). - - - -## Setup - - - -- Fork this repo - -- Clone this repo - - - -```shell - -$ cd lab-react-training - -$ npm install - -$ npm start - -``` - - - - - - - -## Submission - - - -- Upon completion, run the following commands: - - - -``` - -git add . - -git commit -m "done" - -git push origin master - -``` - - - -- Create a Pull Request so we can review your work. - - - -## Instructions - - - -### Iteration 1 | Component: `IdCard` - - - -Create and render an `IdCard` component with 6 props: - - - -- `lastName`: A string - -- `firstName`: A string - -- `gender`: A string, `'male'` or `'female'` - -- `height`: A number - -- `birth`: A date - -- `picture`: A string - - - -**Example:** - - - -```jsx - - - - - - -``` - - - -**Expected Output:** - - - -![image](https://user-images.githubusercontent.com/5306791/52976030-22b0d200-33c8-11e9-91fe-e3ce0fa14078.png) - - - - - ----- - - - - - -### Iteration 2 | Component: `Greetings` - - - -Create a `Greetings` component with 2 props: - - - -- `lang`: A string that can have values: `"de"`, `"en"`, `"es"` or `"fr"` - -- `children`: A text - - - -The component should display a greeting text in the chosen language. - - - -**Example:** - - - -```jsx - -Ludwig - -François - -``` - - - -**Expected Output:** - - - -![image](https://user-images.githubusercontent.com/5306791/52957158-57edfd80-3391-11e9-8726-93c1a3389016.png) - - - - - ----- - - - - - -### Iteration 3 | Component: `Random` - - - -Create a `Random` component with 2 props: - - - -- `min`: A number - -- `max`: A number - - - -The component should display a random integer in the range between the `min` and the `max` number. - - - -**Example:** - - - -```jsx - - - - - -``` - - - -**Expected Output:** - - - -![image](https://user-images.githubusercontent.com/5306791/52957202-718f4500-3391-11e9-9b45-d1172067e877.png) - - - - - ----- - - - - - -### Iteration 4 | Component: `BoxColor` - - - -Create a `BoxColor` component that displays a rectangle with a background color based on props. For this, you will need to add inline styles ([documentation](https://reactjs.org/docs/dom-elements.html#style)). - - - -The component should take 3 props: - - - -- `r`: A number between `0` and `255` representing the amount of red - -- `g`: A number between `0` and `255` representing the amount of green - -- `b`: A number between `0` and `255` representing the amount of blue - - - -**Example:** - - - -```jsx - - - - - -``` - - - -**Expected Output:** - - - -![image](https://user-images.githubusercontent.com/5306791/52957816-ec0c9480-3392-11e9-9e00-67094fa2b431.png) - - - -As a bonus, you can also display the hex values of the color (e.g., `#ff0000` for red). - - - - - ----- - - - - - -### Iteration 5 | Component: `CreditCard` - - - -Create a `CreditCard` component that displays a rectangle with the information coming from the props. - - - -The component should take 8 props: - - - -- `type`: A string that can be `"Visa"` or `"Master Card"` - -- `number`: A string that is the number of the credit card. For security reasons, you should only display the 4 last digits 😉 - -- `expirationMonth`: A number that represents the month, between 1 and 12 - -- `expirationYear`: A number that represents the year - -- `bank`: A string that represents the name of the bank - -- `owner`: A string that represents the name of the owner - -- `bgColor`: A string for the background color of the card - -- `color`: A string for the text color of the card - - - -Take your time to make the component look as close to the *expected output* as possible. You'll probably want to use flexbox. - - - -**Example:** - - - -```jsx - - - - - - - -``` - - - -**Expected Output:** - - - -![image](https://user-images.githubusercontent.com/5306791/52975678-ac5fa000-33c6-11e9-8cbf-7d13a8a0f625.png) - - - - - ----- - - - - - -### Iteration 6 | Component: `Rating` - - - -Create a `Rating` component that displays 5 stars. Depending on the value received, some stars should be empty (☆), and some should be filled (★). - - - -The component should take 1 prop: - - - -- `children`: A number between `0` and `5`. The value can be a floating-point number. If the number received is `3.9`, the component should display 4 stars. - - - -**Example:** - - - -```jsx - -0 - -1.49 - -1.5 - -3 - -4 - -5 - -``` - - - -**Expected Output:** - - - -![image](https://user-images.githubusercontent.com/5306791/52972787-39512c00-33bc-11e9-93d8-428d835442fd.png) - - - - - ----- - - - - - -### Iteration 7 | Component: `DriverCard` - - - -Create a `DriverCard` component that displays a rectangle with content based on the received props. - - - -The component should take 4 props: - - - -- `name`: A string - -- `rating`: A number between `0` and `5`. The value can be a floating point number. - -- `img`: A string - -- `car`: An object with properties `model` and `licensePlate`. - - - -**Example** - - - -```jsx - - - - - - - -``` - - - -**Expected Output:** - - - -![image](https://user-images.githubusercontent.com/5306791/52972847-66054380-33bc-11e9-92e0-8e48d1ab0212.png) - - - - - ----- - - - - - -### Iteration 8 | State: `LikeButton` - - - -Create a `LikeButton` component that displays a button with the initial text `"0 Likes"`. With each click, the number of Likes should increase. - - - -As a bonus, implement the background color change on each click. You can use the following array of colors: `['purple','blue','green','yellow','orange','red']` - - - -**Example:** - - - -```jsx - - - -``` - - - -**Expected Output:** - - - -![](https://media.giphy.com/media/OQJkfIEkYTUdYkgNP7/giphy.gif) - - - - - ----- - - - - - -### Iteration 9: State: `ClickablePicture` - - - -Create a `ClickablePicture` component that displays a picture. On each click, the picture should toggle between the two images passed through the props. - - - -**Example:** - - - -```jsx - - - -``` - - - -**Expected Output:** - - - -![](https://media.giphy.com/media/9FXwCr2LLLIlgNL2sL/giphy.gif) - - - -PS: If you want to use your picture instead, you can create it using this picture: http://www.stickpng.com/assets/images/584999937b7d4d76317f5ffd.png 😎 - - - - - ----- - - - - - -### Iteration 10 | State: `Dice` - - - -Create a `Dice` component that displays a picture with the random dice value (example: `'./assets/images/dice3.png'`). - - - -Every time the user clicks on the component, it should: - - - -- First, display an empty picture (`'./assets/images/dice-empty.png'`) - -- 1 second later, display a new random picture (example: `'./assets/images/dice6.png'`). - - - -**Example:** - - - -```jsx - - - -``` - - - -**Expected Output before the click:** - - - -![image](https://user-images.githubusercontent.com/5306791/52976705-c13e3280-33ca-11e9-8684-f4dbff643b79.png) - - - -**Expected Output immediately after the click:** - - - -![image](https://user-images.githubusercontent.com/5306791/52976790-25f98d00-33cb-11e9-864e-ec14b4ec2a31.png) - - - -**Expected Output 1 second after the click:** - - - -![image](https://user-images.githubusercontent.com/5306791/52976752-f64a8500-33ca-11e9-98ee-b0b17f5e85b2.png) - - - - - ----- - - - - - -### Iteration 11 | State: `Carousel` - - - -Create a `Carousel` component that displays an image and two buttons (Left and Right), which change the picture on each click, respectively. - - - -The component should take 1 prop: - - - -- `images`: An array of strings. Each string should be an image URL. - - - -**Example:** - - - -```jsx - - - -``` - - - -**Expected Output:** - - - -![](https://media.giphy.com/media/1n7cAJu0MWerLnnohR/giphy.gif) - - - - - ----- - - - - - -### Iteration 12 | List and Keys | `NumbersTable` - - - -Create a `NumbersTable` component that displays a list of numbers between `1` and the `limit`. Even numbers must be colored in red. - - - -The component should take 1 prop: - - - -- `limit`: A number. - - - -**Example:** - - - -```jsx - - - -``` - - - -**Expected Output:** - - - -![image](https://user-images.githubusercontent.com/5306791/53028410-13349600-3467-11e9-8199-407375e61ab0.png) - - - - - ----- - - - - - - - - ----- - - - - - ----- - - - - - -### Iteration 13 | Lifting State Up - `RGBColorPicker` - - - -Create 2 components: - - - -- The `RGBColorPicker` component, that displays a square with an rgb color coming from the state. - -The component should have the following state variables: - - - -- `rValue`: A number between `0` and `255`, representing the amount of red - - - -- `gValue`: A number between `0` and `255`, representing the amount of green - - - -- `bValue`: A number between `0` and `255`, representing the amount of blue - - - - - -- The `SingleColorPicker` component should have an input field of type `"number"`, and allow the user to select a number between `0` and `255`. - - - -The component should take 3 props: - - - -- `color`: A string that is either `"r"`, `"g"` or `"b"` - -- `value`: A number between `0` and `255` - -- `onChange`: A method that is triggered when the input is changed - - - - - -The `RGBColorPicker` should render 3 `SingleColorPicker` components and send the state values to them. - - - -**Example:** - - - -```jsx - - { /* ... */ } } -/> - - - - { /* ... */ } } -/> - - - - { /* ... */ } } -/> - -``` - - - - - -**Expected Output** - - - -![image](https://user-images.githubusercontent.com/5306791/53166207-f918c600-35d4-11e9-8c47-c58cdc2d05b0.png) - - - - - -**Happy coding!** :heart: diff --git a/src/App.js b/src/App.js index 3784575..ad8b12d 100644 --- a/src/App.js +++ b/src/App.js @@ -1,23 +1,132 @@ import logo from './logo.svg'; import './App.css'; +import React from 'react'; +import IdCard from './components/Idcard'; +import Greetings from './components/Greetings'; +import Random from './components/Random'; +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 Dice from './components/DiceComponent'; +import Carousel from './components/Carousal'; +import RGBColorPicker from './components/RGBColorPicker'; +import NumbersTable from './components/NumbersTable'; function App() { return (
-
- logo -

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

- - Learn React - -
+

User Details

+ +

Greetings

+ Ludwig +François +

Random Number

+ + +

Box Color

+ + +

Credit Cards

+ + + + + +

Ratings

+ +0 + +1.49 + +1.5 + +3 + +4 + +5 +

Driver Cards +

+ + + +

LikeButton

+ + +

ClickablePicture

+ + +

Dice

+ + +

Carousel

+ + +

Numbers Table

+ + +

RGB Color Picker

+ +
); } diff --git a/src/App.test.js b/src/App.test.js deleted file mode 100644 index 1f03afe..0000000 --- a/src/App.test.js +++ /dev/null @@ -1,8 +0,0 @@ -import { render, screen } from '@testing-library/react'; -import App from './App'; - -test('renders learn react link', () => { - render(); - const linkElement = screen.getByText(/learn react/i); - expect(linkElement).toBeInTheDocument(); -}); diff --git a/src/components/BoxColor.js b/src/components/BoxColor.js new file mode 100644 index 0000000..8bdb1b6 --- /dev/null +++ b/src/components/BoxColor.js @@ -0,0 +1,25 @@ +import React from 'react'; + +function BoxColor({ r, g, b }) { + const divStyle = { + backgroundColor: `rgb(${r},${g},${b})`, + padding: '20px', + margin: '10px', + color: 'white', + textAlign: 'center', + border: '1px solid black', + }; + + const toHex = (r, g, b) => { + return `#${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase()}`; + }; + + return ( +
+ rgb({r}, {g}, {b})
+ {toHex(r, g, b)} +
+ ); +} + +export default BoxColor; \ No newline at end of file diff --git a/src/components/Carousal.js b/src/components/Carousal.js new file mode 100644 index 0000000..fb6b020 --- /dev/null +++ b/src/components/Carousal.js @@ -0,0 +1,27 @@ +import React, { useState } from 'react'; + +function Carousel({ images }) { + const [currentIndex, setCurrentIndex] = useState(0); + + const handleLeftClick = () => { + setCurrentIndex((prevIndex) => (prevIndex === 0 ? images.length - 1 : prevIndex - 1)); + }; + + const handleRightClick = () => { + setCurrentIndex((prevIndex) => (prevIndex === images.length - 1 ? 0 : prevIndex + 1)); + }; + + return ( +
+ + carousel + +
+ ); +} + +export default Carousel; \ No newline at end of file diff --git a/src/components/ClickablePicture.js b/src/components/ClickablePicture.js new file mode 100644 index 0000000..7e54731 --- /dev/null +++ b/src/components/ClickablePicture.js @@ -0,0 +1,20 @@ +import React, { useState } from 'react'; + +function 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/components/CreditCard.js b/src/components/CreditCard.js new file mode 100644 index 0000000..66f345a --- /dev/null +++ b/src/components/CreditCard.js @@ -0,0 +1,40 @@ +import React from 'react'; + +function CreditCard({ type, number, expirationMonth, expirationYear, bank, owner, bgColor, color }) { + const cardTypeImage = type === 'Visa' ? 'https://upload.wikimedia.org/wikipedia/commons/5/5e/Visa_Inc._logo.svg' : 'https://upload.wikimedia.org/wikipedia/commons/a/a4/Mastercard_2019_logo.svg'; + const formattedNumber = `**** **** **** ${number.slice(-4)}`; + const formattedMonth = expirationMonth < 10 ? `0${expirationMonth}` : expirationMonth; + const formattedYear = expirationYear.toString().slice(-2); + + return ( +
+
+ {type} +
+
{formattedNumber}
+
+
+ Expires {formattedMonth}/{formattedYear} +
+
{bank}
+
+
{owner}
+
+ ); +} + +export default CreditCard; \ No newline at end of file diff --git a/src/components/DiceComponent.js b/src/components/DiceComponent.js new file mode 100644 index 0000000..57e68f8 --- /dev/null +++ b/src/components/DiceComponent.js @@ -0,0 +1,32 @@ +import React, { useState } from 'react'; + +function Dice() { + const diceImages = [ + './assets/dice1.png', + './assets/dice2.png', + './assets/dice3.png', + './assets/dice4.png', + './assets/dice5.png', + './assets/dice6.png', + ]; + const [currentImage, setCurrentImage] = useState(diceImages[0]); + + const handleClick = () => { + setCurrentImage('./assets/images/dice-empty.png'); + setTimeout(() => { + const randomImage = diceImages[Math.floor(Math.random() * diceImages.length)]; + setCurrentImage(randomImage); + }, 1000); + }; + + return ( + Dice + ); +} + +export default Dice; \ No newline at end of file diff --git a/src/components/DriverCard.js b/src/components/DriverCard.js new file mode 100644 index 0000000..f53014c --- /dev/null +++ b/src/components/DriverCard.js @@ -0,0 +1,40 @@ +import React from 'react'; +import Rating from './Rating'; + +function DriverCard({ name, rating, img, car }) { + return ( +
+ {name} +
+

{name}

+ {rating} +

{car.model} - {car.licensePlate}

+
+
+ ); +} + +export default DriverCard; \ No newline at end of file diff --git a/src/components/Greetings.js b/src/components/Greetings.js new file mode 100644 index 0000000..da07ffb --- /dev/null +++ b/src/components/Greetings.js @@ -0,0 +1,29 @@ +import React from 'react'; + +function Greetings({ lang, children }) { + let greeting; + switch (lang) { + case 'de': + greeting = 'Hallo'; + break; + case 'en': + greeting = 'Hello'; + break; + case 'es': + greeting = 'Hola'; + break; + case 'fr': + greeting = 'Bonjour'; + break; + default: + greeting = 'Hello'; + } + + return ( +
+ {greeting} {children} +
+ ); + } + + export default Greetings; \ No newline at end of file diff --git a/src/components/Idcard.js b/src/components/Idcard.js new file mode 100644 index 0000000..671fd68 --- /dev/null +++ b/src/components/Idcard.js @@ -0,0 +1,46 @@ +import React from 'react'; +import userData from '../data/berlin.json'; // Adjust the path as necessary + +function IdCard() { + return ( +
+ {userData.map((user, index) => ( +
+ {`${user.firstName} +
+

+ First Name: {user.firstName} +

+

+ Last Name: {user.lastName} +

+

+ Gender: {user.gender} +

+

+ Height: {user.height} cm +

+

+ Birth: {new Date(user.birth).toDateString()} +

+
+
+ ))} +
+ ); +} + +export default IdCard; \ No newline at end of file diff --git a/src/components/LikeButton.js b/src/components/LikeButton.js new file mode 100644 index 0000000..d1767da --- /dev/null +++ b/src/components/LikeButton.js @@ -0,0 +1,30 @@ +import React, { useState } from 'react'; + +function 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/components/NumbersTable.js b/src/components/NumbersTable.js new file mode 100644 index 0000000..a44e2e1 --- /dev/null +++ b/src/components/NumbersTable.js @@ -0,0 +1,28 @@ +import React from 'react'; + +function NumbersTable({ limit }) { + const numbersArray = Array.from({ length: limit }, (_, i) => i + 1); + + return ( +
+ {numbersArray.map((number) => ( +
+ {number} +
+ ))} +
+ ); +} + +export default NumbersTable; \ No newline at end of file diff --git a/src/components/RGBColorPicker.js b/src/components/RGBColorPicker.js new file mode 100644 index 0000000..ba8d499 --- /dev/null +++ b/src/components/RGBColorPicker.js @@ -0,0 +1,34 @@ +import React, { useState } from 'react'; +import SingleColorPicker from './SingleColorPicker'; + +function RGBColorPicker() { + const [rgbValues, setRgbValues] = useState({ r: 0, g: 0, b: 0 }); + + const handleColorChange = (color, value) => { + setRgbValues((prevValues) => ({ + ...prevValues, + [color]: Number(value), + })); + }; + + return ( +
+ + + + +
+

RGB Color: rgb({rgbValues.r}, {rgbValues.g}, {rgbValues.b})

+
+ ); +} + +export default RGBColorPicker; \ No newline at end of file diff --git a/src/components/Random.js b/src/components/Random.js new file mode 100644 index 0000000..e87ac15 --- /dev/null +++ b/src/components/Random.js @@ -0,0 +1,13 @@ +import React from 'react'; + +function Random({ min, max }) { + const randomNumber = Math.floor(Math.random() * (max - min + 1)) + min; + + return ( +
+ Random value between {min} and {max} => {randomNumber} +
+ ); +} + +export default Random; \ No newline at end of file diff --git a/src/components/Rating.js b/src/components/Rating.js new file mode 100644 index 0000000..80021ec --- /dev/null +++ b/src/components/Rating.js @@ -0,0 +1,10 @@ +import React from 'react'; + +function Rating({ children }) { + const roundedRating = Math.round(children); + const stars = '★'.repeat(roundedRating) + '☆'.repeat(5 - roundedRating); + + return
{stars}
; +} + +export default Rating; \ No newline at end of file diff --git a/src/components/SingleColorPicker.js b/src/components/SingleColorPicker.js new file mode 100644 index 0000000..da3997b --- /dev/null +++ b/src/components/SingleColorPicker.js @@ -0,0 +1,19 @@ +import React from 'react'; + +function SingleColorPicker({ color, value, onChange }) { + return ( +
+ + onChange(color, e.target.value)} + style={{ marginLeft: '10px', width: '50px' }} + /> +
+ ); +} + +export default SingleColorPicker; \ No newline at end of file diff --git a/src/setupTests.js b/src/setupTests.js deleted file mode 100644 index 8f2609b..0000000 --- a/src/setupTests.js +++ /dev/null @@ -1,5 +0,0 @@ -// jest-dom adds custom jest matchers for asserting on DOM nodes. -// allows you to do things like: -// expect(element).toHaveTextContent(/react/i) -// learn more: https://github.com/testing-library/jest-dom -import '@testing-library/jest-dom';