From 05ba4ab920b77bdc9ef97b4ad109bfb75b811f80 Mon Sep 17 00:00:00 2001 From: vergiLgood1 Date: Wed, 7 May 2025 08:01:07 +0700 Subject: [PATCH] feat: enhance SidebarInfoTab with detailed map layers and add timeline layer functionality to CrimeMap; update TimelineLegend and TimelinePopup styles --- .../controls/left/sidebar/tabs/info-tab.tsx | 108 +++++++++++++++++- .../app/_components/map/crime-map.tsx | 32 +++++- .../map/legends/timeline-legend.tsx | 16 ++- .../_components/map/pop-up/timeline-popup.tsx | 2 +- 4 files changed, 145 insertions(+), 13 deletions(-) diff --git a/sigap-website/app/_components/map/controls/left/sidebar/tabs/info-tab.tsx b/sigap-website/app/_components/map/controls/left/sidebar/tabs/info-tab.tsx index e265f3f..ee84835 100644 --- a/sigap-website/app/_components/map/controls/left/sidebar/tabs/info-tab.tsx +++ b/sigap-website/app/_components/map/controls/left/sidebar/tabs/info-tab.tsx @@ -1,5 +1,5 @@ import React from 'react' -import { Layers, Info, Eye, Filter, MapPin, AlertTriangle, AlertCircle } from 'lucide-react' +import { Layers, Info, Eye, Filter, MapPin, AlertTriangle, AlertCircle, Clock, Flame, MapPinned, Users, Map, Box, Thermometer } from 'lucide-react' import { Card, CardContent } from "@/app/_components/ui/card" import { Separator } from "@/app/_components/ui/separator" import { CRIME_RATE_COLORS } from "@/app/_utils/const/map" @@ -44,6 +44,112 @@ export function SidebarInfoTab() { + }> + + +
+

+ + Incidents Layer +

+

+ Shows individual crime incidents as map markers. Each marker represents a single crime report and is color-coded by category. + Click on any marker to see detailed information about the incident. +

+
+ +
+

+ + Clusters Layer +

+

+ Groups nearby incidents into clusters for better visibility at lower zoom levels. Numbers show incident count in each cluster. + Clusters are color-coded by size: blue (small), yellow (medium), pink (large). + Click on a cluster to zoom in and see individual incidents. +

+
+
+
+ 1-5 +
+
+
+ 6-15 +
+
+
+ 15+ +
+
+
+ +
+

+ + Heatmap Layer +

+

+ Shows crime density across regions, with warmer colors (red, orange) indicating higher crime concentration + and cooler colors (blue) showing lower concentration. Useful for identifying crime hotspots. +

+
+
+
+ Low + Density + High +
+
+
+ +
+

+ + Units Layer +

+

+ Displays police and security units as blue circles with connecting lines to nearby incidents. + Units are labeled and can be clicked to show more information and related incident details. +

+
+
+ Police/Security Unit +
+
+ +
+

+ + Timeline Layer +

+

+ Shows time patterns of crime incidents with color-coded circles representing average times of day when + incidents occur in each district. Click for detailed time distribution analysis. +

+
+
+
+ Morning +
+
+
+ Afternoon +
+
+
+ Evening +
+
+
+ Night +
+
+
+
+
+
+ }> diff --git a/sigap-website/app/_components/map/crime-map.tsx b/sigap-website/app/_components/map/crime-map.tsx index fe8ca0a..c454df3 100644 --- a/sigap-website/app/_components/map/crime-map.tsx +++ b/sigap-website/app/_components/map/crime-map.tsx @@ -37,6 +37,9 @@ export default function CrimeMap() { const [isTimelapsePlaying, setisTimelapsePlaying] = useState(false) const [isSearchActive, setIsSearchActive] = useState(false) const [showUnitsLayer, setShowUnitsLayer] = useState(false) + const [showClusters, setShowClusters] = useState(false) + const [showHeatmap, setShowHeatmap] = useState(false) + const [showUnclustered, setShowUnclustered] = useState(true) const [useAllYears, setUseAllYears] = useState(false) const [useAllMonths, setUseAllMonths] = useState(false) @@ -153,6 +156,18 @@ export default function CrimeMap() { const handleControlChange = (controlId: ITooltips) => { setActiveControl(controlId); + if (controlId === "clusters") { + setShowClusters(true) + } else { + setShowClusters(false) + } + + if (controlId === "incidents") { + setShowUnclustered(true) + } else { + setShowUnclustered(false) + } + if (controlId === "search") { setIsSearchActive(prev => !prev); } @@ -244,12 +259,19 @@ export default function CrimeMap() { selectedYear={selectedYear} selectedMonth={selectedMonth} /> -
- -
+ {isFullscreen && ( +
+ {showClusters && ( + + )} + {showUnclustered && !showClusters && ( + + )} +
+ )} {isFullscreen && showUnitsLayer && ( -
+
+
)} diff --git a/sigap-website/app/_components/map/legends/timeline-legend.tsx b/sigap-website/app/_components/map/legends/timeline-legend.tsx index c81f34d..2138ba7 100644 --- a/sigap-website/app/_components/map/legends/timeline-legend.tsx +++ b/sigap-website/app/_components/map/legends/timeline-legend.tsx @@ -1,7 +1,7 @@ "use client" import { Card } from "@/app/_components/ui/card" -import { Clock, Moon, Sun } from "lucide-react" +import { Clock, Moon, Sun, Sunset } from "lucide-react" interface TimelineLegendProps { position?: "top-right" | "top-left" | "bottom-right" | "bottom-left" @@ -18,36 +18,40 @@ export default function TimelineLegend({ } return ( - -
-

+ +
+

Incident Time Patterns

-
+
+
Morning (5am-12pm)
+
Afternoon (12pm-5pm)
+
Evening (5pm-9pm)
+
Night (9pm-5am)
-
+
Circles show average incident time. Click for details.
diff --git a/sigap-website/app/_components/map/pop-up/timeline-popup.tsx b/sigap-website/app/_components/map/pop-up/timeline-popup.tsx index 581e358..37d4a1e 100644 --- a/sigap-website/app/_components/map/pop-up/timeline-popup.tsx +++ b/sigap-website/app/_components/map/pop-up/timeline-popup.tsx @@ -59,7 +59,7 @@ export default function TimelinePopup({ anchor="bottom" closeOnClick={false} onClose={onClose} - className="z-10" + className="timeline-popup z-10" maxWidth="300px" >