From 266def4f74612e6610605cf94921f08647664320 Mon Sep 17 00:00:00 2001 From: Caden Buckhalt Date: Tue, 17 Dec 2024 14:37:18 -0800 Subject: [PATCH] improve layers types --- .../containers/Interfaces/Geospatial.tsx | 3 ++ lib/interviewer/hooks/useMapbox.ts | 17 ++----- lib/protocol-validation/schemas/src/8.zod.ts | 45 ++++++++++++------- 3 files changed, 35 insertions(+), 30 deletions(-) diff --git a/lib/interviewer/containers/Interfaces/Geospatial.tsx b/lib/interviewer/containers/Interfaces/Geospatial.tsx index f0bb5188..4ba339d5 100644 --- a/lib/interviewer/containers/Interfaces/Geospatial.tsx +++ b/lib/interviewer/containers/Interfaces/Geospatial.tsx @@ -70,6 +70,9 @@ export default function GeospatialInterface({ const { prompts } = stage; const { promptIndex } = usePrompts(); const currentPrompt = prompts[promptIndex]; + if (!currentPrompt) { + throw new Error('Prompt not found'); + } const { center, token: tokenId, initialZoom } = stage.mapOptions; const layers = currentPrompt?.layers; const stageNodes = usePropSelector(getNetworkNodesForType, { diff --git a/lib/interviewer/hooks/useMapbox.ts b/lib/interviewer/hooks/useMapbox.ts index e06467cd..bafd1814 100644 --- a/lib/interviewer/hooks/useMapbox.ts +++ b/lib/interviewer/hooks/useMapbox.ts @@ -2,6 +2,7 @@ import type { MapMouseEvent } from 'mapbox-gl'; import mapboxgl from 'mapbox-gl'; import { useCallback, useEffect, useRef, useState } from 'react'; import { useSelector } from 'react-redux'; +import type { MapLayer } from '~/lib/protocol-validation/schemas/src/8.zod'; import { getCSSVariableAsString } from '~/lib/ui/utils/CSSVariables'; import { getAssetUrlFromId } from '../selectors/protocol'; @@ -11,18 +12,6 @@ const MAP_CONSTANTS = { DEFAULT_LINE_WIDTH: 1, } as const; -//TODO: import this from schema -// prob should be two types, one for line and one for fill instead of optional fields -type MapLayer = { - id: string; - type: 'line' | 'fill'; - data: string; - color: string; - width?: number; - opacity?: number; - filter?: string; -}; - type UseMapboxProps = { accessToken: string; center: [number, number]; @@ -65,8 +54,8 @@ const useMapboxToken = (tokenId: string) => { export const useMapbox = ({ center, - initialZoom = 10, - layers = [], + initialZoom, + layers, tokenId, getAssetUrl, initialSelectionValue, diff --git a/lib/protocol-validation/schemas/src/8.zod.ts b/lib/protocol-validation/schemas/src/8.zod.ts index e96ef76b..a1bc16d4 100644 --- a/lib/protocol-validation/schemas/src/8.zod.ts +++ b/lib/protocol-validation/schemas/src/8.zod.ts @@ -466,6 +466,29 @@ const familyTreeCensusStage = baseStageSchema.extend({ type: z.literal('FamilyTreeCensus'), }); +const baseLayer = z + .object({ + id: z.string(), + data: z.string(), + color: z.string(), + }) + .strict(); + +const lineLayer = baseLayer.extend({ + type: z.literal('line'), + width: z.number(), +}); + +const fillLayer = baseLayer.extend({ + type: z.literal('fill'), + opacity: z.number().optional(), + filter: z.string(), +}); + +const mapLayer = z.union([lineLayer, fillLayer]); + +export type MapLayer = z.infer; + const geospatialStage = baseStageSchema.extend({ type: z.literal('Geospatial'), subject: subjectSchema, @@ -476,22 +499,12 @@ const geospatialStage = baseStageSchema.extend({ }), prompts: z .array( - promptSchema.extend({ - layers: z.array( - z - .object({ - id: z.string(), - data: z.string(), - type: z.enum(['line', 'fill']), - color: z.string(), - opacity: z.number().optional(), - filter: z.string().optional(), - width: z.number().optional(), - }) - .strict(), - ), - variable: z.string(), - }), + promptSchema + .extend({ + layers: z.array(mapLayer), + variable: z.string(), + }) + .strict(), ) .min(1), });