Add 1 files
Browse files- index.html +97 -11
index.html
CHANGED
|
@@ -33,10 +33,33 @@
|
|
| 33 |
animation: fadeIn 0.3s ease-in-out;
|
| 34 |
}
|
| 35 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
@keyframes fadeIn {
|
| 37 |
from { opacity: 0; transform: translateY(-20px); }
|
| 38 |
to { opacity: 1; transform: translateY(0); }
|
| 39 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 40 |
</style>
|
| 41 |
</head>
|
| 42 |
<body>
|
|
@@ -57,11 +80,6 @@
|
|
| 57 |
</div>
|
| 58 |
</div>
|
| 59 |
</div>
|
| 60 |
-
<div class="hidden md:block">
|
| 61 |
-
<button onclick="openAdminPanel()" class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-md text-sm font-medium">
|
| 62 |
-
<i class="fas fa-user-shield ml-2"></i> پنل مدیریت
|
| 63 |
-
</button>
|
| 64 |
-
</div>
|
| 65 |
<div class="-mr-2 flex md:hidden">
|
| 66 |
<button type="button" class="inline-flex items-center justify-center p-2 rounded-md text-gray-700 hover:text-gray-900 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-blue-500" aria-controls="mobile-menu" aria-expanded="false">
|
| 67 |
<span class="sr-only">Open main menu</span>
|
|
@@ -332,6 +350,11 @@
|
|
| 332 |
</div>
|
| 333 |
</footer>
|
| 334 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 335 |
<!-- Admin Panel Modal -->
|
| 336 |
<div id="admin-modal" class="fixed inset-0 z-50 hidden overflow-y-auto">
|
| 337 |
<div class="flex items-center justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
|
|
@@ -542,7 +565,7 @@
|
|
| 542 |
استعلام قیمت BMW X6
|
| 543 |
</td>
|
| 544 |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
|
| 545 |
-
|
| 546 |
</td>
|
| 547 |
<td class="px-6 py-4 whitespace-nowrap">
|
| 548 |
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-yellow-100 text-yellow-800">
|
|
@@ -727,7 +750,7 @@
|
|
| 727 |
ورود به پنل مدیریت
|
| 728 |
</h3>
|
| 729 |
<div class="mt-4">
|
| 730 |
-
<form class="space-y-4">
|
| 731 |
<div>
|
| 732 |
<label for="username" class="block text-sm font-medium text-gray-700">نام کاربری</label>
|
| 733 |
<input type="text" id="username" class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500">
|
|
@@ -736,13 +759,15 @@
|
|
| 736 |
<label for="password" class="block text-sm font-medium text-gray-700">رمز عبور</label>
|
| 737 |
<input type="password" id="password" class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500">
|
| 738 |
</div>
|
|
|
|
|
|
|
| 739 |
</form>
|
| 740 |
</div>
|
| 741 |
</div>
|
| 742 |
</div>
|
| 743 |
</div>
|
| 744 |
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
|
| 745 |
-
<button type="button" onclick="login()" class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">
|
| 746 |
ورود
|
| 747 |
</button>
|
| 748 |
<button type="button" onclick="closeLoginModal()" class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">
|
|
@@ -824,10 +849,25 @@
|
|
| 824 |
}
|
| 825 |
];
|
| 826 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 827 |
// Load cars on page load
|
| 828 |
document.addEventListener('DOMContentLoaded', function() {
|
| 829 |
renderCars();
|
| 830 |
renderAdminCarsTable();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 831 |
});
|
| 832 |
|
| 833 |
// Render cars for main page
|
|
@@ -1001,22 +1041,68 @@
|
|
| 1001 |
// Login functions
|
| 1002 |
function openLoginModal() {
|
| 1003 |
document.getElementById('login-modal').classList.remove('hidden');
|
|
|
|
|
|
|
|
|
|
| 1004 |
}
|
| 1005 |
|
| 1006 |
function closeLoginModal() {
|
| 1007 |
document.getElementById('login-modal').classList.add('hidden');
|
|
|
|
|
|
|
|
|
|
| 1008 |
}
|
| 1009 |
|
| 1010 |
function login() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1011 |
const username = document.getElementById('username').value;
|
| 1012 |
const password = document.getElementById('password').value;
|
|
|
|
|
|
|
| 1013 |
|
| 1014 |
-
//
|
| 1015 |
-
if (username ===
|
|
|
|
| 1016 |
closeLoginModal();
|
| 1017 |
openAdminPanel();
|
|
|
|
| 1018 |
} else {
|
| 1019 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1020 |
}
|
| 1021 |
}
|
| 1022 |
</script>
|
|
|
|
| 33 |
animation: fadeIn 0.3s ease-in-out;
|
| 34 |
}
|
| 35 |
|
| 36 |
+
.hidden-admin-btn {
|
| 37 |
+
opacity: 0;
|
| 38 |
+
position: fixed;
|
| 39 |
+
bottom: 10px;
|
| 40 |
+
left: 10px;
|
| 41 |
+
z-index: 9999;
|
| 42 |
+
transition: opacity 0.3s;
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
.hidden-admin-btn:hover {
|
| 46 |
+
opacity: 1;
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
@keyframes fadeIn {
|
| 50 |
from { opacity: 0; transform: translateY(-20px); }
|
| 51 |
to { opacity: 1; transform: translateY(0); }
|
| 52 |
}
|
| 53 |
+
|
| 54 |
+
.shake {
|
| 55 |
+
animation: shake 0.5s;
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
@keyframes shake {
|
| 59 |
+
0%, 100% { transform: translateX(0); }
|
| 60 |
+
20%, 60% { transform: translateX(-5px); }
|
| 61 |
+
40%, 80% { transform: translateX(5px); }
|
| 62 |
+
}
|
| 63 |
</style>
|
| 64 |
</head>
|
| 65 |
<body>
|
|
|
|
| 80 |
</div>
|
| 81 |
</div>
|
| 82 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 83 |
<div class="-mr-2 flex md:hidden">
|
| 84 |
<button type="button" class="inline-flex items-center justify-center p-2 rounded-md text-gray-700 hover:text-gray-900 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-blue-500" aria-controls="mobile-menu" aria-expanded="false">
|
| 85 |
<span class="sr-only">Open main menu</span>
|
|
|
|
| 350 |
</div>
|
| 351 |
</footer>
|
| 352 |
|
| 353 |
+
<!-- Hidden Admin Button (Only visible to you) -->
|
| 354 |
+
<button id="hidden-admin-btn" class="hidden-admin-btn bg-blue-600 hover:bg-blue-700 text-white p-3 rounded-full shadow-lg">
|
| 355 |
+
<i class="fas fa-user-shield"></i>
|
| 356 |
+
</button>
|
| 357 |
+
|
| 358 |
<!-- Admin Panel Modal -->
|
| 359 |
<div id="admin-modal" class="fixed inset-0 z-50 hidden overflow-y-auto">
|
| 360 |
<div class="flex items-center justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
|
|
|
|
| 565 |
استعلام قیمت BMW X6
|
| 566 |
</td>
|
| 567 |
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
|
| 568 |
+
۱۴۰۲/۰۵/۱۰
|
| 569 |
</td>
|
| 570 |
<td class="px-6 py-4 whitespace-nowrap">
|
| 571 |
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-yellow-100 text-yellow-800">
|
|
|
|
| 750 |
ورود به پنل مدیریت
|
| 751 |
</h3>
|
| 752 |
<div class="mt-4">
|
| 753 |
+
<form id="login-form" class="space-y-4">
|
| 754 |
<div>
|
| 755 |
<label for="username" class="block text-sm font-medium text-gray-700">نام کاربری</label>
|
| 756 |
<input type="text" id="username" class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500">
|
|
|
|
| 759 |
<label for="password" class="block text-sm font-medium text-gray-700">رمز عبور</label>
|
| 760 |
<input type="password" id="password" class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500">
|
| 761 |
</div>
|
| 762 |
+
<div id="login-error" class="hidden text-red-600 text-sm"></div>
|
| 763 |
+
<div id="login-attempts" class="hidden text-yellow-600 text-sm"></div>
|
| 764 |
</form>
|
| 765 |
</div>
|
| 766 |
</div>
|
| 767 |
</div>
|
| 768 |
</div>
|
| 769 |
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
|
| 770 |
+
<button type="button" onclick="login()" id="login-btn" class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">
|
| 771 |
ورود
|
| 772 |
</button>
|
| 773 |
<button type="button" onclick="closeLoginModal()" class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">
|
|
|
|
| 849 |
}
|
| 850 |
];
|
| 851 |
|
| 852 |
+
// Admin credentials (in a real app, this would be stored securely on the server)
|
| 853 |
+
const ADMIN_CREDENTIALS = {
|
| 854 |
+
username: "admin",
|
| 855 |
+
password: "AutoGallery2000@1402" // Strong password
|
| 856 |
+
};
|
| 857 |
+
|
| 858 |
+
let loginAttempts = 0;
|
| 859 |
+
const MAX_LOGIN_ATTEMPTS = 3;
|
| 860 |
+
let loginBlocked = false;
|
| 861 |
+
|
| 862 |
// Load cars on page load
|
| 863 |
document.addEventListener('DOMContentLoaded', function() {
|
| 864 |
renderCars();
|
| 865 |
renderAdminCarsTable();
|
| 866 |
+
|
| 867 |
+
// Setup hidden admin button
|
| 868 |
+
document.getElementById('hidden-admin-btn').addEventListener('click', function() {
|
| 869 |
+
openLoginModal();
|
| 870 |
+
});
|
| 871 |
});
|
| 872 |
|
| 873 |
// Render cars for main page
|
|
|
|
| 1041 |
// Login functions
|
| 1042 |
function openLoginModal() {
|
| 1043 |
document.getElementById('login-modal').classList.remove('hidden');
|
| 1044 |
+
document.getElementById('login-form').reset();
|
| 1045 |
+
document.getElementById('login-error').classList.add('hidden');
|
| 1046 |
+
document.getElementById('login-attempts').classList.add('hidden');
|
| 1047 |
}
|
| 1048 |
|
| 1049 |
function closeLoginModal() {
|
| 1050 |
document.getElementById('login-modal').classList.add('hidden');
|
| 1051 |
+
document.getElementById('login-form').reset();
|
| 1052 |
+
document.getElementById('login-error').classList.add('hidden');
|
| 1053 |
+
document.getElementById('login-attempts').classList.add('hidden');
|
| 1054 |
}
|
| 1055 |
|
| 1056 |
function login() {
|
| 1057 |
+
if (loginBlocked) {
|
| 1058 |
+
alert('سیستم به دلیل ورود ناموفق متعدد قفل شده است. لطفاً بعداً تلاش کنید.');
|
| 1059 |
+
return;
|
| 1060 |
+
}
|
| 1061 |
+
|
| 1062 |
const username = document.getElementById('username').value;
|
| 1063 |
const password = document.getElementById('password').value;
|
| 1064 |
+
const errorElement = document.getElementById('login-error');
|
| 1065 |
+
const attemptsElement = document.getElementById('login-attempts');
|
| 1066 |
|
| 1067 |
+
// Validate credentials
|
| 1068 |
+
if (username === ADMIN_CREDENTIALS.username && password === ADMIN_CREDENTIALS.password) {
|
| 1069 |
+
// Successful login
|
| 1070 |
closeLoginModal();
|
| 1071 |
openAdminPanel();
|
| 1072 |
+
loginAttempts = 0; // Reset attempts
|
| 1073 |
} else {
|
| 1074 |
+
// Failed login
|
| 1075 |
+
loginAttempts++;
|
| 1076 |
+
|
| 1077 |
+
if (loginAttempts >= MAX_LOGIN_ATTEMPTS) {
|
| 1078 |
+
// Block login after max attempts
|
| 1079 |
+
loginBlocked = true;
|
| 1080 |
+
document.getElementById('login-btn').disabled = true;
|
| 1081 |
+
attemptsElement.textContent = `سیستم به دلیل ${MAX_LOGIN_ATTEMPTS} بار ورود ناموفق قفل شد. لطفاً بعداً تلاش کنید.`;
|
| 1082 |
+
attemptsElement.classList.remove('hidden');
|
| 1083 |
+
|
| 1084 |
+
// Unlock after 5 minutes
|
| 1085 |
+
setTimeout(() => {
|
| 1086 |
+
loginBlocked = false;
|
| 1087 |
+
loginAttempts = 0;
|
| 1088 |
+
document.getElementById('login-btn').disabled = false;
|
| 1089 |
+
attemptsElement.classList.add('hidden');
|
| 1090 |
+
}, 5 * 60 * 1000);
|
| 1091 |
+
} else {
|
| 1092 |
+
// Show error message
|
| 1093 |
+
errorElement.textContent = 'نام کاربری یا رمز عبور اشتباه است!';
|
| 1094 |
+
errorElement.classList.remove('hidden');
|
| 1095 |
+
|
| 1096 |
+
// Show remaining attempts
|
| 1097 |
+
attemptsElement.textContent = `تعداد تلاش های باقیمانده: ${MAX_LOGIN_ATTEMPTS - loginAttempts}`;
|
| 1098 |
+
attemptsElement.classList.remove('hidden');
|
| 1099 |
+
|
| 1100 |
+
// Shake effect
|
| 1101 |
+
document.getElementById('login-form').classList.add('shake');
|
| 1102 |
+
setTimeout(() => {
|
| 1103 |
+
document.getElementById('login-form').classList.remove('shake');
|
| 1104 |
+
}, 500);
|
| 1105 |
+
}
|
| 1106 |
}
|
| 1107 |
}
|
| 1108 |
</script>
|