381 lines
16 KiB
JavaScript
381 lines
16 KiB
JavaScript
import { showAlert, showConfirm, sanitizeInput } from './shared_functions.js';
|
|
import * as api from './api_service.js';
|
|
import { initializeChat, createNewChat, handleSendMessage } from './chat_manager.js'; // Only import needed functions directly used by main
|
|
import * as ui from './chat_ui.js'; // Need UI functions
|
|
|
|
// --- DOM Elements ---
|
|
// Moved some element selections inside setup functions to ensure they exist
|
|
const bodyElement = document.body;
|
|
console.log("main: ")
|
|
console.log(bodyElement)
|
|
let themeToggleButton = null; // Initialize as null
|
|
let logoutBtn = null; // Initialize as null
|
|
|
|
// --- Initialization ---
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
console.log("DOM Content Loaded. Body ID:", bodyElement.id); // Log body ID
|
|
|
|
// Common elements present on all/most pages
|
|
themeToggleButton = document.getElementById('themeToggleBtn');
|
|
logoutBtn = document.getElementById('logoutBtn');
|
|
|
|
loadThemePreference(); // Load theme early
|
|
|
|
// Add common listeners if elements exist
|
|
if (themeToggleButton) {
|
|
console.log("Attaching theme listener");
|
|
themeToggleButton.addEventListener('click', toggleTheme);
|
|
} else {
|
|
console.warn("Theme toggle button not found");
|
|
}
|
|
if (logoutBtn) {
|
|
console.log("Attaching logout listener");
|
|
logoutBtn.addEventListener('click', logout);
|
|
} else {
|
|
console.warn("Logout button not found");
|
|
}
|
|
|
|
// Page specific initialization with error handling for the setup promises
|
|
if (bodyElement.id === 'chat-page') {
|
|
console.log("Running Chat Page Setup");
|
|
setupChatPage()
|
|
.catch(error => {
|
|
console.error("Error during Chat Page Setup:", error);
|
|
showAlert("Ein kritischer Fehler ist beim Laden der Chat-Seite aufgetreten.", "error");
|
|
});
|
|
} else if (bodyElement.id === 'admin-page') {
|
|
console.log("Running Admin Page Setup");
|
|
setupAdminPage()
|
|
.catch(error => {
|
|
// This catch is now primarily for unexpected errors *within* setupAdminPage's try block
|
|
// as checkAdminStatus errors should be handled more specifically inside.
|
|
console.error("Unhandled error during Admin Page Setup:", error);
|
|
if (!error.message?.includes("handled")) { // Avoid double alerts if handled internally
|
|
showAlert("Ein unerwarteter Fehler ist beim Laden der Admin-Seite aufgetreten.", "error");
|
|
}
|
|
});
|
|
} else if (bodyElement.id === 'login-page') {
|
|
console.log("Login/Register page setup handled by auth.js");
|
|
} else {
|
|
console.warn("No specific page setup for body ID:", bodyElement.id);
|
|
}
|
|
});
|
|
|
|
// --- Page Setup Functions ---
|
|
async function setupChatPage() {
|
|
console.log("setupChatPage started");
|
|
if (!localStorage.getItem('token')) {
|
|
redirectToLogin('Kein Token gefunden. Bitte einloggen.');
|
|
return;
|
|
}
|
|
|
|
// Select elements specific to chat page *inside* setup
|
|
const adminPermissionsBtn = document.getElementById('adminPermissionsBtn');
|
|
const newChatButton = document.getElementById('newChatButton');
|
|
const chatInput = document.getElementById('chatInput');
|
|
const sendButton = document.getElementById('sendButton');
|
|
|
|
// Load user data first
|
|
await loadUserDataForChat(); // This function now handles UI updates internally
|
|
|
|
// Setup chat specific event listeners *after* confirming elements exist
|
|
if (newChatButton) {
|
|
console.log("Attaching new chat listener");
|
|
newChatButton.addEventListener('click', createNewChat);
|
|
} else {
|
|
console.error("New Chat button not found!");
|
|
}
|
|
|
|
if (sendButton) {
|
|
console.log("Attaching send listener");
|
|
sendButton.addEventListener('click', processUserInput);
|
|
} else {
|
|
console.error("Send button not found!");
|
|
}
|
|
|
|
if (chatInput) {
|
|
console.log("Attaching input listeners");
|
|
chatInput.addEventListener('keydown', handleChatInputKeydown);
|
|
chatInput.addEventListener('input', ui.autoResizeTextarea);
|
|
// Initial resize
|
|
ui.autoResizeTextarea();
|
|
} else {
|
|
console.error("Chat input not found!");
|
|
}
|
|
|
|
if (adminPermissionsBtn) {
|
|
console.log("Attaching admin button listener");
|
|
adminPermissionsBtn.addEventListener('click', () => { window.location.href = 'admin.html'; });
|
|
} else {
|
|
// This might be expected if the user is not admin, handled by loadUserDataForChat
|
|
// console.warn("Admin permissions button not found (may be expected)");
|
|
}
|
|
|
|
// Initialize chat manager AFTER setting up listeners that might use its functions
|
|
try {
|
|
console.log("Initializing Chat Manager...");
|
|
await initializeChat();
|
|
console.log("Chat Manager Initialized.");
|
|
} catch(error) {
|
|
console.error("Error initializing chat manager:", error);
|
|
showAlert("Fehler beim Initialisieren des Chats.", "error");
|
|
}
|
|
}
|
|
|
|
async function setupAdminPage() {
|
|
console.log("setupAdminPage started");
|
|
if (!localStorage.getItem('token')) {
|
|
redirectToLogin('Kein Token gefunden. Bitte einloggen.');
|
|
return;
|
|
}
|
|
|
|
// Select elements specific to admin page
|
|
const loadUserListBtn = document.getElementById('loadUserListBtn');
|
|
const welcomeButton = document.getElementById('welcomeButton');
|
|
const userListDiv = document.getElementById('user-list'); // Also select user list container
|
|
|
|
if (!userListDiv) {
|
|
console.error("User list container ('user-list') not found on admin page!");
|
|
// Optionally show an error message in the main area if the container is missing
|
|
}
|
|
|
|
|
|
try {
|
|
// Check admin status first. If this fails, it will throw an error.
|
|
// checkAdminStatus handles redirection/alerts for 401/403.
|
|
await checkAdminStatus();
|
|
console.log("Admin status confirmed. Proceeding with admin setup.");
|
|
|
|
// ---- If admin check passes, THEN setup listeners and load list ----
|
|
|
|
// Setup 'Reload List' button listener
|
|
if (loadUserListBtn) {
|
|
console.log("Attaching load user list listener");
|
|
loadUserListBtn.addEventListener('click', () => {
|
|
console.log("Reload list button clicked.");
|
|
loadUserList(); // Call loadUserList on click
|
|
});
|
|
} else {
|
|
console.error("Load user list button ('loadUserListBtn') not found!");
|
|
}
|
|
|
|
// Setup 'Back to Chat' button listener
|
|
if (welcomeButton) {
|
|
console.log("Attaching welcome button listener");
|
|
welcomeButton.addEventListener('click', () => {
|
|
console.log("Welcome button clicked, redirecting...");
|
|
window.location.href = 'welcome.html';
|
|
});
|
|
} else {
|
|
console.error("Welcome (back to chat) button ('welcomeButton') not found!");
|
|
}
|
|
|
|
// Load list initially ONLY if admin check succeeded
|
|
console.log("Initiating initial user list load.");
|
|
await loadUserList(); // Load the list data
|
|
console.log("Initial user list load attempt finished.");
|
|
|
|
} catch (error) {
|
|
// This catch block now primarily handles errors from checkAdminStatus
|
|
// or potentially the initial loadUserList call if it throws unexpectedly.
|
|
console.error("SetupAdminPage failed during admin check or initial load:", error);
|
|
// Most user-facing errors (like redirection or alerts for auth/network issues)
|
|
// should have been handled within checkAdminStatus or loadUserList's call to handleApiError.
|
|
// We might not need to show another alert here unless it's a truly unexpected setup problem.
|
|
// Mark the error as handled to avoid potential double alerts from the outer catch block.
|
|
error.message += " (handled in setupAdminPage)";
|
|
}
|
|
}
|
|
|
|
// --- Event Handlers ---
|
|
function handleChatInputKeydown(event) {
|
|
// console.log("Keydown:", event.key); // Debugging keystrokes
|
|
if (event.key === 'Enter' && !event.shiftKey) {
|
|
console.log("Enter pressed"); // Debugging Enter key
|
|
event.preventDefault();
|
|
processUserInput();
|
|
}
|
|
}
|
|
|
|
function processUserInput() {
|
|
const chatInput = document.getElementById('chatInput'); // Re-select or ensure it's available
|
|
if (!chatInput) {
|
|
console.error("Cannot process user input: chatInput not found.");
|
|
return;
|
|
}
|
|
const messageText = sanitizeInput(chatInput.value.trim());
|
|
console.log("Processing user input:", messageText); // Debugging input processing
|
|
if (messageText) {
|
|
handleSendMessage(messageText) // Call chat manager function
|
|
.then(() => {
|
|
console.log("Message handled by manager.");
|
|
ui.clearChatInput();
|
|
})
|
|
.catch(error => {
|
|
console.error("Error sending message via manager:", error);
|
|
// UI should already be enabled by chat_manager's finally block
|
|
});
|
|
} else {
|
|
console.log("Input is empty, not sending.");
|
|
}
|
|
}
|
|
|
|
|
|
// --- User Data and Auth ---
|
|
async function loadUserDataForChat() {
|
|
const usernameSpan = document.getElementById('username');
|
|
const isAdminSpan = document.getElementById('isAdmin');
|
|
const adminPermissionsBtn = document.getElementById('adminPermissionsBtn');
|
|
|
|
try {
|
|
console.log("Loading user data for chat page...");
|
|
const data = await api.getUserData();
|
|
console.log("User data received:", data);
|
|
if (usernameSpan) usernameSpan.textContent = data.user || 'Unbekannt';
|
|
if (isAdminSpan) isAdminSpan.textContent = data.isAdmin ? 'Ja' : 'Nein';
|
|
if (adminPermissionsBtn) {
|
|
// Control display based on fetched data
|
|
adminPermissionsBtn.style.display = data.isAdmin ? 'inline-block' : 'none';
|
|
console.log("Admin button display set to:", adminPermissionsBtn.style.display);
|
|
}
|
|
} catch (error) {
|
|
console.error("Failed to load user data:", error);
|
|
// Display error state in UI
|
|
if (usernameSpan) usernameSpan.textContent = 'Fehler';
|
|
if (isAdminSpan) isAdminSpan.textContent = 'Fehler';
|
|
handleApiError(error, 'Benutzerdaten laden'); // Show alert, potentially redirect
|
|
}
|
|
}
|
|
|
|
// --- Definition of checkAdminStatus --- Moved here to ensure it's defined before use
|
|
async function checkAdminStatus() {
|
|
console.log("Checking admin status...");
|
|
try {
|
|
// Assuming api.getAdminData() makes the /api/auth/admin call
|
|
// and throws an error (e.g., 401, 403) if the user is not an admin.
|
|
await api.getAdminData();
|
|
console.log("Admin access confirmed.");
|
|
// No need to return true, successful execution implies admin status
|
|
} catch (error) {
|
|
console.warn("Admin status check failed:", error.status, error.message);
|
|
if (error.status === 403 || error.status === 401) { // Forbidden or Unauthorized
|
|
showAlert('Zugriff verweigert. Nur Admins erlaubt.', 'error');
|
|
window.location.href = 'welcome.html'; // Redirect non-admins immediately
|
|
} else {
|
|
// Handle other errors (e.g., network error)
|
|
handleApiError(error, 'Admin-Status prüfen');
|
|
}
|
|
// IMPORTANT: Re-throw the error AFTER handling redirection/alert
|
|
// This signals to the caller (setupAdminPage) that the check failed.
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
async function loadUserList() {
|
|
const userListDiv = document.getElementById('user-list'); // Select inside function
|
|
if (!userListDiv) {
|
|
console.error("User list container not found!");
|
|
return;
|
|
}
|
|
userListDiv.innerHTML = '<p style="padding: 15px; color: var(--text-secondary);">Lade Benutzer...</p>'; // Loading state
|
|
|
|
try {
|
|
const users = await api.getAllUsers();
|
|
userListDiv.innerHTML = ''; // Clear loading/previous list
|
|
|
|
if (users && users.length > 0) {
|
|
users.forEach(user => {
|
|
const userDiv = document.createElement('div');
|
|
userDiv.classList.add('user-list-item');
|
|
userDiv.dataset.userId = user._id;
|
|
|
|
const usernameP = document.createElement('p');
|
|
usernameP.innerHTML = `<strong>User:</strong> ${sanitizeInput(user.username)}`;
|
|
|
|
const emailP = document.createElement('p');
|
|
emailP.innerHTML = `<strong>Email:</strong> ${sanitizeInput(user.email)}`;
|
|
|
|
const adminP = document.createElement('p');
|
|
adminP.innerHTML = `<strong>Admin:</strong> ${user.isAdmin ? 'Ja' : 'Nein'}`;
|
|
|
|
const deleteButton = document.createElement('button');
|
|
deleteButton.classList.add('button-delete', 'header-btn');
|
|
deleteButton.style.backgroundColor = 'var(--error-color)';
|
|
deleteButton.textContent = 'Löschen';
|
|
deleteButton.addEventListener('click', () => handleDeleteUser(user._id, user.isAdmin, user.username)); // Pass userListDiv here if needed
|
|
|
|
userDiv.append(usernameP, emailP, adminP, deleteButton);
|
|
userListDiv.appendChild(userDiv);
|
|
});
|
|
} else {
|
|
userListDiv.innerHTML = '<p style="padding: 15px; color: var(--text-secondary);">Keine Benutzer gefunden.</p>';
|
|
}
|
|
|
|
} catch (error) {
|
|
handleApiError(error, 'Benutzerliste laden');
|
|
userListDiv.innerHTML = '<p style="padding: 15px; color: var(--error-color);">Fehler beim Laden der Benutzerliste.</p>';
|
|
}
|
|
}
|
|
|
|
async function handleDeleteUser(userId, isAdmin, username) {
|
|
const userListDiv = document.getElementById('user-list'); // Select inside function if needed
|
|
const message = `Möchten Sie den Benutzer "${sanitizeInput(username)}" wirklich löschen? ${isAdmin ? ' Dies ist ein Admin!' : ''}`;
|
|
const confirmed = await showConfirm(message, 'error');
|
|
|
|
if (confirmed) {
|
|
try {
|
|
await api.deleteUserById(userId);
|
|
showAlert(`Benutzer "${sanitizeInput(username)}" erfolgreich gelöscht.`, 'success');
|
|
// Remove user from list visually immediately
|
|
const userDiv = userListDiv?.querySelector(`.user-list-item[data-user-id="${userId}"]`);
|
|
if (userDiv) userDiv.remove();
|
|
// Or reload the whole list: await loadUserList();
|
|
} catch (error) {
|
|
handleApiError(error, 'Benutzer löschen');
|
|
}
|
|
}
|
|
}
|
|
|
|
// --- Theme Toggling ---
|
|
function toggleTheme() {
|
|
const isDarkMode = bodyElement.classList.toggle('dark-theme');
|
|
if (themeToggleButton) {
|
|
themeToggleButton.textContent = isDarkMode ? '🌙' : '☀️';
|
|
}
|
|
localStorage.setItem('theme', isDarkMode ? 'dark' : 'light');
|
|
}
|
|
|
|
function loadThemePreference() {
|
|
const savedTheme = localStorage.getItem('theme');
|
|
const prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
const isDark = savedTheme === 'dark' || (!savedTheme && prefersDark);
|
|
|
|
bodyElement.classList.toggle('dark-theme', isDark); // Set class based on isDark boolean
|
|
if (themeToggleButton) { // Check if button exists before setting text
|
|
themeToggleButton.textContent = isDark ? '🌙' : '☀️';
|
|
}
|
|
}
|
|
|
|
// --- Generic Error Handling ---
|
|
function handleApiError(error, context) {
|
|
console.error(`API Error during ${context}:`, error);
|
|
if (error.status === 401 || error.status === 403) {
|
|
redirectToLogin(`Sitzung abgelaufen oder nicht autorisiert (${context}). Bitte erneut einloggen.`);
|
|
} else if (error.message.includes('Network Error')) {
|
|
showAlert(`Netzwerkfehler bei "${context}". Server nicht erreichbar.`, 'error');
|
|
} else {
|
|
// Show specific message from API if available, otherwise generic
|
|
showAlert(`Fehler bei "${context}": ${error.data?.message || error.message || 'Unbekannter Fehler'}`, 'error');
|
|
}
|
|
}
|
|
|
|
// --- Utility Functions --- (logout, redirectToLogin same as before)
|
|
function logout() {
|
|
localStorage.removeItem('token');
|
|
window.location.href = 'index.html';
|
|
}
|
|
|
|
function redirectToLogin(message) {
|
|
if (message) showAlert(message, 'error');
|
|
setTimeout(() => { window.location.href = 'index.html'; }, 1500);
|
|
} |