From 8d8d8462294d44c8043c518f455ce77153603b2e Mon Sep 17 00:00:00 2001 From: Artem Bulgakov Date: Mon, 28 Oct 2024 22:22:34 +0300 Subject: [PATCH] feat(maps): add search feature; insert maps as svg --- src/api/maps/map-image.ts | 22 +++++++ src/api/maps/types.ts | 5 +- src/app/routes/_with_menu/maps.tsx | 9 ++- src/components/maps/MapView.tsx | 61 +++++++++++++------ src/components/maps/MapsPage.tsx | 89 ++++++++++++++++------------ src/components/maps/MapsPageTabs.tsx | 68 +++++++++++++++++++++ 6 files changed, 194 insertions(+), 60 deletions(-) create mode 100644 src/components/maps/MapsPageTabs.tsx diff --git a/src/api/maps/map-image.ts b/src/api/maps/map-image.ts index c2f37b0..9a8ab37 100644 --- a/src/api/maps/map-image.ts +++ b/src/api/maps/map-image.ts @@ -1,3 +1,25 @@ +import { customFetch } from "@/api/helpers/custom-fetch.ts"; +import { useQuery } from "@tanstack/react-query"; + export function getMapImageUrl(svgName: string) { return `${import.meta.env.VITE_MAPS_API_URL}/static/${svgName}`; } + +export function useMapImage(svgName: string) { + const url = getMapImageUrl(svgName); + return useQuery({ + queryKey: ["maps-image", url], + queryFn: async ({ signal }) => { + if (!url) { + return undefined; + } + + // Use client to add the auth token + return customFetch.GET(url, { + parseAs: "text", + signal, + }); + }, + enabled: !!url, + }); +} diff --git a/src/api/maps/types.ts b/src/api/maps/types.ts index d70fcdb..bd8d700 100644 --- a/src/api/maps/types.ts +++ b/src/api/maps/types.ts @@ -122,8 +122,9 @@ export interface components { SearchResult: { /** Scene Id */ scene_id: string; - /** Matching Area Indexes */ - matching_area_indexes: number[]; + area: components["schemas"]["Area"]; + /** Area Index */ + area_index: number; }; /** ValidationError */ ValidationError: { diff --git a/src/app/routes/_with_menu/maps.tsx b/src/app/routes/_with_menu/maps.tsx index 5d5605b..b1d54d2 100644 --- a/src/app/routes/_with_menu/maps.tsx +++ b/src/app/routes/_with_menu/maps.tsx @@ -1,19 +1,21 @@ import { Topbar } from "@/components/layout/Topbar.tsx"; import { MapsPage } from "@/components/maps/MapsPage.tsx"; +import { MapsPageTabs } from "@/components/maps/MapsPageTabs.tsx"; import { createFileRoute } from "@tanstack/react-router"; import { Helmet } from "react-helmet-async"; export const Route = createFileRoute("/_with_menu/maps")({ validateSearch: ( search: Record, - ): { sceneId: string | undefined } => { + ): { sceneId?: string; q?: string } => { return { sceneId: (search.sceneId as string) ?? undefined, + q: (search.q as string) ?? undefined, }; }, component: function RouteComponent() { - const { sceneId } = Route.useSearch(); + const { sceneId, q } = Route.useSearch(); return (
@@ -25,7 +27,8 @@ export const Route = createFileRoute("/_with_menu/maps")({ - + +
); }, diff --git a/src/components/maps/MapView.tsx b/src/components/maps/MapView.tsx index 092dc14..eed6eda 100644 --- a/src/components/maps/MapView.tsx +++ b/src/components/maps/MapView.tsx @@ -1,5 +1,5 @@ import { mapsTypes } from "@/api/maps"; -import { getMapImageUrl } from "@/api/maps/map-image.ts"; +import { useMapImage } from "@/api/maps/map-image.ts"; import { FloatingOverlay, FloatingPortal } from "@floating-ui/react"; import { memo, @@ -10,7 +10,13 @@ import { useState, } from "react"; -export function MapView({ scene }: { scene: mapsTypes.SchemaScene }) { +export function MapView({ + scene, + highlightAreas, +}: { + scene: mapsTypes.SchemaScene; + highlightAreas: mapsTypes.SchemaSearchResult[]; +}) { const [fullscreen, setFullscreen] = useState(false); const switchFullscreen = useCallback(() => setFullscreen((v) => !v), []); @@ -20,7 +26,9 @@ export function MapView({ scene }: { scene: mapsTypes.SchemaScene }) { if (fullscreen) { document.body.requestFullscreen?.(); } else { - document.exitFullscreen?.(); + if (document.fullscreenElement) { + document.exitFullscreen?.(); + } } }, [fullscreen]); @@ -52,8 +60,8 @@ export function MapView({ scene }: { scene: mapsTypes.SchemaScene }) { return ( -
- +
+