Skip to content

Commit

Permalink
commit
Browse files Browse the repository at this point in the history
  • Loading branch information
danielmarv committed Jan 22, 2025
1 parent 4cbcd2c commit 2a6bec6
Show file tree
Hide file tree
Showing 10 changed files with 78 additions and 40 deletions.
2 changes: 1 addition & 1 deletion netmanager-app/app/(authenticated)/data-export/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export default function ExportData() {
</p>
<Card>
<Tabs value={activeTab} onValueChange={(value) => setActiveTab(value as ExportType)}>
<TabsList className="grid w-full grid-cols-4">
<TabsList className="grid w-full grid-cols-3">
<TabsTrigger value="sites">Sites</TabsTrigger>
<TabsTrigger value="devices">Devices</TabsTrigger>
<TabsTrigger value="airqlouds">AirQlouds</TabsTrigger>
Expand Down
1 change: 1 addition & 0 deletions netmanager-app/app/types/grids.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export interface Site {
airqlouds: unknown[];
createdAt: string;
updatedAt?: string;
pm2_5?: number;
}

interface SiteCategory {
Expand Down
3 changes: 1 addition & 2 deletions netmanager-app/components/Analytics/CohortsDashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { MoreHorizontal } from 'lucide-react'
import { PollutantCategory } from './PollutantCategory'
import { LineCharts } from '../Charts/Line'
import { BarCharts } from '../Charts/Bar'
import { ExceedancesChart } from './ExceedeanceLine.tsx'
import { ExceedancesChart } from './ExceedanceLine'
import { Cohort} from '@/app/types/cohorts'

interface CohortDashboardProps {
Expand All @@ -19,7 +19,6 @@ interface CohortDashboardProps {

const CohortDashboard: React.FC<CohortDashboardProps> = ({ loading, cohortId, cohorts }) => {
const [chartType, setChartType] = useState<'line' | 'bar'>('line')
// const [chartTypePM, setChartTypePM] = useState<'line' | 'bar'>('bar')

const categories = [
{ pm25level: "Good", iconClass: "bg-green-500" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import { Label } from "@/components/ui/label";
import { MoreHorizontal } from 'lucide-react';
import { EXCEEDANCES_DATA_URI, DEVICE_EXCEEDANCES_URI } from '@/core/urls';
import createAxiosInstance from '@/core/apis/axiosConfig';
import { Site } from '@/app/types/sites';
import { Device } from '@/app/types/devices';
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts';

Expand Down
13 changes: 9 additions & 4 deletions netmanager-app/components/Analytics/GridDashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { useState, useMemo, useEffect } from "react";
import { PollutantCategory } from "./PollutantCategory";
import { LineCharts } from "../Charts/Line";
import { BarCharts } from "../Charts/Bar";
import { ExceedancesChart } from "./ExceedeanceLine.tsx";
import { ExceedancesChart } from "./ExceedanceLine";
import { PM_25_CATEGORY } from "@/core/hooks/categories";
import { Grid, Site } from "@/app/types/grids";

Expand All @@ -19,6 +19,9 @@ import {
DropdownMenuItem,
} from "@/components/ui/dropdown-menu";

interface Categories {
[key: string]: Site[];
}

interface RecentEventFeature {
properties: {
Expand Down Expand Up @@ -57,11 +60,11 @@ const GridDashboard: React.FC<GridDashboardProps> = ({ gridId, loading, grids, r
useEffect(() => {
if (!activeGrid || !recentEventsData?.features) return;

const categorizeSite = (site: Site, pm2_5: number, categories: any) => {
const categorizeSite = (site: Site, pm2_5: number, categories: Categories) => {
Object.keys(PM_25_CATEGORY).forEach((key) => {
const [min, max] = PM_25_CATEGORY[key as keyof typeof PM_25_CATEGORY];
if (pm2_5 > min && pm2_5 <= max) {
categories[key].push({ ...site, pm2_5 });
if (pm2_5 >= 0 && pm2_5 > min && pm2_5 <= max) {
categories[key].push({ ...site, pm2_5, label: site.label || "" });
}
});
};
Expand Down Expand Up @@ -159,6 +162,8 @@ const GridDashboard: React.FC<GridDashboardProps> = ({ gridId, loading, grids, r
viewBox="0 0 15 15"
fill="none"
xmlns="http://www.w3.org/2000/svg"
role="img"
aria-label="Toggle chart type"
>
<path
d="M8.625 2.5C8.625 3.12132 8.12132 3.625 7.5 3.625C6.87868 3.625 6.375 3.12132 6.375 2.5C6.375 1.87868 6.87868 1.375 7.5 1.375C8.12132 1.375 8.625 1.87868 8.625 2.5ZM8.625 7.5C8.625 8.12132 8.12132 8.625 7.5 8.625C6.87868 8.625 6.375 8.12132 6.375 7.5C6.375 6.87868 6.87868 6.375 7.5 6.375C8.12132 6.375 8.625 6.87868 8.625 7.5ZM7.5 13.625C8.12132 13.625 8.625 13.1213 8.625 12.5C8.625 11.8787 8.12132 11.375 7.5 11.375C6.87868 11.375 6.375 11.8787 6.375 12.5C6.375 13.1213 6.87868 13.625 7.5 13.625Z"
Expand Down
43 changes: 21 additions & 22 deletions netmanager-app/components/Analytics/PollutantCategory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,27 +76,26 @@ export function PollutantCategory({ pm25level, iconClass, sites, devices }: Poll
)
}

function getPm25LevelColor(level: string): string {
switch (level.toLowerCase()) {
case 'good': return 'green-500'
case 'moderate': return 'yellow-500'
case 'unhealthy for sensitive groups': return 'orange-500'
case 'unhealthy': return 'red-500'
case 'very unhealthy': return 'purple-500'
case 'hazardous': return 'rose-900'
default: return 'gray-500'
}
}

function getPm25LevelHexColor(level: string): string {
switch (level.toLowerCase()) {
case 'good': return '#10B981'; // green-500
case 'moderate': return '#FBBF24'; // yellow-500
case 'unhealthy for sensitive groups': return '#F97316'; // orange-500
case 'unhealthy': return '#EF4444'; // red-500
case 'very unhealthy': return '#8B5CF6'; // purple-500
case 'hazardous': return '#9B1C31'; // rose-900
default: return '#6B7280'; // gray-500
}
}
const PM25_LEVEL_COLORS = {
good: { class: 'green-500', hex: '#10B981' },
moderate: { class: 'yellow-500', hex: '#FBBF24' },
'unhealthy for sensitive groups': { class: 'orange-500', hex: '#F97316' },
unhealthy: { class: 'red-500', hex: '#EF4444' },
'very unhealthy': { class: 'purple-500', hex: '#8B5CF6' },
hazardous: { class: 'rose-900', hex: '#9B1C31' },
default: { class: 'gray-500', hex: '#6B7280' }
} as const

function getPm25LevelColors(level: string) {
const key = level.toLowerCase() as keyof typeof PM25_LEVEL_COLORS
return PM25_LEVEL_COLORS[key] || PM25_LEVEL_COLORS.default
}

function getPm25LevelColor(level: string): string {
return getPm25LevelColors(level).class
}

function getPm25LevelHexColor(level: string): string {
return getPm25LevelColors(level).hex
}
2 changes: 1 addition & 1 deletion netmanager-app/components/Analytics/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ const NewAnalytics: React.FC = () => {
const handleDownloadData = async () => {
setDownloadingData(true)
try {
const response = await dataExport({
await dataExport({
sites: !isCohort ? activeGrid?.sites.map(site => site._id) : [],
devices: isCohort ? activeCohort?.devices.map(device => device._id) : [],
startDateTime: new Date(Date.now() - 5 * 24 * 60 * 60 * 1000).toISOString(),
Expand Down
22 changes: 13 additions & 9 deletions netmanager-app/components/export-data/ExportForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { useDevices } from "@/core/hooks/useDevices";
import { DatePicker } from "@/components/ui/date-picker";
import { dataExport } from "@/core/apis/analytics";
import { useAppSelector } from "@/core/redux/hooks";
import { Grid } from "@/app/types/grids";

const pollutantOptions = [
{ value: "pm2.5", label: "PM2.5" },
Expand Down Expand Up @@ -74,7 +75,7 @@ export const roundToStartOfDay = (dateISOString: string): Date => {
export default function ExportForm({ exportType }: ExportFormProps) {
const [loading, setLoading] = useState(false);
const { sites } = useSites();
const { cities } = useGrids();
const { grids } = useGrids();
const { devices } = useDevices();
const activeNetwork = useAppSelector((state) => state.user.activeNetwork);

Expand All @@ -97,28 +98,31 @@ export default function ExportForm({ exportType }: ExportFormProps) {
const [deviceOptions, setDeviceOptions] = useState<Option[]>([]);

useEffect(() => {
let isSubscribed = true;
if (sites?.length) {
const newSiteOptions = sites.map((site: Site) => ({ value: site._id, label: site.name }));
if (JSON.stringify(newSiteOptions) !== JSON.stringify(siteOptions)) {
if (isSubscribed && JSON.stringify(newSiteOptions) !== JSON.stringify(siteOptions)) {
setSiteOptions(newSiteOptions);
}

}
if (cities?.length) {
const newCityOptions = cities.map((city: City) => ({ value: city._id, label: city.name }));
if (JSON.stringify(newCityOptions) !== JSON.stringify(cityOptions)) {
if (grids?.length) {
const newCityOptions = grids.map((grid: Grid) => ({ value: grid._id, label: grid.name }));
if (isSubscribed && JSON.stringify(newCityOptions) !== JSON.stringify(cityOptions)) {
setCityOptions(newCityOptions);
}
}

if (devices?.length) {
const newDeviceOptions = devices.map((device: Device) => ({ value: device._id, label: device.name }));
if (JSON.stringify(newDeviceOptions) !== JSON.stringify(deviceOptions)) {
if (isSubscribed && JSON.stringify(newDeviceOptions) !== JSON.stringify(deviceOptions)) {
setDeviceOptions(newDeviceOptions);
}
}

}, [sites, cities, devices, siteOptions, cityOptions, deviceOptions]);
return () => {
isSubscribed = false;
};
}, [sites, grids, devices]);

const exportData = (data: string, filename: string, type: string) => {
const blob = new Blob([data], { type });
Expand Down Expand Up @@ -310,7 +314,7 @@ export default function ExportForm({ exportType }: ExportFormProps) {
case "devices":
return renderMultiSelect("devices", deviceOptions, "Select devices", { required: "At least one device must be selected" });
case "airqlouds":
return renderMultiSelect("cities", cityOptions, "Select airqlouds", { required: "At least one airqloud must be selected" });
return renderMultiSelect("cities", cityOptions, "Select Grids", { required: "At least one Grids must be selected" });
default:
return null;
}
Expand Down
30 changes: 30 additions & 0 deletions netmanager-app/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions netmanager-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"@radix-ui/react-popover": "^1.1.4",
"@radix-ui/react-select": "^2.1.4",
"@radix-ui/react-slot": "^1.1.1",
"@radix-ui/react-tabs": "^1.1.2",
"@radix-ui/react-tooltip": "^1.1.6",
"@reduxjs/toolkit": "^2.5.0",
"@tanstack/react-query": "^5.62.11",
Expand Down

0 comments on commit 2a6bec6

Please sign in to comment.