Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions NBA Complex/css/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
html, body {
height: 100%;
margin: 0;
padding: 0;
}

body {
display: flex;
flex-direction: column;
align-items: center;
font-family: 'Poppins', sans-serif;
text-align: center;
color: #222;

/* Background placeholder */
background-image: url('/Users/johnzapata/Downloads/Week 8/NBA Complex/images/ASG-court.webp');
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}

.control-box {
background-color: #e0e0e0;
padding: 25px 40px;
border-radius: 12px;
margin-top: 30px;
box-shadow: 0 6px 12px rgba(0,0,0,0.15);
}

.control-box h1 {
margin: 0 0 15px 0;
font-weight: 600;
font-size: 2rem;
}

button {
padding: 12px 25px;
background-color: #007bff;
color: white;
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 1rem;
}

button:hover {
background-color: #0056b3;
}

#playerInfo {
margin-top: 20px;
font-size: 1.1rem;
font-weight: 500;
}

.map-wrapper {
width: 90%;
max-width: 1000px;
height: 600px; /* Fixes Leaflet rendering */
margin: 30px auto;
}

#map {
height: 100%;
width: 100%;
border: 2px solid #ccc;
border-radius: 10px;
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
box-sizing: border-box;
}

/* Leaflet internal fixes */
.leaflet-container {
height: 100%;
width: 100%;
}
Binary file added NBA Complex/images/ASG-court.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
41 changes: 41 additions & 0 deletions NBA Complex/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>NBA Player Randomizer + Map</title>

<!-- Google Font -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600&display=swap" rel="stylesheet">

<!-- Leaflet CSS -->
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />

<!-- Custom CSS -->
<link rel="stylesheet" href="css/style.css" />

<!-- Leaflet JS -->
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
</head>

<body>
<!-- Grey square for header + button -->
<div class="control-box">
<h1>NBA Player Randomizer + Map</h1>
<button id="getPlayer">Get Random Player</button>
</div>

<!-- Player Info -->
<p id="playerInfo"></p>

<!-- Map wrapper -->
<div class="map-wrapper">
<div id="map"></div>
</div>

<!-- Custom JS -->
<script src="js/main.js"></script>
</body>
</html>
98 changes: 98 additions & 0 deletions NBA Complex/js/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
//used chat gpt for assistance with debugging map from Leaflet
const API_KEY = "2964b8ff-5dff-48a5-9dd0-50f4564dd5d4";
const BASE_URL = "https://api.balldontlie.io/v1";

// Grab references to DOM elements
const playerInfo = document.getElementById("playerInfo"); // paragraph to show player info
const getPlayer = document.getElementById("getPlayer"); // button to get a random player

let map; // variable to store Leaflet map instance
let marker; // variable to store the current marker on the map

// Wait until the entire page (HTML + CSS + images) is fully loaded
window.addEventListener("load", () => {
// Initialize the Leaflet map inside the div with id="map"
// Set default center to USA ([latitude, longitude]) and zoom level 4
map = L.map("map").setView([39.5, -98.35], 4);

// Add OpenStreetMap tiles to the map (the visual map layer)
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
maxZoom: 18,
attribution: "© OpenStreetMap contributors",
}).addTo(map);

// Fix rendering issues: tells Leaflet to recalc container size
map.invalidateSize();
});

// Function: given a location (college/high school/country), show it on the map
function showLocationOnMap(location) {
// Use OpenStreetMap's Nominatim API to convert location name to coordinates
const geoUrl = `https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(location)}`;

fetch(geoUrl)
.then(res => res.json()) // Convert the response to JSON
.then(results => {
if (results.length === 0) return; // If no location found, stop

// Grab latitude, longitude, and full display name of the first result
const { lat, lon, display_name } = results[0];

// Remove the old marker if it exists
if (marker) map.removeLayer(marker);

// Add a new marker at the found location
marker = L.marker([lat, lon]).addTo(map);

// Bind a popup to the marker with location name
marker.bindPopup(`<b>${location}</b><br>${display_name}`).openPopup();

// Center the map on this location and zoom in to level 6
map.setView([lat, lon], 6);
})
.catch(err => console.error("Error finding location:", err));
}

// Event listener: when the button is clicked, fun begins...
getPlayer.addEventListener("click", () => {
// Show temporary loading message
playerInfo.textContent = "Loading...";

// Randomly choose a page from the API
const randomPage = Math.floor(Math.random() * 10) + 1;
const url = `${BASE_URL}/players?per_page=100&page=${randomPage}`;

// Fetch data from the API
fetch(url, { headers: { Authorization: API_KEY } })
.then(res => res.json()) // Convert response to JSON
.then(data => {
const players = data.data; // Get the array of players
if (!players.length) { // If no players found, show message
playerInfo.textContent = "No players found.";
return;
}

// Player randomizier
const randomIndex = Math.floor(Math.random() * players.length);
const player = players[randomIndex];

// Display college, high school, or country
const locationInfo = player.college || player.high_school || player.country || "Unknown";

// Player info
playerInfo.textContent = `${player.first_name} ${player.last_name} — ${player.team.full_name} (${player.position || "N/A"}) | ${locationInfo}`;

// find the location if known, and show it on the map
if (locationInfo !== "Unknown") showLocationOnMap(locationInfo);
else {
// unknown location, then remove the marker and reset map to US
if (marker) map.removeLayer(marker);
map.setView([39.5, -98.35], 4);
}
})
.catch(err => {
// If fetch failed, show the error message
console.error("Error fetching player:", err);
playerInfo.textContent = "Error fetching random player.";
});
});
23 changes: 3 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,5 @@
# 📊 Project: Complex API 2
# NBA Player Randomizer

### Goal: Use data returned from one api to make a request to another api and display the data returned
![FF2D74EF-5FEC-4708-AC03-D2EB924E9140](https://github.com/user-attachments/assets/576e0310-6b2e-42f9-ae3d-d02e1ca6b729)

### How to submit your code for review:

- Fork and clone this repo
- Create a new branch called answer
- Checkout answer branch
- Push to your fork
- Issue a pull request
- Your pull request description should contain the following:
- (1 to 5 no 3) I completed the challenge
- (1 to 5 no 3) I feel good about my code
- Anything specific on which you want feedback!

Example:
```
I completed the challenge: 5
I feel good about my code: 4
I'm not sure if my constructors are setup cleanly...
```
The NBA Player Randomizer is a simple web app that gives you a random NBA player along with their team, position, and where they came from, before entering the league. Whether that be college/high school/country. When the user clicks the “Get Player” button, the app fetches data from the BallDon’tLie API and then uses the leaflet API to find and display that location on an interactive map. The project is built using HTML, CSS, and JavaScript, with a clean and centered layout that lays in a background of an NBA court!