More UAT issues resolution

This commit is contained in:
Stephanos A
2026-07-05 21:54:52 +03:00
parent f2c8b9ed71
commit ce5646235a
2 changed files with 78 additions and 3 deletions

View File

@@ -311,6 +311,7 @@ function PassengerCountModal({
const [adultCount, setAdultCount] = useState(1);
const [childCount, setChildCount] = useState(0);
const [departureStationId, setDepartureStationId] = useState('');
const [showStationError, setShowStationError] = useState(false);
const remaining = tier.availableSeats - tier.bookedSeats;
const childFareMinor = Math.round(tier.priceMinor * PKG_CHILD_FARE_RATIO);
const totalMinor = (adultCount * tier.priceMinor + childCount * childFareMinor) * priceMultiplier;
@@ -378,8 +379,10 @@ function PassengerCountModal({
</label>
<select
value={departureStationId}
onChange={(e) => setDepartureStationId(e.target.value)}
className="w-full rounded-xl border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 text-sm text-gray-900 dark:text-white px-3 py-2.5 focus:outline-none focus:ring-2 focus:ring-primary/40"
onChange={(e) => { setDepartureStationId(e.target.value); setShowStationError(false); }}
className={`w-full rounded-xl border bg-white dark:bg-gray-800 text-sm text-gray-900 dark:text-white px-3 py-2.5 focus:outline-none focus:ring-2 focus:ring-primary/40 ${
showStationError && !departureStationId ? 'border-red-400 dark:border-red-500' : 'border-gray-200 dark:border-gray-700'
}`}
>
<option value="">Select your boarding station</option>
{stations.map((s) => (
@@ -389,7 +392,12 @@ function PassengerCountModal({
<p className="text-[10px] text-gray-400 mt-1">For informational purposes pricing remains fixed regardless of boarding point.</p>
</div>
{showStationError && !departureStationId && (
<p className="text-xs text-red-500 -mt-2">Please select your boarding station to continue.</p>
)}
<button type="button" onClick={() => {
if (!departureStationId) { setShowStationError(true); return; }
const station = stations.find(s => s.id === departureStationId);
onConfirm(adultCount, childCount, departureStationId, station?.name ?? '');
}}
@@ -429,7 +437,20 @@ export default function PackageDetailPage() {
queryFn: async () => (await apiClient.get(`/stations?pageSize=100`)) as any,
});
const stations: Station[] = Array.isArray(stationsData) ? stationsData : stationsData?.items || stationsData?.data?.items || [];
const allStations: Station[] = Array.isArray(stationsData) ? stationsData : stationsData?.items || stationsData?.data?.items || [];
// Fetch stops for the outbound schedule to filter stations to only those on the route
const outboundScheduleId = pkg?.outboundSchedule?.id;
const { data: scheduleStops } = useQuery({
queryKey: ["schedule-stops", outboundScheduleId],
queryFn: async () => (await apiClient.get(`/schedules/${outboundScheduleId}/stops`)) as any[],
enabled: !!outboundScheduleId,
});
// Only show stations that are actual stops on the route
const stations: Station[] = scheduleStops?.length
? allStations.filter((s) => scheduleStops.some((stop: any) => stop.stationId === s.id || stop.station?.id === s.id))
: allStations;
const selectedTier = pkg?.priceTiers?.find((t) => t.id === selectedTierId);

View File

@@ -0,0 +1,54 @@
import { NextRequest, NextResponse } from 'next/server';
// Routes that should NOT redirect to home on hard refresh
const PRESERVED_ROUTES = [
'/booking/',
'/login',
'/register',
'/forgot-password',
'/reset-password',
'/set-password',
'/verify-account',
'/fayda-setup',
'/profile',
'/about',
'/contact',
'/help',
'/guide',
'/services',
'/go/',
];
export function middleware(request: NextRequest) {
const { pathname } = request.nextUrl;
// Only intercept hard refreshes (no Referer header = direct navigation / refresh)
const referer = request.headers.get('referer');
const isHardRefresh = !referer;
// Skip Next.js internals, static files, and API routes
if (
pathname.startsWith('/_next') ||
pathname.startsWith('/api') ||
pathname.includes('.') ||
pathname === '/'
) {
return NextResponse.next();
}
// On hard refresh of a preserved route, let it through
if (PRESERVED_ROUTES.some((r) => pathname.startsWith(r))) {
return NextResponse.next();
}
// On hard refresh of package detail or packages list, redirect to home
if (isHardRefresh && (pathname.startsWith('/packages'))) {
return NextResponse.redirect(new URL('/', request.url));
}
return NextResponse.next();
}
export const config = {
matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
};