Daniel Bohry 2 هفته پیش
والد
کامیت
ab0a455d75

+ 8 - 20
src/main/resources/static/admin.html

@@ -75,9 +75,7 @@
                             <th>Actions</th>
                         </tr>
                     </thead>
-                    <tbody id="usersTableBody">
-                        <!-- Users will be loaded here -->
-                    </tbody>
+                    <tbody id="usersTableBody"></tbody>
                 </table>
             </div>
 
@@ -87,9 +85,6 @@
             </div>
 
             <div id="emptyState" class="empty-state" style="display: none;">
-                <svg width="64" height="64" viewBox="0 0 24 24" fill="currentColor" opacity="0.5">
-                    <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>
-                </svg>
                 <h3>No users found</h3>
                 <p>No users match your search criteria.</p>
             </div>
@@ -98,35 +93,28 @@
         <div id="messageContainer" class="message" style="display: none;"></div>
     </div>
 
-    <!-- Edit User Modal -->
     <div id="editUserModal" class="modal" style="display: none;">
         <div class="modal-content">
             <div class="modal-header">
                 <h3>Edit User</h3>
-                <button class="close-btn" onclick="closeEditUserModal()">
-                    <svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
-                        <path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>
-                    </svg>
-                </button>
+                <button class="close-btn" onclick="closeEditUserModal()">×</button>
             </div>
 
             <form id="editUserForm" onsubmit="handleEditUserSubmit(event)">
                 <div class="form-section">
                     <div class="form-group">
                         <label for="editUserEmail">Email Address</label>
-                        <input type="email" id="editUserEmail" name="email" placeholder="Enter email address">
+                        <input type="email" id="editUserEmail" name="email">
                     </div>
                 </div>
 
                 <div class="form-section">
                     <label class="section-label">User Status</label>
-                    <div class="toggle-group">
-                        <label class="toggle-switch">
-                            <input type="checkbox" id="editUserActive" name="isActive">
-                            <span class="toggle-slider"></span>
-                            <span class="toggle-label">Active User</span>
-                        </label>
-                    </div>
+                    <label class="toggle-switch">
+                        <input type="checkbox" id="editUserActive" name="isActive">
+                        <span class="toggle-slider"></span>
+                        <span class="toggle-label">Active User</span>
+                    </label>
                 </div>
 
                 <div class="form-section">

+ 2 - 6
src/main/resources/static/css/admin.css

@@ -512,6 +512,8 @@
     display: flex;
     align-items: center;
     justify-content: center;
+    font-size: 24px;
+    line-height: 1;
 }
 
 .close-btn:hover {
@@ -539,12 +541,6 @@
 }
 
 /* Toggle Switch */
-.toggle-group {
-    display: flex;
-    flex-direction: column;
-    gap: 10px;
-}
-
 .toggle-switch {
     display: flex;
     align-items: center;

+ 0 - 14
src/main/resources/static/css/main.css

@@ -464,20 +464,6 @@ body {
     transition: all 0.3s ease;
 }
 
-/* Admin button special styling */
-.admin-btn-circular {
-    background: linear-gradient(135deg, #ff6b6b, #ee5a52);
-    border-color: #ff6b6b;
-    color: white;
-}
-
-.admin-btn-circular:hover {
-    background: linear-gradient(135deg, #ee5a52, #dc3545);
-    border-color: #ee5a52;
-    color: white;
-    box-shadow: 0 4px 12px rgba(255, 107, 107, 0.4);
-}
-
 /* Active state for edit profile button */
 .action-btn-circular.active {
     background: var(--tab-border);

+ 27 - 108
src/main/resources/static/js/admin.js

@@ -1,19 +1,15 @@
-// Admin Panel JavaScript
 let currentUsers = [];
 let filteredUsers = [];
 
-// Check if user has admin role on page load
 document.addEventListener('DOMContentLoaded', function() {
     initializeTheme();
     checkAdminAccess();
     loadUsers();
 });
 
-// Theme toggle functionality (reused from main.js)
 function toggleTheme() {
     const currentTheme = document.documentElement.getAttribute('data-theme');
     const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
-
     document.documentElement.setAttribute('data-theme', newTheme);
     localStorage.setItem('theme', newTheme);
 }
@@ -23,47 +19,36 @@ function initializeTheme() {
     document.documentElement.setAttribute('data-theme', savedTheme);
 }
 
-// Check admin access
 function checkAdminAccess() {
     const currentUser = getCurrentUser();
-
     if (!currentUser || !hasAdminRole(currentUser.roles)) {
         showMessage('Access denied. Admin privileges required.', 'error');
-        setTimeout(() => {
-            window.location.href = 'index.html';
-        }, 2000);
+        setTimeout(() => window.location.href = 'index.html', 2000);
         return false;
     }
     return true;
 }
 
-// Get current user from localStorage
 function getCurrentUser() {
     try {
         const userData = localStorage.getItem('userData');
-        if (!userData) return null;
-        return JSON.parse(userData);
+        return userData ? JSON.parse(userData) : null;
     } catch (e) {
-        console.error('Error parsing user data:', e);
         return null;
     }
 }
 
-// Check if user has admin role
 function hasAdminRole(roles) {
     return Array.isArray(roles) && roles.includes('ADMIN');
 }
 
-// Load users from API
 async function loadUsers() {
     showLoading(true);
     hideEmptyState();
 
     try {
         const token = localStorage.getItem('authToken');
-        if (!token) {
-            throw new Error('No authentication token found');
-        }
+        if (!token) throw new Error('No authentication token found');
 
         const response = await fetch(API_BASE_URL + '/users', {
             method: 'GET',
@@ -81,15 +66,13 @@ async function loadUsers() {
         }
 
         const users = await response.json();
-
-        // Transform API response to match our display format
         const transformedUsers = users.map(user => ({
             id: user.id,
             username: user.username,
             email: user.email,
             roles: user.roles,
             status: user.active ? 'active' : 'inactive',
-            lastLogin: null // Not provided by API
+            lastLogin: null
         }));
 
         currentUsers = transformedUsers;
@@ -100,11 +83,9 @@ async function loadUsers() {
 
     } catch (error) {
         console.error('Error loading users:', error);
-        if (error.message.includes('Access denied') || error.message.includes('Admin privileges')) {
+        if (error.message.includes('Access denied')) {
             showMessage('Access denied. Admin privileges required.', 'error');
-            setTimeout(() => {
-                window.location.href = 'index.html';
-            }, 2000);
+            setTimeout(() => window.location.href = 'index.html', 2000);
         } else {
             showMessage('Failed to load users. Please try again.', 'error');
         }
@@ -114,7 +95,6 @@ async function loadUsers() {
     }
 }
 
-// Display users in table
 function displayUsers(users) {
     const tableBody = document.getElementById('usersTableBody');
 
@@ -146,23 +126,14 @@ function displayUsers(users) {
             </td>
             <td>
                 <div class="action-buttons">
-                    <button class="action-btn small" onclick="viewUser('${user.id}')" title="View Details">
-                        <svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">
-                            <path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"/>
-                        </svg>
-                    </button>
-                    <button class="action-btn small secondary" onclick="editUser('${user.id}')" title="Edit User">
-                        <svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">
-                            <path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/>
-                        </svg>
-                    </button>
+                    <button class="action-btn small" onclick="viewUser('${user.id}')" title="View Details">👁️</button>
+                    <button class="action-btn small secondary" onclick="editUser('${user.id}')" title="Edit User">✏️</button>
                 </div>
             </td>
         </tr>
         `).join('');
 }
 
-// Update statistics
 function updateStats(users) {
     const totalUsers = users.length;
     const activeUsers = users.filter(u => u.status === 'active').length;
@@ -173,10 +144,8 @@ function updateStats(users) {
     document.getElementById('adminUsers').textContent = adminUsers;
 }
 
-// Filter users based on search input
 function filterUsers() {
     const searchTerm = document.getElementById('searchInput').value.toLowerCase();
-
     filteredUsers = currentUsers.filter(user =>
         user.username.toLowerCase().includes(searchTerm) ||
         user.id.toLowerCase().includes(searchTerm) ||
@@ -184,11 +153,9 @@ function filterUsers() {
         user.roles.some(role => role.toLowerCase().includes(searchTerm)) ||
         user.status.toLowerCase().includes(searchTerm)
     );
-
     displayUsers(filteredUsers);
 }
 
-// User action functions
 function viewUser(userId) {
     const user = currentUsers.find(u => u.id === userId);
     if (user) {
@@ -206,53 +173,35 @@ function viewUser(userId) {
 
 function editUser(userId) {
     const user = currentUsers.find(u => u.id === userId);
-    if (user) {
-        openEditUserModal(user);
-    }
+    if (user) openEditUserModal(user);
 }
 
-// Edit User Modal Functions
 let currentEditUserId = null;
 
 function openEditUserModal(user) {
     currentEditUserId = user.id;
     const modal = document.getElementById('editUserModal');
 
-    // Populate form with user data
     document.getElementById('editUserEmail').value = user.email || '';
     document.getElementById('editUserActive').checked = user.status === 'active';
 
-    // Clear all role checkboxes first
     document.querySelectorAll('input[name="role"]').forEach(checkbox => {
         checkbox.checked = false;
     });
 
-    // Check the roles the user has
     user.roles.forEach(role => {
         const checkbox = document.querySelector(`input[name="role"][value="${role}"]`);
-        if (checkbox) {
-            checkbox.checked = true;
-        }
+        if (checkbox) checkbox.checked = true;
     });
 
-    // Clear any previous messages
     clearEditUserMessage();
-
-    // Show modal
     modal.style.display = 'flex';
-
-    // Focus on email input
-    setTimeout(() => {
-        document.getElementById('editUserEmail').focus();
-    }, 100);
+    setTimeout(() => document.getElementById('editUserEmail').focus(), 100);
 }
 
 function closeEditUserModal() {
-    const modal = document.getElementById('editUserModal');
-    modal.style.display = 'none';
+    document.getElementById('editUserModal').style.display = 'none';
     currentEditUserId = null;
-
-    // Reset form
     document.getElementById('editUserForm').reset();
     clearEditUserMessage();
 }
@@ -283,13 +232,11 @@ async function handleEditUserSubmit(event) {
     const email = formData.get('email').trim();
     const isActive = formData.has('isActive');
 
-    // Get selected roles
     const selectedRoles = [];
     document.querySelectorAll('input[name="role"]:checked').forEach(checkbox => {
         selectedRoles.push(checkbox.value);
     });
 
-    // Validation
     if (selectedRoles.length === 0) {
         showEditUserMessage('Please select at least one role', 'error');
         return;
@@ -300,14 +247,12 @@ async function handleEditUserSubmit(event) {
         return;
     }
 
-    // Prepare request data
     const requestData = {
         roles: selectedRoles,
         email: email || null,
         isActive: isActive
     };
 
-    // Update UI
     const saveBtn = document.getElementById('saveUserBtn');
     const originalText = saveBtn.textContent;
     saveBtn.textContent = 'Saving...';
@@ -316,9 +261,7 @@ async function handleEditUserSubmit(event) {
 
     try {
         const token = localStorage.getItem('authToken');
-        if (!token) {
-            throw new Error('No authentication token found');
-        }
+        if (!token) throw new Error('No authentication token found');
 
         const response = await fetch(`${API_BASE_URL}/users/${currentEditUserId}`, {
             method: 'PUT',
@@ -345,8 +288,6 @@ async function handleEditUserSubmit(event) {
         }
 
         showEditUserMessage('User updated successfully!', 'success');
-
-        // Refresh the users list to show updated data
         setTimeout(() => {
             loadUsers();
             closeEditUserModal();
@@ -362,31 +303,10 @@ async function handleEditUserSubmit(event) {
 }
 
 function isValidEmail(email) {
-    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
-    return emailRegex.test(email);
+    return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
 }
 
-// Close modal when clicking outside of it
-document.addEventListener('click', function(event) {
-    const modal = document.getElementById('editUserModal');
-    if (event.target === modal) {
-        closeEditUserModal();
-    }
-});
-
-// Close modal with Escape key
-document.addEventListener('keydown', function(event) {
-    if (event.key === 'Escape') {
-        const modal = document.getElementById('editUserModal');
-        if (modal.style.display === 'flex') {
-            closeEditUserModal();
-        }
-    }
-});
-
-// Utility functions
 function formatUserId(id) {
-    // Format UUID for display (show first 8 characters)
     return id.substring(0, 8) + '...';
 }
 
@@ -397,8 +317,7 @@ function formatDate(dateString) {
 }
 
 function showLoading(show) {
-    const indicator = document.getElementById('loadingIndicator');
-    indicator.style.display = show ? 'block' : 'none';
+    document.getElementById('loadingIndicator').style.display = show ? 'block' : 'none';
 }
 
 function showEmptyState() {
@@ -415,19 +334,19 @@ function showMessage(message, type = 'info') {
     messageContainer.className = `message ${type}`;
     messageContainer.style.display = 'block';
 
-    // Auto-hide message after 3 seconds for success messages
     if (type === 'success') {
-        setTimeout(() => {
-            messageContainer.style.display = 'none';
-        }, 3000);
+        setTimeout(() => messageContainer.style.display = 'none', 3000);
     }
 }
 
-// Export functions for potential use in other scripts
-window.adminAPI = {
-    loadUsers,
-    filterUsers,
-    viewUser,
-    editUser,
-    toggleTheme
-};
+document.addEventListener('click', function(event) {
+    const modal = document.getElementById('editUserModal');
+    if (event.target === modal) closeEditUserModal();
+});
+
+document.addEventListener('keydown', function(event) {
+    if (event.key === 'Escape') {
+        const modal = document.getElementById('editUserModal');
+        if (modal.style.display === 'flex') closeEditUserModal();
+    }
+});