Extend useAppSettings with flightStatus and buyTicket button config

This commit is contained in:
2026-04-17 01:20:11 +03:00
parent 0fe62a0f1a
commit aa60c29685
3 changed files with 82 additions and 5 deletions
+20 -1
View File
@@ -6,6 +6,25 @@ export interface AppSettingsFilterOptions {
timeStep?: string;
}
export interface AppSettingsButtonsBuyTicketPeriod {
min?: string;
max?: string;
}
export interface AppSettingsButtonsBuyTicket {
period?: AppSettingsButtonsBuyTicketPeriod;
}
export interface AppSettingsButtonsFlightStatus {
availableFrom?: string;
visible?: string;
}
export interface AppSettingsButtons {
flightStatus?: AppSettingsButtonsFlightStatus;
buyTicket?: AppSettingsButtonsBuyTicket;
}
export interface AppSettingsResponse {
showDebugVersion?: string;
uiOptions?: {
@@ -14,7 +33,7 @@ export interface AppSettingsResponse {
onlineboard?: AppSettingsFilterOptions;
schedule?: AppSettingsFilterOptions;
};
buttons?: Record<string, unknown>;
buttons?: AppSettingsButtons;
};
}
+30
View File
@@ -82,4 +82,34 @@ describe("useAppSettings", () => {
expect(result.current.error).toBe(err);
expect(result.current.onlineboardSearchFrom).toBe(2);
});
it("parses buttons config into hour numbers", async () => {
const response: AppSettingsResponse = {
uiOptions: {
buttons: {
flightStatus: { availableFrom: "24h" },
buyTicket: { period: { min: "2h", max: "72h" } },
},
},
};
mockGetAppSettings.mockResolvedValue(response);
const { result } = renderHook(() => useAppSettings());
await waitFor(() => expect(result.current.loading).toBe(false));
expect(result.current.flightStatusAvailableFromHours).toBe(24);
expect(result.current.buyTicketMinHours).toBe(2);
expect(result.current.buyTicketMaxHours).toBe(72);
});
it("returns button-config defaults when fields are missing", async () => {
mockGetAppSettings.mockResolvedValue({});
const { result } = renderHook(() => useAppSettings());
await waitFor(() => expect(result.current.loading).toBe(false));
expect(result.current.flightStatusAvailableFromHours).toBe(24);
expect(result.current.buyTicketMinHours).toBe(2);
expect(result.current.buyTicketMaxHours).toBe(72);
});
});
+32 -4
View File
@@ -3,33 +3,52 @@ import { useApiClient } from "@/shared/api/provider.js";
import { getAppSettings } from "@/shared/api/appSettings.js";
const DAYS_PATTERN = /^(\d+)d$/;
const HOURS_PATTERN = /^(\d+)h$/;
const DEFAULTS = {
onlineboardSearchFrom: 2,
onlineboardSearchTo: 14,
scheduleSearchFrom: 30,
scheduleSearchTo: 30,
flightStatusAvailableFromHours: 24,
buyTicketMinHours: 2,
buyTicketMaxHours: 72,
} as const;
function parseDays(value: string | undefined, fallback: number): number {
function parsePattern(
value: string | undefined,
pattern: RegExp,
fallback: number,
): number {
if (!value) return fallback;
const match = DAYS_PATTERN.exec(value);
const match = pattern.exec(value);
if (!match) return fallback;
return parseInt(match[1]!, 10);
}
function parseDays(value: string | undefined, fallback: number): number {
return parsePattern(value, DAYS_PATTERN, fallback);
}
function parseHours(value: string | undefined, fallback: number): number {
return parsePattern(value, HOURS_PATTERN, fallback);
}
export interface UseAppSettingsResult {
onlineboardSearchFrom: number;
onlineboardSearchTo: number;
scheduleSearchFrom: number;
scheduleSearchTo: number;
flightStatusAvailableFromHours: number;
buyTicketMinHours: number;
buyTicketMaxHours: number;
loading: boolean;
error: Error | null;
}
/**
* Fetches the global app settings and exposes day-range numbers.
* On error or parse failure, returns default values (2/14/30/30).
* Fetches the global app settings and exposes day-range and button-config numbers.
* On error or parse failure, returns defaults.
*/
export function useAppSettings(): UseAppSettingsResult {
const client = useApiClient();
@@ -45,11 +64,20 @@ export function useAppSettings(): UseAppSettingsResult {
if (cancelled) return;
const ob = response.uiOptions?.filter?.onlineboard;
const sc = response.uiOptions?.filter?.schedule;
const fs = response.uiOptions?.buttons?.flightStatus;
const bt = response.uiOptions?.buttons?.buyTicket;
setState({
onlineboardSearchFrom: parseDays(ob?.searchFrom, DEFAULTS.onlineboardSearchFrom),
onlineboardSearchTo: parseDays(ob?.searchTo, DEFAULTS.onlineboardSearchTo),
scheduleSearchFrom: parseDays(sc?.searchFrom, DEFAULTS.scheduleSearchFrom),
scheduleSearchTo: parseDays(sc?.searchTo, DEFAULTS.scheduleSearchTo),
flightStatusAvailableFromHours: parseHours(
fs?.availableFrom,
DEFAULTS.flightStatusAvailableFromHours,
),
buyTicketMinHours: parseHours(bt?.period?.min, DEFAULTS.buyTicketMinHours),
buyTicketMaxHours: parseHours(bt?.period?.max, DEFAULTS.buyTicketMaxHours),
});
setLoading(false);
})