Skip to content

Commit 39c0195

Browse files
committed
Revert "store data client side"
This reverts commit eabfa53.
1 parent eabfa53 commit 39c0195

File tree

3 files changed

+78
-57
lines changed

3 files changed

+78
-57
lines changed

src/app/hk-tunnels-tolls/data/tolls.json renamed to public/api/hk-tunnels-tolls/tolls.json

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"version": "0.4.0",
2+
"version": "0.3.7",
33
"tunnels": {
44
"western": {
55
"name": "西隧",
@@ -278,20 +278,27 @@
278278
"vehicleTypes": {
279279
"privateCar": {
280280
"name": "私家車",
281-
"hasTimeVaryingToll": true
281+
"hasTimeVaryingToll": true,
282+
"fixedTolls": {
283+
"tates_cairn": 20
284+
}
282285
},
283286
"motorcycle": {
284287
"name": "電單車",
285288
"hasTimeVaryingToll": true,
286-
"multiplier": 0.4
289+
"multiplier": 0.4,
290+
"fixedTolls": {
291+
"tates_cairn": 15
292+
}
287293
},
288294
"taxi": {
289295
"name": "的士",
290296
"hasTimeVaryingToll": false,
291297
"fixedTolls": {
292298
"western": 25,
293299
"cross_eastern": 25,
294-
"tai_lam": 28
300+
"tai_lam": 28,
301+
"tates_cairn": 20
295302
}
296303
},
297304
"commercial": {

src/app/hk-tunnels-tolls/page.tsx

Lines changed: 67 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,10 @@
22

33
import "@/styles/components/card.css";
44
import { StatsCollection, SiteFooter, SiteHeader } from "@/components/SiteFormat";
5-
import { useState, useEffect, Suspense } from "react";
5+
import { useState, useEffect, memo, Suspense } from "react";
66
import { Button, HeroUIProvider } from "@heroui/react";
77
import { ThemeProvider } from "next-themes";
88
import { useSearchParams } from "next/navigation";
9-
import * as PublicHolidayData from "./data/public_holidays.json";
10-
import * as tollData from "./data/tolls.json";
119

1210
interface NumberRange {
1311
range: number[];
@@ -34,18 +32,16 @@ interface HKTunnel {
3432
}
3533

3634
interface VehicleType {
37-
name: VehicleTypeIdentifier | string;
35+
name: VehicleTypeIdentifier;
3836
hasTimeVaryingToll: boolean;
3937
fixedTolls?: Record<HKTunnelIdentifier, number | undefined>;
4038
multiplier?: number;
4139
description?: string;
4240
}
4341

44-
type DateTimeRange = [string, { value: string }];
45-
4642
interface PublicHoliday {
47-
dtstart: DateTimeRange;
48-
dtend: DateTimeRange;
43+
dtstart: [string, { value: string }];
44+
dtend: [string, { value: string }];
4945
summary: string;
5046
uid: string;
5147
}
@@ -69,6 +65,7 @@ interface TollCardProps {
6965
tunnel: HKTunnel;
7066
vehicle: VehicleTypeIdentifier;
7167
priceAlert?: string;
68+
tollData: TollData | null;
7269
currentDate: Date;
7370
isPublicHoliday: boolean;
7471
}
@@ -105,16 +102,19 @@ function timeToMinutes(time: string): number {
105102

106103
// Function to get current toll for a specific tunnel
107104
function getCurrentTollForTunnel(
105+
tollData: TollData | null,
108106
selectedVehicle: VehicleTypeIdentifier,
109107
tunnelKey: HKTunnelIdentifier,
110108
currentTime: Date,
111109
isPublicHoliday: boolean
112110
): string {
111+
if (!tollData) return "載入中...";
112+
113113
const vehicle = tollData.vehicleTypes[selectedVehicle];
114114
const tunnel = tollData.tunnels[tunnelKey];
115115

116116
// Fixed toll vehicles
117-
if ("fixedTolls" in vehicle && tunnelKey in vehicle.fixedTolls) {
117+
if (vehicle.fixedTolls && tunnelKey in vehicle.fixedTolls) {
118118
return `$${vehicle.fixedTolls[tunnelKey]}`;
119119
}
120120

@@ -140,17 +140,18 @@ function getCurrentTollForTunnel(
140140
if (typeof tollForTunnel === "object" && "range" in tollForTunnel) {
141141
// Transition period - show range
142142
const [min, max] = tollForTunnel.range;
143-
if ("multiplier" in vehicle) {
143+
if (vehicle.multiplier) {
144144
const minMoto = Math.round(min * vehicle.multiplier * 10) / 10;
145145
const maxMoto = Math.round(max * vehicle.multiplier * 10) / 10;
146146
return `$${minMoto} - $${maxMoto}`;
147147
}
148148
return `$${min} - $${max}`;
149-
} // Apply multiplier for motorcycles
150-
else if ("multiplier" in vehicle) {
151-
const motorcycleToll = Math.round(tollForTunnel * vehicle.multiplier * 10) / 10;
152-
return `$${motorcycleToll}`;
153149
} else {
150+
// Apply multiplier for motorcycles
151+
if (vehicle.multiplier) {
152+
const motorcycleToll = Math.round(tollForTunnel * vehicle.multiplier * 10) / 10;
153+
return `$${motorcycleToll}`;
154+
}
154155
return `$${tollForTunnel}`;
155156
}
156157
}
@@ -160,15 +161,15 @@ function getCurrentTollForTunnel(
160161
}
161162

162163
function HKTollCard(props: TollCardProps): JSX.Element {
163-
const { tunnelKey, tunnel, priceAlert, vehicle, currentDate, isPublicHoliday } = props;
164+
const { tunnelKey, tunnel, priceAlert, vehicle, tollData, currentDate, isPublicHoliday } = props;
164165

165166
return (
166167
<div key={tunnelKey} className="border-b border-black dark:border-white pb-1 last:border-b-0">
167168
<div className="flex flex-col sm:flex-row sm:justify-between sm:items-start sm:gap-2">
168169
<span className="text-3xl md:text-2xl font-medium text-center sm:text-left">{tunnel.name}</span>
169170
<div className="text-center sm:text-right">
170171
<p className="text-5xl py-1 md:py-2 font-bold text-green-600">
171-
{getCurrentTollForTunnel(vehicle, tunnelKey, currentDate, isPublicHoliday)}
172+
{getCurrentTollForTunnel(tollData, vehicle, tunnelKey, currentDate, isPublicHoliday)}
172173
</p>
173174
{priceAlert && (
174175
<span className="text-[1.45rem] md:text-lg bg-amber-100 text-amber-800 dark:bg-amber-900 dark:text-amber-200 px-3 rounded-md font-medium inline-block text-center">
@@ -184,18 +185,28 @@ function HKTollCard(props: TollCardProps): JSX.Element {
184185
function HKTunnelsTollsApp(): JSX.Element {
185186
const [selectedVehicle, setSelectedVehicle] = useState<VehicleTypeIdentifier>("privateCar");
186187
const [currentTime, setCurrentTime] = useState<Date>(new Date());
188+
const [tollData, setTollData] = useState<TollData | null>(null);
189+
const [publicHolidays, setPublicHolidays] = useState<Set<string>>(new Set());
187190
const [isPublicHoliday, setIsPublicHoliday] = useState<boolean>(false);
188191
const searchParams = useSearchParams();
189192

190193
// Load public holidays data
191-
const publicHolidays = new Set<string>();
192-
if (PublicHolidayData.vcalendar && PublicHolidayData.vcalendar[0] && PublicHolidayData.vcalendar[0].vevent) {
193-
PublicHolidayData.vcalendar[0].vevent.forEach((event) => {
194-
// Extract date from dtstart format "20240101"
195-
const dateStr = event.dtstart[0] as string;
196-
publicHolidays.add(dateStr);
197-
});
198-
}
194+
useEffect(() => {
195+
fetch("/api/hk-tunnels-tolls/public_holidays.json")
196+
.then((response) => response.json())
197+
.then((data: PublicHolidayData) => {
198+
const holidays = new Set<string>();
199+
if (data.vcalendar && data.vcalendar[0] && data.vcalendar[0].vevent) {
200+
data.vcalendar[0].vevent.forEach((event) => {
201+
// Extract date from dtstart format "20240101"
202+
const dateStr = event.dtstart[0];
203+
holidays.add(dateStr);
204+
});
205+
}
206+
setPublicHolidays(holidays);
207+
})
208+
.catch((error) => console.error("載入公眾假期資料失敗:", error));
209+
}, []);
199210

200211
// Check if current date is a public holiday
201212
useEffect(() => {
@@ -204,6 +215,14 @@ function HKTunnelsTollsApp(): JSX.Element {
204215
setIsPublicHoliday(publicHolidays.has(dateStr));
205216
}, [currentTime, publicHolidays]);
206217

218+
// Load toll data
219+
useEffect(() => {
220+
fetch("/api/hk-tunnels-tolls/tolls.json")
221+
.then((response) => response.json())
222+
.then((data) => setTollData(data))
223+
.catch((error) => console.error("載入收費資料失敗:", error));
224+
}, []);
225+
207226
// Update current time every minute
208227
useEffect(() => {
209228
const timer = setInterval(() => {
@@ -276,18 +295,20 @@ function HKTunnelsTollsApp(): JSX.Element {
276295

277296
if (typeof nextToll === "object" && "range" in nextToll) {
278297
const [min, max] = nextToll.range;
279-
if ("multiplier" in vehicle) {
298+
if (vehicle.multiplier) {
280299
const minMoto = Math.round(min * vehicle.multiplier * 10) / 10;
281300
const maxMoto = Math.round(max * vehicle.multiplier * 10) / 10;
282301
nextTollDisplay = `$${minMoto} - $${maxMoto}`;
283302
} else {
284303
nextTollDisplay = `$${min} - $${max}`;
285304
}
286-
} else if ("multiplier" in vehicle) {
287-
const motorcycleToll = Math.round(nextToll * vehicle.multiplier * 10) / 10;
288-
nextTollDisplay = `$${motorcycleToll}`;
289305
} else {
290-
nextTollDisplay = `$${nextToll}`;
306+
if (vehicle.multiplier) {
307+
const motorcycleToll = Math.round(nextToll * vehicle.multiplier * 10) / 10;
308+
nextTollDisplay = `$${motorcycleToll}`;
309+
} else {
310+
nextTollDisplay = `$${nextToll}`;
311+
}
291312
}
292313

293314
return `${nextPeriod.timeRange.split(" - ")[0]} 變為 ${nextTollDisplay}`;
@@ -311,7 +332,7 @@ function HKTunnelsTollsApp(): JSX.Element {
311332
{/* Current Toll Display */}
312333
<div className="card-base-min mb-4">
313334
<h3 className="text-xl md:text-lg font-semibold">
314-
目前收費 - {vehicleType.name} {"description" in vehicleType ? `(${vehicleType.description})` : ""}
335+
目前收費 - {vehicleType.name} {vehicleType.description ? `(${vehicleType.description})` : ""}
315336
</h3>
316337
<div>
317338
<div className="space-y-2">
@@ -328,9 +349,10 @@ function HKTunnelsTollsApp(): JSX.Element {
328349
<HKTollCard
329350
key={key}
330351
tunnelKey={key}
331-
tunnel={tunnel as HKTunnel}
352+
tunnel={tunnel}
332353
priceAlert={priceAlert}
333354
vehicle={selectedVehicle}
355+
tollData={tollData}
334356
currentDate={hkTime}
335357
isPublicHoliday={isPublicHoliday}
336358
/>
@@ -362,9 +384,7 @@ function HKTunnelsTollsApp(): JSX.Element {
362384
{/* Cross-Harbour Tunnels Time Periods Table */}
363385
<div className="card-base-min mb-4">
364386
<h3 className="text-2xl md:text-lg font-semibold border-b">
365-
過海隧道收費時段表 (
366-
<span suppressHydrationWarning>{hkTime.getDay() === 0 || isPublicHoliday ? "星期日及公眾假期" : "平日"}</span>
367-
)
387+
過海隧道收費時段表 ({hkTime.getDay() === 0 || isPublicHoliday ? "星期日及公眾假期" : "平日"})
368388
</h3>
369389
<div className="overflow-x-auto">
370390
<table className="w-full">
@@ -437,12 +457,12 @@ function HKTunnelsTollsApp(): JSX.Element {
437457
<td className="px-6 py-4 whitespace-nowrap">{period.timeRange}</td>
438458
<td className="px-6 py-4 whitespace-nowrap">
439459
{vehicle.hasTimeVaryingToll
440-
? formatToll("western", period, "multiplier" in vehicle ? vehicle.multiplier : undefined)
460+
? formatToll("western", period, vehicle.multiplier)
441461
: getFixedToll("western", vehicle)}
442462
</td>
443463
<td className="px-6 py-4 whitespace-nowrap">
444464
{vehicle.hasTimeVaryingToll
445-
? formatToll("cross_eastern", period, "multiplier" in vehicle ? vehicle.multiplier : undefined)
465+
? formatToll("cross_eastern", period, vehicle.multiplier)
446466
: getFixedToll("cross_eastern", vehicle)}
447467
</td>
448468
</tr>
@@ -455,9 +475,7 @@ function HKTunnelsTollsApp(): JSX.Element {
455475
{/* Tai Lam Tunnel Time Periods Table */}
456476
<div className="card-base-min mb-8">
457477
<h3 className="text-2xl md:text-lg font-semibold border-b">
458-
大欖隧道收費時段表 (
459-
<span suppressHydrationWarning>{hkTime.getDay() === 0 || isPublicHoliday ? "星期日及公眾假期" : "平日"}</span>
460-
)
478+
大欖隧道收費時段表 ({hkTime.getDay() === 0 || isPublicHoliday ? "星期日及公眾假期" : "平日"})
461479
</h3>
462480
<div className="overflow-x-auto">
463481
<table className="w-full">
@@ -520,9 +538,7 @@ function HKTunnelsTollsApp(): JSX.Element {
520538
<td className="px-6 py-4 whitespace-nowrap font-medium">{period.name}</td>
521539
<td className="px-6 py-4 whitespace-nowrap">{period.timeRange}</td>
522540
<td className="px-6 py-4 whitespace-nowrap">
523-
{vehicle.hasTimeVaryingToll
524-
? formatToll(period, "multiplier" in vehicle ? vehicle.multiplier : undefined)
525-
: getFixedToll(vehicle)}
541+
{vehicle.hasTimeVaryingToll ? formatToll(period, vehicle.multiplier) : getFixedToll(vehicle)}
526542
</td>
527543
</tr>
528544
));
@@ -559,17 +575,15 @@ function HKTunnelsTollsApp(): JSX.Element {
559575
</p>
560576
<p>
561577
最後更新:
562-
<span suppressHydrationWarning>
563-
{hkTime.toLocaleString("zh-HK", {
564-
year: "numeric",
565-
month: "2-digit",
566-
day: "2-digit",
567-
hour: "2-digit",
568-
minute: "2-digit",
569-
second: "2-digit",
570-
hour12: false,
571-
})}
572-
</span>
578+
{hkTime.toLocaleString("zh-HK", {
579+
year: "numeric",
580+
month: "2-digit",
581+
day: "2-digit",
582+
hour: "2-digit",
583+
minute: "2-digit",
584+
second: "2-digit",
585+
hour12: false,
586+
})}
573587
</p>
574588
</div>
575589
</div>

0 commit comments

Comments
 (0)