nguyenhai266 commited on
Commit
eb3cc2a
·
1 Parent(s): a007dd6

Enable Thymeleaf, add homepage & CSS

Browse files

Add spring-boot-starter-thymeleaf dependency and enable Thymeleaf properties in application.properties; adjust datasource configuration to use the MySQL 'attendance' DB. Add a new homepage template and stylesheet (homePage.html, homePage.css). Refactor auth.css, consolidate layout styles, and update header/footer/login templates to use the new CSS paths and correct Thymeleaf fragment references.

pom.xml CHANGED
@@ -1,7 +1,7 @@
1
  <?xml version="1.0" encoding="UTF-8"?>
2
  <project xmlns="http://maven.apache.org/POM/4.0.0"
3
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
5
  <modelVersion>4.0.0</modelVersion>
6
  <parent>
7
  <groupId>org.springframework.boot</groupId>
@@ -95,7 +95,10 @@
95
  <artifactId>mysql-connector-j</artifactId>
96
  <scope>runtime</scope>
97
  </dependency>
98
-
 
 
 
99
  </dependencies>
100
 
101
  <build>
 
1
  <?xml version="1.0" encoding="UTF-8"?>
2
  <project xmlns="http://maven.apache.org/POM/4.0.0"
3
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
5
  <modelVersion>4.0.0</modelVersion>
6
  <parent>
7
  <groupId>org.springframework.boot</groupId>
 
95
  <artifactId>mysql-connector-j</artifactId>
96
  <scope>runtime</scope>
97
  </dependency>
98
+ <dependency>
99
+ <groupId>org.springframework.boot</groupId>
100
+ <artifactId>spring-boot-starter-thymeleaf</artifactId>
101
+ </dependency>
102
  </dependencies>
103
 
104
  <build>
src/main/resources/application.properties CHANGED
@@ -6,11 +6,11 @@ spring.servlet.multipart.max-request-size=10MB
6
  spring.mvc.view.prefix=/WEB-INF/views/
7
  spring.mvc.view.suffix=.jsp
8
  # Thymeleaf Configuration
9
- # spring.thymeleaf.prefix=classpath:/templates/
10
- # spring.thymeleaf.suffix=.html
11
- # spring.thymeleaf.cache=false
12
- # spring.thymeleaf.encoding=UTF-8
13
- # spring.thymeleaf.mode=HTML
14
 
15
  # Google OAuth2
16
  # spring.security.oauth2.client.registration.google.client-id=
@@ -23,14 +23,14 @@ spring.devtools.livereload.enabled=true
23
  server.servlet.jsp.init-parameters.development=true
24
 
25
  # DataSource Configuration for SQL Server
26
- spring.datasource.url=jdbc:mariadb://localhost:3306/ATTENDANCE
27
- spring.datasource.username=root
28
- spring.datasource.password=QQQewqwqa401!
29
- spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
30
-
31
- # spring.datasource.url=jdbc:mysql://localhost:3306/game_promo_web
32
  # spring.datasource.username=root
33
- # spring.datasource.password=annguyenthanh2k5
 
 
 
 
 
34
 
35
 
36
  # SMPT EMAIL
 
6
  spring.mvc.view.prefix=/WEB-INF/views/
7
  spring.mvc.view.suffix=.jsp
8
  # Thymeleaf Configuration
9
+ spring.thymeleaf.prefix=classpath:/templates/
10
+ spring.thymeleaf.suffix=.html
11
+ spring.thymeleaf.cache=false
12
+ spring.thymeleaf.encoding=UTF-8
13
+ spring.thymeleaf.mode=HTML
14
 
15
  # Google OAuth2
16
  # spring.security.oauth2.client.registration.google.client-id=
 
23
  server.servlet.jsp.init-parameters.development=true
24
 
25
  # DataSource Configuration for SQL Server
26
+ # spring.datasource.url=jdbc:mariadb://localhost:3306/ATTENDANCE
 
 
 
 
 
27
  # spring.datasource.username=root
28
+ # spring.datasource.password=QQQewqwqa401!
29
+ # spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
30
+
31
+ spring.datasource.url=jdbc:mysql://localhost:3306/attendance
32
+ spring.datasource.username=root
33
+ spring.datasource.password=annguyenthanh2k5
34
 
35
 
36
  # SMPT EMAIL
src/main/resources/static/css/auth.css CHANGED
@@ -1,281 +1,128 @@
1
- /* ==========================================
2
- LOGIN PAGE
3
- ========================================== */
4
 
5
- .login-section {
 
 
 
 
 
 
6
  min-height: 100vh;
7
- padding-top: 30px;
8
- /* display: flex; */
9
- align-items: center;
10
- padding-bottom: 30px;
11
  background:
12
  radial-gradient(circle at top left,
13
- rgba(37,99,235,.18),
14
  transparent 30%),
15
-
16
  radial-gradient(circle at bottom right,
17
- rgba(239,68,68,.12),
18
  transparent 40%),
19
-
20
  #070b16;
 
21
  }
22
 
23
- /* ==========================================
24
- LEFT SIDE
25
- ========================================== */
26
-
27
- .welcome-panel {
28
- color: white;
29
- padding-right: 60px;
30
- }
31
-
32
- .logo-circle {
33
- width: 80px;
34
- height: 80px;
35
-
36
- border-radius: 24px;
37
-
38
- background: rgba(37,99,235,.15);
39
-
40
  display: flex;
41
- align-items: center;
42
  justify-content: center;
43
-
44
- margin-bottom: 30px;
45
- }
46
-
47
- .logo-circle i {
48
- color: #3b82f6;
49
- font-size: 42px;
50
- }
51
-
52
- .left-title {
53
- color: white;
54
-
55
- font-size: 3.8rem;
56
- font-weight: 700;
57
-
58
- margin-bottom: 25px;
59
-
60
- line-height: 1.1;
61
- }
62
-
63
- .left-description {
64
- color: #94a3b8;
65
-
66
- font-size: 1.1rem;
67
-
68
- line-height: 1.8;
69
- }
70
-
71
- /* ==========================================
72
- LOGIN CARD
73
- ========================================== */
74
-
75
-
76
- .card-header{
77
- display: flex;
78
  align-items: center;
79
- gap: 20px;
80
- margin-bottom: 20px;
81
  }
82
 
83
- .login-card {
 
 
84
  background: #111827;
85
-
86
- border: 1px solid rgba(59,130,246,.2);
87
-
88
  border-radius: 24px;
89
-
90
- padding: 20px;
91
-
92
- max-width: 480px;
93
-
94
  box-shadow:
95
- 0 20px 60px rgba(0,0,0,.35),
96
- 0 0 0 1px rgba(59,130,246,.05);
97
  }
98
 
99
- .card-icon {
100
- width: 70px;
101
- height: 70px;
102
-
103
- border-radius: 18px;
104
-
105
- background: rgba(16,185,129,.15);
106
-
107
  display: flex;
108
- align-items: center;
109
- justify-content: center;
110
-
111
- margin-bottom: 20px;
112
- }
113
-
114
- .card-icon i {
115
- color: #10b981;
116
- font-size: 32px;
117
  }
118
 
119
- .login-card h2 {
120
- color: white;
121
-
122
  font-size: 2rem;
123
  font-weight: 700;
 
124
 
125
- margin-bottom: 25px;
 
126
  }
127
 
128
- /* ==========================================
129
- FORM
130
- ========================================== */
 
 
131
 
132
- .form-group {
133
  margin-bottom: 18px;
134
  }
135
 
136
- .form-group label {
137
  display: block;
138
-
139
  color: #cbd5e1;
140
-
141
- font-weight: 500;
142
-
143
  margin-bottom: 8px;
 
144
  }
145
 
146
- .form-control {
147
  width: 100%;
148
-
149
- height: 54px;
150
-
151
- background: #0f172a;
152
-
153
  border: 1px solid #334155;
154
-
155
- border-radius: 14px;
156
-
157
- color: white;
158
- }
159
-
160
- .form-control:focus {
161
  background: #0f172a;
162
-
163
- color: white;
164
-
165
- border-color: #3b82f6;
166
-
167
- box-shadow: 0 0 0 4px rgba(59,130,246,.15);
168
- }
169
-
170
- .form-check-label {
171
- color: #94a3b8;
172
- }
173
-
174
- /* ==========================================
175
- BUTTONS
176
- ========================================== */
177
-
178
- .btn-danger {
179
- width: 100%;
180
-
181
- height: 50px;
182
-
183
- border: none;
184
-
185
- border-radius: 14px;
186
-
187
- background: #051863;
188
-
189
  color: white;
190
-
191
- font-weight: 600;
192
  }
193
 
194
- .btn-danger:hover {
195
- background: #dc2626;
 
196
  }
197
 
198
- .btn-primary {
199
  width: 100%;
200
-
201
- height: 54px;
202
-
203
  border: none;
204
-
205
- border-radius: 14px;
206
-
207
  background: #2563eb;
208
-
209
  color: white;
210
-
211
  font-weight: 600;
212
-
213
  margin-top: 10px;
214
  }
215
 
216
- .btn-primary:hover {
217
- background: #1d4ed8;
 
 
 
218
  }
219
 
220
- /* ==========================================
221
- LINKS
222
- ========================================== */
223
-
224
- .btn-link,
225
- .text-end a {
226
-
227
  color: #60a5fa;
228
  text-decoration: none;
 
229
  }
230
 
231
- .btn-link:hover,
232
- .text-end a:hover {
233
  color: white;
234
  }
235
 
236
- .text-end {
237
- display:flex;
238
- justify-content:space-around;
239
- margin-top: 10px;
240
- }
241
-
242
- /* ==========================================
243
- ALERT
244
- ========================================== */
245
-
246
- .alert-danger {
247
- background: rgba(239,68,68,.15);
248
-
249
- border: 1px solid rgba(239,68,68,.3);
250
-
251
- color: #fecaca;
252
-
253
- border-radius: 12px;
254
- }
255
-
256
- /* ==========================================
257
- MOBILE
258
- ========================================== */
259
-
260
- @media (max-width: 991px) {
261
-
262
- .welcome-panel {
263
- text-align: center;
264
-
265
- padding-right: 0;
266
-
267
- margin-bottom: 50px;
268
- }
269
-
270
- .logo-circle {
271
- margin: 0 auto 25px;
272
- }
273
-
274
- .left-title {
275
- font-size: 2.5rem;
276
- }
277
-
278
- .login-card {
279
- max-width: 100%;
280
- }
281
  }
 
1
+ @import url("/css/layout/header.css");
2
+ @import url("/css/layout/footer.css");
 
3
 
4
+ * {
5
+ margin: 0;
6
+ padding: 0;
7
+ box-sizing: border-box;
8
+ }
9
+
10
+ body {
11
  min-height: 100vh;
 
 
 
 
12
  background:
13
  radial-gradient(circle at top left,
14
+ rgba(37, 99, 235, .18),
15
  transparent 30%),
 
16
  radial-gradient(circle at bottom right,
17
+ rgba(239, 68, 68, .12),
18
  transparent 40%),
 
19
  #070b16;
20
+ font-family: Arial, Helvetica, sans-serif;
21
  }
22
 
23
+ .layout {
24
+ margin-top: 60px;
25
+ min-height: calc(100vh - 140px);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  display: flex;
 
27
  justify-content: center;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  align-items: center;
29
+ padding: 40px 20px;
 
30
  }
31
 
32
+ .card {
33
+ width: 100%;
34
+ max-width: 480px;
35
  background: #111827;
36
+ border: 1px solid rgba(59, 130, 246, .2);
 
 
37
  border-radius: 24px;
38
+ padding: 30px;
 
 
 
 
39
  box-shadow:
40
+ 0 20px 60px rgba(0, 0, 0, .35),
41
+ 0 0 0 1px rgba(59, 130, 246, .05);
42
  }
43
 
44
+ .card-header {
 
 
 
 
 
 
 
45
  display: flex;
46
+ flex-direction: column;
47
+ gap: 10px;
48
+ text-align: center;
49
+ margin-bottom: 24px;
 
 
 
 
 
50
  }
51
 
52
+ .card-title {
53
+ color: #fff;
 
54
  font-size: 2rem;
55
  font-weight: 700;
56
+ }
57
 
58
+ .card-description {
59
+ color: #94a3b8;
60
  }
61
 
62
+ .divider {
63
+ height: 1px;
64
+ background: #334155;
65
+ margin-bottom: 24px;
66
+ }
67
 
68
+ .auth-group {
69
  margin-bottom: 18px;
70
  }
71
 
72
+ .auth-group label {
73
  display: block;
 
74
  color: #cbd5e1;
 
 
 
75
  margin-bottom: 8px;
76
+ font-weight: 500;
77
  }
78
 
79
+ .auth-group input {
80
  width: 100%;
81
+ height: 52px;
82
+ padding: 0 16px;
83
+ border-radius: 12px;
 
 
84
  border: 1px solid #334155;
 
 
 
 
 
 
 
85
  background: #0f172a;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
  color: white;
87
+ outline: none;
 
88
  }
89
 
90
+ .auth-group input:focus {
91
+ border-color: #3b82f6;
92
+ box-shadow: 0 0 0 4px rgba(59, 130, 246, .15);
93
  }
94
 
95
+ .auth-btn {
96
  width: 100%;
97
+ height: 52px;
 
 
98
  border: none;
99
+ border-radius: 12px;
 
 
100
  background: #2563eb;
 
101
  color: white;
 
102
  font-weight: 600;
103
+ cursor: pointer;
104
  margin-top: 10px;
105
  }
106
 
107
+ .auth-btn:hover {}
108
+ .other-option {
109
+ display: flex;
110
+ justify-content: space-between;
111
+ width: 100%;
112
  }
113
 
114
+ .other-option a {
 
 
 
 
 
 
115
  color: #60a5fa;
116
  text-decoration: none;
117
+ cursor: pointer;
118
  }
119
 
120
+ .other-option a:hover {
 
121
  color: white;
122
  }
123
 
124
+ .error-message {
125
+ color: #ef4444;
126
+ font-size: 14px;
127
+ margin-top: 4px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
  }
src/main/resources/static/css/homePage.css ADDED
@@ -0,0 +1,345 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ /* =========================
3
+ HOME PAGE
4
+ ========================= */
5
+
6
+ .home-page {
7
+ min-height: 100vh;
8
+ background:
9
+ radial-gradient(circle at top left,
10
+ rgba(99, 102, 241, .15),
11
+ transparent 30%),
12
+ radial-gradient(circle at bottom right,
13
+ rgba(139, 92, 246, .12),
14
+ transparent 40%),
15
+ #020617;
16
+ }
17
+
18
+ /* =========================
19
+ CONTAINER
20
+ ========================= */
21
+
22
+ .container {
23
+ width: 100%;
24
+ max-width: 1280px;
25
+ margin: auto;
26
+ padding: 0 24px;
27
+ }
28
+
29
+ /* =========================
30
+ NAVBAR
31
+ ========================= */
32
+
33
+ .navbar {
34
+ position: sticky;
35
+ top: 0;
36
+ z-index: 100;
37
+ background: rgba(2, 6, 23, .7);
38
+ backdrop-filter: blur(20px);
39
+ border-bottom: 1px solid rgba(255, 255, 255, .08);
40
+ }
41
+
42
+ .navbar-content {
43
+ height: 72px;
44
+ display: flex;
45
+ justify-content: space-between;
46
+ align-items: center;
47
+ }
48
+
49
+ .brand {
50
+ display: flex;
51
+ align-items: center;
52
+ gap: 12px;
53
+ }
54
+
55
+ .brand-icon {
56
+ width: 44px;
57
+ height: 44px;
58
+ border-radius: 14px;
59
+ background: var(--primary-gradient);
60
+ display: flex;
61
+ justify-content: center;
62
+ align-items: center;
63
+ color: white;
64
+ }
65
+
66
+ .brand-name {
67
+ font-size: 1.35rem;
68
+ font-weight: 700;
69
+ }
70
+
71
+ .navbar-actions {
72
+ display: flex;
73
+ gap: 12px;
74
+ }
75
+
76
+ .nav-link {
77
+ color: #cbd5e1;
78
+ text-decoration: none;
79
+ padding: 10px 18px;
80
+ transition: .3s;
81
+ }
82
+
83
+ .nav-link:hover {
84
+ color: white;
85
+ }
86
+
87
+ .nav-btn {
88
+ text-decoration: none;
89
+ background: var(--primary-gradient);
90
+ color: white;
91
+ padding: 10px 18px;
92
+ border-radius: 12px;
93
+ font-weight: 600;
94
+ transition: .3s;
95
+ }
96
+
97
+ .nav-btn:hover {
98
+ transform: translateY(-2px);
99
+ }
100
+
101
+ /* =========================
102
+ HERO
103
+ ========================= */
104
+
105
+ .hero {
106
+ padding: 100px 0;
107
+ }
108
+
109
+ .hero-grid {
110
+ display: grid;
111
+ grid-template-columns: 1.1fr 0.9fr;
112
+ gap: 60px;
113
+ align-items: center;
114
+ }
115
+
116
+ .hero-title {
117
+ line-height: 1.05;
118
+ margin-bottom: 24px;
119
+ }
120
+
121
+ .hero-title-gradient {
122
+ font-size: clamp(3rem, 8vw, 5.5rem);
123
+ font-weight: 800;
124
+ background: linear-gradient(to right,
125
+ #818cf8,
126
+ #a78bfa,
127
+ #f472b6);
128
+ -webkit-background-clip: text;
129
+ -webkit-text-fill-color: transparent;
130
+ }
131
+
132
+ .hero-title-white {
133
+ font-size: clamp(3rem, 8vw, 5rem);
134
+ font-weight: 800;
135
+ color: white;
136
+ }
137
+
138
+ .hero-description {
139
+ color: #94a3b8;
140
+ font-size: 1.2rem;
141
+ line-height: 1.8;
142
+ max-width: 650px;
143
+ margin-bottom: 40px;
144
+ }
145
+
146
+ .hero-actions {
147
+ display: flex;
148
+ gap: 16px;
149
+ }
150
+
151
+ .primary-btn {
152
+ text-decoration: none;
153
+ background: var(--primary-gradient);
154
+ color: white;
155
+ padding: 14px 26px;
156
+ border-radius: 14px;
157
+ font-weight: 600;
158
+ transition: .3s;
159
+ }
160
+
161
+ .primary-btn:hover {
162
+ transform: translateY(-3px);
163
+ }
164
+
165
+ .secondary-btn {
166
+ text-decoration: none;
167
+ color: white;
168
+ border: 1px solid rgba(255, 255, 255, .15);
169
+ padding: 14px 26px;
170
+ border-radius: 14px;
171
+ transition: .3s;
172
+ }
173
+
174
+ .secondary-btn:hover {
175
+ background: rgba(255, 255, 255, .05);
176
+ }
177
+
178
+ /* =========================
179
+ STATS
180
+ ========================= */
181
+
182
+ .stats-panel {
183
+ padding: 30px;
184
+ border-radius: 28px;
185
+ background: rgba(255, 255, 255, .04);
186
+ backdrop-filter: blur(20px);
187
+ border: 1px solid rgba(255, 255, 255, .08);
188
+
189
+ display: grid;
190
+ grid-template-columns: repeat(2, 1fr);
191
+ gap: 20px;
192
+ }
193
+
194
+ .stats-card {
195
+ background: rgba(15, 23, 42, .7);
196
+ border: 1px solid rgba(255, 255, 255, .06);
197
+ border-radius: 20px;
198
+ padding: 28px;
199
+ text-align: center;
200
+ transition: .3s;
201
+ }
202
+
203
+ .stats-card:hover {
204
+ transform: translateY(-4px);
205
+ }
206
+
207
+ .stats-card i {
208
+ color: #818cf8;
209
+ margin-bottom: 14px;
210
+ }
211
+
212
+ .stats-value {
213
+ color: white;
214
+ font-size: 2rem;
215
+ font-weight: 700;
216
+ }
217
+
218
+ .stats-label {
219
+ margin-top: 6px;
220
+ color: #94a3b8;
221
+ }
222
+
223
+ /* =========================
224
+ FEATURES
225
+ ========================= */
226
+
227
+ .features {
228
+ padding: 100px 0;
229
+ background: rgba(15, 23, 42, .4);
230
+ }
231
+
232
+ .section-header {
233
+ text-align: center;
234
+ margin-bottom: 70px;
235
+ }
236
+
237
+ .section-title {
238
+ color: white;
239
+ font-size: 3rem;
240
+ margin-bottom: 12px;
241
+ }
242
+
243
+ .section-description {
244
+ color: #94a3b8;
245
+ font-size: 1.15rem;
246
+ }
247
+
248
+ .feature-grid {
249
+ display: grid;
250
+ grid-template-columns: repeat(4, 1fr);
251
+ gap: 24px;
252
+ }
253
+
254
+ .feature-card {
255
+ background: rgba(15, 23, 42, .55);
256
+ backdrop-filter: blur(12px);
257
+ border: 1px solid rgba(255, 255, 255, .08);
258
+ border-radius: 24px;
259
+ padding: 30px;
260
+ transition: .3s;
261
+ }
262
+
263
+ .feature-card:hover {
264
+ transform: translateY(-5px);
265
+ border-color: rgba(255, 255, 255, .15);
266
+ }
267
+
268
+ .feature-icon {
269
+ width: 60px;
270
+ height: 60px;
271
+ border-radius: 18px;
272
+ background: var(--primary-gradient);
273
+ display: flex;
274
+ justify-content: center;
275
+ align-items: center;
276
+ color: white;
277
+ margin-bottom: 20px;
278
+ }
279
+
280
+ .feature-title {
281
+ color: white;
282
+ margin-bottom: 12px;
283
+ font-size: 1.2rem;
284
+ }
285
+
286
+ .feature-description {
287
+ color: #94a3b8;
288
+ line-height: 1.7;
289
+ }
290
+
291
+ /* =========================
292
+ FOOTER
293
+ ========================= */
294
+
295
+ .footer {
296
+ border-top: 1px solid rgba(255, 255, 255, .08);
297
+ padding: 40px 0;
298
+ text-align: center;
299
+ }
300
+
301
+ .footer p {
302
+ color: #94a3b8;
303
+ }
304
+
305
+ /* =========================
306
+ RESPONSIVE
307
+ ========================= */
308
+
309
+ @media (max-width: 992px) {
310
+
311
+ .hero-grid {
312
+ grid-template-columns: 1fr;
313
+ }
314
+
315
+ .feature-grid {
316
+ grid-template-columns: repeat(2, 1fr);
317
+ }
318
+ }
319
+
320
+ @media (max-width: 768px) {
321
+
322
+ .navbar-content {
323
+ flex-direction: column;
324
+ gap: 16px;
325
+ height: auto;
326
+ padding: 16px 0;
327
+ }
328
+
329
+ .hero {
330
+ padding: 60px 0;
331
+ }
332
+
333
+ .feature-grid,
334
+ .stats-panel {
335
+ grid-template-columns: 1fr;
336
+ }
337
+
338
+ .hero-actions {
339
+ flex-direction: column;
340
+ }
341
+
342
+ .section-title {
343
+ font-size: 2rem;
344
+ }
345
+ }
src/main/resources/templates/cms/auth/login.html CHANGED
@@ -5,13 +5,15 @@
5
  <meta charset="UTF-8">
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
  <title>Đăng Nhập - Face ID Attendance</title>
8
- <link rel="stylesheet" href="css/components.css">
 
 
9
  </head>
10
 
11
  <body>
12
  <div class="bg-img"></div>
13
 
14
- <div th:replace="~{cms/layouts/header :: header}"></div>
15
 
16
  <div class="layout">
17
  <div class="card">
@@ -22,7 +24,7 @@
22
  </div>
23
 
24
  <div class="divider"></div>
25
-
26
  <div class="card-body">
27
  <p class="error-message"></p>
28
 
@@ -50,11 +52,11 @@
50
 
51
  <hr style="margin: 1rem 0; opacity: 0.2;" />
52
  <div class="other-option">
53
- <a class="register-link">
54
  Tạo tài khoản mới
55
  </a>
56
 
57
- <a class="forgotPass-link">
58
  Quên mật khẩu
59
  </a>
60
  </div>
@@ -62,7 +64,7 @@
62
  </div>
63
  </div>
64
 
65
- <div th:replace="~{cms/layouts/footer :: footer}"></div>
66
 
67
  </body>
68
 
 
5
  <meta charset="UTF-8">
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
  <title>Đăng Nhập - Face ID Attendance</title>
8
+ <link rel="stylesheet" href="/css/auth.css">
9
+
10
+
11
  </head>
12
 
13
  <body>
14
  <div class="bg-img"></div>
15
 
16
+ <div th:replace="~{cms/layout/header :: header}"></div>
17
 
18
  <div class="layout">
19
  <div class="card">
 
24
  </div>
25
 
26
  <div class="divider"></div>
27
+
28
  <div class="card-body">
29
  <p class="error-message"></p>
30
 
 
52
 
53
  <hr style="margin: 1rem 0; opacity: 0.2;" />
54
  <div class="other-option">
55
+ <a href="#" class="register-link">
56
  Tạo tài khoản mới
57
  </a>
58
 
59
+ <a href="#" class="forgotPass-link">
60
  Quên mật khẩu
61
  </a>
62
  </div>
 
64
  </div>
65
  </div>
66
 
67
+ <div th:replace="~{cms/layout/footer :: footer}"></div>
68
 
69
  </body>
70
 
src/main/resources/templates/cms/homePage.html ADDED
@@ -0,0 +1,194 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="vi">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>Đăng Nhập - Face ID Attendance</title>
8
+ <link rel="stylesheet" href="/css/homePage.css">
9
+
10
+
11
+ </head>
12
+
13
+ <body>
14
+ <div class="bg-img"></div>
15
+
16
+
17
+ <div class="home-page">
18
+
19
+ <!-- Navigation -->
20
+ <header class="navbar">
21
+ <div class="container navbar-content">
22
+
23
+ <div class="brand">
24
+ <div class="brand-icon">
25
+ <i data-lucide="camera"></i>
26
+ </div>
27
+
28
+ <span class="brand-name">
29
+ Smart Attendance
30
+ </span>
31
+ </div>
32
+
33
+ <div class="navbar-actions">
34
+ <a href="/login" class="nav-link">
35
+ Đăng nhập
36
+ </a>
37
+
38
+ <a href="/register" class="nav-btn">
39
+ Bắt đầu ngay
40
+ </a>
41
+ </div>
42
+
43
+ </div>
44
+ </header>
45
+
46
+ <!-- Hero -->
47
+ <section class="hero">
48
+ <div class="container hero-grid">
49
+
50
+ <div class="hero-content">
51
+ <h1 class="hero-title">
52
+ <span class="hero-title-gradient">
53
+ SMART ATTENDANCE
54
+ </span>
55
+ <br>
56
+ <span class="hero-title-white">
57
+ SYSTEM
58
+ </span>
59
+ </h1>
60
+
61
+ <p class="hero-description">
62
+ Giải pháp điểm danh Face ID thông minh cho doanh nghiệp và cơ sở giáo dục.
63
+ Quản lý hiệu quả, chính xác và an toàn.
64
+ </p>
65
+
66
+ <div class="hero-actions">
67
+ <a href="/register" class="primary-btn">
68
+ Bắt đầu ngay
69
+ </a>
70
+
71
+ <a href="/login" class="secondary-btn">
72
+ Xem Demo
73
+ </a>
74
+ </div>
75
+ </div>
76
+
77
+ <div class="hero-stats">
78
+
79
+ <div class="stats-panel">
80
+
81
+ <div class="stats-card">
82
+ <i data-lucide="users"></i>
83
+ <div class="stats-value">5000+</div>
84
+ <div class="stats-label">Người dùng</div>
85
+ </div>
86
+
87
+ <div class="stats-card">
88
+ <i data-lucide="target"></i>
89
+ <div class="stats-value">99.8%</div>
90
+ <div class="stats-label">Độ chính xác</div>
91
+ </div>
92
+
93
+ <div class="stats-card">
94
+ <i data-lucide="building-2"></i>
95
+ <div class="stats-value">50+</div>
96
+ <div class="stats-label">Đơn vị</div>
97
+ </div>
98
+
99
+ <div class="stats-card">
100
+ <i data-lucide="clock"></i>
101
+ <div class="stats-value">24/7</div>
102
+ <div class="stats-label">Hoạt động</div>
103
+ </div>
104
+
105
+ </div>
106
+
107
+ </div>
108
+
109
+ </div>
110
+ </section>
111
+
112
+ <!-- Features -->
113
+ <section class="features">
114
+ <div class="container">
115
+
116
+ <div class="section-header">
117
+ <h2 class="section-title">
118
+ Tính năng nổi bật
119
+ </h2>
120
+
121
+ <p class="section-description">
122
+ Giải pháp toàn diện cho quản lý điểm danh
123
+ </p>
124
+ </div>
125
+
126
+ <div class="feature-grid">
127
+
128
+ <article class="feature-card">
129
+ <div class="feature-icon">
130
+ <i data-lucide="camera"></i>
131
+ </div>
132
+
133
+ <h3 class="feature-title">
134
+ Face Recognition
135
+ </h3>
136
+
137
+ <p class="feature-description">
138
+ Nhận diện khuôn mặt chính xác với AI, chống điểm danh hộ
139
+ </p>
140
+ </article>
141
+
142
+ <article class="feature-card">
143
+ <div class="feature-icon">
144
+ <i data-lucide="bar-chart-3"></i>
145
+ </div>
146
+
147
+ <h3 class="feature-title">
148
+ Analytics Dashboard
149
+ </h3>
150
+
151
+ <p class="feature-description">
152
+ Thống kê realtime, biểu đồ trực quan, báo cáo chi tiết
153
+ </p>
154
+ </article>
155
+
156
+ <article class="feature-card">
157
+ <div class="feature-icon">
158
+ <i data-lucide="file-text"></i>
159
+ </div>
160
+
161
+ <h3 class="feature-title">
162
+ Report Management
163
+ </h3>
164
+
165
+ <p class="feature-description">
166
+ Quản lý báo cáo công việc hằng ngày và cuối tuần
167
+ </p>
168
+ </article>
169
+
170
+ <article class="feature-card">
171
+ <div class="feature-icon">
172
+ <i data-lucide="calendar"></i>
173
+ </div>
174
+
175
+ <h3 class="feature-title">
176
+ Leave Management
177
+ </h3>
178
+
179
+ <p class="feature-description">
180
+ Xin nghỉ phép, duyệt đơn, theo dõi lịch sử nghỉ
181
+ </p>
182
+ </article>
183
+
184
+ </div>
185
+
186
+ </div>
187
+ </section>
188
+
189
+
190
+ <div th:replace="~{cms/layout/footer :: footer}"></div>
191
+
192
+ </body>
193
+
194
+ </html>
src/main/resources/templates/cms/layout/footer.html CHANGED
@@ -5,7 +5,7 @@
5
  <meta charset="UTF-8">
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
  <title>Đăng Ký - Face ID Attendance</title>
8
- <link rel="stylesheet" href="css/components.css">
9
  </head>
10
 
11
  <body>
 
5
  <meta charset="UTF-8">
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
  <title>Đăng Ký - Face ID Attendance</title>
8
+ <link rel="stylesheet" href="/css/layout/footer.css">
9
  </head>
10
 
11
  <body>
src/main/resources/templates/cms/layout/header.html CHANGED
@@ -1,15 +1,4 @@
1
- <!DOCTYPE html>
2
- <html lang="vi">
3
-
4
- <head>
5
- <meta charset="UTF-8">
6
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
- <title>Đăng Ký - Face ID Attendance</title>
8
- <link rel="stylesheet" href="css/auths/header.css">
9
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css">
10
- </head>
11
-
12
- <body>
13
  <header class="header-layout">
14
  <div class="header-container">
15
 
@@ -45,6 +34,3 @@
45
 
46
  </div>
47
  </header>
48
- </body>
49
-
50
- </html>
 
1
+
 
 
 
 
 
 
 
 
 
 
 
2
  <header class="header-layout">
3
  <div class="header-container">
4
 
 
34
 
35
  </div>
36
  </header>