Initial Commit

This commit is contained in:
2025-11-16 16:00:51 +00:00
commit ba324b370e
52 changed files with 8014 additions and 0 deletions

165
src/pages/MapPage.tsx Normal file
View 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>
);
}