From 2e14127a2c2ff59a83edc113a5355c58ccee7c6e Mon Sep 17 00:00:00 2001 From: chark1es Date: Wed, 12 Mar 2025 04:23:24 -0700 Subject: [PATCH] much better ui --- .../EventRequestDetails.tsx | 470 +++++++++++------- .../EventRequestManagementTable.tsx | 62 +-- .../EventRequestModal.tsx | 118 +++-- 3 files changed, 391 insertions(+), 259 deletions(-) diff --git a/src/components/dashboard/Officer_EventRequestManagement/EventRequestDetails.tsx b/src/components/dashboard/Officer_EventRequestManagement/EventRequestDetails.tsx index fdbec64..dee8075 100644 --- a/src/components/dashboard/Officer_EventRequestManagement/EventRequestDetails.tsx +++ b/src/components/dashboard/Officer_EventRequestManagement/EventRequestDetails.tsx @@ -29,6 +29,10 @@ interface ExtendedEventRequest extends SchemaEventRequest { invoice_files?: string[]; // Array of invoice file IDs flyer_files?: string[]; // Add this for PR-related files files?: string[]; // Generic files field + room_reservation_needed?: boolean; + room_reservation_location?: string; + room_reservation_confirmed?: boolean; + additional_notes?: string; } interface EventRequestDetailsProps { @@ -1104,28 +1108,22 @@ const EventRequestDetails = ({ onClose, onStatusChange }: EventRequestDetailsProps): React.ReactNode => { - const [activeTab, setActiveTab] = useState<'details' | 'pr' | 'funding'>('details'); - const [status, setStatus] = useState<"submitted" | "pending" | "completed" | "declined">(request.status); - const [isStatusChanging, setIsStatusChanging] = useState(false); + const [activeTab, setActiveTab] = useState('details'); + const [isConfirmModalOpen, setIsConfirmModalOpen] = useState(false); + const [newStatus, setNewStatus] = useState<"submitted" | "pending" | "completed" | "declined">("pending"); + const [isSubmitting, setIsSubmitting] = useState(false); + const [alertInfo, setAlertInfo] = useState<{ show: boolean; type: "success" | "error" | "warning" | "info"; message: string }>({ + show: false, + type: "info", + message: "" + }); - // Format date for display const formatDate = (dateString: string) => { - if (!dateString) return 'Not specified'; - try { - const date = new Date(dateString); - return date.toLocaleDateString('en-US', { - year: 'numeric', - month: 'short', - day: 'numeric', - hour: '2-digit', - minute: '2-digit' - }); - } catch (e) { - return dateString; - } + if (!dateString) return "Not specified"; + const date = new Date(dateString); + return date.toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute: 'numeric' }); }; - // Get status badge class based on status const getStatusBadge = (status?: "submitted" | "pending" | "completed" | "declined") => { if (!status) return 'badge-warning'; @@ -1143,46 +1141,95 @@ const EventRequestDetails = ({ } }; - // Handle status change const handleStatusChange = async (newStatus: "submitted" | "pending" | "completed" | "declined") => { - setIsStatusChanging(true); - await onStatusChange(request.id, newStatus); - setStatus(newStatus); - setIsStatusChanging(false); + setNewStatus(newStatus); + setIsConfirmModalOpen(true); }; - // Animation variants - const fadeInVariants = { - hidden: { opacity: 0, y: 20 }, - visible: { opacity: 1, y: 0, transition: { duration: 0.4 } } - }; + const confirmStatusChange = async () => { + setIsSubmitting(true); + setAlertInfo({ show: false, type: "info", message: "" }); - const tabVariants = { - hidden: { opacity: 0, y: 10 }, - visible: { opacity: 1, y: 0, transition: { duration: 0.3 } } + try { + await onStatusChange(request.id, newStatus); + setAlertInfo({ + show: true, + type: "success", + message: `Status successfully changed to ${newStatus}.` + }); + } catch (error) { + setAlertInfo({ + show: true, + type: "error", + message: `Failed to update status: ${error}` + }); + } finally { + setIsSubmitting(false); + setIsConfirmModalOpen(false); + } }; return ( - -
-
-
+
+ {/* Tabs navigation */} +
+
+ + {request.as_funding_required && ( + + )} + {request.flyers_needed && ( + + )} +
+
+ + {/* Alert for status updates */} + {alertInfo.show && ( +
+ setAlertInfo({ ...alertInfo, show: false })} + /> +
+ )} + + {/* Status bar */} +
+
+
Requested by: {request.requested_user_expand?.name || @@ -1196,164 +1243,215 @@ const EventRequestDetails = ({ 'No email available'}
+
+ + {request.status?.charAt(0).toUpperCase() + request.status?.slice(1) || 'Pending'} + + + Submitted on {formatDate(request.created)} + +
- + + + + +
+
- {/* Tabs */} -
- setActiveTab('details')} - whileHover={{ scale: 1.02 }} - whileTap={{ scale: 0.98 }} - > - Event Details - - setActiveTab('pr')} - whileHover={{ scale: 1.02 }} - whileTap={{ scale: 0.98 }} - > - PR Materials - - setActiveTab('funding')} - whileHover={{ scale: 1.02 }} - whileTap={{ scale: 0.98 }} - > - AS Funding - -
- - {/* Content */} - - {/* Event Details Tab */} - {activeTab === 'details' && ( - -
-
-
-

Event Name

-

{request.name}

+ {/* Tab content */} +
+ {activeTab === 'details' && ( +
+
+
+

+ + + + Event Information +

+
+
+ +

{request.name}

-
-

Location

-

{request.location || 'Not specified'}

+
+ +

{request.event_description}

-
-

Start Date & Time

-

{formatDate(request.start_date_time)}

-
-
-

End Date & Time

-

{formatDate(request.end_date_time)}

-
-
-

Expected Attendance

-

{request.expected_attendance || 'Not specified'}

-
-
-
-
-

Event Description

-

{request.event_description || 'No description provided'}

-
-
-

Room Booking

-
- {request.will_or_have_room_booking ? ( - Yes - ) : ( - No - )} +
+
+ +

{formatDate(request.start_date_time)}

- - {/* Display room booking file if available */} - {request.room_booking && ( -
- -
- )} -
-
-

Food/Drinks Served

-
- {request.food_drinks_being_served ? ( - Yes - ) : ( - No - )} +
+ +

{formatDate(request.end_date_time)}

-
-

Submission Date

-

{formatDate(request.created)}

+
+ +

{request.location}

- - )} - {/* PR Materials Tab */} - {activeTab === 'pr' && ( - - - - )} +
+

+ + + + Requirements & Special Requests +

+
+
+
+ {request.as_funding_required ? 'Yes' : 'No'} +
+

AS Funding Required

+
+
+
+ {request.flyers_needed ? 'Yes' : 'No'} +
+

PR Materials Needed

+
+
+
+ {request.room_reservation_needed ? 'Yes' : 'No'} +
+

Room Reservation Needed

+
+
+
+
- {/* AS Funding Tab */} - {activeTab === 'funding' && ( - - - - )} - +
+ {request.room_reservation_needed && ( +
+

+ + + + Room Reservation Details +

+
+
+ +

{request.room_reservation_location || 'Not specified'}

+
+
+ +

{request.room_reservation_confirmed ? 'Confirmed' : 'Not confirmed'}

+
+
+
+ )} + + {request.files && request.files.length > 0 && ( +
+

+ + + + Event Files +

+
+ {request.files.map((file, index) => ( + + ))} +
+
+ )} +
+
+ )} + + {activeTab === 'funding' && request.as_funding_required && } + {activeTab === 'pr' && request.flyers_needed && }
- + + {/* Confirmation modal */} + {isConfirmModalOpen && ( +
+
+

Confirm Status Change

+

+ Are you sure you want to change the status to {newStatus}? +

+
+ + +
+
+
+ )} +
); }; diff --git a/src/components/dashboard/Officer_EventRequestManagement/EventRequestManagementTable.tsx b/src/components/dashboard/Officer_EventRequestManagement/EventRequestManagementTable.tsx index 772b2e0..2863699 100644 --- a/src/components/dashboard/Officer_EventRequestManagement/EventRequestManagementTable.tsx +++ b/src/components/dashboard/Officer_EventRequestManagement/EventRequestManagementTable.tsx @@ -221,21 +221,21 @@ const EventRequestManagementTable = ({ if (request.expand?.requested_user) { const user = request.expand.requested_user; // Show "Loading..." instead of "Unknown" while data is being fetched - const name = user.name || 'Unknown'; + const name = user.name || 'Loading...'; // Always show email regardless of emailVisibility - const email = user.email || 'Unknown'; + const email = user.email || 'Loading...'; return { name, email }; } // Then try the requested_user_expand if (request.requested_user_expand) { - const name = request.requested_user_expand.name || 'Unknown'; - const email = request.requested_user_expand.email || 'Unknown'; + const name = request.requested_user_expand.name || 'Loading...'; + const email = request.requested_user_expand.email || 'Loading...'; return { name, email }; } // Last fallback - don't use "Unknown" to avoid confusing users - return { name: 'Unknown', email: '(Unknown)' }; + return { name: 'Loading...', email: 'Loading...' }; }; // Update openDetailModal to call the prop function @@ -317,13 +317,13 @@ const EventRequestManagementTable = ({ initial={{ opacity: 0, y: 10 }} animate={{ opacity: 1, y: 0 }} transition={{ duration: 0.3 }} - className="bg-base-200 rounded-xl p-8 text-center shadow-sm" + className="bg-gradient-to-b from-base-200 to-base-300 rounded-xl p-8 text-center shadow-sm border border-base-300/30" >
-

No Event Requests Found

+

No Event Requests Found

{statusFilter !== 'all' || searchTerm ? 'No event requests match your current filters. Try adjusting your search criteria.' @@ -331,7 +331,7 @@ const EventRequestManagementTable = ({

{(statusFilter !== 'all' || searchTerm) && (