Initial Commit
This commit is contained in:
165
src/pages/MapPage.tsx
Normal file
165
src/pages/MapPage.tsx
Normal file
@@ -0,0 +1,165 @@
|
||||
import { useState } from 'react';
|
||||
import { MapView, MapFilters } from '@/components/map';
|
||||
import type { Report, FilterState } from '@/types';
|
||||
|
||||
/**
|
||||
* Map page - Interactive map displaying litter reports and cleanup events
|
||||
*/
|
||||
export function MapPage() {
|
||||
const [selectedReportId, setSelectedReportId] = useState<string | null>(null);
|
||||
const [filters, setFilters] = useState<FilterState>({});
|
||||
const [showClusters, setShowClusters] = useState(true);
|
||||
|
||||
// Sample data for demonstration (will be replaced with API data in later tasks)
|
||||
const sampleReports: Report[] = [
|
||||
{
|
||||
id: '1',
|
||||
userId: 'user1',
|
||||
latitude: 53.3498,
|
||||
longitude: -6.2603,
|
||||
locationSource: 'gps',
|
||||
photoUrls: ['https://example.com/photo1.jpg'],
|
||||
litterType: 'plastic',
|
||||
quantity: 'moderate',
|
||||
description: 'Plastic bottles and bags near the shore',
|
||||
createdAt: new Date('2024-01-15'),
|
||||
updatedAt: new Date('2024-01-15'),
|
||||
submittedAt: new Date('2024-01-15'),
|
||||
verificationStatus: 'verified',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
userId: 'user2',
|
||||
latitude: 53.2707,
|
||||
longitude: -9.0568,
|
||||
locationSource: 'gps',
|
||||
photoUrls: ['https://example.com/photo2.jpg'],
|
||||
litterType: 'glass',
|
||||
quantity: 'minimal',
|
||||
description: 'Broken glass bottles',
|
||||
createdAt: new Date('2024-01-16'),
|
||||
updatedAt: new Date('2024-01-16'),
|
||||
submittedAt: new Date('2024-01-16'),
|
||||
verificationStatus: 'pending',
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
userId: 'user3',
|
||||
latitude: 51.8969,
|
||||
longitude: -8.4863,
|
||||
locationSource: 'manual',
|
||||
photoUrls: ['https://example.com/photo3.jpg'],
|
||||
litterType: 'metal',
|
||||
quantity: 'significant',
|
||||
description: 'Metal cans and containers',
|
||||
createdAt: new Date('2024-01-17'),
|
||||
updatedAt: new Date('2024-01-17'),
|
||||
submittedAt: new Date('2024-01-17'),
|
||||
verificationStatus: 'verified',
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
userId: 'user4',
|
||||
latitude: 53.3520,
|
||||
longitude: -6.2650,
|
||||
locationSource: 'gps',
|
||||
photoUrls: ['https://example.com/photo4.jpg'],
|
||||
litterType: 'plastic',
|
||||
quantity: 'severe',
|
||||
description: 'Large amount of plastic waste',
|
||||
createdAt: new Date('2024-01-18'),
|
||||
updatedAt: new Date('2024-01-18'),
|
||||
submittedAt: new Date('2024-01-18'),
|
||||
verificationStatus: 'verified',
|
||||
},
|
||||
{
|
||||
id: '5',
|
||||
userId: 'user5',
|
||||
latitude: 53.3450,
|
||||
longitude: -6.2580,
|
||||
locationSource: 'gps',
|
||||
photoUrls: ['https://example.com/photo5.jpg'],
|
||||
litterType: 'hazardous',
|
||||
quantity: 'moderate',
|
||||
description: 'Chemical containers',
|
||||
createdAt: new Date('2024-01-19'),
|
||||
updatedAt: new Date('2024-01-19'),
|
||||
submittedAt: new Date('2024-01-19'),
|
||||
verificationStatus: 'disputed',
|
||||
},
|
||||
{
|
||||
id: '6',
|
||||
userId: 'user6',
|
||||
latitude: 53.3480,
|
||||
longitude: -6.2620,
|
||||
locationSource: 'manual',
|
||||
photoUrls: ['https://example.com/photo6.jpg'],
|
||||
litterType: 'organic',
|
||||
quantity: 'minimal',
|
||||
description: 'Seaweed and organic debris',
|
||||
createdAt: new Date('2024-01-20'),
|
||||
updatedAt: new Date('2024-01-20'),
|
||||
submittedAt: new Date('2024-01-20'),
|
||||
verificationStatus: 'verified',
|
||||
},
|
||||
];
|
||||
|
||||
const handleMarkerClick = (reportId: string) => {
|
||||
setSelectedReportId(reportId);
|
||||
console.log('Report clicked:', reportId);
|
||||
// In later tasks, this will open a modal with full report details
|
||||
};
|
||||
|
||||
const handleMapClick = (lat: number, lng: number) => {
|
||||
console.log('Map clicked at:', lat, lng);
|
||||
// In later tasks, this can be used for manual location selection
|
||||
};
|
||||
|
||||
const handleToggleClusters = () => {
|
||||
setShowClusters(!showClusters);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="h-screen flex flex-col">
|
||||
<div className="bg-white border-b border-gray-200 px-4 py-4 sm:px-6 lg:px-8">
|
||||
<h2 className="text-2xl font-bold text-gray-900">Interactive Map</h2>
|
||||
<p className="mt-1 text-sm text-gray-600">
|
||||
View litter reports and cleanup events across Ireland
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="flex-1 p-4">
|
||||
<div className="h-full bg-white rounded-lg shadow-lg overflow-hidden relative">
|
||||
<MapView
|
||||
reports={sampleReports}
|
||||
filters={filters}
|
||||
showClusters={showClusters}
|
||||
onMarkerClick={handleMarkerClick}
|
||||
onMapClick={handleMapClick}
|
||||
/>
|
||||
|
||||
<MapFilters
|
||||
filters={filters}
|
||||
onFiltersChange={setFilters}
|
||||
onToggleClusters={handleToggleClusters}
|
||||
showClusters={showClusters}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{selectedReportId && (
|
||||
<div className="fixed bottom-4 left-4 bg-white p-4 rounded-lg shadow-lg z-[1000]">
|
||||
<p className="text-sm text-gray-600">
|
||||
Selected Report ID: {selectedReportId}
|
||||
</p>
|
||||
<button
|
||||
onClick={() => setSelectedReportId(null)}
|
||||
className="mt-2 text-xs text-blue-600 hover:text-blue-800"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user