Spaces:
Running
Running
| <html lang="fa" dir="rtl"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>سامانه اطلاعات اتوبوس</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link href="https://fonts.googleapis.com/css2?family=Vazirmatn:wght@300;400;500;700&display=swap" rel="stylesheet"> | |
| <script src="https://cdn.jsdelivr.net/npm/moment-jalaali@0.9.2/build/moment-jalaali.js"></script> | |
| <style> | |
| body { | |
| font-family: 'Vazirmatn', sans-serif; | |
| background: linear-gradient(45deg, #3490dc, #6574cd, #9561e2, #f66d9b); | |
| background-size: 400% 400%; | |
| animation: gradientBG 15s ease infinite; | |
| } | |
| @keyframes gradientBG { | |
| 0% { background-position: 0% 50%; } | |
| 50% { background-position: 100% 50%; } | |
| 100% { background-position: 0% 50%; } | |
| } | |
| .glass { | |
| background: rgba(255, 255, 255, 0.25); | |
| box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37); | |
| backdrop-filter: blur(4px); | |
| -webkit-backdrop-filter: blur(4px); | |
| border-radius: 10px; | |
| border: 1px solid rgba(255, 255, 255, 0.18); | |
| } | |
| .loading { | |
| width: 50px; | |
| height: 50px; | |
| border: 5px solid #f3f3f3; | |
| border-top: 5px solid #3498db; | |
| border-radius: 50%; | |
| animation: spin 1s linear infinite; | |
| } | |
| @keyframes spin { | |
| 0% { transform: rotate(0deg); } | |
| 100% { transform: rotate(360deg); } | |
| } | |
| .bus-icon { | |
| animation: drive 5s linear infinite; | |
| } | |
| @keyframes drive { | |
| 0% { transform: translateX(-100%); } | |
| 100% { transform: translateX(100%); } | |
| } | |
| </style> | |
| </head> | |
| <body class="min-h-screen flex flex-col"> | |
| <header class="glass text-white p-4 mb-8"> | |
| <div class="container mx-auto flex justify-between items-center"> | |
| <h1 class="text-2xl font-bold">سامانه اطلاعات اتوبوس</h1> | |
| <div id="clock" class="text-xl font-semibold"></div> | |
| </div> | |
| </header> | |
| <main class="flex-grow container mx-auto px-4 py-8"> | |
| <div class="glass p-6 mb-8 max-w-3xl mx-auto"> | |
| <form id="search-form" class="mb-4"> | |
| <div class="flex flex-col sm:flex-row"> | |
| <input type="text" id="station-id" class="flex-grow px-4 py-2 rounded-lg sm:rounded-l-none border-2 border-blue-500 focus:outline-none focus:border-blue-600 mb-2 sm:mb-0" placeholder="کد ایستگاه را وارد کنید" required> | |
| <button type="submit" class="px-6 py-2 bg-blue-500 text-white rounded-lg sm:rounded-r-lg hover:bg-blue-600 transition-colors duration-200">جستجو</button> | |
| </div> | |
| </form> | |
| <div id="error" class="text-red-500"></div> | |
| <div class="relative overflow-hidden h-8"> | |
| <svg class="bus-icon h-8 w-8 text-blue-500 absolute" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7v8a2 2 0 002 2h6M8 7V5a2 2 0 012-2h4a2 2 0 012 2v2M8 7H6a2 2 0 00-2 2v9a2 2 0 002 2h12a2 2 0 002-2V9a2 2 0 00-2-2h-2M9 7h6" /> | |
| </svg> | |
| </div> | |
| </div> | |
| <div id="loading" class="hidden flex justify-center items-center mb-4"> | |
| <div class="loading"></div> | |
| </div> | |
| <div id="result" class="glass p-6 max-w-3xl mx-auto"></div> | |
| </main> | |
| <footer class="glass text-white p-4 mt-8"> | |
| <div class="container mx-auto text-center"> | |
| <p>© ۱۴۰۳ سامانه اطلاعات اتوبوس. تمامی حقوق محفوظ است.</p> | |
| </div> | |
| </footer> | |
| <script> | |
| const form = document.getElementById('search-form'); | |
| const stationIdInput = document.getElementById('station-id'); | |
| const errorDiv = document.getElementById('error'); | |
| const resultDiv = document.getElementById('result'); | |
| const loadingDiv = document.getElementById('loading'); | |
| const clockDiv = document.getElementById('clock'); | |
| form.addEventListener('submit', async (e) => { | |
| e.preventDefault(); | |
| const stationId = stationIdInput.value.trim(); | |
| if (!stationId) { | |
| showError('لطفاً کد ایستگاه را وارد کنید.'); | |
| return; | |
| } | |
| try { | |
| showLoading(); | |
| const data = await fetchStationData(stationId); | |
| hideLoading(); | |
| showResult(data); | |
| } catch (error) { | |
| hideLoading(); | |
| showError('خطایی در دریافت اطلاعات رخ داد. لطفاً دوباره تلاش کنید.'); | |
| } | |
| }); | |
| function showError(message) { | |
| errorDiv.textContent = message; | |
| resultDiv.innerHTML = ''; | |
| } | |
| function showLoading() { | |
| loadingDiv.classList.remove('hidden'); | |
| resultDiv.innerHTML = ''; | |
| } | |
| function hideLoading() { | |
| loadingDiv.classList.add('hidden'); | |
| } | |
| function showResult(data) { | |
| errorDiv.textContent = ''; | |
| let html = '<h2 class="text-xl font-semibold mb-4">اطلاعات ایستگاه</h2>'; | |
| html += '<div class="overflow-x-auto"><table class="w-full table-auto">'; | |
| html += '<thead><tr class="bg-blue-100"><th class="px-4 py-2">مسیر</th><th class="px-4 py-2">اطلاعات</th></tr></thead><tbody>'; | |
| data.forEach((item, index) => { | |
| html += `<tr class="${index % 2 === 0 ? 'bg-white' : 'bg-blue-50'}">`; | |
| html += `<td class="border px-4 py-2 font-semibold">مسیر ${item.route_code}</td>`; | |
| html += `<td class="border px-4 py-2"> | |
| <p><span class="font-medium">زمان تقریبی رسیدن:</span> ${item.eta}</p> | |
| <p><span class="font-medium">مقصد:</span> ${item.destination_name}</p> | |
| <p><span class="font-medium">اتوبوس:</span> ${item.bus}</p> | |
| <p><span class="font-medium">نوع:</span> ${item.route_type}</p> | |
| </td>`; | |
| html += '</tr>'; | |
| }); | |
| html += '</tbody></table></div>'; | |
| resultDiv.innerHTML = html; | |
| } | |
| function updateClock() { | |
| const now = moment(); | |
| const jalaliDate = now.format('jYYYY/jMM/jDD'); | |
| const time = now.format('HH:mm:ss'); | |
| clockDiv.textContent = `${jalaliDate} ${time}`; | |
| } | |
| setInterval(updateClock, 1000); | |
| updateClock(); | |
| async function fetchStationData(stationId) { | |
| const response = await fetch(`http://server1.ththt.ir:9204/api/update_eta/${stationId}`); | |
| if (!response.ok) { | |
| throw new Error('Network response was not ok'); | |
| } | |
| return await response.json(); | |
| } | |
| </script> | |
| </body> | |
| </html> |