diff --git a/frontend/index.html b/frontend/index.html index 9773824..7f650ca 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -34,6 +34,10 @@

Course Registration System

Registrations + diff --git a/frontend/script.js b/frontend/script.js index 174617a..425c36b 100644 --- a/frontend/script.js +++ b/frontend/script.js @@ -1,6 +1,28 @@ // Configuration const API_BASE_URL = 'http://localhost:5210/api'; +// Theme Management +function initializeTheme() { + // Get saved theme from localStorage or default to 'light' + const savedTheme = localStorage.getItem('theme') || 'light'; + applyTheme(savedTheme); +} + +function toggleTheme() { + const currentTheme = document.documentElement.getAttribute('data-theme') || 'light'; + const newTheme = currentTheme === 'light' ? 'dark' : 'light'; + applyTheme(newTheme); + localStorage.setItem('theme', newTheme); +} + +function applyTheme(theme) { + document.documentElement.setAttribute('data-theme', theme); + // The CSS handles the icon visibility through the data-theme attribute +} + +// Export theme functions +window.toggleTheme = toggleTheme; + // DOM Elements const addCourseForm = document.getElementById('add-course-form'); const submitBtn = document.getElementById('submit-btn'); @@ -9,6 +31,7 @@ const loadingOverlay = document.getElementById('loading-overlay'); // Initialize the application document.addEventListener('DOMContentLoaded', function() { + initializeTheme(); initializeForm(); loadCourses(); updateNavigation(); diff --git a/frontend/styles.css b/frontend/styles.css index 757453e..05bb41d 100644 --- a/frontend/styles.css +++ b/frontend/styles.css @@ -5,30 +5,91 @@ box-sizing: border-box; } +:root { + /* Light theme colors */ + --bg-gradient-start: #667eea; + --bg-gradient-end: #764ba2; + --container-bg: white; + --text-primary: #2d3748; + --text-secondary: #64748b; + --border-color: #e2e8f0; + --border-color-light: #e5e7eb; + --input-bg: #fafafa; + --input-border: #e5e7eb; + --card-bg: white; + --card-shadow: rgba(0, 0, 0, 0.1); + --modal-bg: rgba(0, 0, 0, 0.7); + --header-bg: white; + --nav-link-color: #64748b; + --nav-link-hover-bg: #667eea; + --section-bg: transparent; + --empty-state-icon: #cbd5e1; + --filter-bg: #f8fafc; + --form-container-bg: white; + --btn-secondary-bg: #f8fafc; + --btn-secondary-border: #e2e8f0; + --btn-secondary-hover-bg: #f1f5f9; + --btn-secondary-hover-border: #cbd5e1; + --loading-overlay-bg: rgba(255, 255, 255, 0.9); + --loading-spinner-bg: white; +} + +[data-theme="dark"] { + /* Dark theme colors */ + --bg-gradient-start: #0f172a; + --bg-gradient-end: #1e293b; + --container-bg: #0f172a; + --text-primary: #f1f5f9; + --text-secondary: #94a3b8; + --border-color: #1e293b; + --border-color-light: #334155; + --input-bg: #1e293b; + --input-border: #334155; + --card-bg: #1e293b; + --card-shadow: rgba(0, 0, 0, 0.5); + --modal-bg: rgba(0, 0, 0, 0.85); + --header-bg: #0f172a; + --nav-link-color: #94a3b8; + --nav-link-hover-bg: #667eea; + --section-bg: transparent; + --empty-state-icon: #475569; + --filter-bg: #1e293b; + --form-container-bg: #1e293b; + --btn-secondary-bg: #334155; + --btn-secondary-border: #475569; + --btn-secondary-hover-bg: #475569; + --btn-secondary-hover-border: #64748b; + --loading-overlay-bg: rgba(15, 23, 42, 0.95); + --loading-spinner-bg: #1e293b; +} + body { font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; line-height: 1.6; - color: #2d3748; - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: var(--text-primary); + background: linear-gradient(135deg, var(--bg-gradient-start) 0%, var(--bg-gradient-end) 100%); min-height: 100vh; + transition: background 0.3s ease, color 0.3s ease; } .container { max-width: 1200px; margin: 0 auto; min-height: 100vh; - background: white; - box-shadow: 0 0 50px rgba(0, 0, 0, 0.1); + background: var(--container-bg); + box-shadow: 0 0 50px var(--card-shadow); + transition: background 0.3s ease; } /* Header Styles */ .header { - background: white; - border-bottom: 1px solid #e2e8f0; - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + background: var(--header-bg); + border-bottom: 1px solid var(--border-color); + box-shadow: 0 1px 3px var(--card-shadow); position: sticky; top: 0; z-index: 100; + transition: background 0.3s ease, border-color 0.3s ease; } .header-content { @@ -52,7 +113,8 @@ body { .logo h1 { font-size: 1.5rem; font-weight: 700; - color: #2d3748; + color: var(--text-primary); + transition: color 0.3s ease; } .nav-menu { @@ -66,7 +128,7 @@ body { gap: 0.5rem; padding: 0.5rem 1rem; text-decoration: none; - color: #64748b; + color: var(--nav-link-color); border-radius: 0.5rem; transition: all 0.2s ease; font-weight: 500; @@ -74,10 +136,82 @@ body { .nav-link:hover, .nav-link.active { - background: #667eea; + background: var(--nav-link-hover-bg); color: white; } +/* Theme Toggle Button */ +.theme-toggle { + position: relative; + display: flex; + align-items: center; + justify-content: center; + width: 60px; + height: 32px; + border: none; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + border-radius: 2rem; + cursor: pointer; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + margin-left: 1rem; + box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3); + overflow: hidden; +} + +.theme-toggle:hover { + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(102, 126, 234, 0.5); +} + +.theme-toggle:active { + transform: translateY(0); +} + +.theme-toggle::before { + content: ''; + position: absolute; + width: 26px; + height: 26px; + background: white; + border-radius: 50%; + left: 3px; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); +} + +[data-theme="dark"] .theme-toggle::before { + left: 31px; + background: #1a202c; +} + +.theme-toggle i { + position: relative; + z-index: 1; + font-size: 0.9rem; + color: white; + transition: all 0.3s ease; +} + +.theme-toggle .fa-moon { + position: absolute; + left: 8px; + opacity: 1; +} + +.theme-toggle .fa-sun { + position: absolute; + right: 8px; + opacity: 0; +} + +[data-theme="dark"] .theme-toggle .fa-moon { + opacity: 0; +} + +[data-theme="dark"] .theme-toggle .fa-sun { + opacity: 1; +} + /* Main Content */ .main-content { padding: 2rem; @@ -99,12 +233,13 @@ body { .section-header h2 { font-size: 2rem; font-weight: 700; - color: #2d3748; + color: var(--text-primary); margin-bottom: 0.5rem; display: flex; align-items: center; justify-content: center; gap: 0.75rem; + transition: color 0.3s ease; } .section-header h2 i { @@ -112,8 +247,9 @@ body { } .section-header p { - color: #64748b; + color: var(--text-secondary); font-size: 1.1rem; + transition: color 0.3s ease; } .section-actions { @@ -127,10 +263,11 @@ body { .form-container { max-width: 800px; margin: 0 auto; - background: white; + background: var(--form-container-bg); border-radius: 1rem; - box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1); + box-shadow: 0 4px 20px var(--card-shadow); overflow: hidden; + transition: background 0.3s ease; } .form { @@ -153,9 +290,10 @@ body { align-items: center; gap: 0.5rem; font-weight: 600; - color: #374151; + color: var(--text-primary); margin-bottom: 0.5rem; font-size: 0.9rem; + transition: color 0.3s ease; } .form-label i { @@ -167,18 +305,19 @@ body { .form-textarea { width: 100%; padding: 0.75rem 1rem; - border: 2px solid #e5e7eb; + border: 2px solid var(--input-border); border-radius: 0.5rem; font-size: 1rem; transition: all 0.2s ease; - background: #fafafa; + background: var(--input-bg); + color: var(--text-primary); } .form-input:focus, .form-textarea:focus { outline: none; border-color: #667eea; - background: white; + background: var(--card-bg); box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1); } @@ -196,8 +335,9 @@ body { .character-count { text-align: right; font-size: 0.8rem; - color: #64748b; + color: var(--text-secondary); margin-top: 0.25rem; + transition: color 0.3s ease; } .error-message { @@ -249,14 +389,14 @@ body { } .btn-secondary { - background: #f8fafc; - color: #64748b; - border: 2px solid #e2e8f0; + background: var(--btn-secondary-bg); + color: var(--text-secondary); + border: 2px solid var(--btn-secondary-border); } .btn-secondary:hover:not(:disabled) { - background: #f1f5f9; - border-color: #cbd5e1; + background: var(--btn-secondary-hover-bg); + border-color: var(--btn-secondary-hover-border); } .form-actions { @@ -265,7 +405,8 @@ body { align-items: center; margin-top: 2rem; padding-top: 2rem; - border-top: 1px solid #e5e7eb; + border-top: 1px solid var(--border-color-light); + transition: border-color 0.3s ease; } /* Search Styles */ @@ -292,10 +433,11 @@ body { .search-box input { width: 100%; padding: 0.75rem 1rem 0.75rem 2.5rem; - border: 2px solid #e5e7eb; + border: 2px solid var(--input-border); border-radius: 2rem; font-size: 1rem; - background: white; + background: var(--card-bg); + color: var(--text-primary); transition: all 0.2s ease; } @@ -319,9 +461,10 @@ body { gap: 1rem; margin: 1.5rem 0; padding: 1rem; - background: #f8fafc; + background: var(--filter-bg); border-radius: 0.5rem; flex-wrap: wrap; + transition: background 0.3s ease; } .filter-group { @@ -349,12 +492,12 @@ body { } .registration-card { - background: white; + background: var(--card-bg); border-radius: 1rem; padding: 1.5rem; - box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); + box-shadow: 0 2px 10px var(--card-shadow); transition: all 0.2s ease; - border: 1px solid #e5e7eb; + border: 1px solid var(--border-color-light); cursor: pointer; } @@ -377,8 +520,9 @@ body { .registration-card .student-name { font-size: 1.1rem; font-weight: 700; - color: #2d3748; + color: var(--text-primary); margin-bottom: 0.25rem; + transition: color 0.3s ease; } .registration-card .course-name { @@ -401,7 +545,8 @@ body { display: flex; align-items: center; gap: 0.5rem; - color: #64748b; + color: var(--text-secondary); + transition: color 0.3s ease; } .registration-info-item i { @@ -438,12 +583,12 @@ body { } .course-card { - background: white; + background: var(--card-bg); border-radius: 1rem; padding: 1.5rem; - box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); + box-shadow: 0 2px 10px var(--card-shadow); transition: all 0.2s ease; - border: 1px solid #e5e7eb; + border: 1px solid var(--border-color-light); cursor: pointer; } @@ -455,8 +600,9 @@ body { .course-card h3 { font-size: 1.25rem; font-weight: 700; - color: #2d3748; + color: var(--text-primary); margin-bottom: 0.5rem; + transition: color 0.3s ease; } .course-card .instructor { @@ -469,12 +615,13 @@ body { } .course-card .description { - color: #64748b; + color: var(--text-secondary); margin-bottom: 1rem; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; + transition: color 0.3s ease; } .course-card .details { @@ -487,7 +634,8 @@ body { display: flex; align-items: center; gap: 0.5rem; - color: #64748b; + color: var(--text-secondary); + transition: color 0.3s ease; } .course-detail i { @@ -526,12 +674,13 @@ body { left: 0; width: 100%; height: 100%; - background: rgba(0, 0, 0, 0.7); + background: var(--modal-bg); display: flex; align-items: center; justify-content: center; z-index: 1000; animation: fadeIn 0.2s ease; + transition: background 0.3s ease; } .modal.hidden { @@ -539,16 +688,17 @@ body { } .modal-content { - background: white; + background: var(--card-bg); border-radius: 1rem; padding: 2rem; max-width: 500px; width: 90%; max-height: 90vh; overflow-y: auto; - box-shadow: 0 25px 50px rgba(0, 0, 0, 0.25); + box-shadow: 0 25px 50px var(--card-shadow); animation: slideUp 0.3s ease; position: relative; + transition: background 0.3s ease; } .modal-content.success { @@ -569,7 +719,8 @@ body { .modal-header h3 { font-size: 1.5rem; font-weight: 700; - color: #2d3748; + color: var(--text-primary); + transition: color 0.3s ease; } .modal-header i { @@ -591,7 +742,7 @@ body { background: none; border: none; font-size: 1.5rem; - color: #64748b; + color: var(--text-secondary); cursor: pointer; padding: 0.5rem; border-radius: 0.5rem; @@ -599,14 +750,15 @@ body { } .modal-close:hover { - background: #f1f5f9; - color: #2d3748; + background: var(--filter-bg); + color: var(--text-primary); } .modal-body { margin-bottom: 1.5rem; - color: #64748b; + color: var(--text-secondary); line-height: 1.6; + transition: color 0.3s ease; } .modal-actions { @@ -623,8 +775,9 @@ body { justify-content: center; gap: 0.75rem; padding: 3rem; - color: #64748b; + color: var(--text-secondary); font-size: 1.1rem; + transition: color 0.3s ease; } .loading i { @@ -639,11 +792,12 @@ body { left: 0; width: 100%; height: 100%; - background: rgba(255, 255, 255, 0.9); + background: var(--loading-overlay-bg); display: flex; align-items: center; justify-content: center; z-index: 2000; + transition: background 0.3s ease; } .loading-overlay.hidden { @@ -653,9 +807,10 @@ body { .loading-spinner { text-align: center; padding: 2rem; - background: white; + background: var(--loading-spinner-bg); border-radius: 1rem; - box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1); + box-shadow: 0 10px 25px var(--card-shadow); + transition: background 0.3s ease; } .loading-spinner i { @@ -666,15 +821,17 @@ body { } .loading-spinner p { - color: #64748b; + color: var(--text-secondary); font-weight: 600; + transition: color 0.3s ease; } /* Empty State */ .empty-state { text-align: center; padding: 4rem 2rem; - color: #64748b; + color: var(--text-secondary); + transition: color 0.3s ease; } .empty-state.hidden { @@ -683,8 +840,9 @@ body { .empty-state i { font-size: 4rem; - color: #cbd5e1; + color: var(--empty-state-icon); margin-bottom: 1rem; + transition: color 0.3s ease; } .empty-state h3 {