perfect-postcode/frontend/src/App.jsx
2026-01-25 21:07:48 +00:00

54 lines
1.6 KiB
JavaScript

import React, { useState, useEffect, useCallback } from 'react';
import Map from './components/Map';
import Filters from './components/Filters';
import { DEFAULT_FILTERS } from './lib/constants';
export default function App() {
const [filters, setFilters] = useState(DEFAULT_FILTERS);
const [data, setData] = useState([]);
const [resolution, setResolution] = useState(8);
const [loading, setLoading] = useState(false);
const fetchData = useCallback(async () => {
setLoading(true);
try {
const params = new URLSearchParams({
resolution: resolution.toString(),
min_year: filters.minYear.toString(),
max_year: filters.maxYear.toString(),
min_price: filters.minPrice.toString(),
max_price: filters.maxPrice.toString(),
});
const res = await fetch(`/api/hexagons?${params}`);
const json = await res.json();
setData(
json.features.map((f) => ({
h3: f.properties.h3,
...f.properties,
}))
);
} catch (err) {
console.error('Failed to fetch data:', err);
} finally {
setLoading(false);
}
}, [filters, resolution]);
useEffect(() => {
fetchData();
}, [fetchData]);
return (
<div className="h-screen flex">
<Filters filters={filters} onChange={setFilters} />
<div className="flex-1 relative">
<Map data={data} onZoom={setResolution} />
{loading && (
<div className="absolute top-4 right-4 bg-white px-3 py-1 rounded shadow">
Loading...
</div>
)}
</div>
</div>
);
}