From c4fb202935d8cba691530100abc3b9678e9bc8c1 Mon Sep 17 00:00:00 2001 From: DylanBarnes Date: Wed, 20 May 2026 13:39:19 +0000 Subject: [PATCH] feat: Add API integration with Fetch & JSONPlaceholder on team page --- js/api-users.js | 82 +++++++++++++++++++++++++ team.html | 158 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 240 insertions(+) create mode 100644 js/api-users.js diff --git a/js/api-users.js b/js/api-users.js new file mode 100644 index 0000000..4d292d9 --- /dev/null +++ b/js/api-users.js @@ -0,0 +1,82 @@ +// ====================== API INTEGRATION ====================== +// Fetch & Display Users from JSONPlaceholder API + +const API_URL = 'https://jsonplaceholder.typicode.com/users'; +const apiContainer = document.getElementById('apiUsersContainer'); + +/** + * Fetches users from JSONPlaceholder API + * Parses response as JSON and renders to DOM + * Includes error handling with catch() + */ +function fetchAndDisplayUsers() { + if (!apiContainer) { + console.log('API container not found on this page'); + return; + } + + // Show loading state + apiContainer.innerHTML = '

Daten werden geladen...

'; + + fetch(API_URL) + .then(response => { + console.log('Response Status:', response.status); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + return response.json(); + }) + .then(data => { + console.log('Fetched Users Data:', data); + + // Clear container + apiContainer.innerHTML = ''; + + // Create list of users using createElement + const userList = document.createElement('ul'); + userList.className = 'api-users-list'; + + data.forEach(user => { + const listItem = document.createElement('li'); + listItem.className = 'api-user-item'; + + // Create user card with detailed information + const userCard = document.createElement('div'); + userCard.className = 'api-user-card'; + + userCard.innerHTML = ` +
+

${user.name}

+ ID: ${user.id} +
+
+

Username: ${user.username}

+

Email: ${user.email}

+

Telefon: ${user.phone}

+

Website: ${user.website}

+

Firma: ${user.company.name}

+
+ `; + + listItem.appendChild(userCard); + userList.appendChild(listItem); + }); + + apiContainer.appendChild(userList); + console.log(`Successfully loaded and displayed ${data.length} users`); + }) + .catch(error => { + console.error('Error fetching users:', error); + apiContainer.innerHTML = ` +
+

⚠️ Fehler beim Laden der Daten

+

${error.message}

+

Bitte versuchen Sie es später erneut oder kontaktieren Sie den Administrator.

+ +
+ `; + }); +} + +// Execute on page load +document.addEventListener('DOMContentLoaded', fetchAndDisplayUsers); diff --git a/team.html b/team.html index 281fbf7..d8bfe9a 100644 --- a/team.html +++ b/team.html @@ -137,6 +137,153 @@ font-size: 0.9rem; line-height: 1.6; } + + /* API Integration Styles */ + .api-section { + background: linear-gradient(135deg, rgba(102, 126, 234, 0.05) 0%, rgba(118, 75, 162, 0.05) 100%); + border-top: 2px solid rgba(102, 126, 234, 0.2); + border-bottom: 2px solid rgba(102, 126, 234, 0.2); + } + + .api-container { + margin-top: 2rem; + } + + .api-users-list { + list-style: none; + padding: 0; + display: grid; + grid-template-columns: repeat(auto-fill, minmax(350px, 1fr)); + gap: 1.5rem; + } + + .api-user-item { + animation: fadeIn 0.5s ease-in; + } + + @keyframes fadeIn { + from { + opacity: 0; + transform: translateY(10px); + } + to { + opacity: 1; + transform: translateY(0); + } + } + + .api-user-card { + background: white; + border-radius: 12px; + padding: 1.5rem; + border: 2px solid #e2e8f0; + transition: all 0.3s ease; + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.08); + } + + .api-user-card:hover { + border-color: #667eea; + box-shadow: 0 8px 25px rgba(102, 126, 234, 0.15); + transform: translateY(-5px); + } + + .api-user-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 1rem; + padding-bottom: 1rem; + border-bottom: 2px solid #f1f5f9; + } + + .api-user-name { + font-size: 1.4rem; + font-weight: 700; + color: #1e293b; + margin: 0; + flex: 1; + } + + .api-user-id { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + padding: 0.3rem 0.8rem; + border-radius: 20px; + font-size: 0.8rem; + font-weight: 600; + } + + .api-user-details { + color: #475569; + line-height: 1.8; + } + + .api-user-details p { + margin: 0.7rem 0; + font-size: 0.95rem; + } + + .api-user-details strong { + color: #667eea; + font-weight: 600; + } + + .api-user-details a { + color: #667eea; + text-decoration: none; + border-bottom: 1px solid #667eea; + transition: all 0.2s ease; + } + + .api-user-details a:hover { + color: #764ba2; + border-bottom-color: #764ba2; + } + + .loading { + text-align: center; + padding: 2rem; + font-size: 1.1rem; + color: #667eea; + animation: pulse 1.5s ease-in-out infinite; + } + + @keyframes pulse { + 0%, 100% { opacity: 1; } + 50% { opacity: 0.5; } + } + + .error-message { + background: #fee2e2; + border: 2px solid #fca5a5; + border-radius: 10px; + padding: 2rem; + text-align: center; + color: #991b1b; + } + + .error-message h3 { + margin-top: 0; + color: #dc2626; + } + + .retry-btn { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + border: none; + padding: 0.8rem 1.5rem; + border-radius: 8px; + font-size: 1rem; + font-weight: 600; + cursor: pointer; + transition: all 0.3s ease; + margin-top: 1rem; + } + + .retry-btn:hover { + transform: scale(1.05); + box-shadow: 0 8px 20px rgba(102, 126, 234, 0.3); + } @@ -209,6 +356,16 @@ + +
+

📡 API Integration Demo

+

Hier demonstrieren wir die Integration einer öffentlichen API mit Fetch & JavaScript. Die Daten werden dynamisch von JSONPlaceholder geladen und im DOM gerendert.

+ +
+ +
+
+