Skip to content

Commit 7aa66b1

Browse files
styling fixes and start of error states
1 parent d28934e commit 7aa66b1

File tree

8 files changed

+99
-60
lines changed

8 files changed

+99
-60
lines changed

frontend/app/location-based-risk/hooks/useGeoJSONLayers.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export const useGeoJSONLayers = (
2626
const hasAddedLayersRef = useRef(false);
2727

2828
const [loading, setLoading] = useState(true);
29+
const [error, setError] = useState(false);
2930
const {
3031
data: geoJsonCountyData,
3132
isLoading: isLoadingGeoJsonData,
@@ -70,11 +71,10 @@ export const useGeoJSONLayers = (
7071
}).addTo(map);
7172
setLoading(false);
7273
hasAddedLayersRef.current = true;
73-
} catch (err) {
74-
setLoading(false);
75-
console.error("Error adding GeoJSON layers:", err);
74+
} catch (_err) {
75+
setError(true);
7676
}
7777
}, [geoJsonCountyData, femaRiskCountyLookup, map]);
7878

79-
return { loading };
79+
return { loading, error };
8080
};

frontend/app/location-based-risk/hooks/useLeafletLoader.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { useEffect, useState } from "react";
55
*/
66
export const useLeafletLoader = () => {
77
const [isLoaded, setIsLoaded] = useState(false);
8-
const [error, setError] = useState<string | null>(null);
8+
const [error, setError] = useState(false);
99

1010
useEffect(() => {
1111
if (window.L) {
@@ -30,10 +30,9 @@ export const useLeafletLoader = () => {
3030
script.onerror = () => reject(new Error("Failed to load Leaflet"));
3131
document.head.appendChild(script);
3232
});
33-
3433
setIsLoaded(true);
35-
} catch (err) {
36-
setError(err instanceof Error ? err.message : "Failed to load Leaflet");
34+
} catch (_err) {
35+
setError(true);
3736
}
3837
};
3938

frontend/app/location-based-risk/hooks/useLeafletMap.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export const useLeafletMap = (
1111
) => {
1212
const mapInstanceRef = useRef<Map | null>(null);
1313
const [isReady, setIsReady] = useState(false);
14+
const [error, setError] = useState(false);
1415

1516
// Initialize map
1617
useEffect(() => {
@@ -39,8 +40,8 @@ export const useLeafletMap = (
3940
}).addTo(map);
4041

4142
setIsReady(true);
42-
} catch (err) {
43-
console.error("Error initializing map:", err);
43+
} catch (_err) {
44+
setError(true);
4445
}
4546
}, 50);
4647

@@ -70,5 +71,6 @@ export const useLeafletMap = (
7071
map: mapInstanceRef.current,
7172
isReady,
7273
panTo,
74+
error,
7375
};
7476
};
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { FaExclamation } from "react-icons/fa6";
2+
3+
export default function ErrorDisplay() {
4+
return (
5+
<div className="flex flex-1 flex-col items-center justify-center h-full text-center gap-4 z-10 relative">
6+
<div className="flex w-16 h-16 bg-fuchsia rounded-full items-center justify-center">
7+
<FaExclamation color="white" size={50} />
8+
</div>
9+
<div>
10+
<h3 className="text-lg font-bold mb-2">Error Fetching Data</h3>
11+
<p className="text-sm text-gray-600">Please try again later</p>
12+
</div>
13+
</div>
14+
);
15+
}

frontend/components/dashboard/DashboardBody.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,18 @@ export default function DashboardBody() {
3333
</div>
3434

3535
{/* Two Column Grid for Revenue and Next Steps */}
36-
<div className="grid grid-cols-1 lg:grid-cols-6 gap-6">
36+
<div className="grid grid-cols-1 xl:grid-cols-6 gap-6">
3737
{/* Left Column - Revenue & Expenses */}
38-
<div className="w-full lg:col-span-4 relative">
39-
{hasData?.hasExternalData || hasData?.hasFinancialData ? (
38+
<div className="w-full xl:col-span-4 relative">
39+
{hasData?.hasExternalData || hasData?.hasFinancialData || hasDataLoading ? (
4040
<RevenueAndExpenses />
4141
) : (
4242
<RevenueAndExpensesNoData />
4343
)}
4444
</div>
4545

4646
{/* Right Column - Next Steps */}
47-
<div className="w-full lg:col-span-2">
47+
<div className="w-full xl:col-span-2">
4848
<NextSteps bannerData={bannerData ?? { status: "no-disaster" }} />
4949
</div>
5050
</div>
@@ -59,7 +59,7 @@ export default function DashboardBody() {
5959
{/* Right Column - Net Disaster Expense */}
6060
<div className="w-full lg:col-span-2">
6161
{bannerData?.status === "has-claim" &&
62-
(hasData?.hasExternalData || hasData?.hasFinancialData ? (
62+
(hasData?.hasExternalData || hasData?.hasFinancialData || hasDataLoading ? (
6363
<NetDisasterExpense bannerData={bannerData ?? { status: "no-disaster" }} />
6464
) : (
6565
<NetDisasterExpenseNoData />

frontend/components/dashboard/LocationRisk.tsx

Lines changed: 56 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,20 @@ import { useLeafletMap } from "@/app/location-based-risk/hooks/useLeafletMap";
1010
import { useGeoJSONLayers } from "@/app/location-based-risk/hooks/useGeoJSONLayers";
1111
import { useLeafletLoader } from "@/app/location-based-risk/hooks/useLeafletLoader";
1212
import { LargeLoading } from "../loading";
13+
import ErrorDisplay from "../ErrorDisplay";
1314

1415
export default function LocationRisk() {
1516
const { availableLocations, selectedLocation, setSelectedLocation } = useSelectedLocation();
1617
const { countyLookup: femaRiskCountyLookup, lastUpdated } = useFEMARiskScore();
1718

1819
const mapRef = useRef<HTMLDivElement>(null);
19-
const { isLoaded: leafletLoaded } = useLeafletLoader();
20+
const { isLoaded: leafletLoaded, error: leafletError } = useLeafletLoader();
2021
const [userLocation, setUserLocation] = useState<[number, number]>([
2122
selectedLocation?.lat || 0,
2223
selectedLocation?.long || 0,
2324
]);
24-
const { map, isReady: mapReady, panTo } = useLeafletMap(mapRef, leafletLoaded, userLocation);
25-
const { loading: geoJsonLoading } = useGeoJSONLayers(map, mapReady, femaRiskCountyLookup);
25+
const { map, isReady: mapReady, panTo, error: mapError } = useLeafletMap(mapRef, leafletLoaded, userLocation);
26+
const { loading: geoJsonLoading, error: geoJsonError } = useGeoJSONLayers(map, mapReady, femaRiskCountyLookup);
2627

2728
// Pan to new location whenever selectedLocation changes
2829
useEffect(() => {
@@ -34,6 +35,8 @@ export default function LocationRisk() {
3435

3536
const isLoading = !leafletLoaded || !mapReady || geoJsonLoading;
3637

38+
const error = leafletError || mapError || geoJsonError;
39+
3740
useEffect(() => {
3841
console.log("Loading states:", {
3942
leafletLoaded,
@@ -63,46 +66,58 @@ export default function LocationRisk() {
6366
/>
6467
</div>
6568
</CardTitle>
66-
<div className="relative">
67-
{isLoading && (
68-
<CardContent className="absolute inset-0 z-10 flex items-center justify-center bg-white w-[100%] border-none shadow-none p-0">
69-
<LargeLoading />
70-
</CardContent>
71-
)}
72-
<CardContent className="w-[100%] flex flex-row px-0">
73-
<div className="w-[100%] flex flex-col">
74-
<div className="w-[100%] flex flex-row">
75-
<div>
76-
<div ref={mapRef} className="w-96 h-full rounded-xl z-0" />
77-
</div>
78-
<div className="w-full pl-4 flex flex-col gap-2">
79-
<RiskIndexOverviewCard
80-
riskAttributes={femaRiskCountyLookup.get(
81-
`${selectedLocation?.fipsStateCode.toString().padStart(2, "0")}${selectedLocation?.fipsCountyCode.toString().padStart(3, "0")}`
82-
)}
83-
loading={isLoading}
84-
/>
85-
<HazardIndexOverviewCard
86-
riskAttributes={femaRiskCountyLookup.get(
87-
`${selectedLocation?.fipsStateCode.toString().padStart(2, "0")}${selectedLocation?.fipsCountyCode.toString().padStart(3, "0")}`
88-
)}
89-
loading={isLoading}
90-
/>
69+
70+
{error ? (
71+
<CardContent
72+
className={`h-[400px] w-full flex items-center justify-center bg-white border-none shadow-none p-0`}
73+
>
74+
<ErrorDisplay />
75+
</CardContent>
76+
) : (
77+
<>
78+
{isLoading && (
79+
<CardContent
80+
className={`h-[400px] w-full flex items-center justify-center bg-white border-none shadow-none p-0`}
81+
>
82+
<LargeLoading />
83+
</CardContent>
84+
)}
85+
86+
<CardContent className={`w-[100%] flex flex-row px-0 ${isLoading && "hidden"}`}>
87+
<div className={`w-[100%] flex flex-col`}>
88+
<div className="w-[100%] flex flex-row">
89+
<div>
90+
<div ref={mapRef} className="w-96 h-full rounded-xl z-0" />
91+
</div>
92+
<div className="w-full pl-4 flex flex-col gap-2">
93+
<RiskIndexOverviewCard
94+
riskAttributes={femaRiskCountyLookup.get(
95+
`${selectedLocation?.fipsStateCode.toString().padStart(2, "0")}${selectedLocation?.fipsCountyCode.toString().padStart(3, "0")}`
96+
)}
97+
loading={isLoading}
98+
/>
99+
<HazardIndexOverviewCard
100+
riskAttributes={femaRiskCountyLookup.get(
101+
`${selectedLocation?.fipsStateCode.toString().padStart(2, "0")}${selectedLocation?.fipsCountyCode.toString().padStart(3, "0")}`
102+
)}
103+
loading={isLoading}
104+
/>
105+
</div>
91106
</div>
107+
{lastUpdated && (
108+
<p className="text-sm text-gray-600 italic">
109+
This data was last updated{" "}
110+
{lastUpdated.toLocaleString("en-US", {
111+
timeZone: "America/New_York",
112+
dateStyle: "medium",
113+
timeStyle: "short",
114+
})}
115+
</p>
116+
)}
92117
</div>
93-
{lastUpdated && (
94-
<p className="text-sm text-gray-600 italic">
95-
This data was last updated{" "}
96-
{lastUpdated.toLocaleString("en-US", {
97-
timeZone: "America/New_York",
98-
dateStyle: "medium",
99-
timeStyle: "short",
100-
})}
101-
</p>
102-
)}
103-
</div>
104-
</CardContent>
105-
</div>
118+
</CardContent>
119+
</>
120+
)}
106121
</Card>
107122
);
108123
}

frontend/components/dashboard/RevenueAndExpenses.tsx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import Link from "next/link";
1010
import { FaCircle } from "react-icons/fa";
1111
import { LargeLoading } from "../loading";
1212
import { FaExclamation } from "react-icons/fa6";
13+
import ErrorDisplay from "../ErrorDisplay";
1314

1415
export function RevenueAndExpensesNoData() {
1516
return (
@@ -107,12 +108,15 @@ export default function RevenueAndExpenses({ onDashboard = true }: { onDashboard
107108
},
108109
} satisfies ChartConfig;
109110

111+
const isLoading = expensesQueries.some((q) => q.isLoading) || revenueQueries.some((q) => q.isLoading);
112+
const error = expensesQueries.some((q) => q.error) || revenueQueries.some((q) => q.error);
113+
110114
return (
111-
<Card className="h-full p-6 border-none shadow-none flex flex-col">
115+
<Card className="h-full p-6 border-none shadow-none flex flex-col min-h-[260px]">
112116
<div className="flex flex-col mb-4 gap-2">
113117
<CardTitle className="text-2xl font-bold">Revenue and Expenses</CardTitle>
114118

115-
{!(expensesQueries.some((q) => q.isLoading) || revenueQueries.some((q) => q.isLoading)) && (
119+
{!isLoading && !error && (
116120
<div className="flex items-center gap-2 text-sm py-1 rounded">
117121
<div
118122
className={`flex items-center rounded py-1 px-2 ${percentChange >= 0 ? "bg-seafoam" : "bg-pink"}`}
@@ -127,7 +131,11 @@ export default function RevenueAndExpenses({ onDashboard = true }: { onDashboard
127131
)}
128132
</div>
129133

130-
{expensesQueries.some((q) => q.isLoading) || revenueQueries.some((q) => q.isLoading) ? (
134+
{error ? (
135+
<CardContent className="p-0 flex-1 flex gap-6">
136+
<ErrorDisplay />
137+
</CardContent>
138+
) : isLoading ? (
131139
<CardContent className="p-0 flex-1 flex gap-6">
132140
<LargeLoading />
133141
</CardContent>

frontend/components/dashboard/locationsDropDown.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export const LocationsDropDown = ({ availableLocations, handleSelect, selectedLo
1616
<Button
1717
variant="outline"
1818
size="sm"
19-
className="h-8 w-96 flex gap-2 rounded-full bg-muted text-black text-[20px] border border-border/40 hover:bg-muted/80 justify-between"
19+
className="h-8 w-[60%] flex gap-2 rounded-full bg-muted text-black text-[20px] border border-border/40 hover:bg-muted/80 justify-between"
2020
>
2121
<div className="flex items-center gap-1">
2222
<MapIcon className="h-4 w-4" />

0 commit comments

Comments
 (0)