diff options
| -rw-r--r-- | index.html | 1 | ||||
| -rw-r--r-- | src/index.css | 32 | ||||
| -rw-r--r-- | src/main.tsx | 1 | ||||
| -rw-r--r-- | src/pages/Home.tsx | 58 | ||||
| -rw-r--r-- | src/pages/Stop.tsx | 26 |
5 files changed, 79 insertions, 39 deletions
@@ -7,6 +7,7 @@ <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="manifest" href="/manifest.webmanifest" /> + <link rel="stylesheet" href="https://cdn.simplecss.org/simple.min.css"> <title>UrbanoVigo Web</title> </head> diff --git a/src/index.css b/src/index.css deleted file mode 100644 index 29b518f..0000000 --- a/src/index.css +++ /dev/null @@ -1,32 +0,0 @@ -:root { - font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; - line-height: 1.5; - font-weight: 400; - - color-scheme: light dark; - - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -body { - display: flex; - flex-direction: column; - place-items: center; - - margin: 0; - min-width: 320px; - min-height: 100vh; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} - -a:hover { - color: #535bf2; -}
\ No newline at end of file diff --git a/src/main.tsx b/src/main.tsx index 590bb08..f638946 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,6 +1,5 @@ import { StrictMode } from 'react' import { createRoot } from 'react-dom/client' -import './index.css' import { createBrowserRouter, RouterProvider } from 'react-router-dom' import { Home } from './pages/Home.tsx' import { Stop } from './pages/Stop.tsx' diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx index 79f1ec2..14d5d7a 100644 --- a/src/pages/Home.tsx +++ b/src/pages/Home.tsx @@ -1,3 +1,4 @@ +import { useNavigate } from "react-router-dom"; import useSWR from "swr"; interface Stop { @@ -8,12 +9,50 @@ interface Stop { lines: string[]; } +interface CachedStopList { + timetsamp: number; + data: Stop[]; +} + export function Home() { + const navigate = useNavigate() const { data, error, isLoading } = useSWR<Stop[]>('home', async () => { + const cachedData = localStorage.getItem('cachedStopList') + if (cachedData) { + const parsedData: CachedStopList = JSON.parse(cachedData) + + // Cache for 12 hours + if (Date.now() - parsedData.timetsamp < 1000 * 60 * 60 * 12) { + console.log("parsed data: ", parsedData.data) + return parsedData.data + } else { + localStorage.removeItem('cachedStopList') + } + } + const response = await fetch('/api/ListStops') - return response.json() + const body = await response.json(); + + localStorage.setItem('cachedStopList', JSON.stringify({ + timestamp: Date.now(), + data: body + })); + + return body; }); + const handleStopSearch = async (event: React.FormEvent) => { + event.preventDefault() + + const stopId = (event.target as HTMLFormElement).stopId.value + const searchNumber = parseInt(stopId) + if (data?.find(stop => stop.stopId === searchNumber)) { + navigate(`/${searchNumber}`) + } else { + alert("Parada no encontrada") + } + } + if (isLoading) return <h1>Loading...</h1> if (error) return <h1>Error</h1> @@ -21,10 +60,23 @@ export function Home() { <> <h1>Home</h1> + <form action="none" onSubmit={handleStopSearch}> + <div> + <label htmlFor="stopId"> + ID + </label> + <input type="number" placeholder="ID de parada" id="stopId" /> + </div> + + <button type="submit">Buscar</button> + </form> + <ul> - {data?.map((stop: Stop) => ( + {data?.sort((a, b) => a.stopId - b.stopId).map((stop: Stop) => ( <li key={stop.stopId}> - {stop.name} - {stop.lines?.join(', ')} + <a href={`/${stop.stopId}`}> + ({stop.stopId}) {stop.name} - {stop.lines?.join(', ')} + </a> </li> ))} </ul> diff --git a/src/pages/Stop.tsx b/src/pages/Stop.tsx index 2ee077c..33f1a31 100644 --- a/src/pages/Stop.tsx +++ b/src/pages/Stop.tsx @@ -19,7 +19,7 @@ interface StopDetails { export function Stop(): JSX.Element { const params = useParams(); - const { data, error, isLoading } = useSWR<StopDetails>('home', async () => { + const { data, error, isLoading } = useSWR<StopDetails>(`stop-${params.stopId}`, async () => { let response; try { @@ -31,6 +31,15 @@ export function Stop(): JSX.Element { } }); + const absoluteArrivalTime = (minutes: number) => { + const now = new Date() + const arrival = new Date(now.getTime() + minutes * 60000) + return Intl.DateTimeFormat(navigator.language, { + hour: '2-digit', + minute: '2-digit' + }).format(arrival) + } + if (isLoading) return <h1>Loading...</h1> if (error) return <h1>Error: {JSON.stringify(error)}</h1> if (data === undefined) return <h1>No data</h1> @@ -58,12 +67,23 @@ export function Stop(): JSX.Element { <tr key={idx}> <td>{estimate.line}</td> <td>{estimate.route}</td> - <td>{estimate.minutes}</td> - <td>{estimate.meters}</td> + <td> + {estimate.minutes} ({absoluteArrivalTime(estimate.minutes)}) + </td> + <td> + {estimate.meters > -1 + ? `${estimate.meters} metros` + : "No disponible" + } + </td> </tr> ))} </tbody> </table> + + <p> + <a href="/">Volver al inicio</a> + </p> </> ) } |
