Created
November 20, 2024 05:02
-
-
Save diegoolipa/edefdb43e87f693f6698c020acb64f87 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="es"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Dashboard de APIs</title> | |
<style> | |
* { | |
margin: 0; | |
padding: 0; | |
box-sizing: border-box; | |
} | |
body { | |
font-family: Arial, sans-serif; | |
padding: 20px; | |
background-color: #f0f2f5; | |
} | |
.container { | |
max-width: 1200px; | |
margin: 0 auto; | |
} | |
.header { | |
display: flex; | |
justify-content: space-between; | |
align-items: center; | |
margin-bottom: 20px; | |
} | |
.grid { | |
display: grid; | |
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); | |
gap: 20px; | |
} | |
.card { | |
background: white; | |
border-radius: 8px; | |
padding: 20px; | |
box-shadow: 0 2px 4px rgba(0,0,0,0.1); | |
} | |
.card-title { | |
font-size: 1.2em; | |
margin-bottom: 15px; | |
color: #333; | |
} | |
.card-content { | |
min-height: 150px; | |
} | |
button { | |
background-color: #007bff; | |
color: white; | |
border: none; | |
padding: 8px 16px; | |
border-radius: 4px; | |
cursor: pointer; | |
transition: background-color 0.3s; | |
} | |
button:hover { | |
background-color: #0056b3; | |
} | |
button:disabled { | |
background-color: #cccccc; | |
cursor: not-allowed; | |
} | |
.loading { | |
opacity: 0.5; | |
} | |
img { | |
max-width: 100%; | |
height: auto; | |
border-radius: 4px; | |
} | |
.pokemon-info { | |
text-align: center; | |
} | |
.pokemon-types { | |
display: flex; | |
gap: 8px; | |
justify-content: center; | |
margin-top: 8px; | |
} | |
.type-badge { | |
background: #e0e0e0; | |
padding: 4px 8px; | |
border-radius: 12px; | |
font-size: 0.9em; | |
} | |
.error { | |
color: red; | |
margin-top: 10px; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="container"> | |
<div class="header"> | |
<h1>Dashboard de APIs</h1> | |
<button id="refreshAll">Actualizar Todo</button> | |
</div> | |
<div class="grid"> | |
<!-- Chuck Norris Card --> | |
<div class="card"> | |
<h2 class="card-title">Chuck Norris Joke</h2> | |
<div class="card-content" id="chuckContent"></div> | |
<button onclick="fetchChuckNorrisJoke()">Nueva Broma</button> | |
</div> | |
<!-- Cocktail Card --> | |
<div class="card"> | |
<h2 class="card-title">Cocktail Aleatorio</h2> | |
<div class="card-content" id="cocktailContent"></div> | |
<button onclick="fetchRandomCocktail()">Otro Cocktail</button> | |
</div> | |
<!-- Pokemon Card --> | |
<div class="card"> | |
<h2 class="card-title">Pokémon Aleatorio</h2> | |
<div class="card-content" id="pokemonContent"></div> | |
<button onclick="fetchRandomPokemon()">Otro Pokémon</button> | |
</div> | |
</div> | |
</div> | |
<script> | |
// Elementos del DOM | |
const chuckContent = document.getElementById('chuckContent'); | |
const cocktailContent = document.getElementById('cocktailContent'); | |
const pokemonContent = document.getElementById('pokemonContent'); | |
const refreshAllButton = document.getElementById('refreshAll'); | |
// Función para manejar errores | |
function handleError(element, error) { | |
console.error(error); | |
element.innerHTML = `<p class="error">Error: No se pudieron cargar los datos. Por favor, intenta de nuevo.</p>`; | |
} | |
// Chuck Norris API | |
async function fetchChuckNorrisJoke() { | |
try { | |
chuckContent.classList.add('loading'); | |
const response = await fetch('https://api.chucknorris.io/jokes/random'); | |
const data = await response.json(); | |
chuckContent.innerHTML = `<p>${data.value}</p>`; | |
} catch (error) { | |
handleError(chuckContent, error); | |
} finally { | |
chuckContent.classList.remove('loading'); | |
} | |
} | |
// Cocktail API | |
async function fetchRandomCocktail() { | |
try { | |
cocktailContent.classList.add('loading'); | |
const response = await fetch('https://www.thecocktaildb.com/api/json/v1/1/random.php'); | |
const data = await response.json(); | |
const drink = data.drinks[0]; | |
cocktailContent.innerHTML = ` | |
<img src="${drink.strDrinkThumb}" alt="${drink.strDrink}" style="max-height: 200px; object-fit: cover;"> | |
<h3 style="margin: 10px 0">${drink.strDrink}</h3> | |
<p>Categoría: ${drink.strCategory}</p> | |
`; | |
} catch (error) { | |
handleError(cocktailContent, error); | |
} finally { | |
cocktailContent.classList.remove('loading'); | |
} | |
} | |
// Pokemon API | |
async function fetchRandomPokemon() { | |
try { | |
pokemonContent.classList.add('loading'); | |
const randomId = Math.floor(Math.random() * 151) + 1; | |
const response = await fetch(`https://pokeapi.co/api/v2/pokemon/${randomId}`); | |
const pokemon = await response.json(); | |
const types = pokemon.types | |
.map(type => `<span class="type-badge">${type.type.name}</span>`) | |
.join(''); | |
pokemonContent.innerHTML = ` | |
<div class="pokemon-info"> | |
<img src="${pokemon.sprites.front_default}" alt="${pokemon.name}" style="height: 120px;"> | |
<h3 style="margin: 10px 0; text-transform: capitalize;">${pokemon.name}</h3> | |
<div class="pokemon-types">${types}</div> | |
</div> | |
`; | |
} catch (error) { | |
handleError(pokemonContent, error); | |
} finally { | |
pokemonContent.classList.remove('loading'); | |
} | |
} | |
// Función para actualizar todo | |
async function refreshAll() { | |
refreshAllButton.disabled = true; | |
refreshAllButton.textContent = 'Cargando...'; | |
await Promise.all([ | |
fetchChuckNorrisJoke(), | |
fetchRandomCocktail(), | |
fetchRandomPokemon() | |
]); | |
refreshAllButton.disabled = false; | |
refreshAllButton.textContent = 'Actualizar Todo'; | |
} | |
// Event Listeners | |
refreshAllButton.addEventListener('click', refreshAll); | |
// Cargar datos iniciales | |
refreshAll(); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment