From 4bd9b27909ca3bd9917d2a5c488c5da48553bcbc Mon Sep 17 00:00:00 2001 From: bernard-ng Date: Sun, 12 Oct 2025 13:47:44 +0200 Subject: [PATCH] chore(release): v1.0.0 --- .github/workflows/backend-tests.yml | 6 ++++++ .github/workflows/frontend-quality.yml | 2 +- client/src/App.tsx | 19 ------------------- client/src/components/app/header-overlay.tsx | 19 +++++++------------ client/src/components/app/sidebar-panels.tsx | 11 +++-------- .../src/components/panels/map-tiles-panel.tsx | 10 ++++------ server/.env.test | 1 + server/src/Controller/SignalController.php | 5 ++++- server/src/Service/SignalSnapshotBuilder.php | 10 ++++++---- 9 files changed, 32 insertions(+), 51 deletions(-) diff --git a/.github/workflows/backend-tests.yml b/.github/workflows/backend-tests.yml index 606c01b..588cfe5 100644 --- a/.github/workflows/backend-tests.yml +++ b/.github/workflows/backend-tests.yml @@ -36,5 +36,11 @@ jobs: - name: Install dependencies run: composer install --no-interaction --prefer-dist + - name: Set up database + run: | + APP_ENV=test php bin/console doctrine:database:create --env=test + APP_ENV=test php bin/console doctrine:migrations:migrate --no-interaction --env=test + APP_ENV=test php bin/console doctrine:fixtures:load --no-interaction --env=test + - name: Run PHPUnit run: vendor/bin/phpunit diff --git a/.github/workflows/frontend-quality.yml b/.github/workflows/frontend-quality.yml index ab902f7..4d58fe7 100644 --- a/.github/workflows/frontend-quality.yml +++ b/.github/workflows/frontend-quality.yml @@ -55,7 +55,7 @@ jobs: run: npm ci - name: Check formatting - run: npx prettier --check . + run: npm run check typecheck: name: Type Check diff --git a/client/src/App.tsx b/client/src/App.tsx index 72aa5c9..1fe6238 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -7,7 +7,6 @@ import { ConfirmSignalDialog } from "@/components/app/confirm-signal-dialog"; import { HeaderOverlay } from "@/components/app/header-overlay"; import { SidebarPanels } from "@/components/app/sidebar-panels"; import { MapViewport } from "@/components/map/map-viewport"; -// Alert dialog moved into a dedicated component import { SidebarProvider, Sidebar, SidebarContent, SidebarInset } from "@/components/ui/sidebar"; import { Toaster } from "@/components/ui/sonner"; import { useFeedDerivations } from "@/hooks/use-feed-derivations"; @@ -41,12 +40,7 @@ export default function App() { const isRequestingLocation = useAppStore(state => state.isRequestingLocation); const isDetailsOpen = useAppStore(state => state.isSidebarOpen); const setIsDetailsOpen = useAppStore(state => state.setIsSidebarOpen); - const isHeaderCollapsed = useAppStore(state => state.isHeaderCollapsed); - const setIsHeaderCollapsed = useAppStore(state => state.setIsHeaderCollapsed); - const isMobileHeaderOpen = useAppStore(state => state.isMobileHeaderOpen); - const setIsMobileHeaderOpen = useAppStore(state => state.setIsMobileHeaderOpen); const tileProvider = useAppStore(state => state.tileProvider); - const setTileProvider = useAppStore(state => state.setTileProvider); const { refresh: refreshLocation } = useUserLocation(); const { @@ -73,8 +67,6 @@ export default function App() { [selectVisibleLatestByUser, userLocation] ); - // Derived lists depend on focusOn; initialize map first, then derive. - const statusLabel = t(`status.${status}`); const lastUpdatedLabel = lastUpdated ? formatRelativeTime(lastUpdated, locale) : t("common.never"); const isLoading = status === "loading"; @@ -166,11 +158,9 @@ export default function App() { setIsConfirmOpen(true); }, [userLocation]); - // recentActivity and dangerCells returned above const confirmationLat = pendingSpot ? formatCoordinate(pendingSpot.lat, locale) : "--"; const confirmationLng = pendingSpot ? formatCoordinate(pendingSpot.lng, locale) : "--"; const isDialogDisabled = !pendingSpot || isConfirming; - const detailsToggleLabel = isDetailsOpen ? t("details.close") : t("details.open"); return ( <> @@ -187,9 +177,6 @@ export default function App() { isBusy={isPosting || isConfirming} locationHint={locationHint} showLocationCta={showLocationCta} - hasLocation={hasLocation} - tileProvider={tileProvider} - setTileProvider={setTileProvider} dangerCells={dangerCells} recentActivity={recentActivity} /> @@ -219,12 +206,6 @@ export default function App() { disableHeat={visibleDensity.length === 0} disableLocate={!hasLocation} disableMySignal={!myVisibleSignal} - isDetailsOpen={isDetailsOpen} - detailsToggleLabel={detailsToggleLabel} - isHeaderCollapsed={isHeaderCollapsed} - setIsHeaderCollapsed={setIsHeaderCollapsed} - isMobileHeaderOpen={isMobileHeaderOpen} - setIsMobileHeaderOpen={setIsMobileHeaderOpen} /> void; - isMobileHeaderOpen: boolean; - setIsMobileHeaderOpen: (open: boolean) => void; } export function HeaderOverlay({ @@ -38,14 +33,14 @@ export function HeaderOverlay({ disableHeat, disableLocate, disableMySignal, - isDetailsOpen, - detailsToggleLabel, - isHeaderCollapsed, - setIsHeaderCollapsed, - isMobileHeaderOpen, - setIsMobileHeaderOpen, }: HeaderOverlayProps) { const { t } = useTranslation(); + const isDetailsOpen = useAppStore(state => state.isSidebarOpen); + const isHeaderCollapsed = useAppStore(state => state.isHeaderCollapsed); + const setIsHeaderCollapsed = useAppStore(state => state.setIsHeaderCollapsed); + const isMobileHeaderOpen = useAppStore(state => state.isMobileHeaderOpen); + const setIsMobileHeaderOpen = useAppStore(state => state.setIsMobileHeaderOpen); + const detailsToggleLabel = isDetailsOpen ? t("details.close") : t("details.open"); return (
diff --git a/client/src/components/app/sidebar-panels.tsx b/client/src/components/app/sidebar-panels.tsx index f0e2fff..2ea6152 100644 --- a/client/src/components/app/sidebar-panels.tsx +++ b/client/src/components/app/sidebar-panels.tsx @@ -6,8 +6,8 @@ import { MapTilesPanel } from "@/components/panels/map-tiles-panel"; import { OverviewPanel } from "@/components/panels/overview-panel"; import { ScrollArea } from "@/components/ui/scroll-area"; import type { FeedError } from "@/hooks/use-hotsop-feed"; -import type { TileProvider } from "@/hooks/use-leaflet-heatmap"; import { formatRelativeTime } from "@/lib/utils"; +import { useAppStore } from "@/store/use-app-store"; type DangerCell = { id: string; @@ -36,9 +36,6 @@ interface SidebarPanelsProps { isBusy: boolean; locationHint: string; showLocationCta: boolean; - hasLocation: boolean; - tileProvider: TileProvider; - setTileProvider: (p: TileProvider) => void; dangerCells: DangerCell[]; recentActivity: ActivityItem[]; } @@ -53,14 +50,12 @@ export function SidebarPanels({ isBusy, locationHint, showLocationCta, - hasLocation, - tileProvider, - setTileProvider, dangerCells, recentActivity, }: SidebarPanelsProps) { const { i18n, t } = useTranslation(); const locale = i18n.language === "fr" ? "fr-FR" : "en-US"; + const hasLocation = useAppStore(state => Boolean(state.userLocation)); return ( @@ -80,7 +75,7 @@ export function SidebarPanels({ /> - +
); diff --git a/client/src/components/panels/map-tiles-panel.tsx b/client/src/components/panels/map-tiles-panel.tsx index 4ad7ea2..ad6937e 100644 --- a/client/src/components/panels/map-tiles-panel.tsx +++ b/client/src/components/panels/map-tiles-panel.tsx @@ -6,14 +6,12 @@ import { useTranslation } from "react-i18next"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import type { TileProvider } from "@/hooks/use-leaflet-heatmap"; +import { useAppStore } from "@/store/use-app-store"; -interface MapTilesPanelProps { - tileProvider: TileProvider; - setTileProvider: (provider: TileProvider) => void; -} - -export function MapTilesPanel({ tileProvider, setTileProvider }: MapTilesPanelProps) { +export function MapTilesPanel() { const { t } = useTranslation(); + const tileProvider = useAppStore(state => state.tileProvider); + const setTileProvider = useAppStore(state => state.setTileProvider); const tileOptions = useMemo( () => [ { value: "openstreetmap" as TileProvider, label: t("map.tiles.openstreetmap") }, diff --git a/server/.env.test b/server/.env.test index 8f4ac7c..03b0ae3 100644 --- a/server/.env.test +++ b/server/.env.test @@ -2,3 +2,4 @@ KERNEL_CLASS='App\Kernel' APP_SECRET='$ecretf0rt3st' CORS_ALLOW_ORIGIN='^https?://(?:localhost|127\\.0\\.0\\.1)(?::[0-9]+)?$' +DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db" diff --git a/server/src/Controller/SignalController.php b/server/src/Controller/SignalController.php index 604cf97..528f508 100644 --- a/server/src/Controller/SignalController.php +++ b/server/src/Controller/SignalController.php @@ -45,7 +45,10 @@ class SignalController 'clientKey' => $clientKey, 'point' => [ 'id' => $signal->id->toString(), - 'signalLocation' => $signal->signalLocation, + 'signalLocation' => [ + 'lat' => $signal->signalLocation->getLat(), + 'lng' => $signal->signalLocation->getLng(), + ], 'createdAt' => $signal->createdAt->format(DATE_ATOM), 'userKey' => $signal->userKey, ], diff --git a/server/src/Service/SignalSnapshotBuilder.php b/server/src/Service/SignalSnapshotBuilder.php index 41dc71b..e00e9bb 100644 --- a/server/src/Service/SignalSnapshotBuilder.php +++ b/server/src/Service/SignalSnapshotBuilder.php @@ -5,7 +5,6 @@ declare(strict_types=1); namespace App\Service; use App\Entity\Signal; -use App\ValueObject\Point; class SignalSnapshotBuilder { @@ -15,14 +14,14 @@ class SignalSnapshotBuilder * @return array{ * points: list, * density: list, * latestByUser: list, @@ -38,7 +37,10 @@ class SignalSnapshotBuilder foreach ($signals as $signal) { $point = [ 'id' => $signal->id->toString(), - 'signalLocation' => $signal->signalLocation, + 'signalLocation' => [ + 'lat' => $signal->signalLocation->getLat(), + 'lng' => $signal->signalLocation->getLng(), + ], 'createdAt' => $signal->createdAt->format(DATE_ATOM), 'userKey' => $signal->userKey, ];