User-Panel gebaut
This commit is contained in:
136
Dashboard/templates/admin.html
Normal file
136
Dashboard/templates/admin.html
Normal file
@@ -0,0 +1,136 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Admin Dashboard</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
|
||||
<style>
|
||||
/* Hier kannst du noch eigene Anpassungen vornehmen */
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-gray-100 dark:bg-gray-900 text-gray-800 dark:text-gray-100">
|
||||
<!-- Navigation -->
|
||||
<nav class="bg-white dark:bg-gray-800 shadow">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="flex justify-between h-16">
|
||||
<div class="flex">
|
||||
<div class="flex-shrink-0 flex items-center">
|
||||
<img class="h-8 w-auto" src="{{ url_for('static', filename='clickcandit.png') }}" alt="Logo">
|
||||
</div>
|
||||
<div class="hidden sm:-my-px sm:ml-6 sm:flex sm:space-x-8">
|
||||
<a href="{{ url_for('dashboard') }}" class="border-indigo-500 text-gray-900 dark:text-gray-100 inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium">Dashboard</a>
|
||||
<a href="{{ url_for('admin') }}" class="border-transparent text-gray-500 dark:text-gray-400 hover:border-gray-300 hover:text-gray-700 dark:hover:text-gray-200 inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium">Admin Panel</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hidden sm:ml-6 sm:flex sm:items-center">
|
||||
<div class="ml-3 relative">
|
||||
<button type="button" class="max-w-xs bg-white dark:bg-gray-800 flex items-center text-sm rounded-full focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" id="user-menu-button">
|
||||
<span class="sr-only">Benutzermenü öffnen</span>
|
||||
<img class="h-8 w-8 rounded-full" src="https://via.placeholder.com/150" alt="User Avatar">
|
||||
</button>
|
||||
<div class="origin-top-right absolute right-0 mt-2 w-48 rounded-md shadow-lg py-1 bg-white dark:bg-gray-800 ring-1 ring-black ring-opacity-5 hidden" id="user-dropdown">
|
||||
<a href="{{ url_for('dashboard') }}" class="block px-4 py-2 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700">Dashboard</a>
|
||||
<a href="{{ url_for('logout') }}" class="block px-4 py-2 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700">Abmelden</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="-mr-2 flex items-center sm:hidden">
|
||||
<button type="button" class="bg-white dark:bg-gray-800 inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500" id="mobile-menu-button">
|
||||
<span class="sr-only">Menü öffnen</span>
|
||||
<svg class="block h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/>
|
||||
</svg>
|
||||
<svg class="hidden h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Mobile Menü -->
|
||||
<div class="sm:hidden hidden" id="mobile-menu">
|
||||
<div class="pt-2 pb-3 space-y-1">
|
||||
<a href="{{ url_for('dashboard') }}" class="bg-indigo-50 border-indigo-500 text-indigo-700 block pl-3 pr-4 py-2 border-l-4 text-base font-medium">Dashboard</a>
|
||||
<a href="{{ url_for('admin') }}" class="border-transparent text-gray-600 dark:text-gray-400 hover:bg-gray-50 hover:border-gray-300 hover:text-gray-800 dark:hover:text-gray-200 block pl-3 pr-4 py-2 border-l-4 text-base font-medium">Admin Panel</a>
|
||||
</div>
|
||||
<div class="pt-4 pb-3 border-t border-gray-200 dark:border-gray-700">
|
||||
<div class="flex items-center px-4">
|
||||
<div class="flex-shrink-0">
|
||||
<img class="h-10 w-10 rounded-full" src="https://via.placeholder.com/150" alt="User Avatar">
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<div class="text-base font-medium text-gray-800 dark:text-gray-100">{{ user }}</div>
|
||||
<div class="text-sm font-medium text-gray-500 dark:text-gray-400">{{ session['user_email'] if session.get('user_email') else '' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-3 space-y-1">
|
||||
<a href="{{ url_for('dashboard') }}" class="block px-4 py-2 text-base font-medium text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700">Dashboard</a>
|
||||
<a href="{{ url_for('logout') }}" class="block px-4 py-2 text-base font-medium text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700">Abmelden</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- Hauptinhalt -->
|
||||
<main class="max-w-7xl mx-auto p-6">
|
||||
<h2 class="text-2xl font-semibold text-gray-700 dark:text-gray-300 mb-4">Benutzerverwaltung</h2>
|
||||
<div class="bg-white dark:bg-gray-800 shadow rounded-lg overflow-hidden">
|
||||
<div class="px-4 py-5 sm:px-6">
|
||||
<h3 class="text-lg leading-6 font-medium text-gray-900 dark:text-gray-100">Übersicht aller Benutzer</h3>
|
||||
<p class="mt-1 max-w-2xl text-sm text-gray-500">Alle registrierten Benutzer werden hier aufgelistet.</p>
|
||||
</div>
|
||||
<div class="border-t border-gray-200 dark:border-gray-700">
|
||||
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
|
||||
<thead class="bg-gray-50 dark:bg-gray-700">
|
||||
<tr>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">ID</th>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Name</th>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Email</th>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Rolle</th>
|
||||
<th scope="col" class="px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider">Aktionen</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
|
||||
{% for user in users %}
|
||||
<tr>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900 dark:text-gray-100">{{ user.id }}</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-gray-100">{{ user.name }}</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{{ user.email }}</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{{ user.role }}</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
||||
<a href="{{ url_for('edit_bookmarks', user_id=user.id) }}" class="text-indigo-600 dark:text-indigo-400 hover:text-indigo-900 mr-4">Lesezeichen bearbeiten</a>
|
||||
{% if session['user_id'] != user.id %}
|
||||
<form action="{{ url_for('delete_user', user_id=user.id) }}" method="POST" class="inline">
|
||||
<button type="submit" class="text-red-600 dark:text-red-400 hover:text-red-900" onclick="return confirm('Benutzer wirklich löschen?');">Löschen</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-6 flex justify-between items-center">
|
||||
<a href="{{ url_for('register') }}" class="bg-indigo-600 text-white px-4 py-2 rounded hover:bg-indigo-700">Neuen Benutzer anlegen</a>
|
||||
<a href="{{ url_for('dashboard') }}" class="text-indigo-600 hover:underline">Zurück zum Dashboard</a>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<script>
|
||||
// Mobile Menü
|
||||
const mobileMenuButton = document.getElementById('mobile-menu-button');
|
||||
const mobileMenu = document.getElementById('mobile-menu');
|
||||
mobileMenuButton.addEventListener('click', () => {
|
||||
mobileMenu.style.display = mobileMenu.style.display === 'none' || mobileMenu.style.display === '' ? 'block' : 'none';
|
||||
});
|
||||
// User-Dropdown
|
||||
const userMenuButton = document.getElementById('user-menu-button');
|
||||
const userDropdown = document.getElementById('user-dropdown');
|
||||
userMenuButton.addEventListener('click', () => {
|
||||
userDropdown.classList.toggle('hidden');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
610
Dashboard/templates/dashboard.html
Normal file
610
Dashboard/templates/dashboard.html
Normal file
@@ -0,0 +1,610 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de" class="dark">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Dashboard</title>
|
||||
<!-- Tailwind & FontAwesome -->
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" rel="stylesheet">
|
||||
<!-- GSAP (Animations) -->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.9.1/gsap.min.js"></script>
|
||||
<script>
|
||||
tailwind.config = {
|
||||
darkMode: 'class',
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
primary: '#3b82f6',
|
||||
secondary: '#10b981',
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
/* Hintergrundbild per CSS (aus settings) */
|
||||
body {
|
||||
background-image: url('{{ url_for("static", filename=wallpaper) }}');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-attachment: fixed;
|
||||
}
|
||||
.glassmorphism {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
backdrop-filter: blur(10px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
border-radius: 10px;
|
||||
}
|
||||
.dark .glassmorphism {
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
/* Eingabe-Felder in Dark Mode */
|
||||
.dark input[type="text"],
|
||||
.dark input[type="email"],
|
||||
.dark input[type="password"],
|
||||
.dark textarea,
|
||||
.dark select {
|
||||
background-color: #374151;
|
||||
color: #fff;
|
||||
}
|
||||
.dock-icon {
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
.dock-icon:hover {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="min-h-screen bg-gray-100 dark:bg-gray-900 text-gray-800 dark:text-white transition-colors duration-300">
|
||||
<div class="container mx-auto p-4 sm:p-6 lg:p-8 pb-20 flex flex-col items-center">
|
||||
<!-- Bookmark Modal (Pop-up für Lesezeichen) -->
|
||||
<div id="bookmarkModal" class="fixed inset-0 bg-black bg-opacity-50 hidden items-center justify-center z-50">
|
||||
<div class="bg-white dark:bg-gray-800 glassmorphism p-6 rounded-lg max-w-md w-full mx-4">
|
||||
<h2 class="text-2xl font-bold mb-4 text-gray-900 dark:text-white">Lesezeichen</h2>
|
||||
<div class="mb-4">
|
||||
<input type="text" id="bookmarkInput" placeholder="URL eingeben..." class="w-full p-2 border rounded bg-white dark:bg-gray-700 text-gray-900 dark:text-white">
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<button id="addBookmark" class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded transition-colors duration-200">Hinzufügen</button>
|
||||
<button class="bg-gray-300 dark:bg-gray-600 hover:bg-gray-400 dark:hover:bg-gray-500 text-gray-800 dark:text-white px-4 py-2 rounded transition-colors duration-200 close-modal">Schließen</button>
|
||||
</div>
|
||||
<div class="mt-6">
|
||||
<h3 class="text-lg font-semibold mb-2 text-gray-900 dark:text-white">Meine Lesezeichen</h3>
|
||||
<ul id="bookmarksList" class="space-y-2 max-h-60 overflow-y-auto">
|
||||
<!-- Dynamisch per JS -->
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bookmark-Button (öffnet das Modal) -->
|
||||
<button id="bookmarkButton" class="fixed top-4 left-4 z-10 w-12 h-12 bg-blue-500 hover:bg-blue-600 text-white rounded-xl transition-colors duration-200 flex items-center justify-center">
|
||||
<i class="fas fa-bookmark text-xl"></i>
|
||||
</button>
|
||||
|
||||
<!-- Dark Mode Toggle (Sonne/Mond) -->
|
||||
<button id="darkModeToggle" class="fixed top-4 right-4 w-12 h-12 rounded-xl bg-gray-200 dark:bg-gray-800 z-10 transition-colors duration-300">
|
||||
<i class="fas fa-sun text-yellow-400 dark:hidden text-xl"></i>
|
||||
<i class="fas fa-moon text-blue-200 hidden dark:inline text-xl"></i>
|
||||
</button>
|
||||
|
||||
<!-- Logo, Begrüßung, Uhr -->
|
||||
<div class="flex flex-col items-center justify-center space-y-4 text-center mb-6">
|
||||
<a id="logo-link" href="https://{{ domain }}" target="_blank">
|
||||
<img id="logo-img" src="{{ logo_path }}" alt="Firmenlogo" class="w-20 h-auto mb-2">
|
||||
</a>
|
||||
<h1 class="text-2xl sm:text-3xl font-bold text-gray-800 dark:text-white transition-colors duration-300">
|
||||
Willkommen zurück, {{ user }}
|
||||
</h1>
|
||||
<div id="clock" class="text-xl sm:text-2xl font-semibold"></div>
|
||||
</div>
|
||||
|
||||
<!-- Flash Messages -->
|
||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||
{% if messages %}
|
||||
<div class="mb-4">
|
||||
{% for category, message in messages %}
|
||||
<div class="alert flex items-center bg-{{ category }}-500 text-white text-sm font-bold px-4 py-3" role="alert">
|
||||
<p>{{ message }}</p>
|
||||
<svg class="fill-current h-6 w-6 text-white ml-auto close-flash" role="button" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
|
||||
<title>Schließen</title>
|
||||
<path d="M14.348 14.849a1.2 1.2 0 0 1-1.697 0L10 11.819l-2.651 3.029a1.2 1.2 0 1 1-1.697-1.697L8.302 10 5.651 7.349a1.2 1.2 0 1 1 1.697-1.697L10 8.181l2.651-2.529a1.2 1.2 0 1 1 1.697 1.697L11.698 10l2.651 2.651a1.2 1.2 0 0 1 0 1.698z"/>
|
||||
</svg>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
|
||||
<!-- Widgets (Wetter, Speicher, usw.) -->
|
||||
<div class="grid grid-cols-1 sm:grid-cols-3 gap-4 mb-6 w-full max-w-3xl">
|
||||
<!-- Wetter-Box -->
|
||||
<div class="glassmorphism p-2 sm:p-3 shadow-lg rounded-md">
|
||||
<h2 class="text-xs sm:text-sm font-semibold mb-1 text-center sm:text-left">Wetter in {{ city }}</h2>
|
||||
<div class="flex items-center justify-center sm:justify-start mb-2">
|
||||
<i class="fas {{ weather_icon }} text-base sm:text-lg md:text-xl mr-1"></i>
|
||||
<p class="text-sm sm:text-base md:text-lg font-bold">{{ current_temp }}°C</p>
|
||||
</div>
|
||||
<!-- Forecast -->
|
||||
<div class="space-y-1">
|
||||
{% for day in forecast %}
|
||||
<div class="flex items-center justify-between rounded-sm p-1">
|
||||
<div class="flex items-center">
|
||||
<i class="fas {{ day.weather_icon }} text-2xs sm:text-xs mr-1"></i>
|
||||
<p class="text-2xs sm:text-xs">{{ day.date }}</p>
|
||||
</div>
|
||||
<p class="text-2xs sm:text-xs font-semibold">{{ day.day.avgtemp_c }}°C</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<!-- Beispiel: Speicher / RAM (nur Demo, falls du Systemdaten abrufst) -->
|
||||
<div class="glassmorphism p-4 shadow-lg">
|
||||
<h2 class="text-lg font-semibold mb-2">Speicher</h2>
|
||||
<p class="text-xl font-bold mb-1">— Demo —</p>
|
||||
</div>
|
||||
<div class="glassmorphism p-4 shadow-lg">
|
||||
<h2 class="text-lg font-semibold mb-2">RAM-Nutzung</h2>
|
||||
<p class="text-xl font-bold mb-1">— Demo —</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- App Launcher (Carousel) -->
|
||||
<div class="glassmorphism p-4 mb-12 relative w-full max-w-3xl">
|
||||
<div id="appCarousel" class="overflow-hidden">
|
||||
<div class="flex transition-transform duration-300 ease-in-out">
|
||||
{% for app_chunk in user_app_chunks %}
|
||||
<div class="w-full flex-shrink-0">
|
||||
<div class="grid grid-cols-3 sm:grid-cols-5 gap-4">
|
||||
{% for app in app_chunk %}
|
||||
<a href="https://{{ app.subdomain }}.{{ domain }}" class="flex flex-col items-center" title="{{ app.appkey }}">
|
||||
<div class="w-12 h-12 flex items-center justify-center {{ app.bg_color }} rounded-xl mb-1 hover:scale-110 transition-transform">
|
||||
<i class="{{ app.icon_class }} text-white text-xl"></i>
|
||||
</div>
|
||||
<p class="text-center text-xs font-medium">{{ app.name }}</p>
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<button id="prevSlide" class="absolute top-1/2 left-2 transform -translate-y-1/2 bg-white/50 dark:bg-black/50 text-gray-800 dark:text-white rounded-full p-1 hover:bg-white/70 dark:hover:bg-black/70 transition-colors duration-200">
|
||||
<i class="fas fa-chevron-left text-sm"></i>
|
||||
</button>
|
||||
<button id="nextSlide" class="absolute top-1/2 right-2 transform -translate-y-1/2 bg-white/50 dark:bg-black/50 text-gray-800 dark:text-white rounded-full p-1 hover:bg-white/70 dark:hover:bg-black/70 transition-colors duration-200">
|
||||
<i class="fas fa-chevron-right text-sm"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Dock mit Buttons: Home, Suche, Settings, Support -->
|
||||
<div class="fixed bottom-4 left-1/2 transform -translate-x-1/2 glassmorphism p-2 flex space-x-4">
|
||||
<button class="dock-icon w-12 h-12 flex items-center justify-center bg-blue-500 hover:bg-blue-600 rounded-xl" data-modal="homeModal">
|
||||
<i class="fas fa-home text-white text-xl"></i>
|
||||
</button>
|
||||
<button class="dock-icon w-12 h-12 flex items-center justify-center bg-green-500 hover:bg-green-600 rounded-xl" data-modal="searchModal">
|
||||
<i class="fas fa-search text-white text-xl"></i>
|
||||
</button>
|
||||
<button class="dock-icon w-12 h-12 flex items-center justify-center bg-yellow-500 hover:bg-yellow-600 rounded-xl" data-modal="settingsModal">
|
||||
<i class="fas fa-cog text-white text-xl"></i>
|
||||
</button>
|
||||
<button class="dock-icon w-12 h-12 flex items-center justify-center bg-purple-500 hover:bg-purple-600 rounded-xl" data-modal="supportModal">
|
||||
<i class="fas fa-question-circle text-white text-xl"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Home Modal (Konto löschen, Daten-Export, Logout) -->
|
||||
<div id="homeModal" class="fixed inset-0 bg-black bg-opacity-50 hidden items-center justify-center z-50">
|
||||
<div class="bg-white dark:bg-gray-800 glassmorphism p-6 rounded-lg max-w-md w-full mx-auto shadow-lg">
|
||||
<h2 class="text-2xl font-bold mb-4 text-gray-900 dark:text-white">
|
||||
Willkommen Zuhause, {{ user }}!
|
||||
</h2>
|
||||
<p class="mb-4">Schneller Zugriff auf wichtige Funktionen</p>
|
||||
|
||||
<!-- Datenexport -->
|
||||
<form action="{{ url_for('request_data_export') }}" method="GET" class="mb-3">
|
||||
<button type="submit" class="w-full bg-green-500 hover:bg-green-600 text-white font-bold py-2 px-4 rounded transition ease-in-out duration-150">
|
||||
Daten exportieren
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Konto löschen -->
|
||||
<form action="{{ url_for('delete_account') }}" method="POST">
|
||||
<button type="submit" class="w-full bg-red-500 hover:bg-red-600 text-white font-bold py-2 px-4 rounded transition ease-in-out duration-150" onclick="return confirm('Sind Sie sicher, dass Sie Ihr Konto löschen möchten? Diese Aktion kann nicht rückgängig gemacht werden.');">
|
||||
Konto löschen
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Logout -->
|
||||
<form action="{{ url_for('logout') }}" method="POST" class="mb-3 mt-2">
|
||||
<button type="submit" class="w-full bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded transition ease-in-out duration-150">
|
||||
Abmelden
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<button class="mt-4 bg-gray-300 dark:bg-gray-700 hover:bg-gray-400 dark:hover:bg-gray-800 text-gray-800 dark:text-white font-bold py-2 px-4 rounded transition ease-in-out duration-150 close-modal">
|
||||
Schließen
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Search Modal -->
|
||||
<div id="searchModal" class="fixed inset-0 bg-black bg-opacity-50 hidden items-center justify-center">
|
||||
<div class="bg-white dark:bg-gray-800 glassmorphism p-6 rounded-lg max-w-md w-full mx-4">
|
||||
<h2 class="text-2xl font-bold mb-4">Suche</h2>
|
||||
<input type="text" id="searchInput" placeholder="Suchen..." class="w-full p-2 border rounded mb-4">
|
||||
<select id="searchEngine" class="w-full p-2 border rounded mb-4">
|
||||
<option value="qwant">Qwant</option>
|
||||
<option value="google">Google</option>
|
||||
</select>
|
||||
<button id="startSearch" class="bg-green-500 text-white px-4 py-2 rounded">Suche starten</button>
|
||||
<button class="mt-4 bg-blue-500 text-white px-4 py-2 rounded close-modal">Schließen</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Einstellungen-Modal -->
|
||||
<div id="settingsModal" class="fixed inset-0 bg-black bg-opacity-50 hidden items-center justify-center overflow-auto">
|
||||
<div class="bg-white dark:bg-gray-800 glassmorphism p-6 rounded-lg w-full max-w-md max-h-screen overflow-y-auto mx-4">
|
||||
<h2 class="text-2xl font-bold mb-4">Einstellungen</h2>
|
||||
<p>Hier können Sie Ihre Einstellungen anpassen und das System nach Ihren Wünschen konfigurieren.</p>
|
||||
|
||||
<!-- Wallpaper-Auswahl -->
|
||||
<h3 class="text-lg font-semibold mb-2">Hintergrundbild auswählen</h3>
|
||||
<div id="wallpaperSelection" class="grid grid-cols-2 sm:grid-cols-3 gap-2 mb-4">
|
||||
{% for i in range(1, 27) %}
|
||||
<img src="{{ url_for('static', filename=i ~ '.png') }}"
|
||||
alt="Wallpaper {{ i }}"
|
||||
class="w-full h-auto wallpaper-thumb cursor-pointer border-2
|
||||
{{ 'border-blue-500' if wallpaper == i ~ '.png' else 'border-transparent' }}
|
||||
rounded"
|
||||
data-wallpaper="{{ i }}.png">
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<!-- Stadt -->
|
||||
<h3 class="text-lg font-semibold mb-2">Stadt ändern</h3>
|
||||
<input type="text" id="cityInput" class="w-full p-2 border rounded mb-4" placeholder="Geben Sie Ihre Stadt ein" value="{{ city }}">
|
||||
|
||||
<!-- Wettervorhersage Toggle (versteckt, aber im Code notwendig) -->
|
||||
<div style="display: none;">
|
||||
<h3 class="text-lg font-semibold mb-2">Wochenvorhersage anzeigen</h3>
|
||||
<label class="inline-flex items-center mt-2">
|
||||
<input type="checkbox"
|
||||
id="weatherForecastToggle"
|
||||
class="form-checkbox h-5 w-5 text-blue-600"
|
||||
{% if show_forecast %} checked {% endif %}>
|
||||
<span class="ml-2 text-gray-700 dark:text-gray-300">Wochenvorhersage anzeigen</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- Nur für Admins: Benutzerverwaltung -->
|
||||
{% if role == 'admin' %}
|
||||
<div class="mt-6 p-4 bg-gray-100 dark:bg-gray-700 rounded">
|
||||
<h3 class="text-lg font-semibold mb-2 text-gray-900 dark:text-white">Benutzerverwaltung</h3>
|
||||
<p class="text-sm mb-3">
|
||||
Als Admin kannst du hier neue Benutzer anlegen, bearbeiten oder löschen
|
||||
</p>
|
||||
<a href="{{ url_for('admin') }}"
|
||||
class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded">
|
||||
Zum Admin-Panel
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<button id="saveSettings" class="mt-4 bg-yellow-500 text-white px-4 py-2 rounded hover:bg-yellow-600 transition-colors duration-200">Speichern</button>
|
||||
<button class="mt-4 ml-2 bg-gray-500 text-white px-4 py-2 rounded hover:bg-gray-600 transition-colors duration-200 close-modal">Schließen</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Support Modal -->
|
||||
<div id="supportModal" class="fixed inset-0 bg-black bg-opacity-50 hidden items-center justify-center">
|
||||
<div class="bg-white dark:bg-gray-800 p-8 rounded-lg max-w-md w-full">
|
||||
<h2 class="text-2xl font-bold mb-4">Support kontaktieren</h2>
|
||||
<label for="problemType" class="block mb-2 text-lg font-semibold">Art des Problems</label>
|
||||
<select id="problemType" class="w-full p-2 border rounded mb-4">
|
||||
<option value="Technisches Problem">Technisches Problem</option>
|
||||
<option value="Account Problem">Account Problem</option>
|
||||
<option value="Sonstiges">Sonstiges</option>
|
||||
</select>
|
||||
<label for="emailInput" class="block mb-2 text-lg font-semibold">Ihre E-Mail</label>
|
||||
<input type="email" id="emailInput" class="w-full p-2 border rounded mb-4" placeholder="Ihre E-Mail-Adresse">
|
||||
<label for="messageInput" class="block mb-2 text-lg font-semibold">Nachricht</label>
|
||||
<textarea id="messageInput" class="w-full p-2 border rounded mb-4" rows="4" placeholder="Beschreiben Sie Ihr Problem"></textarea>
|
||||
<button id="sendSupportMessage" class="bg-purple-500 text-white px-4 py-2 rounded hover:bg-purple-600 transition-colors duration-200">
|
||||
Nachricht senden
|
||||
</button>
|
||||
<button class="mt-4 bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600 transition-colors duration-200 close-modal">
|
||||
Schließen
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- JavaScript für Modal, Dark Mode, Clock, App Carousel, Bookmarks, usw. -->
|
||||
<script>
|
||||
// Dark Mode
|
||||
const darkModeToggle = document.getElementById('darkModeToggle');
|
||||
function toggleDarkMode() {
|
||||
document.documentElement.classList.toggle('dark');
|
||||
localStorage.setItem('darkMode', document.documentElement.classList.contains('dark'));
|
||||
}
|
||||
darkModeToggle.addEventListener('click', toggleDarkMode);
|
||||
if (localStorage.getItem('darkMode') === 'true' ||
|
||||
(!('darkMode' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
||||
document.documentElement.classList.add('dark');
|
||||
}
|
||||
|
||||
// Uhr
|
||||
function updateClock() {
|
||||
const now = new Date();
|
||||
const timeString = now.toLocaleTimeString('de-DE');
|
||||
const dateString = now.toLocaleDateString('de-DE', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' });
|
||||
document.getElementById('clock').innerHTML = `${timeString}<br><span class="text-sm font-normal">${dateString}</span>`;
|
||||
}
|
||||
setInterval(updateClock, 1000);
|
||||
updateClock();
|
||||
|
||||
// Carousel
|
||||
const carousel = document.getElementById('appCarousel');
|
||||
const carouselContent = carousel.querySelector('.flex');
|
||||
const prevButton = document.getElementById('prevSlide');
|
||||
const nextButton = document.getElementById('nextSlide');
|
||||
let currentSlide = 0;
|
||||
const totalSlides = carouselContent.children.length;
|
||||
|
||||
function showSlide(index) {
|
||||
currentSlide = index;
|
||||
const offset = -currentSlide * 100;
|
||||
gsap.to(carouselContent, {duration: 0.5, x: `${offset}%`, ease: "power2.inOut"});
|
||||
}
|
||||
|
||||
prevButton.addEventListener('click', () => {
|
||||
currentSlide = (currentSlide - 1 + totalSlides) % totalSlides;
|
||||
showSlide(currentSlide);
|
||||
});
|
||||
|
||||
nextButton.addEventListener('click', () => {
|
||||
currentSlide = (currentSlide + 1) % totalSlides;
|
||||
showSlide(currentSlide);
|
||||
});
|
||||
|
||||
// Animations
|
||||
gsap.from(".glassmorphism", {duration: 1, opacity: 0, y: 50, stagger: 0.2, ease: "power3.out"});
|
||||
gsap.from(".dock-icon", {duration: 0.5, opacity: 0, y: 20, stagger: 0.1, ease: "back.out(1.7)", delay: 1});
|
||||
|
||||
// Modal-Fenster öffnen/schließen
|
||||
const modals = document.querySelectorAll('[id$="Modal"]');
|
||||
const modalTriggers = document.querySelectorAll('[data-modal]');
|
||||
const closeButtons = document.querySelectorAll('.close-modal');
|
||||
|
||||
modalTriggers.forEach(trigger => {
|
||||
trigger.addEventListener('click', () => {
|
||||
const modalId = trigger.getAttribute('data-modal');
|
||||
const modal = document.getElementById(modalId);
|
||||
modal.classList.remove('hidden');
|
||||
modal.classList.add('flex');
|
||||
});
|
||||
});
|
||||
|
||||
closeButtons.forEach(button => {
|
||||
button.addEventListener('click', () => {
|
||||
const modal = button.closest('[id$="Modal"]');
|
||||
modal.classList.remove('flex');
|
||||
modal.classList.add('hidden');
|
||||
});
|
||||
});
|
||||
|
||||
modals.forEach(modal => {
|
||||
modal.addEventListener('click', (e) => {
|
||||
if (e.target === modal) {
|
||||
modal.classList.remove('flex');
|
||||
modal.classList.add('hidden');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Wallpaper-Auswahl
|
||||
let selectedWallpaper = '{{ wallpaper }}';
|
||||
const wallpaperThumbnails = document.querySelectorAll('.wallpaper-thumb');
|
||||
wallpaperThumbnails.forEach(thumb => {
|
||||
thumb.addEventListener('click', function() {
|
||||
wallpaperThumbnails.forEach(t => {
|
||||
t.classList.remove('border-blue-500');
|
||||
t.classList.add('border-transparent');
|
||||
});
|
||||
this.classList.remove('border-transparent');
|
||||
this.classList.add('border-blue-500');
|
||||
selectedWallpaper = this.getAttribute('data-wallpaper');
|
||||
});
|
||||
});
|
||||
|
||||
// Save Settings
|
||||
document.getElementById('saveSettings').addEventListener('click', function() {
|
||||
const city = document.getElementById('cityInput').value.trim();
|
||||
const showForecast = document.getElementById('weatherForecastToggle').checked;
|
||||
|
||||
// Aktuelle Settings laden, um Bookmarks nicht zu überschreiben
|
||||
fetch('/get_settings')
|
||||
.then(res => res.json())
|
||||
.then(settings => {
|
||||
const bookmarks = settings.bookmarks || [];
|
||||
fetch('/save_settings', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
'wallpaper': selectedWallpaper,
|
||||
'city': city,
|
||||
'show_forecast': showForecast,
|
||||
'bookmarks': bookmarks
|
||||
})
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
location.reload();
|
||||
} else {
|
||||
alert('Fehler beim Speichern der Einstellungen: ' + (data.message || 'unbekannt'));
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Websuche
|
||||
document.getElementById('startSearch').addEventListener('click', () => {
|
||||
const query = document.getElementById('searchInput').value.trim();
|
||||
const engine = document.getElementById('searchEngine').value;
|
||||
if (query) {
|
||||
let searchURL = '';
|
||||
if (engine === 'qwant') {
|
||||
searchURL = `https://www.qwant.com/?q=${encodeURIComponent(query)}`;
|
||||
} else {
|
||||
searchURL = `https://www.google.com/search?q=${encodeURIComponent(query)}`;
|
||||
}
|
||||
window.open(searchURL, '_blank');
|
||||
}
|
||||
});
|
||||
|
||||
// Bookmarks
|
||||
const bookmarkModal = document.getElementById('bookmarkModal');
|
||||
const bookmarkButton = document.getElementById('bookmarkButton');
|
||||
const bookmarkInput = document.getElementById('bookmarkInput');
|
||||
const addBookmark = document.getElementById('addBookmark');
|
||||
const bookmarksList = document.getElementById('bookmarksList');
|
||||
|
||||
function openBookmarkModal() {
|
||||
bookmarkModal.classList.remove('hidden');
|
||||
bookmarkModal.classList.add('flex');
|
||||
loadBookmarks();
|
||||
}
|
||||
function closeBookmarkModal() {
|
||||
bookmarkModal.classList.remove('flex');
|
||||
bookmarkModal.classList.add('hidden');
|
||||
}
|
||||
bookmarkButton.addEventListener('click', openBookmarkModal);
|
||||
bookmarkModal.addEventListener('click', (e) => {
|
||||
if (e.target === bookmarkModal) {
|
||||
closeBookmarkModal();
|
||||
}
|
||||
});
|
||||
closeButtons.forEach(button => {
|
||||
button.addEventListener('click', closeBookmarkModal);
|
||||
});
|
||||
|
||||
addBookmark.addEventListener('click', () => {
|
||||
let url = bookmarkInput.value.trim();
|
||||
if (url) {
|
||||
const urlPattern = /^https?:\/\//i;
|
||||
if (!urlPattern.test(url)) {
|
||||
alert('Bitte gib eine vollständige URL mit http:// oder https:// ein.');
|
||||
return;
|
||||
}
|
||||
addBookmarkToList(url);
|
||||
bookmarkInput.value = '';
|
||||
saveBookmarks();
|
||||
}
|
||||
});
|
||||
|
||||
function addBookmarkToList(url) {
|
||||
const li = document.createElement('li');
|
||||
li.innerHTML = `
|
||||
<div class="flex items-center justify-between p-2 bg-gray-100 dark:bg-gray-700 rounded">
|
||||
<a href="${url}" target="_blank" class="text-blue-600 dark:text-blue-400 hover:underline truncate">${url}</a>
|
||||
<button class="delete-bookmark text-red-500 hover:text-red-700">
|
||||
<i class="fas fa-trash-alt"></i>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
bookmarksList.appendChild(li);
|
||||
|
||||
const deleteButton = li.querySelector('.delete-bookmark');
|
||||
deleteButton.addEventListener('click', () => {
|
||||
li.remove();
|
||||
saveBookmarks();
|
||||
});
|
||||
}
|
||||
|
||||
function loadBookmarks() {
|
||||
fetch('/get_settings')
|
||||
.then(res => res.json())
|
||||
.then(settings => {
|
||||
const b = settings.bookmarks || [];
|
||||
bookmarksList.innerHTML = '';
|
||||
b.forEach(bookmark => addBookmarkToList(bookmark));
|
||||
});
|
||||
}
|
||||
|
||||
function saveBookmarks() {
|
||||
const b = Array.from(bookmarksList.children).map(li => li.querySelector('a').href);
|
||||
fetch('/get_settings')
|
||||
.then(res => res.json())
|
||||
.then(settings => {
|
||||
const city = settings.city;
|
||||
const wallpaper = settings.wallpaper_url.split('/').pop();
|
||||
const show_forecast = settings.show_forecast;
|
||||
fetch('/save_settings', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
bookmarks: b,
|
||||
city: city,
|
||||
wallpaper: wallpaper,
|
||||
show_forecast: show_forecast
|
||||
})
|
||||
}).then(response => {
|
||||
if (!response.ok) {
|
||||
alert('Fehler beim Speichern der Lesezeichen.');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
// Beim Laden sofort Lesezeichen laden
|
||||
window.addEventListener('DOMContentLoaded', loadBookmarks);
|
||||
|
||||
// Support Modal
|
||||
const supportModal = document.getElementById('supportModal');
|
||||
const supportModalToggle = document.querySelector('[data-modal="supportModal"]');
|
||||
supportModalToggle.addEventListener('click', () => {
|
||||
supportModal.classList.remove('hidden');
|
||||
supportModal.classList.add('flex');
|
||||
});
|
||||
|
||||
const sendSupportMessage = document.getElementById('sendSupportMessage');
|
||||
sendSupportMessage.addEventListener('click', () => {
|
||||
const email = document.getElementById('emailInput').value.trim();
|
||||
const problemType = document.getElementById('problemType').value;
|
||||
const message = document.getElementById('messageInput').value.trim();
|
||||
if (email && message) {
|
||||
fetch('/send_support_message', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ email, problemType, message })
|
||||
}).then(response => {
|
||||
if (response.ok) {
|
||||
alert('Ihre Nachricht wurde erfolgreich gesendet.');
|
||||
supportModal.classList.remove('flex');
|
||||
supportModal.classList.add('hidden');
|
||||
} else {
|
||||
alert('Fehler beim Senden der Nachricht.');
|
||||
}
|
||||
});
|
||||
} else {
|
||||
alert('Bitte füllen Sie alle Felder aus.');
|
||||
}
|
||||
});
|
||||
|
||||
// Flash-Nachrichten per Klick schließen
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const flashCloseBtns = document.querySelectorAll('.close-flash');
|
||||
flashCloseBtns.forEach(btn => {
|
||||
btn.addEventListener('click', function () {
|
||||
const alertBox = this.closest('.alert');
|
||||
alertBox.style.transition = 'opacity 0.5s ease';
|
||||
alertBox.style.opacity = '0';
|
||||
setTimeout(() => alertBox.remove(), 500);
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
94
Dashboard/templates/edit_bookmarks.html
Normal file
94
Dashboard/templates/edit_bookmarks.html
Normal file
@@ -0,0 +1,94 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Lesezeichen bearbeiten</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
|
||||
</head>
|
||||
<body class="bg-gray-100 dark:bg-gray-900 text-gray-800 dark:text-gray-100">
|
||||
<div class="max-w-4xl mx-auto p-6">
|
||||
<!-- Header -->
|
||||
<header class="mb-8">
|
||||
<h1 class="text-3xl font-bold">Lesezeichen bearbeiten</h1>
|
||||
<p class="mt-2 text-gray-600 dark:text-gray-400">
|
||||
Bearbeiten Sie die Lesezeichen dieses Benutzers. Fügen Sie neue Einträge hinzu oder entfernen Sie bestehende.
|
||||
</p>
|
||||
</header>
|
||||
<!-- Formular -->
|
||||
<form id="editBookmarksForm" method="POST" action="{{ url_for('edit_bookmarks', user_id=user_id) }}">
|
||||
<!-- Dynamische Bookmark-Liste -->
|
||||
<div id="bookmarksContainer" class="mb-6 space-y-4">
|
||||
{% for bookmark in bookmarks %}
|
||||
<div class="flex items-center space-x-3">
|
||||
<input type="url" name="bookmarks_list" value="{{ bookmark }}" class="flex-1 p-2 border border-gray-300 rounded focus:outline-none focus:ring-2 focus:ring-indigo-500 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100">
|
||||
<button type="button" class="deleteBookmark bg-red-500 text-white px-3 py-2 rounded hover:bg-red-600 focus:outline-none">
|
||||
Löschen
|
||||
</button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<!-- Neuen Bookmark hinzufügen -->
|
||||
<div class="mb-6">
|
||||
<div class="flex items-center space-x-3">
|
||||
<input type="url" id="newBookmarkInput" placeholder="https://example.com" class="flex-1 p-2 border border-gray-300 rounded focus:outline-none focus:ring-2 focus:ring-indigo-500 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100">
|
||||
<button type="button" id="addBookmarkBtn" class="bg-indigo-600 text-white px-3 py-2 rounded hover:bg-indigo-700 focus:outline-none">
|
||||
Hinzufügen
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Aktionen -->
|
||||
<div class="flex space-x-4">
|
||||
<button type="submit" class="bg-green-600 text-white px-4 py-2 rounded hover:bg-green-700 transition-colors focus:outline-none">
|
||||
Speichern
|
||||
</button>
|
||||
<a href="{{ url_for('admin') }}" class="bg-gray-500 text-white px-4 py-2 rounded hover:bg-gray-600 transition-colors">
|
||||
Zurück
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const addBookmarkBtn = document.getElementById('addBookmarkBtn');
|
||||
const newBookmarkInput = document.getElementById('newBookmarkInput');
|
||||
const bookmarksContainer = document.getElementById('bookmarksContainer');
|
||||
|
||||
addBookmarkBtn.addEventListener('click', () => {
|
||||
const url = newBookmarkInput.value.trim();
|
||||
if(url === '') return;
|
||||
// Optional: URL-Validierung
|
||||
if(!/^https?:\/\//i.test(url)){
|
||||
alert('Bitte geben Sie eine vollständige URL mit http:// oder https:// ein.');
|
||||
return;
|
||||
}
|
||||
// Neues Element erstellen
|
||||
const div = document.createElement('div');
|
||||
div.className = 'flex items-center space-x-3';
|
||||
const input = document.createElement('input');
|
||||
input.type = 'url';
|
||||
input.name = 'bookmarks_list';
|
||||
input.value = url;
|
||||
input.className = 'flex-1 p-2 border border-gray-300 rounded focus:outline-none focus:ring-2 focus:ring-indigo-500 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100';
|
||||
const btn = document.createElement('button');
|
||||
btn.type = 'button';
|
||||
btn.className = 'deleteBookmark bg-red-500 text-white px-3 py-2 rounded hover:bg-red-600 focus:outline-none';
|
||||
btn.textContent = 'Löschen';
|
||||
btn.addEventListener('click', () => {
|
||||
div.remove();
|
||||
});
|
||||
div.appendChild(input);
|
||||
div.appendChild(btn);
|
||||
bookmarksContainer.appendChild(div);
|
||||
newBookmarkInput.value = '';
|
||||
});
|
||||
|
||||
// Vorhandene Löschen-Buttons initialisieren
|
||||
document.querySelectorAll('.deleteBookmark').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
btn.parentElement.remove();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
22
Dashboard/templates/login.html
Normal file
22
Dashboard/templates/login.html
Normal file
@@ -0,0 +1,22 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Login - ClickCandit</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
</head>
|
||||
<body class="flex items-center justify-center h-screen bg-gray-900">
|
||||
<div class="w-full max-w-sm p-8 space-y-4 bg-gray-800 rounded shadow-md">
|
||||
<h2 class="text-2xl font-bold text-center text-white">Login</h2>
|
||||
<form method="POST">
|
||||
<input type="email" name="email" placeholder="E-Mail" required
|
||||
class="w-full p-2 text-white bg-gray-700 rounded focus:outline-none">
|
||||
<input type="password" name="password" placeholder="Passwort" required
|
||||
class="w-full p-2 mt-2 text-white bg-gray-700 rounded focus:outline-none">
|
||||
<button type="submit" class="w-full p-2 mt-4 bg-blue-500 rounded hover:bg-blue-600">Login</button>
|
||||
</form>
|
||||
<p class="text-gray-400">Noch kein Konto? <a href="{{ url_for('register') }}" class="text-blue-400">Registrieren</a></p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
24
Dashboard/templates/register.html
Normal file
24
Dashboard/templates/register.html
Normal file
@@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Registrierung - ClickCandit</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
</head>
|
||||
<body class="flex items-center justify-center h-screen bg-gray-900">
|
||||
<div class="w-full max-w-sm p-8 space-y-4 bg-gray-800 rounded shadow-md">
|
||||
<h2 class="text-2xl font-bold text-center text-white">Registrieren</h2>
|
||||
<form method="POST">
|
||||
<input type="text" name="name" placeholder="Name" required
|
||||
class="w-full p-2 text-white bg-gray-700 rounded focus:outline-none">
|
||||
<input type="email" name="email" placeholder="E-Mail" required
|
||||
class="w-full p-2 mt-2 text-white bg-gray-700 rounded focus:outline-none">
|
||||
<input type="password" name="password" placeholder="Passwort" required
|
||||
class="w-full p-2 mt-2 text-white bg-gray-700 rounded focus:outline-none">
|
||||
<button type="submit" class="w-full p-2 mt-4 bg-green-500 rounded hover:bg-green-600">Registrieren</button>
|
||||
</form>
|
||||
<p class="text-gray-400">Bereits ein Konto? <a href="{{ url_for('login') }}" class="text-blue-400">Login</a></p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user