Merge branch 'develop' into codex/point
This commit is contained in:
@@ -3,6 +3,17 @@ import { createRootRoute, createRoute, Outlet } from "@tanstack/react-router"
|
||||
import { AppLayout } from "@/app/layout/app-layout"
|
||||
import { ComponentsPreviewPage } from "@/features/components/pages/components-preview-page"
|
||||
import { HomePage } from "@/features/home/pages/home-page"
|
||||
import {
|
||||
radarMetricKinds,
|
||||
radarRankSides,
|
||||
radarViews,
|
||||
sectorTypes,
|
||||
type RadarMetricKind,
|
||||
type RadarRankSide,
|
||||
type RadarView,
|
||||
type SectorType,
|
||||
} from "@/features/sector-radar/api/sector-radar.types"
|
||||
import { SectorRadarPage } from "@/features/sector-radar/pages/sector-radar-page"
|
||||
import {
|
||||
selectionCategoryFilters,
|
||||
selectionSorts,
|
||||
@@ -28,6 +39,63 @@ const indexRoute = createRoute({
|
||||
component: HomePage,
|
||||
})
|
||||
|
||||
const sectorRadarRoute = createRoute({
|
||||
getParentRoute: () => workspaceRoute,
|
||||
path: "/sector-radar",
|
||||
validateSearch: (search: Record<string, unknown>) => {
|
||||
const rawPage = Number(search.page)
|
||||
const rawPageSize = Number(search.pageSize)
|
||||
const rawRankChangeDays = Number(search.rankChangeDays)
|
||||
const page =
|
||||
Number.isFinite(rawPage) && rawPage >= 1 ? Math.floor(rawPage) : 1
|
||||
const pageSize = [10, 20, 50].includes(rawPageSize) ? rawPageSize : 20
|
||||
const rankChangeDays =
|
||||
Number.isFinite(rawRankChangeDays) &&
|
||||
rawRankChangeDays >= 1 &&
|
||||
rawRankChangeDays <= 5
|
||||
? Math.floor(rawRankChangeDays)
|
||||
: 1
|
||||
const searchValue =
|
||||
typeof search.search === "string" ? search.search.slice(0, 100) : ""
|
||||
const tradeDate =
|
||||
typeof search.tradeDate === "string" && isValidTradeDate(search.tradeDate)
|
||||
? search.tradeDate
|
||||
: undefined
|
||||
const sectorType = validatedSearchValue<SectorType>(
|
||||
search.sectorType,
|
||||
sectorTypes,
|
||||
"concept",
|
||||
)
|
||||
const view = validatedSearchValue<RadarView>(
|
||||
search.view,
|
||||
radarViews,
|
||||
"amount",
|
||||
)
|
||||
const rankChangeMetric = validatedSearchValue<RadarMetricKind>(
|
||||
search.rankChangeMetric,
|
||||
radarMetricKinds,
|
||||
"amount",
|
||||
)
|
||||
const side = validatedSearchValue<RadarRankSide>(
|
||||
search.side,
|
||||
radarRankSides,
|
||||
"all",
|
||||
)
|
||||
return {
|
||||
tradeDate,
|
||||
sectorType,
|
||||
view,
|
||||
rankChangeMetric,
|
||||
rankChangeDays,
|
||||
side,
|
||||
search: searchValue,
|
||||
page,
|
||||
pageSize,
|
||||
}
|
||||
},
|
||||
component: SectorRadarPage,
|
||||
})
|
||||
|
||||
const selectionRoute = createRoute({
|
||||
getParentRoute: () => workspaceRoute,
|
||||
path: "/selection",
|
||||
@@ -72,8 +140,31 @@ const componentsRoute = createRoute({
|
||||
export const routeTree = rootRoute.addChildren([
|
||||
workspaceRoute.addChildren([
|
||||
indexRoute,
|
||||
sectorRadarRoute,
|
||||
selectionRoute,
|
||||
syncRoute,
|
||||
componentsRoute,
|
||||
]),
|
||||
])
|
||||
|
||||
function validatedSearchValue<Value extends string>(
|
||||
value: unknown,
|
||||
allowed: readonly Value[],
|
||||
fallback: Value,
|
||||
): Value {
|
||||
return typeof value === "string" && allowed.includes(value as Value)
|
||||
? (value as Value)
|
||||
: fallback
|
||||
}
|
||||
|
||||
function isValidTradeDate(value: string) {
|
||||
const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value)
|
||||
if (!match) return false
|
||||
const parsed = new Date(`${value}T00:00:00Z`)
|
||||
return (
|
||||
!Number.isNaN(parsed.getTime()) &&
|
||||
parsed.getUTCFullYear() === Number(match[1]) &&
|
||||
parsed.getUTCMonth() + 1 === Number(match[2]) &&
|
||||
parsed.getUTCDate() === Number(match[3])
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user