Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions webapp/src/app/app-seed.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { AppWrapper } from "./app-wrapper";
import { AppRouterSeed } from "./routes/app-router-seed";

import "./styles/globals.css";
import "./styles/seed.css";

const AppSeed = () => {
return (
<AppWrapper>
<AppRouterSeed />
</AppWrapper>
);
};

export default AppSeed;
6 changes: 3 additions & 3 deletions webapp/src/app/global-router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { lazy } from "react";
import { BrowserRouter, Navigate, Route, Routes } from "react-router-dom";

const AppAll4Trees = lazy(() => import("./app-all4trees"));
// const AppSeed = lazy(() => import("./app-seed")); #uncomment next PR
const AppSeed = lazy(() => import("./app-seed"));

export default function GlobalRouter() {
return (
Expand All @@ -12,10 +12,10 @@ export default function GlobalRouter() {
element={<AppAll4Trees />}
path="/all4trees/*"
/>
{/* <Route #uncomment next PR
<Route
element={<AppSeed />}
path="/seed/*"
/> */}
/>
<Route
element={<Navigate to="/all4trees" />}
index
Expand Down
77 changes: 77 additions & 0 deletions webapp/src/app/providers/map-provider-seed.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { createMap, EVENTS } from "coordo";
import { type ReactNode, useCallback, useRef, useState } from "react";

import { API_URL } from "@shared/api/client";
import { MapContext } from "@shared/contexts/map-context-seed";
import { useLocalStorage } from "@shared/hooks/use-local-storage";

const STYLE_URL = `${API_URL}/maps/style.json`;

type MapSettings = {
zoom: number;
center: [number, number];
};

const DEFAULT_MAP_SETTINGS: MapSettings = {
center: [34.1246, -23.0758],
zoom: 3.8,
};

type MapProviderSeedProps = {
children: ReactNode;
};

export function MapProviderSeed({ children }: MapProviderSeedProps) {
const [isReady, setIsReady] = useState(false);
const mapApiRef = useRef<ReturnType<typeof createMap> | null>(null);
const [mapSettings, setMapSettings] = useLocalStorage<MapSettings>(
"d4g:map-settings:seed",
DEFAULT_MAP_SETTINGS,
);

// Callback ref pattern — called by React when the DOM node mounts/unmounts.
// See: https://dev.to/gilfink/quick-tip-using-callback-refs-in-react-4gef
// biome-ignore lint/correctness/useExhaustiveDependencies: map init should run only once on mount
const mapContainerRef = useCallback((node: HTMLElement | null) => {
if (!node || mapApiRef.current) return;

const handleReady = () => {
setIsReady(true);
};

node.addEventListener(EVENTS.MAP_READY, handleReady);

try {
mapApiRef.current = createMap(`#${node.id}`, STYLE_URL, {
center: mapSettings.center,
zoom: mapSettings.zoom,
});
if (import.meta.env.DEV) {
// biome-ignore lint/suspicious/noExplicitAny : debug only
(window as any).__map__ = mapApiRef.current?.mapInstance;
}
// biome-ignore lint/suspicious/noExplicitAny : <no types from the lib coordo>
mapApiRef.current.addEventListener("move", (event: any) => {
setMapSettings({
center: event.target.getCenter().toArray(),
zoom: event.target.getZoom(),
});
});
} catch (error) {
console.error("Error when initializing the map:", error);
}
}, []);

return (
<MapContext
value={{
isReady,
mapApiRef,
mapContainerRef,
setIsReady,
}}
>
{children}
</MapContext>
);
}
20 changes: 20 additions & 0 deletions webapp/src/app/routes/app-router-seed.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { lazy } from "react";

import { MapProviderSeed } from "@app/providers/map-provider-seed";

import { AppRouterBase } from "./app-router-base";

const MainPage = lazy(() => import("@pages/seed/main"));

export const AppRouterSeed = () => {
return (
<AppRouterBase
MainPage={MainPage}
MapProvider={MapProviderSeed}
rootLayoutProps={{
hasDashboard: false,
logoSrc: "/seed-logo.png",
}}
/>
);
};
161 changes: 161 additions & 0 deletions webapp/src/app/styles/seed.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
/* ==========================================================================
Charte Graphique Seed - Variables CSS & Classes Utilitaires
--------------------------------------------------------------------------
-> Utiliser le préfix seed pour les variables de la charte graphique.
-> Utiliser le préfix custom pour les variables du Figma.
-> Pour utiliser les niveaux d'alpha, il faut utiliser la notation rgb
--seed-rgb-my-color: 123, 123, 123;
--seed-color-my-color: rgba(var(--seed-rgb-my-color), 1);
--other-usage: rgba(var(--seed-rgb-my-color), 0.3);
========================================================================== */

@import "tailwindcss";
@import "./index.css";

:root {
/* ========================================================================
COULEURS PRINCIPALES - CHARTE SEED

/!\ WRONG VALUES AND TOKENS => THESE ARE FOR TESTING NOW
======================================================================== */

--seed-color-nuit: #0f0f0f;
--seed-color-onyx: #424242;
--seed-color-brunswick-green: #224d41;
--seed-rgb-vert-kelly: 153, 207, 22;
--seed-color-vert-kelly: rgba(var(--seed-rgb-vert-kelly), 1);
--seed-color-jaune-vert: #99cf16;
--seed-color-citrouille: #e40000;
--seed-color-alabaster: #e1cd16;

/* ========================================================================
COULEURS LA FORET - CHARTE SEED
======================================================================== */
--seed-color-bleu: #123762;
--seed-color-vert-de-gris: #7dabae;

/* ========================================================================
COULEURS AJUSTEES - POUR UNE MEILLEURE UI
======================================================================== */
--custom-color-green-dark: #358055;
--custom-color-green-main: #0d1d18;
--custom-color-green-pastel: #31d181;
--custom-color-grey-light: #e5e7eb;
--custom-color-blue-dark: #207ee2;
--custom-color-blue-light: #52a4ff;

--custom-color-socio-eco: #1447e6; /* Same as in socio-eco-icon */
--custom-color-inventaire: #5e1a1a; /* Same as in inventaire-icon */

/* ========================================================================
TYPOGRAPHIE - CHARTE SEED
======================================================================== */

--font-title-primary:
"Phosphate", "Phosphate Solid", Impact, "Arial Black", system-ui, sans-serif;
--font-body-primary: Arial, system-ui, -apple-system, "Segoe UI", sans-serif;

--font-title-secondary:
"Century Gothic", "Century Gothic Black", "Arial Black", system-ui,
sans-serif;
--font-body-secondary:
"Open Sans", Arial, system-ui, -apple-system, "Segoe UI", sans-serif;
}

/* ========================================================================
THEME TOKEN CONFIGURATIONS ALL 4 TREES: light (root) and dark
Docs: https://ui.shadcn.com/docs/theming
======================================================================== */
:root {
/* LIGHT MODE SHADCN */
--background: var(--seed-color-alabaster);
--foreground: var(--seed-color-nuit);

--card: var(--custom-color-grey-light);
--card-foreground: var(--seed-color-nuit);

--popover: var(--seed-color-alabaster);
--popover-foreground: var(--seed-color-nuit);

--primary: var(--seed-color-vert-kelly);
--primary-foreground: var(--seed-color-nuit);
--secondary: var(--seed-color-jaune-vert);
--secondary-foreground: var(--seed-color-nuit);

--muted: #e5e7eb;
--muted-foreground: var(--seed-color-onyx);
--accent: var(--seed-color-jaune-vert);
--accent-foreground: var(--seed-color-nuit);
--destructive: #dc2626;
--info: var(--custom-color-blue-light);
--info-foreground: var(--custom-color-blue-dark);

--border: rgba(0, 0, 0, 0.15);
--input: #ffffff;
--ring: var(--seed-color-vert-kelly);

--chart-1: var(--seed-color-vert-kelly);
--chart-2: var(--seed-color-citrouille);
--chart-3: var(--seed-color-bleu);
--chart-4: #895bf5;
--chart-5: #f04646;
--chart-6: var(--seed-color-onyx);

--sidebar: var(--seed-color-alabaster);
--sidebar-foreground: var(--seed-color-alabaster);
--sidebar-primary: var(--seed-color-brunswick-green);
--sidebar-primary-foreground: var(--seed-color-alabaster);
--sidebar-accent: var(--seed-color-citrouille);
--sidebar-accent-foreground: #ffffff;
--sidebar-border: #e5e7eb;
--sidebar-ring: var(--seed-color-vert-kelly);
}

.dark {
--background: var(--custom-color-green-dark);
--foreground: var(--seed-color-alabaster);

--card: var(--custom-color-blue-dark);
--card-foreground: var(--seed-color-alabaster);

--popover: var(--seed-color-nuit);
--popover-foreground: var(--seed-color-alabaster);

--primary: var(--seed-color-brunswick-green);
--primary-foreground: var(--custom-color-green-pastel);
--secondary: var(--seed-color-vert-de-gris);
--secondary-foreground: var(--seed-color-nuit);

--muted: var(--seed-color-onyx);
--muted-foreground: #9ca3af;
--accent: var(--custom-color-green-main);
--accent-foreground: var(--custom-color-green-pastel);
--destructive: #ef4444;
--info: var(--custom-color-blue-dark);
--info-foreground: var(--custom-color-blue-light);

--border: rgba(255, 255, 255, 0.15);
--input: rgba(255, 255, 255, 0.05);
--ring: var(--seed-color-jaune-vert);

--sidebar: var(--seed-color-onyx);
--sidebar-foreground: var(--seed-color-alabaster);
--sidebar-primary: var(--seed-color-onyx);
--sidebar-primary-foreground: var(--seed-color-vert-kelly);
--sidebar-accent: var(--seed-color-citrouille);
--sidebar-accent-foreground: var(--seed-color-nuit);
--sidebar-border: rgba(255, 255, 255, 0.15);
--sidebar-ring: var(--seed-color-jaune-vert);
}

@theme inline {
--color-socio-eco: var(--custom-color-socio-eco);
--color-inventaire: var(--custom-color-inventaire);
}

@layer components {
* {
outline-color: rgba(#a21111, 0.2);
border-color: var(--border);
}
}
43 changes: 43 additions & 0 deletions webapp/src/pages/seed/main.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { MapSeed } from "@widgets/map/map-seed";

import { SidebarProvider } from "@shared/ui/sidebar";

import {
ResizableHandle,
ResizablePanel,
ResizablePanelGroup,
} from "@ui/resizable";

export interface MainPageProps {
userData?: unknown;
}

function MainPage() {
return (
<>
{/* TODO: Integrate Sidebar with Resizable Panels smoothly: https://github.com/huntabyte/shadcn-svelte/discussions/1657 */}
<ResizablePanelGroup
className="bg-background"
direction="horizontal"
>
<SidebarProvider>
<ResizablePanel
className="h-full"
defaultSize={20}
>
<p>This is seed !</p>
</ResizablePanel>

<ResizableHandle />

<ResizablePanel defaultSize={80}>
<MapSeed />
</ResizablePanel>
</SidebarProvider>
</ResizablePanelGroup>
</>
);
}

// Default export for lazy loading import
export default MainPage;
26 changes: 26 additions & 0 deletions webapp/src/shared/contexts/map-context-seed.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import type { createMap } from "coordo";
import {
createContext,
type RefCallback,
type RefObject,
useContext,
} from "react";

export type Category = { value: string; label: string };

export interface MapContextType {
isReady: boolean;
mapApiRef: RefObject<ReturnType<typeof createMap> | null>;
mapContainerRef: RefCallback<HTMLElement>;
setIsReady: (isReady: boolean) => void;
}

export const MapContext = createContext<MapContextType | undefined>(undefined);

export function useMapContext() {
const context = useContext(MapContext);
if (!context) {
throw new Error("useMapContext must be used within a MapProvider");
}
return context;
}
11 changes: 11 additions & 0 deletions webapp/src/widgets/map/assets/seed-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading