@ -13,355 +13,51 @@
<!-- Google Fonts -->
< link rel = "preconnect" href = "https://fonts.googleapis.com" >
< link rel = "preconnect" href = "https://fonts.gstatic.com" crossorigin >
< link href = "https://fonts.googleapis.com/css2?family=Outfit:wght@400;500;600;700;800&family=Poppins:wght@300;400;500;600;700&display=swap" rel = "stylesheet" >
< link
href="https://fonts.googleapis.com/css2?family=Outfit:wght@400;500;600;700;800&family=Poppins:wght@300; 400;500;600;700& display=swap"
rel="stylesheet">
<!-- Bootstrap CSS -->
< link rel = "stylesheet" th:href = "@{/assets/bootstrap-5.3.2/css/bootstrap.min.css}" type = "text/css " >
<!-- Include CSS -->
< link rel = "stylesheet" type = "text/css" th:href = "@{/assets/css/login-form-styles.css} " >
<!-- Awesome Font -->
< link th:href = "@{/assets/font-awesome-6.5.2/css/all.min.css}" rel = "stylesheet" type = "text/css" >
< style >
:root {
--primary-brand: #0d4b68;
--primary-dark: #072e41;
--accent-cyan: #06b6d4;
--accent-amber: #f59e0b;
--gradient-bg: linear-gradient(135deg, #072e41 0%, #0d4b68 50%, #155e75 100%);
--card-bg: rgba(255, 255, 255, 0.96);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Poppins', sans-serif;
background: var(--gradient-bg);
min-height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 20px;
position: relative;
overflow-x: hidden;
}
/* Decorative ambient glow circles */
.ambient-glow {
position: absolute;
border-radius: 50%;
filter: blur(80px);
opacity: 0.25;
pointer-events: none;
z-index: 0;
}
.glow-1 {
width: 350px;
height: 350px;
background: #06b6d4;
top: -50px;
left: -50px;
}
.glow-2 {
width: 400px;
height: 400px;
background: #f59e0b;
bottom: -80px;
right: -80px;
}
.login-card {
position: relative;
z-index: 1;
width: 100%;
max-width: 460px;
background: var(--card-bg);
backdrop-filter: blur(12px);
border-radius: 24px;
padding: 40px 36px;
box-shadow: 0 20px 50px rgba(0, 0, 0, 0.3), 0 0 0 1px rgba(255, 255, 255, 0.2);
animation: slideUp 0.6s cubic-bezier(0.16, 1, 0.3, 1);
}
@keyframes slideUp {
from {
opacity: 0;
transform: translateY(25px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.header-branding {
text-align: center;
margin-bottom: 28px;
}
.logo-wrap {
width: 84px;
height: 84px;
margin: 0 auto 16px;
border-radius: 20px;
background: #ffffff;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 8px 20px rgba(13, 75, 104, 0.15);
padding: 10px;
transition: transform 0.3s ease;
}
.logo-wrap:hover {
transform: scale(1.05) rotate(2deg);
}
.logo-wrap img {
max-width: 100%;
max-height: 100%;
object-fit: contain;
}
.brand-title-en {
font-family: 'Outfit', sans-serif;
font-size: 1.15rem;
font-weight: 800;
letter-spacing: 0.8px;
color: #0d4b68;
text-transform: uppercase;
margin-bottom: 2px;
}
.brand-title-ta {
font-size: 0.82rem;
color: #475569;
font-weight: 600;
margin-bottom: 12px;
}
.badge-module {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 6px 14px;
background: linear-gradient(135deg, #e0f2fe, #e2e8f0);
color: #0369a1;
border: 1px solid #bae6fd;
border-radius: 30px;
font-size: 0.78rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.badge-module i {
color: #0284c7;
}
.form-title {
font-family: 'Outfit', sans-serif;
font-size: 1.4rem;
font-weight: 700;
color: #0f172a;
margin: 18px 0 6px;
text-align: center;
}
.form-subtitle {
font-size: 0.85rem;
color: #64748b;
text-align: center;
margin-bottom: 24px;
}
.form-floating-custom {
position: relative;
margin-bottom: 20px;
}
.form-floating-custom .input-icon {
position: absolute;
left: 16px;
top: 50%;
transform: translateY(-50%);
color: #94a3b8;
font-size: 1.1rem;
transition: color 0.3s ease;
pointer-events: none;
}
.form-floating-custom input {
width: 100%;
height: 52px;
padding: 12px 16px 12px 46px;
font-size: 0.92rem;
color: #1e293b;
background: #f8fafc;
border: 1.5px solid #e2e8f0;
border-radius: 12px;
outline: none;
transition: all 0.3s ease;
}
.form-floating-custom input:focus {
background: #ffffff;
border-color: #0284c7;
box-shadow: 0 0 0 4px rgba(2, 132, 199, 0.12);
}
.form-floating-custom input:focus + .input-icon {
color: #0284c7;
}
.btn-submit {
width: 100%;
height: 52px;
background: linear-gradient(135deg, #0d4b68 0%, #0284c7 100%);
color: #ffffff;
border: none;
border-radius: 12px;
font-family: 'Outfit', sans-serif;
font-size: 1rem;
font-weight: 700;
letter-spacing: 0.5px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
transition: all 0.3s ease;
box-shadow: 0 8px 20px rgba(13, 75, 104, 0.25);
margin-top: 10px;
}
.btn-submit:hover:not(:disabled) {
background: linear-gradient(135deg, #093448 0%, #0369a1 100%);
box-shadow: 0 12px 25px rgba(13, 75, 104, 0.35);
transform: translateY(-2px);
}
.btn-submit:disabled {
opacity: 0.7;
cursor: not-allowed;
}
#error-box {
background: #fef2f2;
border: 1px solid #fecaca;
color: #b91c1c;
padding: 12px 16px;
border-radius: 10px;
font-size: 0.84rem;
font-weight: 500;
margin-bottom: 20px;
display: none;
align-items: center;
gap: 10px;
animation: shake 0.4s ease;
}
@keyframes shake {
0%, 100% { transform: translateX(0); }
25% { transform: translateX(-5px); }
75% { transform: translateX(5px); }
}
.system-badge-footer {
margin-top: 25px;
text-align: center;
font-size: 0.76rem;
color: #94a3b8;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
}
.system-badge-footer span {
display: inline-block;
width: 6px;
height: 6px;
background: #22c55e;
border-radius: 50%;
box-shadow: 0 0 8px #22c55e;
}
.back-portal-link {
display: block;
text-align: center;
margin-top: 18px;
color: #0284c7;
text-decoration: none;
font-size: 0.85rem;
font-weight: 600;
transition: color 0.2s;
}
.back-portal-link:hover {
color: #0369a1;
text-decoration: underline;
}
< / style >
< / head >
< body >
< div class = "ambient-glow glow-1" > < / div >
< div class = "ambient-glow glow-2" > < / div >
< div class = "login-card" >
< div class = "header-branding" >
< div class = "logo-wrap" >
< img th:src = "@{/assets/header-images/gcc1.png}" alt = "Greater Chennai Corporation Logo" >
< / div >
< h2 class = "brand-title-en" > Greater Chennai Corporation< / h2 >
< p class = "brand-title-ta" > பெருநகர சென்னை மாநகராட்சி< / p >
< div class = "badge-module" >
< i class = "fa-solid fa-boxes-packing" > < / i >
< span > Rental Management System< / span >
< / div >
< div class = "container" >
< img th:src = "@{/assets/header-images/gcc1.png}" alt = "Greater Chennai Corporation" class = "small-logo" >
< h3 > GREATER CHENNAI CORPORATION< / h3 >
< h4 > பெருநகர சென்னை மாநகராட்சி< / h4 >
< br >
< h2 > GCC IT Cell Rental Management System< / h2 >
< br >
< h2 > Login< / h2 >
< div id = "error-box"
style="color: #c0392b; font-weight: 500; font-size: 0.85rem; margin-bottom: 1.5rem; text-align: center; display: none;">
< i class = "fa-solid fa-circle-exclamation" > < / i > < span id = "error-text" > Invalid username or password!< / span >
< / div >
< h3 class = "form-title" > Portal Sign In< / h3 >
< p class = "form-subtitle" > Work Orders • Requests • Challans • Issue & Return< / p >
< div id = "error-box" >
< i class = "fa-solid fa-circle-exclamation fs-5" > < / i >
< span id = "error-text" > Invalid username or password!< / span >
< / div >
< form id = "rentalLoginForm" onsubmit = "handleRentalLogin(event)" >
< div class = "form-floating-custom" >
< input type = "text" name = "usrName" id = "usrName" placeholder = "Enter Username / Employee ID" required autocomplete = "username" >
< i class = "fa-solid fa-user input-icon" > < / i >
< form id = "loginForm" onsubmit = "handleRentalLogin(event)" >
< div class = "input-field" >
< input type = "text" name = "usrName" id = "usrName" placeholder = "Enter Username" required
autocomplete="username">
< div class = "underline" > < / div >
< / div >
< div class = "form-floating-custom" >
< input type = "password" name = "usrPass" id = "usrPass" placeholder = "Enter Password" required autocomplete = "current-password" >
< i class = "fa-solid fa-lock input-icon " > < / i >
< div class = "input-field" >
< input type = "password" name = "usrPass" id = "usrPass" placeholder = "Enter Password" required
autocomplete="current-password">
< div class = "underline" > < / div >
< / div >
< button type = "submit" id = "submit-btn" class = "btn-submit" >
< span > Sign In to Rental System< / span >
< i class = "fa-solid fa-arrow-right-to-bracket" > < / i >
< / button >
< input type = "submit" value = "Login" id = "submit-btn" >
< / form >
< a th:href = "@{/}" class = "back-portal-link" >
< i class = "fa-solid fa-arrow-left me-1" > < / i > Return to Main GCC Home
< / a >
< div class = "system-badge-footer" >
< span > < / span >
< span > GCC IT Cell Secured System • Active Version 2.0< / span >
< / div >
< / div >
<!-- Footer Fragment -->
< th:block th:replace = "~{fragments/footer :: footer}" > < / th:block >
<!-- Custom JS -->
< script th:inline = "javascript" >
const contextPath = /*[[@{/}]]*/ '/';
@ -377,7 +73,7 @@
errorBox.style.display = "none";
submitBtn.disabled = true;
submitBtn.innerHTML = '< i class = "fa-solid fa-circle-notch fa-spin" > < / i > Authenticating...';
submitBtn.value = ' Authenticating...';
const username = document.getElementById("usrName").value.trim();
const password = document.getElementById("usrPass").value;
@ -386,6 +82,8 @@
urlParams.append('usrName', username);
urlParams.append('usrPass', password);
console.log(username, password);
// Fetch CSRF tokens if available
const csrfToken = document.querySelector("meta[name='_csrf']")?.getAttribute("content");
const csrfHeader = document.querySelector("meta[name='_csrf_header']")?.getAttribute("content");
@ -402,28 +100,29 @@
headers: headers,
body: urlParams
})
.then(response => response.json())
.then(data => {
if (data.result) {
sessionStorage.setItem("rental_usrName", data.usrName);
sessionStorage.setItem("rental_usrRole", data.usrRole || "USER");
window.location.href = contextPath + 'gccrentalmanagement/dashboard';
} else {
.then(response => response.json())
.then(data => {
console.log(data);
if (data.result) {
sessionStorage.setItem("rental_usrName", data.usrName);
sessionStorage.setItem("rental_usrRole", data.usrRole || "USER");
window.location.href = contextPath + 'gccrentalmanagement/dashboard';
} else {
submitBtn.disabled = false;
submitBtn.value = 'Login';
errorText.textContent = data.error || "Authentication failed.";
errorBox.style.display = "block";
}
})
.catch(err => {
console.error("Login Error:", err);
submitBtn.disabled = false;
submitBtn.innerHTML = '< span > Sign In to Rental System< / span > < i class = "fa-solid fa-arrow-right-to-bracket" > < / i > ';
errorText.textContent = data.error || "Authentication failed. Check your username and password.";
errorBox.style.display = "flex";
}
})
.catch(err => {
console.error("Login Error:", err);
submitBtn.disabled = false;
submitBtn.innerHTML = '< span > Sign In to Rental System< / span > < i class = "fa-solid fa-arrow-right-to-bracket" > < / i > ';
errorText.textContent = "Network error. Please try again later.";
errorBox.style.display = "flex";
});
submitBtn.value = 'Login';
errorText.textContent = "Network error. Please try again later.";
errorBox.style.display = "block";
});
}
< / script >
< / body >
< / html >
< / html >