import { useState, useEffect } from 'react'; import { useParams, useNavigate } from 'react-router-dom'; import { useAuth } from '@/hooks/useAuth'; import { userService, type UserProfile, type UserActivity } from '@/services/userService'; import type { Report, CleanupEvent } from '@/types'; import { MapContainer, TileLayer, Marker, Popup } from 'react-leaflet'; import 'leaflet/dist/leaflet.css'; import L from 'leaflet'; // Fix Leaflet default marker icon issue import markerIcon2x from 'leaflet/dist/images/marker-icon-2x.png'; import markerIcon from 'leaflet/dist/images/marker-icon.png'; import markerShadow from 'leaflet/dist/images/marker-shadow.png'; delete (L.Icon.Default.prototype as any)._getIconUrl; L.Icon.Default.mergeOptions({ iconUrl: markerIcon, iconRetinaUrl: markerIcon2x, shadowUrl: markerShadow, }); export function UserProfilePage() { const { userId } = useParams<{ userId: string }>(); const { user: currentUser } = useAuth(); const navigate = useNavigate(); const [profile, setProfile] = useState(null); const [reports, setReports] = useState([]); const [events, setEvents] = useState([]); const [activity, setActivity] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [activeTab, setActiveTab] = useState<'overview' | 'reports' | 'events' | 'activity'>('overview'); const [isEditing, setIsEditing] = useState(false); const [editForm, setEditForm] = useState({ firstName: '', lastName: '', username: '', }); const isOwnProfile = currentUser?.id === userId; useEffect(() => { if (!userId) { setError('User ID is required'); setLoading(false); return; } loadProfileData(); }, [userId]); const loadProfileData = async () => { if (!userId) return; try { setLoading(true); setError(null); const [profileData, reportsData, eventsData, activityData] = await Promise.all([ userService.getProfile(userId), userService.getUserReports(userId), userService.getUserEvents(userId), userService.getUserActivity(userId), ]); setProfile(profileData); setReports(reportsData); setEvents(eventsData); setActivity(activityData); setEditForm({ firstName: profileData.firstName || '', lastName: profileData.lastName || '', username: profileData.username || '', }); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to load profile'); } finally { setLoading(false); } }; const handleEditProfile = () => { setIsEditing(true); }; const handleCancelEdit = () => { setIsEditing(false); if (profile) { setEditForm({ firstName: profile.firstName || '', lastName: profile.lastName || '', username: profile.username || '', }); } }; const handleSaveProfile = async () => { if (!userId) return; try { await userService.updateProfile(userId, editForm); setIsEditing(false); await loadProfileData(); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to update profile'); } }; const calculateImpactScore = () => { if (!profile) return 0; // Impact score calculation: reports * 10 + events attended * 20 return profile.reportCount * 10 + profile.eventCount * 20; }; const formatDate = (date: Date) => { return new Date(date).toLocaleDateString('en-IE', { year: 'numeric', month: 'short', day: 'numeric', }); }; if (loading) { return (

Loading profile...

); } if (error || !profile) { return (

{error || 'Profile not found'}

); } return (
{/* Profile Header */}
{profile.avatarUrl && ( {profile.username} )}
{isEditing ? (
setEditForm({ ...editForm, firstName: e.target.value })} placeholder="First name" className="px-3 py-1 border border-gray-300 rounded-md" /> setEditForm({ ...editForm, lastName: e.target.value })} placeholder="Last name" className="px-3 py-1 border border-gray-300 rounded-md" />
setEditForm({ ...editForm, username: e.target.value })} placeholder="Username" className="px-3 py-1 border border-gray-300 rounded-md w-full" />
) : ( <>

{profile.firstName && profile.lastName ? `${profile.firstName} ${profile.lastName}` : profile.username}

@{profile.username}

)}
{isOwnProfile && (
{isEditing ? ( <> ) : ( )}
)}
{/* Statistics */}

Reports Submitted

{profile.reportCount}

Events Attended

{profile.eventCount}

Impact Score

{calculateImpactScore()}

{/* Tabs */}
{activeTab === 'overview' && (

Contribution Map

{reports.length > 0 && reports[0] ? (
{reports.map((report) => (

{report.litterType}

{formatDate(report.createdAt)}

))}
) : (

No reports submitted yet

)}

Recent Activity

{activity.length > 0 ? (
{activity.slice(0, 5).map((item) => (
{item.type === 'report' && (
📍
)} {item.type.startsWith('event') && (
🗓️
)}

{item.title}

{item.description && (

{item.description}

)}

{formatDate(item.timestamp)}

))}
) : (

No activity yet

)}
)} {activeTab === 'reports' && (

Submitted Reports

{reports.length > 0 ? (
{reports.map((report) => (
{report.photoUrls.length > 0 && ( Report )}

{report.litterType}

Quantity: {report.quantity}

{report.description && (

{report.description}

)}

{formatDate(report.createdAt)}

))}
) : (

No reports submitted yet

)}
)} {activeTab === 'events' && (

Events

{events.length > 0 ? (
{events.map((event) => (

{event.title}

{event.description}

📍 {event.locationName}

🗓️ {formatDate(event.scheduledDate)}

👥 {event.participantCount} participants

{event.litterCollected && (

♻️ {event.litterCollected} kg collected

)}
{event.status}
))}
) : (

No events yet

)}
)} {activeTab === 'activity' && (

Activity Timeline

{activity.length > 0 ? (
{activity.map((item) => (
{item.type === 'report' && 📍} {item.type === 'event_created' && ➕} {item.type === 'event_attended' && ✅} {item.type === 'event_completed' && 🎉}

{item.title}

{item.description && (

{item.description}

)} {item.location && (

📍 {item.location.locationName || `${item.location.latitude?.toFixed(4)}, ${item.location.longitude?.toFixed(4)}`}

)}

{formatDate(item.timestamp)}

))}
) : (

No activity yet

)}
)}
); }