[31b88f42] Add staff locations and reach visualization to Heatmap Tool
This commit is contained in:
@@ -28,6 +28,18 @@ export interface HeatmapPoint {
|
||||
attributes_summary?: Record<string, string[]>;
|
||||
}
|
||||
|
||||
export interface StaffLocation {
|
||||
name: string;
|
||||
plz: string;
|
||||
lat: number;
|
||||
lon: number;
|
||||
}
|
||||
|
||||
export interface StaffData {
|
||||
sales: StaffLocation[];
|
||||
technicians: StaffLocation[];
|
||||
}
|
||||
|
||||
export type MapMode = 'points' | 'heatmap';
|
||||
|
||||
function App() {
|
||||
@@ -42,6 +54,22 @@ function App() {
|
||||
const [availableColumns, setAvailableColumns] = useState<string[]>([]);
|
||||
const [tooltipColumns, setTooltipColumns] = useState<TooltipColumn[]>([]);
|
||||
|
||||
const [staffData, setStaffData] = useState<StaffData>({ sales: [], technicians: [] });
|
||||
const [showSales, setShowSales] = useState(false);
|
||||
const [showTechnicians, setShowTechnicians] = useState(false);
|
||||
const [travelRadius, setTravelRadius] = useState(50); // In km
|
||||
|
||||
useEffect(() => {
|
||||
const fetchStaffLocations = async () => {
|
||||
try {
|
||||
const response = await axios.get('/heatmap/api/staff-locations');
|
||||
setStaffData(response.data);
|
||||
} catch (err) {
|
||||
console.error("Failed to fetch staff locations:", err);
|
||||
}
|
||||
};
|
||||
fetchStaffLocations();
|
||||
}, []);
|
||||
|
||||
const handleUploadSuccess = (response: any) => {
|
||||
setError(null);
|
||||
@@ -153,6 +181,34 @@ function App() {
|
||||
Heatmap
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="staff-toggles" style={{ marginBottom: '15px' }}>
|
||||
<label style={{ display: 'block', marginBottom: '5px' }}>
|
||||
<input type="checkbox" checked={showSales} onChange={(e) => setShowSales(e.target.checked)} />
|
||||
Show Sales Reps
|
||||
</label>
|
||||
<label style={{ display: 'block', marginBottom: '15px' }}>
|
||||
<input type="checkbox" checked={showTechnicians} onChange={(e) => setShowTechnicians(e.target.checked)} />
|
||||
Show Technicians
|
||||
</label>
|
||||
</div>
|
||||
|
||||
{(showSales || showTechnicians) && (
|
||||
<div className="radius-control" style={{ marginBottom: '20px' }}>
|
||||
<label htmlFor="travel-radius">Travel Radius: {travelRadius} km</label>
|
||||
<input
|
||||
type="range"
|
||||
id="travel-radius"
|
||||
min="10"
|
||||
max="200"
|
||||
step="5"
|
||||
value={travelRadius}
|
||||
onChange={(e) => setTravelRadius(parseInt(e.target.value))}
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<label htmlFor="radius-slider">Marker Size: {radiusMultiplier.toFixed(1)}x</label>
|
||||
<input
|
||||
type="range"
|
||||
@@ -180,6 +236,10 @@ function App() {
|
||||
radiusMultiplier={radiusMultiplier}
|
||||
viewMode={viewMode}
|
||||
tooltipColumns={tooltipColumns}
|
||||
staffData={staffData}
|
||||
showSales={showSales}
|
||||
showTechnicians={showTechnicians}
|
||||
travelRadius={travelRadius}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user