feat([2fd88f42]): implement smart PLZ column selection
This commit is contained in:
@@ -30,13 +30,44 @@ function App() {
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [radiusMultiplier, setRadiusMultiplier] = useState(1);
|
||||
const [viewMode, setViewMode] = useState<MapMode>('points');
|
||||
|
||||
const [plzColumnNeeded, setPlzColumnNeeded] = useState(false);
|
||||
const [availableColumns, setAvailableColumns] = useState<string[]>([]);
|
||||
|
||||
const handleUploadSuccess = (newFilters: FilterOptions) => {
|
||||
setFilters(newFilters);
|
||||
setHeatmapData([]); // Clear previous heatmap data
|
||||
|
||||
const handleUploadSuccess = (response: any) => {
|
||||
setError(null);
|
||||
// Automatically fetch data with no filters on successful upload
|
||||
handleFilterChange({});
|
||||
if (response.plz_column_needed) {
|
||||
setAvailableColumns(response.columns);
|
||||
setPlzColumnNeeded(true);
|
||||
setFilters({});
|
||||
setHeatmapData([]);
|
||||
} else {
|
||||
setPlzColumnNeeded(false);
|
||||
setFilters(response.filters);
|
||||
setHeatmapData([]); // Clear previous heatmap data
|
||||
// Automatically fetch data with no filters on successful upload
|
||||
handleFilterChange({});
|
||||
}
|
||||
};
|
||||
|
||||
const handlePlzColumnSubmit = async (selectedColumn: string) => {
|
||||
setIsLoading(true);
|
||||
setError(null);
|
||||
try {
|
||||
const response = await axios.post('/api/set-plz-column', {
|
||||
plz_column: selectedColumn,
|
||||
});
|
||||
handleUploadSuccess(response.data); // Re-use the success handler
|
||||
} catch (error: any) {
|
||||
if (axios.isAxiosError(error) && error.response) {
|
||||
setError(`Failed to set PLZ column: ${error.response.data.detail || error.message}`);
|
||||
} else {
|
||||
setError(`Failed to set PLZ column: ${error.message}`);
|
||||
}
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleFilterChange = async (selectedFilters: FilterOptions) => {
|
||||
@@ -72,36 +103,46 @@ function App() {
|
||||
setIsLoading={setIsLoading}
|
||||
setError={setError}
|
||||
/>
|
||||
<FilterPanel
|
||||
filters={filters}
|
||||
onFilterChange={handleFilterChange}
|
||||
{plzColumnNeeded ? (
|
||||
<PlzSelector
|
||||
columns={availableColumns}
|
||||
onSubmit={handlePlzColumnSubmit}
|
||||
isLoading={isLoading}
|
||||
/>
|
||||
<div className="map-controls" style={{ marginTop: '20px', paddingTop: '20px', borderTop: '1px solid #555' }}>
|
||||
<h3>Map Settings</h3>
|
||||
<div className="toggle-switch" style={{ marginBottom: '15px' }}>
|
||||
<label>
|
||||
<input type="radio" value="points" checked={viewMode === 'points'} onChange={() => setViewMode('points')} />
|
||||
Points
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" value="heatmap" checked={viewMode === 'heatmap'} onChange={() => setViewMode('heatmap')} />
|
||||
Heatmap
|
||||
</label>
|
||||
</div>
|
||||
<label htmlFor="radius-slider">Marker Size: {radiusMultiplier.toFixed(1)}x</label>
|
||||
<input
|
||||
type="range"
|
||||
id="radius-slider"
|
||||
min="0.1"
|
||||
max="5"
|
||||
step="0.1"
|
||||
value={radiusMultiplier}
|
||||
onChange={(e) => setRadiusMultiplier(parseFloat(e.target.value))}
|
||||
style={{ width: '100%' }}
|
||||
disabled={viewMode === 'heatmap'}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<FilterPanel
|
||||
filters={filters}
|
||||
onFilterChange={handleFilterChange}
|
||||
isLoading={isLoading}
|
||||
/>
|
||||
<div className="map-controls" style={{ marginTop: '20px', paddingTop: '20px', borderTop: '1px solid #555' }}>
|
||||
<h3>Map Settings</h3>
|
||||
<div className="toggle-switch" style={{ marginBottom: '15px' }}>
|
||||
<label>
|
||||
<input type="radio" value="points" checked={viewMode === 'points'} onChange={() => setViewMode('points')} />
|
||||
Points
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" value="heatmap" checked={viewMode === 'heatmap'} onChange={() => setViewMode('heatmap')} />
|
||||
Heatmap
|
||||
</label>
|
||||
</div>
|
||||
<label htmlFor="radius-slider">Marker Size: {radiusMultiplier.toFixed(1)}x</label>
|
||||
<input
|
||||
type="range"
|
||||
id="radius-slider"
|
||||
min="0.1"
|
||||
max="5"
|
||||
step="0.1"
|
||||
value={radiusMultiplier}
|
||||
onChange={(e) => setRadiusMultiplier(parseFloat(e.target.value))}
|
||||
style={{ width: '100%' }}
|
||||
disabled={viewMode === 'heatmap'}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<div className="map-container">
|
||||
{isLoading && <p>Loading map data...</p>}
|
||||
|
||||
@@ -44,7 +44,7 @@ const FileUpload: React.FC<FileUploadProps> = ({ onUploadSuccess, setIsLoading,
|
||||
'Content-Type': 'multipart/form-data',
|
||||
},
|
||||
});
|
||||
onUploadSuccess(response.data.filters);
|
||||
onUploadSuccess(response.data);
|
||||
} catch (error: any) {
|
||||
if (axios.isAxiosError(error) && error.response) {
|
||||
setError(`Upload failed: ${error.response.data.detail || error.message}`);
|
||||
|
||||
Reference in New Issue
Block a user