Restrict event completion to after event date
- Only allow organizers to complete events after the scheduled date has passed - Show informative message to organizers before event date - Prevents premature event completion
This commit is contained in:
@@ -108,7 +108,7 @@
|
|||||||
- Create event detail page with participant count
|
- Create event detail page with participant count
|
||||||
- _Requirements: 4.1, 4.2, 4.3, 4.4_
|
- _Requirements: 4.1, 4.2, 4.3, 4.4_
|
||||||
|
|
||||||
- [-] 14. Implement event completion workflow
|
- [x] 14. Implement event completion workflow
|
||||||
- Create event completion form for organizers
|
- Create event completion form for organizers
|
||||||
- Add litter collected quantity input
|
- Add litter collected quantity input
|
||||||
- Implement photo upload for cleanup results
|
- Implement photo upload for cleanup results
|
||||||
|
|||||||
@@ -42,6 +42,10 @@ export function EventDetailModal({
|
|||||||
const mapInstanceRef = useRef<L.Map | null>(null);
|
const mapInstanceRef = useRef<L.Map | null>(null);
|
||||||
const [showCompletionForm, setShowCompletionForm] = useState(false);
|
const [showCompletionForm, setShowCompletionForm] = useState(false);
|
||||||
|
|
||||||
|
// Check if event date has passed
|
||||||
|
const hasEventPassed = new Date(event.scheduledDate) < new Date();
|
||||||
|
const canComplete = isOrganizer && event.status === 'upcoming' && hasEventPassed;
|
||||||
|
|
||||||
// Initialize map
|
// Initialize map
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!mapRef.current || mapInstanceRef.current) return;
|
if (!mapRef.current || mapInstanceRef.current) return;
|
||||||
@@ -241,7 +245,7 @@ export function EventDetailModal({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Completion Form for Organizers */}
|
{/* Completion Form for Organizers */}
|
||||||
{isOrganizer && event.status === 'upcoming' && showCompletionForm && (
|
{canComplete && showCompletionForm && (
|
||||||
<div className="px-6 pb-6">
|
<div className="px-6 pb-6">
|
||||||
<EventCompletionForm
|
<EventCompletionForm
|
||||||
eventId={event.id}
|
eventId={event.id}
|
||||||
@@ -258,7 +262,7 @@ export function EventDetailModal({
|
|||||||
{/* Footer Actions */}
|
{/* Footer Actions */}
|
||||||
{event.status === 'upcoming' && (
|
{event.status === 'upcoming' && (
|
||||||
<div className="bg-gray-50 px-6 py-4 border-t border-gray-200">
|
<div className="bg-gray-50 px-6 py-4 border-t border-gray-200">
|
||||||
{isOrganizer ? (
|
{canComplete ? (
|
||||||
<div className="flex gap-3">
|
<div className="flex gap-3">
|
||||||
<button
|
<button
|
||||||
onClick={() => setShowCompletionForm(!showCompletionForm)}
|
onClick={() => setShowCompletionForm(!showCompletionForm)}
|
||||||
@@ -268,6 +272,21 @@ export function EventDetailModal({
|
|||||||
{showCompletionForm ? 'Hide Completion Form' : 'Complete Event'}
|
{showCompletionForm ? 'Hide Completion Form' : 'Complete Event'}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
) : isOrganizer && !hasEventPassed ? (
|
||||||
|
<div className="bg-blue-50 border border-blue-200 rounded-lg p-4">
|
||||||
|
<div className="flex items-center">
|
||||||
|
<svg className="h-5 w-5 text-blue-600 mr-2" fill="currentColor" viewBox="0 0 20 20">
|
||||||
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z"
|
||||||
|
clipRule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<span className="text-sm text-blue-800">
|
||||||
|
You can complete this event after {format(new Date(event.scheduledDate), 'MMM d, yyyy')}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
) : isRegistered ? (
|
) : isRegistered ? (
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div className="flex items-center text-green-600">
|
<div className="flex items-center text-green-600">
|
||||||
|
|||||||
Reference in New Issue
Block a user