diff --git a/frontend/components.json b/frontend/components.json index 0e1e0366..079cc5d6 100644 --- a/frontend/components.json +++ b/frontend/components.json @@ -9,7 +9,7 @@ }, "rsc": false, "aliases": { - "utils": "@/lib/utils", + "utils": "@/libs/utils", "components": "@/components" } } diff --git a/frontend/components/providers/map-store-provider.tsx b/frontend/components/providers/map-store-provider.tsx index 211c3a40..c9b35116 100644 --- a/frontend/components/providers/map-store-provider.tsx +++ b/frontend/components/providers/map-store-provider.tsx @@ -3,7 +3,7 @@ import { createContext, useContext, useRef, type ReactNode } from "react" import { useStore, type StoreApi } from "zustand" -import { createMapStore, type MapStore } from "@/lib/stores/map-store" +import { createMapStore, type MapStore } from "@/libs/stores/map-store" export const MapStoreContext = createContext | null>(null) diff --git a/frontend/components/providers/vessels-store-provider.tsx b/frontend/components/providers/vessels-store-provider.tsx index 6f57d813..633f8d32 100644 --- a/frontend/components/providers/vessels-store-provider.tsx +++ b/frontend/components/providers/vessels-store-provider.tsx @@ -2,7 +2,7 @@ import { createContext, useContext, useRef, type ReactNode } from "react" import { useStore, type StoreApi } from "zustand" -import { VesselsState, createVesselsStore, type VesselsStore } from "@/lib/stores/vessels-store" +import { VesselsState, createVesselsStore, type VesselsStore } from "@/libs/stores/vessels-store" export const VesselsStoreContext = createContext | null>(null) diff --git a/frontend/components/ui/button.tsx b/frontend/components/ui/button.tsx index 0ba42773..7a2330cf 100644 --- a/frontend/components/ui/button.tsx +++ b/frontend/components/ui/button.tsx @@ -2,7 +2,7 @@ import * as React from "react" import { Slot } from "@radix-ui/react-slot" import { cva, type VariantProps } from "class-variance-authority" -import { cn } from "@/lib/utils" +import { cn } from "@/libs/utils" const buttonVariants = cva( "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", diff --git a/frontend/components/ui/command.tsx b/frontend/components/ui/command.tsx index 4fd4eeff..80567b4b 100644 --- a/frontend/components/ui/command.tsx +++ b/frontend/components/ui/command.tsx @@ -3,7 +3,7 @@ import { type DialogProps } from "@radix-ui/react-dialog" import { Command as CommandPrimitive } from "cmdk" import { Search } from "lucide-react" -import { cn } from "@/lib/utils" +import { cn } from "@/libs/utils" import { Dialog, DialogContent } from "@/components/ui/dialog" const Command = React.forwardRef< diff --git a/frontend/components/ui/dialog.tsx b/frontend/components/ui/dialog.tsx index 224081c2..852e7b63 100644 --- a/frontend/components/ui/dialog.tsx +++ b/frontend/components/ui/dialog.tsx @@ -2,7 +2,7 @@ import * as React from "react" import * as DialogPrimitive from "@radix-ui/react-dialog" import { X } from "lucide-react" -import { cn } from "@/lib/utils" +import { cn } from "@/libs/utils" const Dialog = DialogPrimitive.Root diff --git a/frontend/libs/fonts.ts b/frontend/libs/fonts.ts new file mode 100644 index 00000000..eb51e118 --- /dev/null +++ b/frontend/libs/fonts.ts @@ -0,0 +1,11 @@ +import { JetBrains_Mono as FontMono, Inter as FontSans } from "next/font/google" + +export const fontSans = FontSans({ + subsets: ["latin"], + variable: "--font-sans", +}) + +export const fontMono = FontMono({ + subsets: ["latin"], + variable: "--font-mono", +}) diff --git a/frontend/libs/stores/map-store.ts b/frontend/libs/stores/map-store.ts new file mode 100644 index 00000000..ffb81053 --- /dev/null +++ b/frontend/libs/stores/map-store.ts @@ -0,0 +1,115 @@ +import { VesselExcursionSegment, VesselExcursionSegments, VesselExcursionSegmentsGeo, VesselPosition } from "@/types/vessel" +import { MapViewState } from "@deck.gl/core" +import { createStore } from "zustand/vanilla" + +export interface ViewState { + longitude: number + latitude: number + zoom: number + pitch?: number + bearing?: number + transitionDuration?: number + transitionInterpolator?: any +} + +export type MapState = { + count: number + viewState: MapViewState + latestPositions: VesselPosition[] + activePosition: VesselPosition | null + trackedVesselIDs: number[] + trackedVesselSegments: VesselExcursionSegments[] +} + +export type MapActions = { + decrementCount: () => void + incrementCount: () => void + setViewState: (viewState: MapViewState) => void + setZoom: (zoom: number) => void + setLatestPositions: (latestPositions: VesselPosition[]) => void + setActivePosition: (activePosition: VesselPosition | null) => void + addTrackedVessel: (vesselID: number, segments: VesselExcursionSegment[]) => void + removeTrackedVessel: (vesselID: number) => void + clearLatestPositions: () => void + cleartrackedVessels: () => void +} + +export type MapStore = MapState & MapActions + +export const defaultInitState: MapState = { + count: 0, + viewState: { + longitude: 3.788086, + latitude: 47.840291, + zoom: 5, + pitch: 20, + bearing: 0, + }, + latestPositions: [], + activePosition: null, + trackedVesselIDs: [], + trackedVesselSegments: [] +} + +export const createMapStore = (initState: MapState = defaultInitState) => { + return createStore()((set) => ({ + ...initState, + decrementCount: () => set((state) => ({ count: state.count - 1 })), + incrementCount: () => set((state) => ({ count: state.count + 1 })), + setViewState: (viewState?: MapViewState) => { + set((state) => ({ + ...state, + viewState, + })) + }, + setZoom: (zoom: number) => { + set((state) => ({ + ...state, + viewState: { ...state.viewState, zoom }, + })) + }, + setLatestPositions: (latestPositions: VesselPosition[]) => { + set((state) => ({ + ...state, + latestPositions, + })) + }, + setActivePosition: (activePosition: VesselPosition | null) => { + set((state) => ({ + ...state, + activePosition, + })) + }, + addTrackedVessel: (vesselId: number, segments: VesselExcursionSegment[]) => { + set((state) => ({ + ...state, + trackedVesselIDs: [...state.trackedVesselIDs, vesselId], + trackedVesselSegments: [...state.trackedVesselSegments, { vesselId, segments }] + })) + }, + removeTrackedVessel: (vesselId: number) => { + set((state) => ({ + ...state, + trackedVesselIDs: state.trackedVesselIDs.filter( + (id) => id !== vesselId + ), + trackedVesselSegments: state.trackedVesselSegments.filter( + ({vesselId}) => vesselId !== vesselId + ), + })) + }, + clearLatestPositions: () => { + set((state) => ({ + ...state, + latestPositions: [], + })) + }, + cleartrackedVessels: () => { + set((state) => ({ + ...state, + trackedVesselIDs: [], + trackedVesselSegments: [] + })) + }, + })) +} diff --git a/frontend/libs/stores/vessels-store.ts b/frontend/libs/stores/vessels-store.ts new file mode 100644 index 00000000..01311725 --- /dev/null +++ b/frontend/libs/stores/vessels-store.ts @@ -0,0 +1,34 @@ +import { Vessel } from "@/types/vessel" +import { createStore } from "zustand/vanilla" + +export type VesselsState = { + count: number; + vessels: Vessel[]; +} + +export type MapActions = { + decrementCount: () => void + incrementCount: () => void + setVessels: (vessels: Vessel[]) => void +} + +export type VesselsStore = VesselsState & MapActions + +export const defaultInitState: VesselsState = { + count: 0, + vessels: [], +} + +export const createVesselsStore = (initState: VesselsState = defaultInitState) => { + return createStore()((set) => ({ + ...initState, + decrementCount: () => set((state) => ({ count: state.count - 1 })), + incrementCount: () => set((state) => ({ count: state.count + 1 })), + setVessels: (vessels: Vessel[]) => { + set((state) => ({ + ...state, + vessels, + })) + } + })) +} diff --git a/frontend/libs/utils.ts b/frontend/libs/utils.ts new file mode 100644 index 00000000..bd0c391d --- /dev/null +++ b/frontend/libs/utils.ts @@ -0,0 +1,6 @@ +import { clsx, type ClassValue } from "clsx" +import { twMerge } from "tailwind-merge" + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)) +} diff --git a/frontend/prettier.config.js b/frontend/prettier.config.js index 6dd23b3a..eff440e6 100644 --- a/frontend/prettier.config.js +++ b/frontend/prettier.config.js @@ -13,7 +13,7 @@ module.exports = { "^types$", "^@/types/(.*)$", "^@/config/(.*)$", - "^@/lib/(.*)$", + "^@/libs/(.*)$", "^@/hooks/(.*)$", "^@/components/ui/(.*)$", "^@/components/(.*)$",