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 {