diff --git a/Recruit-Training/Telemetry-Recruit-Training/first-training/src/App.css b/Recruit-Training/Telemetry-Recruit-Training/first-training/src/App.css index e69de29b..942d2f01 100644 --- a/Recruit-Training/Telemetry-Recruit-Training/first-training/src/App.css +++ b/Recruit-Training/Telemetry-Recruit-Training/first-training/src/App.css @@ -0,0 +1,63 @@ +/* Main page container */ +.app { + max-width: 1200px; + margin: 0 auto; + padding: 2rem; + box-sizing: border-box; +} + +/* Page title at the top */ +.page-title { + text-align: center; + font-size: 2rem; + font-weight: 700; + margin-bottom: 2rem; +} + +/* Image grid setup */ +.grid { + display: grid; + grid-template-columns: repeat(3, 1fr); /* Desktop: 3 columns */ + gap: 10px; +} + +/* Card wrapper for each image + title */ +.image-box { + display: flex; + flex-direction: column; + gap: 5px; /* EXACT 5px gap between title and image */ + align-items: center; + background-color: rgba(0, 0, 0, 0.15); + padding: 10px; + border-radius: 10px; +} + +/* Smaller title above each image */ +.image-title { + font-size: 1rem; + font-weight: 600; + text-align: center; + margin: 0; +} + +/* Image styling */ +.image-card { + width: 100%; + height: 200px; + object-fit: cover; + border-radius: 6px; +} + +/* Tablet breakpoint (md): 2 columns */ +@media (max-width: 992px) { + .grid { + grid-template-columns: repeat(2, 1fr); + } +} + +/* Mobile breakpoint (sm): 1 column */ +@media (max-width: 768px) { + .grid { + grid-template-columns: 1fr; + } +} diff --git a/Recruit-Training/Telemetry-Recruit-Training/first-training/src/App.jsx b/Recruit-Training/Telemetry-Recruit-Training/first-training/src/App.jsx index 6f23bfc7..60b8b09a 100644 --- a/Recruit-Training/Telemetry-Recruit-Training/first-training/src/App.jsx +++ b/Recruit-Training/Telemetry-Recruit-Training/first-training/src/App.jsx @@ -1,16 +1,75 @@ import "./App.css"; /** - Here are the images that you use in your app: - https://upload.wikimedia.org/wikipedia/commons/thumb/a/a5/Irbis4.JPG/1200px-Irbis4.JPG - https://files.worldwildlife.org/wwfcmsprod/images/Snow_Leopard_hero_species_2021/hero_small/8hwbyi3z8p_species_snowleopard_hero.jpg - https://images.saymedia-content.com/.image/t_share/MTc2NDYyMTcxMDg4Mjk5OTk0/the-endangered-snow-leopard.jpg - https://cdn.hswstatic.com/gif/gettyimages-1789936680.jpg - https://cdn.i-scmp.com/sites/default/files/styles/1020x680/public/images/methode/2018/05/23/b70f3e2e-5d99-11e8-a4de-9f5e0e4dd719_1280x720_095446.JPG?itok=b7E9r0SX - https://cdn.britannica.com/52/170952-050-A545E35D/carnivore-Snow-leopard-regions-subcontinent-Asia-Indian.jpg + * Array containing snow leopard images including a title for the image */ + +const snowLeopardGrid = [ + { + title: "Image #1", + src: "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a5/Irbis4.JPG/1200px-Irbis4.JPG", + + }, + { + title: "Image #2", + src: "https://files.worldwildlife.org/wwfcmsprod/images/Snow_Leopard_hero_species_2021/hero_small/8hwbyi3z8p_species_snowleopard_hero.jpg", + + }, + { + title: "Image #3", + src: "https://images.saymedia-content.com/.image/t_share/MTc2NDYyMTcxMDg4Mjk5OTk0/the-endangered-snow-leopard.jpg", + + }, + { + title: "Image #4", + src: "https://cdn.hswstatic.com/gif/gettyimages-1789936680.jpg", + + }, + { + title: "Image #5", + src: "https://cdn.i-scmp.com/sites/default/files/styles/1020x680/public/images/methode/2018/05/23/b70f3e2e-5d99-11e8-a4de-9f5e0e4dd719_1280x720_095446.JPG?itok=b7E9r0SX", + + }, + { + title: "Image #6", + src: "https://cdn.britannica.com/52/170952-050-A545E35D/carnivore-Snow-leopard-regions-subcontinent-Asia-Indian.jpg", + + }, +]; + +/** + * Displays the snow leopards and gets a title and src through props + */ + +function ImageBox({title, src}){ + return ( +
+

{title}

+ {title}/ +
+ ); +} + +/** + * Maps over an array of images and renders an ImageBox for each item + */ + +function Grid({images}) { + return ( +
+ {images.map((image) => ( + + ))} +
+ ); +} function App() { - return
; + return ( +
+

Snow Leopard: Images

+ +
+ ); } export default App; diff --git a/Recruit-Training/Telemetry-Recruit-Training/second-training/src/App.css b/Recruit-Training/Telemetry-Recruit-Training/second-training/src/App.css index 902778b7..e54fabed 100644 --- a/Recruit-Training/Telemetry-Recruit-Training/second-training/src/App.css +++ b/Recruit-Training/Telemetry-Recruit-Training/second-training/src/App.css @@ -4,3 +4,17 @@ padding: 2rem; text-align: center; } + +.telemetry-dashboard { + display: flex; + flex-direction: column; + gap: 2rem; + text-align: center; +} + +.telemetry-grid { + display: flex; + flex-direction: column; + gap: 2rem; + text-align: center; +} diff --git a/Recruit-Training/Telemetry-Recruit-Training/second-training/src/App.jsx b/Recruit-Training/Telemetry-Recruit-Training/second-training/src/App.jsx index 82779b0f..9321574f 100644 --- a/Recruit-Training/Telemetry-Recruit-Training/second-training/src/App.jsx +++ b/Recruit-Training/Telemetry-Recruit-Training/second-training/src/App.jsx @@ -1,85 +1,94 @@ +/** +ERRORS IN ORIGINAL FILE: + +1. Massive code duplication - The same JSX structure is repeated 7 times for different components +2. Hardcoded data - All telemetry values are hardcoded instead of being in a data structure +3. No reusable components - Everything is in one giant component +4. Poor maintainability - Adding a new telemetry component would require copying and pasting more code + +CHANGES MADE: + +1. Created telemetryData is an array with all the objects that have an id +2. Created TelemteryCard maps over the array of data and renders it using props +3. Implemented data mapping to create telemetry cards + */ + import "./App.css"; -function App() { +/** + * Contains all the data with id, name, type and values + */ + +const telemetryData =[ + { + id:"battery-pack" , + name: "Battery Pack", + data: [ + {label:"Voltage: ", value : "48.2V", status :"GOOD"}, + {label: "Current: ", value: "12.4A", status :"GOOD"}, + {label: "Temperature: ", value: "32°C", status :"WARNING"}, + {label: "State of Charge:", value: "87%", status : "GOOD"}, + ], + }, + + { + id: "motor-controller" , + name: "Motor Contoller", + data: [ + {label:"RPM: ", value : "2847", status : "ERROR"}, + {label: "Power: ", value : "1.2kW", status : "GOOD"}, + {label: "Temperature: ", value : "45°C", status : "WARNING"}, + {label: "Effeciency:", value : "94%", status : "GOOD"}, + ], + }, + + { + id: "solar-array" , + name: "Solar Array Section", + data: [ + {label:"Voltage: ", value : "51.8V", status : "GOOD"}, + {label: "Current: ", value: "8.3A", status : "GOOD"}, + {label: "Power: ", value : "430W", status : "GOOD"}, + {label: "Irradiance:", value : "67 W/m²", status : "ERROR"}, + ], + }, +]; + +/** + * Maps over the array of data and renders using props + */ + +function TelemetryCard ({name, data }){ return ( - <> -
-

Solar Car Telemetry Dashboard

+
+

{name}

-
-

Battery Pack

-
- Voltage: - 48.2V - GOOD -
-
- Current: - 12.4A - GOOD -
-
- Temperature: - 32°C - WARNING -
-
- State of Charge: - 87% - GOOD -
+ {data.map((data) => ( +
+ {data.label} + {data.value} + {data.status}
+ ))} +
+ ); +} -
-

Motor Controller

-
- RPM: - 2847 - ERROR -
-
- Power: - 1.2kW - GOOD -
-
- Temperature: - 45°C - WARNING -
-
- Efficiency: - 94% - GOOD -
-
+/** + * App component + */ -
-

Solar Array Section

-
- Voltage: - 51.8V - GOOD -
-
- Current: - 8.3A - GOOD -
-
- Power Output: - 430W - GOOD -
-
- Irradiance: - 867 W/m² - ERROR -
-
+function App() { + return ( +
+

Solar Car Telemetry Dashboard

+
+ {telemetryData.map((item) => ( + + ))}
- +
); } -export default App; +export default App; \ No newline at end of file