Initial Commit
This commit is contained in:
15
src/pages/AnalyticsPage.tsx
Normal file
15
src/pages/AnalyticsPage.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* Analytics page - placeholder for task 10-12
|
||||
*/
|
||||
export function AnalyticsPage() {
|
||||
return (
|
||||
<div className="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
|
||||
<h2 className="text-2xl font-bold text-gray-900 mb-4">Analytics Dashboard</h2>
|
||||
<div className="bg-white rounded-lg shadow p-8">
|
||||
<p className="text-gray-500">
|
||||
Analytics dashboard will be implemented in tasks 10-12
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
15
src/pages/EventsPage.tsx
Normal file
15
src/pages/EventsPage.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* Events page - placeholder for task 13-14
|
||||
*/
|
||||
export function EventsPage() {
|
||||
return (
|
||||
<div className="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
|
||||
<h2 className="text-2xl font-bold text-gray-900 mb-4">Clean-up Events</h2>
|
||||
<div className="bg-white rounded-lg shadow p-8">
|
||||
<p className="text-gray-500">
|
||||
Events management will be implemented in tasks 13-14
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
90
src/pages/HomePage.tsx
Normal file
90
src/pages/HomePage.tsx
Normal file
@@ -0,0 +1,90 @@
|
||||
import { SignedIn, SignedOut } from '@clerk/clerk-react';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
/**
|
||||
* Home page with welcome message and call-to-action
|
||||
*/
|
||||
export function HomePage() {
|
||||
return (
|
||||
<div className="max-w-7xl mx-auto py-12 px-4 sm:px-6 lg:px-8">
|
||||
<div className="text-center">
|
||||
<h2 className="text-4xl font-extrabold text-gray-900 sm:text-5xl">
|
||||
Track and Clean Ireland's Beaches
|
||||
</h2>
|
||||
<p className="mt-4 text-xl text-gray-600 max-w-3xl mx-auto">
|
||||
Join our community in mapping beach litter, organizing clean-up events,
|
||||
and protecting our coastal environment through data-driven action.
|
||||
</p>
|
||||
|
||||
<SignedOut>
|
||||
<div className="mt-8 flex justify-center space-x-4">
|
||||
<Link
|
||||
to="/sign-up"
|
||||
className="px-8 py-3 border border-transparent text-base font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700 md:py-4 md:text-lg md:px-10"
|
||||
>
|
||||
Get Started
|
||||
</Link>
|
||||
<Link
|
||||
to="/map"
|
||||
className="px-8 py-3 border border-gray-300 text-base font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 md:py-4 md:text-lg md:px-10"
|
||||
>
|
||||
View Map
|
||||
</Link>
|
||||
</div>
|
||||
</SignedOut>
|
||||
|
||||
<SignedIn>
|
||||
<div className="mt-8 flex justify-center space-x-4">
|
||||
<Link
|
||||
to="/reports/new"
|
||||
className="px-8 py-3 border border-transparent text-base font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700 md:py-4 md:text-lg md:px-10"
|
||||
>
|
||||
Report Litter
|
||||
</Link>
|
||||
<Link
|
||||
to="/map"
|
||||
className="px-8 py-3 border border-gray-300 text-base font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 md:py-4 md:text-lg md:px-10"
|
||||
>
|
||||
View Map
|
||||
</Link>
|
||||
</div>
|
||||
</SignedIn>
|
||||
</div>
|
||||
|
||||
<div className="mt-16 grid grid-cols-1 gap-8 md:grid-cols-3">
|
||||
<div className="bg-white p-6 rounded-lg shadow">
|
||||
<div className="text-blue-600 text-3xl mb-4">📍</div>
|
||||
<h3 className="text-lg font-semibold text-gray-900 mb-2">
|
||||
Report Litter
|
||||
</h3>
|
||||
<p className="text-gray-600">
|
||||
Document beach litter with photos and location data to raise awareness
|
||||
and track pollution patterns.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-white p-6 rounded-lg shadow">
|
||||
<div className="text-blue-600 text-3xl mb-4">🗺️</div>
|
||||
<h3 className="text-lg font-semibold text-gray-900 mb-2">
|
||||
Interactive Maps
|
||||
</h3>
|
||||
<p className="text-gray-600">
|
||||
Visualize litter hotspots, view reports from your area, and identify
|
||||
areas that need attention.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-white p-6 rounded-lg shadow">
|
||||
<div className="text-blue-600 text-3xl mb-4">🤝</div>
|
||||
<h3 className="text-lg font-semibold text-gray-900 mb-2">
|
||||
Organize Events
|
||||
</h3>
|
||||
<p className="text-gray-600">
|
||||
Create and join clean-up events, coordinate with volunteers, and make
|
||||
a real impact on coastal health.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
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>
|
||||
);
|
||||
}
|
||||
13
src/pages/README.md
Normal file
13
src/pages/README.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Pages Directory
|
||||
|
||||
This directory contains page-level components that represent different routes in the application.
|
||||
|
||||
## Planned Pages
|
||||
|
||||
- `HomePage.tsx` - Landing page with map view
|
||||
- `ReportPage.tsx` - Report submission page
|
||||
- `AnalyticsPage.tsx` - Analytics dashboard
|
||||
- `EventsPage.tsx` - Event listing and management
|
||||
- `EventDetailPage.tsx` - Individual event details
|
||||
- `ProfilePage.tsx` - User profile page
|
||||
- `NotFoundPage.tsx` - 404 error page
|
||||
15
src/pages/ReportFormPage.tsx
Normal file
15
src/pages/ReportFormPage.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* Report form page - placeholder for task 6-9
|
||||
*/
|
||||
export function ReportFormPage() {
|
||||
return (
|
||||
<div className="max-w-3xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
|
||||
<h2 className="text-2xl font-bold text-gray-900 mb-4">Report Litter</h2>
|
||||
<div className="bg-white rounded-lg shadow p-8">
|
||||
<p className="text-gray-500">
|
||||
Report form will be implemented in tasks 6-9
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
5
src/pages/index.ts
Normal file
5
src/pages/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export { HomePage } from './HomePage';
|
||||
export { MapPage } from './MapPage';
|
||||
export { ReportFormPage } from './ReportFormPage';
|
||||
export { EventsPage } from './EventsPage';
|
||||
export { AnalyticsPage } from './AnalyticsPage';
|
||||
Reference in New Issue
Block a user