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}
+

+
+ );
+}
+
+/**
+ * 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