planner: give the Yjs document a typed schema seam
The routeData Y.Map's ~15 string keys (geojson, coordinates, segmentBoundaries, road metadata, profile, colorMode, baseLayer, overlays, poiCategories) were read and written raw at ~30 call sites, each with its own JSON parsing and casts; parseJsonArray existed twice and waypoint extraction four times. GPX assembly was duplicated between SaveToJournalButton and ExportButton, so the saved plan and the exported file could silently diverge. - new lib/route-data.ts owns the routeData (+ noGoAreas) schema: typed read/write, JSON encoding internal, ColorMode moves here (re-exported from ColoredRoute for existing importers) - new lib/gpx-export.ts owns GPX assembly: buildRouteGpx / buildPlanGpx / buildDayGpxFiles / hasDayBreaks; multi-day splitting becomes a pure, tested function - waypoint-ymap.ts gains extractWaypoints / extractWaypointData; the four hand-rolled copies (use-routing, use-waypoint-manager, WaypointSidebar, use-days) now share it, and WaypointSidebar's moveWaypoint reuses the round-trip helpers instead of re-listing every waypoint field - all hooks/components consume the seam; no raw routeData key strings remain outside route-data.ts Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
06c385f6ac
commit
3b9672e0ff
21 changed files with 921 additions and 322 deletions
|
|
@ -1,7 +1,13 @@
|
|||
import { useEffect, useState } from "react";
|
||||
import * as Y from "yjs";
|
||||
import type { ColorMode } from "~/components/ColoredRoute";
|
||||
import type { ElevationPoint } from "~/lib/elevation-chart-draw";
|
||||
import {
|
||||
getColorMode,
|
||||
getGeojson,
|
||||
readRoadMetadata,
|
||||
type ColorMode,
|
||||
type RoadMetadata,
|
||||
} from "~/lib/route-data";
|
||||
|
||||
function haversine(lat1: number, lon1: number, lat2: number, lon2: number): number {
|
||||
const R = 6371000;
|
||||
|
|
@ -44,21 +50,9 @@ function extractElevation(geojsonStr: string): ElevationPoint[] {
|
|||
}
|
||||
}
|
||||
|
||||
function parseJsonArray(json: string | undefined): string[] {
|
||||
if (!json) return [];
|
||||
try { return JSON.parse(json); } catch { return []; }
|
||||
}
|
||||
|
||||
export interface ElevationData {
|
||||
export interface ElevationData extends RoadMetadata {
|
||||
points: ElevationPoint[];
|
||||
colorMode: ColorMode;
|
||||
surfaces: string[];
|
||||
highways: string[];
|
||||
maxspeeds: string[];
|
||||
smoothnesses: string[];
|
||||
tracktypes: string[];
|
||||
cycleways: string[];
|
||||
bikeroutes: string[];
|
||||
}
|
||||
|
||||
export function useElevationData(routeData: Y.Map<unknown>): ElevationData {
|
||||
|
|
@ -76,17 +70,11 @@ export function useElevationData(routeData: Y.Map<unknown>): ElevationData {
|
|||
|
||||
useEffect(() => {
|
||||
const update = () => {
|
||||
const geojson = routeData.get("geojson") as string | undefined;
|
||||
const geojson = getGeojson(routeData);
|
||||
setData({
|
||||
points: geojson ? extractElevation(geojson) : [],
|
||||
colorMode: (routeData.get("colorMode") as ColorMode | undefined) ?? "plain",
|
||||
surfaces: parseJsonArray(routeData.get("surfaces") as string | undefined),
|
||||
highways: parseJsonArray(routeData.get("highways") as string | undefined),
|
||||
maxspeeds: parseJsonArray(routeData.get("maxspeeds") as string | undefined),
|
||||
smoothnesses: parseJsonArray(routeData.get("smoothnesses") as string | undefined),
|
||||
tracktypes: parseJsonArray(routeData.get("tracktypes") as string | undefined),
|
||||
cycleways: parseJsonArray(routeData.get("cycleways") as string | undefined),
|
||||
bikeroutes: parseJsonArray(routeData.get("bikeroutes") as string | undefined),
|
||||
colorMode: getColorMode(routeData),
|
||||
...readRoadMetadata(routeData),
|
||||
});
|
||||
};
|
||||
routeData.observe(update);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue