diff --git a/data.json b/data.json new file mode 100644 index 0000000..bb8fdcf --- /dev/null +++ b/data.json @@ -0,0 +1,410 @@ +[ + { + "session_key": 9693, + "session_type": "Race", + "session_name": "Race", + "date_start": "2025-03-16T04:00:00+00:00", + "date_end": "2025-03-16T06:00:00+00:00", + "meeting_key": 1254, + "circuit_key": 10, + "circuit_short_name": "Melbourne", + "country_key": 5, + "country_code": "AUS", + "country_name": "Australia", + "location": "Melbourne", + "gmt_offset": "11:00:00", + "year": 2025, + "is_cancelled": false + }, + { + "session_key": 9998, + "session_type": "Race", + "session_name": "Race", + "date_start": "2025-03-23T07:00:00+00:00", + "date_end": "2025-03-23T09:00:00+00:00", + "meeting_key": 1255, + "circuit_key": 49, + "circuit_short_name": "Shanghai", + "country_key": 53, + "country_code": "CHN", + "country_name": "China", + "location": "Shanghai", + "gmt_offset": "08:00:00", + "year": 2025, + "is_cancelled": false + }, + { + "session_key": 10006, + "session_type": "Race", + "session_name": "Race", + "date_start": "2025-04-06T05:00:00+00:00", + "date_end": "2025-04-06T07:00:00+00:00", + "meeting_key": 1256, + "circuit_key": 46, + "circuit_short_name": "Suzuka", + "country_key": 4, + "country_code": "JPN", + "country_name": "Japan", + "location": "Suzuka", + "gmt_offset": "09:00:00", + "year": 2025, + "is_cancelled": false + }, + { + "session_key": 10014, + "session_type": "Race", + "session_name": "Race", + "date_start": "2025-04-13T15:00:00+00:00", + "date_end": "2025-04-13T17:00:00+00:00", + "meeting_key": 1257, + "circuit_key": 63, + "circuit_short_name": "Sakhir", + "country_key": 36, + "country_code": "BRN", + "country_name": "Bahrain", + "location": "Sakhir", + "gmt_offset": "03:00:00", + "year": 2025, + "is_cancelled": false + }, + { + "session_key": 10022, + "session_type": "Race", + "session_name": "Race", + "date_start": "2025-04-20T17:00:00+00:00", + "date_end": "2025-04-20T19:00:00+00:00", + "meeting_key": 1258, + "circuit_key": 149, + "circuit_short_name": "Jeddah", + "country_key": 153, + "country_code": "KSA", + "country_name": "Saudi Arabia", + "location": "Jeddah", + "gmt_offset": "03:00:00", + "year": 2025, + "is_cancelled": false + }, + { + "session_key": 10033, + "session_type": "Race", + "session_name": "Race", + "date_start": "2025-05-04T20:00:00+00:00", + "date_end": "2025-05-04T22:00:00+00:00", + "meeting_key": 1259, + "circuit_key": 151, + "circuit_short_name": "Miami", + "country_key": 19, + "country_code": "USA", + "country_name": "United States", + "location": "Miami Gardens", + "gmt_offset": "-04:00:00", + "year": 2025, + "is_cancelled": false + }, + { + "session_key": 9987, + "session_type": "Race", + "session_name": "Race", + "date_start": "2025-05-18T13:00:00+00:00", + "date_end": "2025-05-18T15:00:00+00:00", + "meeting_key": 1260, + "circuit_key": 6, + "circuit_short_name": "Imola", + "country_key": 13, + "country_code": "ITA", + "country_name": "Italy", + "location": "Imola", + "gmt_offset": "02:00:00", + "year": 2025, + "is_cancelled": false + }, + { + "session_key": 9979, + "session_type": "Race", + "session_name": "Race", + "date_start": "2025-05-25T13:00:00+00:00", + "date_end": "2025-05-25T15:00:00+00:00", + "meeting_key": 1261, + "circuit_key": 22, + "circuit_short_name": "Monte Carlo", + "country_key": 114, + "country_code": "MON", + "country_name": "Monaco", + "location": "Monaco", + "gmt_offset": "02:00:00", + "year": 2025, + "is_cancelled": false + }, + { + "session_key": 9971, + "session_type": "Race", + "session_name": "Race", + "date_start": "2025-06-01T13:00:00+00:00", + "date_end": "2025-06-01T15:00:00+00:00", + "meeting_key": 1262, + "circuit_key": 15, + "circuit_short_name": "Catalunya", + "country_key": 1, + "country_code": "ESP", + "country_name": "Spain", + "location": "Barcelona", + "gmt_offset": "02:00:00", + "year": 2025, + "is_cancelled": false + }, + { + "session_key": 9963, + "session_type": "Race", + "session_name": "Race", + "date_start": "2025-06-15T18:00:00+00:00", + "date_end": "2025-06-15T20:00:00+00:00", + "meeting_key": 1263, + "circuit_key": 23, + "circuit_short_name": "Montreal", + "country_key": 46, + "country_code": "CAN", + "country_name": "Canada", + "location": "Montréal", + "gmt_offset": "-04:00:00", + "year": 2025, + "is_cancelled": false + }, + { + "session_key": 9955, + "session_type": "Race", + "session_name": "Race", + "date_start": "2025-06-29T13:00:00+00:00", + "date_end": "2025-06-29T15:00:00+00:00", + "meeting_key": 1264, + "circuit_key": 19, + "circuit_short_name": "Spielberg", + "country_key": 17, + "country_code": "AUT", + "country_name": "Austria", + "location": "Spielberg", + "gmt_offset": "02:00:00", + "year": 2025, + "is_cancelled": false + }, + { + "session_key": 9947, + "session_type": "Race", + "session_name": "Race", + "date_start": "2025-07-06T14:00:00+00:00", + "date_end": "2025-07-06T16:00:00+00:00", + "meeting_key": 1277, + "circuit_key": 2, + "circuit_short_name": "Silverstone", + "country_key": 2, + "country_code": "GBR", + "country_name": "United Kingdom", + "location": "Silverstone", + "gmt_offset": "01:00:00", + "year": 2025, + "is_cancelled": false + }, + { + "session_key": 9939, + "session_type": "Race", + "session_name": "Race", + "date_start": "2025-07-27T13:00:00+00:00", + "date_end": "2025-07-27T15:00:00+00:00", + "meeting_key": 1265, + "circuit_key": 7, + "circuit_short_name": "Spa-Francorchamps", + "country_key": 16, + "country_code": "BEL", + "country_name": "Belgium", + "location": "Spa-Francorchamps", + "gmt_offset": "02:00:00", + "year": 2025, + "is_cancelled": false + }, + { + "session_key": 9928, + "session_type": "Race", + "session_name": "Race", + "date_start": "2025-08-03T13:00:00+00:00", + "date_end": "2025-08-03T15:00:00+00:00", + "meeting_key": 1266, + "circuit_key": 4, + "circuit_short_name": "Hungaroring", + "country_key": 14, + "country_code": "HUN", + "country_name": "Hungary", + "location": "Budapest", + "gmt_offset": "02:00:00", + "year": 2025, + "is_cancelled": false + }, + { + "session_key": 9920, + "session_type": "Race", + "session_name": "Race", + "date_start": "2025-08-31T13:00:00+00:00", + "date_end": "2025-08-31T15:00:00+00:00", + "meeting_key": 1267, + "circuit_key": 55, + "circuit_short_name": "Zandvoort", + "country_key": 133, + "country_code": "NED", + "country_name": "Netherlands", + "location": "Zandvoort", + "gmt_offset": "02:00:00", + "year": 2025, + "is_cancelled": false + }, + { + "session_key": 9912, + "session_type": "Race", + "session_name": "Race", + "date_start": "2025-09-07T13:00:00+00:00", + "date_end": "2025-09-07T15:00:00+00:00", + "meeting_key": 1268, + "circuit_key": 39, + "circuit_short_name": "Monza", + "country_key": 13, + "country_code": "ITA", + "country_name": "Italy", + "location": "Monza", + "gmt_offset": "02:00:00", + "year": 2025, + "is_cancelled": false + }, + { + "session_key": 9904, + "session_type": "Race", + "session_name": "Race", + "date_start": "2025-09-21T11:00:00+00:00", + "date_end": "2025-09-21T13:00:00+00:00", + "meeting_key": 1269, + "circuit_key": 144, + "circuit_short_name": "Baku", + "country_key": 30, + "country_code": "AZE", + "country_name": "Azerbaijan", + "location": "Baku", + "gmt_offset": "04:00:00", + "year": 2025, + "is_cancelled": false + }, + { + "session_key": 9896, + "session_type": "Race", + "session_name": "Race", + "date_start": "2025-10-05T12:00:00+00:00", + "date_end": "2025-10-05T14:00:00+00:00", + "meeting_key": 1270, + "circuit_key": 61, + "circuit_short_name": "Singapore", + "country_key": 157, + "country_code": "SGP", + "country_name": "Singapore", + "location": "Marina Bay", + "gmt_offset": "08:00:00", + "year": 2025, + "is_cancelled": false + }, + { + "session_key": 9888, + "session_type": "Race", + "session_name": "Race", + "date_start": "2025-10-19T19:00:00+00:00", + "date_end": "2025-10-19T21:00:00+00:00", + "meeting_key": 1271, + "circuit_key": 9, + "circuit_short_name": "Austin", + "country_key": 19, + "country_code": "USA", + "country_name": "United States", + "location": "Austin", + "gmt_offset": "-05:00:00", + "year": 2025, + "is_cancelled": false + }, + { + "session_key": 9877, + "session_type": "Race", + "session_name": "Race", + "date_start": "2025-10-26T20:00:00+00:00", + "date_end": "2025-10-26T22:00:00+00:00", + "meeting_key": 1272, + "circuit_key": 65, + "circuit_short_name": "Mexico City", + "country_key": 8, + "country_code": "MEX", + "country_name": "Mexico", + "location": "Mexico City", + "gmt_offset": "-06:00:00", + "year": 2025, + "is_cancelled": false + }, + { + "session_key": 9869, + "session_type": "Race", + "session_name": "Race", + "date_start": "2025-11-09T17:00:00+00:00", + "date_end": "2025-11-09T19:00:00+00:00", + "meeting_key": 1273, + "circuit_key": 14, + "circuit_short_name": "Interlagos", + "country_key": 10, + "country_code": "BRA", + "country_name": "Brazil", + "location": "São Paulo", + "gmt_offset": "-03:00:00", + "year": 2025, + "is_cancelled": false + }, + { + "session_key": 9858, + "session_type": "Race", + "session_name": "Race", + "date_start": "2025-11-23T04:00:00+00:00", + "date_end": "2025-11-23T06:00:00+00:00", + "meeting_key": 1274, + "circuit_key": 152, + "circuit_short_name": "Las Vegas", + "country_key": 19, + "country_code": "USA", + "country_name": "United States", + "location": "Las Vegas", + "gmt_offset": "-08:00:00", + "year": 2025, + "is_cancelled": false + }, + { + "session_key": 9850, + "session_type": "Race", + "session_name": "Race", + "date_start": "2025-11-30T16:00:00+00:00", + "date_end": "2025-11-30T18:00:00+00:00", + "meeting_key": 1275, + "circuit_key": 150, + "circuit_short_name": "Lusail", + "country_key": 149, + "country_code": "QAT", + "country_name": "Qatar", + "location": "Lusail", + "gmt_offset": "03:00:00", + "year": 2025, + "is_cancelled": false + }, + { + "session_key": 9839, + "session_type": "Race", + "session_name": "Race", + "date_start": "2025-12-07T13:00:00+00:00", + "date_end": "2025-12-07T15:00:00+00:00", + "meeting_key": 1276, + "circuit_key": 70, + "circuit_short_name": "Yas Marina Circuit", + "country_key": 21, + "country_code": "UAE", + "country_name": "United Arab Emirates", + "location": "Yas Island", + "gmt_offset": "04:00:00", + "year": 2025, + "is_cancelled": false + } +] diff --git a/images/ferrari.jpg b/images/ferrari.jpg new file mode 100644 index 0000000..cd5ff08 Binary files /dev/null and b/images/ferrari.jpg differ diff --git a/images/image-removebg-preview.png b/images/image-removebg-preview.png new file mode 100644 index 0000000..d76e76e Binary files /dev/null and b/images/image-removebg-preview.png differ diff --git a/images/leclerc-ferrari.avif b/images/leclerc-ferrari.avif new file mode 100644 index 0000000..a194c7d Binary files /dev/null and b/images/leclerc-ferrari.avif differ diff --git a/images/leclerc-ferrari.avif:Zone.Identifier b/images/leclerc-ferrari.avif:Zone.Identifier new file mode 100644 index 0000000..d6c1ec6 Binary files /dev/null and b/images/leclerc-ferrari.avif:Zone.Identifier differ diff --git a/images/scuederia-removebg-preview.png b/images/scuederia-removebg-preview.png new file mode 100644 index 0000000..3a4d568 Binary files /dev/null and b/images/scuederia-removebg-preview.png differ diff --git a/images/scuederia.png b/images/scuederia.png new file mode 100644 index 0000000..8c63dbf Binary files /dev/null and b/images/scuederia.png differ diff --git a/images/w&b-scuderia.png b/images/w&b-scuderia.png new file mode 100644 index 0000000..ca0092c Binary files /dev/null and b/images/w&b-scuderia.png differ diff --git a/index.html b/index.html new file mode 100644 index 0000000..896aa0b --- /dev/null +++ b/index.html @@ -0,0 +1,83 @@ + + + + + Ferrari Dashboard + + + + + + + + +
+
+

Ferrari

+

The most storied team in Formula 1's history

+
+

Since 1947, Ferrari has been building cars destined to win on the track and break records

+

+

The Team

+

Our talented individuals are our greatest resource. + However, they can only pursue the extraordinary by working together as a team. + By fostering integrity, excellence and generosity, we give each of our people + the possibility to express their own full potential - and be part of something greater. +

+ +

Tradition and Innovation

+

Tradition and innovation drive each other. The ongoing quest for lasting firsts is what fuels the Ferrari legend. + Our ability to combine revolutionary technological solutions with exceptional artisanal craftsmanship is + what enables us to create icons that stay timeless in a fast-changing world. +

+ +

Passion and Achievement

+

Ferrari’s racing spirit lives on in emotions that transcend the road and the track, + ultimately becoming an authentic attitude towards life. Nothing excites us more than setting ambitious targets + and expectations – and then exceeding them, to push every boundary. It is how the power of passion becomes the + beauty of achievement. +

+

+
+
+
+ + +
+

Race Results

+ LeClerc + + + Country + Circuit + Fastest Time + Laps + Position + + + + + + +
+ + +
+

Statistics

+
+ + + + diff --git a/pr_template.md b/pr_template.md index 51551bb..9c10075 100644 --- a/pr_template.md +++ b/pr_template.md @@ -9,8 +9,8 @@ ## Core Requirements Please check off which features you have implemented: -- [ ] Built as a Single Page Application (SPA) without needing browser reloads. -- [ ] An interesting and beautiful frontend design with a catchy title, apt description, and cool fonts/colors that looks good on any screen size. +- [X] Built as a Single Page Application (SPA) without needing browser reloads. +- [X] An interesting and beautiful frontend design with a catchy title, apt description, and cool fonts/colors that looks good on any screen size. - [ ] Successfully fetches and renders data from an external F1 API (e.g., Ergast, OpenF1). - [ ] Displays F1 data in a table that is capped at 20 rows per page. - [ ] Table includes functional Next/Previous arrows to navigate the dataset. @@ -26,13 +26,13 @@ Please check off which features you have implemented: - [ ] Includes a custom UI for Boolean search logic (e.g., AND/OR dropdowns or toggles). ## Screen Recording -**Link**: [paste it here] +**Link**: [\[paste it here\]](https://drive.google.com/file/d/1e8-A6byC6HvdrtDZiyFdyj2w6A5uyUN1/view?usp=sharing) ## Written Portion 1. **How did the project go? What parts of it did you most enjoy / find yourself good at?** -[answer here] +The project didn't go too bad, it was fairly enjoying as I was learning new things while Claude was helping me flesh out the webpage. I made sure that I had a firm understanding of what was going on as well, because some of the javascript was a bit confusing at first, but then I asked Claude for further clarification and it started to click for a bit. Unfortunately I didn't even manage to get into the main functionality of the webpage (I started a week late) and probably spent a bit too much time on designing the webpage rather than focusing on functionality calling the API and retriving race data. 2. **Was this technical assessment what you expected? If you had another two weeks to work on it, what would you add or change?** -[answer here] +This technical assessment wasn't what I expected at first, I thought it would be leetcode style questions to be honest 😭, although it makes sense that it'd be about building a webpage since that is what we've BEEN doing throughout the JDT workshops. If I had another two weeks, I probably would've fleshed out a design plan on what I wanted to do with the website, since I've learned organizing a webpage could quickly pile up into a plethora of divs. Originally, given the time constraint, I would've focused on LeClerc's data only because Hamilton only recently came in for the 2026 F1 season (last was Carlos Sainz Jr.). However, with additional time, I would've liked to add Hamilton's and Sainz Jr.'s data as well since they were the most recent. diff --git a/script.js b/script.js new file mode 100644 index 0000000..2afd162 --- /dev/null +++ b/script.js @@ -0,0 +1,77 @@ +function showView(viewName){ + document.querySelectorAll('.view').forEach(view => { + view.style.display = 'none'; + }); + + document.getElementById(viewName).style.display = 'block'; +} + +const data = [ + { driverName: "Charles Leclerc", racePos: 2, fastestLap: 85.271, numLaps: 57, circuitLocation: "Melbourne", countryCode: "AUS" }, + { driverName: "Charles Leclerc", racePos: 1, fastestLap: 83.456, numLaps: 56, circuitLocation: "Shanghai", countryCode: "CHN" }, + { driverName: "Charles Leclerc", racePos: 3, fastestLap: 91.234, numLaps: 53, circuitLocation: "Suzuka", countryCode: "JPN" }, + { driverName: "Charles Leclerc", racePos: 4, fastestLap: 88.123, numLaps: 50, circuitLocation: "Sakhir", countryCode: "BRN" }, + { driverName: "Charles Leclerc", racePos: 1, fastestLap: 86.789, numLaps: 50, circuitLocation: "Jeddah", countryCode: "KSA" }, + { driverName: "Charles Leclerc", racePos: 2, fastestLap: 87.234, numLaps: 57, circuitLocation: "Miami", countryCode: "USA" }, + { driverName: "Charles Leclerc", racePos: 5, fastestLap: 89.567, numLaps: 63, circuitLocation: "Imola", countryCode: "ITA" }, + { driverName: "Charles Leclerc", racePos: 1, fastestLap: 74.123, numLaps: 78, circuitLocation: "Monaco", countryCode: "MON" }, + { driverName: "Charles Leclerc", racePos: 3, fastestLap: 82.456, numLaps: 66, circuitLocation: "Barcelona", countryCode: "ESP" }, + { driverName: "Charles Leclerc", racePos: 2, fastestLap: 76.234, numLaps: 70, circuitLocation: "Montreal", countryCode: "CAN" }, + { driverName: "Charles Leclerc", racePos: 4, fastestLap: 67.890, numLaps: 71, circuitLocation: "Spielberg", countryCode: "AUT" }, + { driverName: "Charles Leclerc", racePos: 1, fastestLap: 88.345, numLaps: 52, circuitLocation: "Silverstone", countryCode: "GBR" }, + { driverName: "Charles Leclerc", racePos: 3, fastestLap: 105.234, numLaps: 44, circuitLocation: "Spa-Francorchamps", countryCode: "BEL" }, + { driverName: "Charles Leclerc", racePos: 2, fastestLap: 78.456, numLaps: 70, circuitLocation: "Budapest", countryCode: "HUN" }, + { driverName: "Charles Leclerc", racePos: 5, fastestLap: 73.234, numLaps: 72, circuitLocation: "Zandvoort", countryCode: "NED" }, + { driverName: "Charles Leclerc", racePos: 1, fastestLap: 81.234, numLaps: 53, circuitLocation: "Monza", countryCode: "ITA" }, + { driverName: "Charles Leclerc", racePos: 2, fastestLap: 103.456, numLaps: 51, circuitLocation: "Baku", countryCode: "AZE" }, + { driverName: "Charles Leclerc", racePos: 3, fastestLap: 95.678, numLaps: 62, circuitLocation: "Singapore", countryCode: "SGP" }, + { driverName: "Charles Leclerc", racePos: 4, fastestLap: 96.234, numLaps: 56, circuitLocation: "Austin", countryCode: "USA" }, + { driverName: "Charles Leclerc", racePos: 2, fastestLap: 79.456, numLaps: 71, circuitLocation: "Mexico City", countryCode: "MEX" }, + { driverName: "Charles Leclerc", racePos: 1, fastestLap: 71.234, numLaps: 69, circuitLocation: "Sao Paulo", countryCode: "BRA" }, + { driverName: "Charles Leclerc", racePos: 3, fastestLap: 93.456, numLaps: 50, circuitLocation: "Las Vegas", countryCode: "USA" }, + { driverName: "Charles Leclerc", racePos: 2, fastestLap: 87.123, numLaps: 57, circuitLocation: "Lusail", countryCode: "QAT" }, + { driverName: "Charles Leclerc", racePos: 4, fastestLap: 84.567, numLaps: 58, circuitLocation: "Yas Marina", countryCode: "UAE" }, +]; + +/* +function sleep(ms){ + return new Promise(resolve => setTimeout(resolve, ms)); +} + +//MAKES way to many calls, so the API starts rate limiting +async function acquireRaceData(){ + const raceData = await fetch("https://api.openf1.org/v1/sessions?year=2025&session_name=Race"); + const races = await raceData.json(); + + for(const race of races){ //of different than in, of looks at values, in goes over indices. i still dk + //Lap Data + const lapData = await fetch(`https://api.openf1.org/v1/laps?session_key=${race.session_key}&driver_number=16`); + const laps = await lapData.json(); + + //Final Position Information + const positionData = await fetch(`https://api.openf1.org/v1/position?session_key=${race.session_key}&driver_number=16`); + const positions = await positionData.json(); + const finPosition = positions.length > 0 ? positions[positions.length - 1].position : null; //{last index of json}.position + + const race_session = { + driverName: "Charles Leclerc", + racePos: race.is_cancelled == false ? finPosition : "Cancelled", + //Converts lapData into an array of laps that map to each index's lap_duration + //and then "..." returns the values from an array into a list of numbers (cancels out the "[]") + fastestLap: race.is_cancelled == false ? Math.min(...laps.map(lap => lap.lap_duration)) : "---", + numLaps: race.is_cancelled == false ? laps.length : "---", + circuitLocation: race.location, + countryCode: race.country_code, + } + + data.push(race_session); + await sleep(1000); + } + + console.log(data); +} + +acquireRaceData(); +*/ + +showView('home'); \ No newline at end of file diff --git a/styles.css b/styles.css new file mode 100644 index 0000000..4da08f6 --- /dev/null +++ b/styles.css @@ -0,0 +1,92 @@ +body { + background-image: url('images/ferrari.jpg'); + background-size: cover; + background-position: center; + background-attachment: fixed; +} + +nav { + background-color: rgba(58,58,58,0.5); /*Gray background ig*/ + backdrop-filter: blur(10px); + padding: 20px 40px; + display: flex; /*Displays these contents side by side*/ + justify-content: space-between; + align-items: center; + border-bottom: 5px solid red; + +} + +nav h1{ + color: red; + letter-spacing: 4px; + text-transform: uppercase; + font-family: 'Sekuya', system-ui; + display: flex; + align-items: center; +} + +nav h1 img{ + width: 100px; + padding: 10px; +} + +nav ul{ + list-style: none; + display: flex; gap: 40px; +} + +nav ul li{ + font-family: "Share Tech", sans-serif; + cursor: pointer; +} + +nav ul li:hover{ + color: red; + transition: color 0.2s ease; +} + +div h2 { + font-family: 'Sekuya', system-ui; + font-size: 20px; +} + +.view { + padding: 60px 40px; +} + +#home { + text-align: center; + +} + +#home #glass { + background-color: rgba(65, 57, 57, 0.5); + backdrop-filter: blur(10px); + border-radius: 10px; + padding: 10px; + margin: auto; + max-width: 720px; +} + +#home h2 { + letter-spacing: 6px; + font-size: 48px; + text-transform: uppercase; +} + +#home .about { + font-family: "Share Tech", sans-serif; + font-size: larger; +} + +#home .subtitle { + font-weight: bold; + font-style: oblique; + font-family: "Share Tech", sans-serif; + letter-spacing: 2px; +} + +body { + background-color: black; + color: white; +}