removed feedback

This commit is contained in:
chark1es 2025-03-07 21:54:59 -08:00
parent aeda1094b5
commit f48e2ff32a
3 changed files with 166 additions and 261 deletions

View file

@ -13,21 +13,20 @@ const auth = Authentication.getInstance();
// Extended EventRequest interface with additional properties needed for this component // Extended EventRequest interface with additional properties needed for this component
interface ExtendedEventRequest extends EventRequest { interface ExtendedEventRequest extends EventRequest {
requested_user_expand?: { requested_user_expand?: {
name: string; name: string;
email: string; email: string;
};
expand?: {
requested_user?: {
id: string;
name: string;
email: string;
[key: string]: any;
}; };
expand?: { [key: string]: any;
requested_user?: { };
id: string; [key: string]: any; // For other optional properties
name: string;
email: string;
[key: string]: any;
};
[key: string]: any;
};
feedback?: string;
[key: string]: any; // For other optional properties
} }
// Initialize variables for all event requests // Initialize variables for all event requests
@ -35,185 +34,175 @@ let allEventRequests: ExtendedEventRequest[] = [];
let error = null; let error = null;
try { try {
// Don't check authentication here - let the client component handle it // Don't check authentication here - let the client component handle it
// The server-side check is causing issues when the token is valid client-side but not server-side // The server-side check is causing issues when the token is valid client-side but not server-side
console.log("Fetching event requests in Astro component..."); console.log("Fetching event requests in Astro component...");
// Expand the requested_user field to get user details // Expand the requested_user field to get user details
allEventRequests = await get allEventRequests = await get
.getAll<ExtendedEventRequest>( .getAll<ExtendedEventRequest>(Collections.EVENT_REQUESTS, "", "-created", {
Collections.EVENT_REQUESTS, expand: ["requested_user"],
"", })
"-created", .catch((err) => {
{ console.error("Error in get.getAll:", err);
expand: ["requested_user"], // Return empty array instead of throwing
} return [];
)
.catch((err) => {
console.error("Error in get.getAll:", err);
// Return empty array instead of throwing
return [];
});
console.log(
`Fetched ${allEventRequests.length} event requests in Astro component`
);
// Process the event requests to add the requested_user_expand property
allEventRequests = allEventRequests.map((request) => {
const requestWithExpand = { ...request };
// Add the requested_user_expand property if the expand data is available
if (
request.expand &&
request.expand.requested_user &&
request.expand.requested_user.name &&
request.expand.requested_user.email
) {
requestWithExpand.requested_user_expand = {
name: request.expand.requested_user.name,
email: request.expand.requested_user.email,
};
}
return requestWithExpand;
}); });
console.log(
`Fetched ${allEventRequests.length} event requests in Astro component`,
);
// Process the event requests to add the requested_user_expand property
allEventRequests = allEventRequests.map((request) => {
const requestWithExpand = { ...request };
// Add the requested_user_expand property if the expand data is available
if (
request.expand &&
request.expand.requested_user &&
request.expand.requested_user.name &&
request.expand.requested_user.email
) {
requestWithExpand.requested_user_expand = {
name: request.expand.requested_user.name,
email: request.expand.requested_user.email,
};
}
return requestWithExpand;
});
} catch (err) { } catch (err) {
console.error("Error fetching event requests:", err); console.error("Error fetching event requests:", err);
error = err; error = err;
} }
--- ---
<div class="w-full max-w-7xl mx-auto py-8 px-4"> <div class="w-full max-w-7xl mx-auto py-8 px-4">
<style> <style>
.event-table-container { .event-table-container {
min-height: 600px; min-height: 600px;
height: auto !important; height: auto !important;
max-height: none !important; max-height: none !important;
} }
.event-table-container table { .event-table-container table {
height: auto !important; height: auto !important;
} }
.event-table-container .overflow-x-auto { .event-table-container .overflow-x-auto {
max-height: none !important; max-height: none !important;
} }
</style> </style>
<div class="mb-8"> <div class="mb-8">
<h1 class="text-3xl font-bold text-white mb-2"> <h1 class="text-3xl font-bold text-white mb-2">Event Request Management</h1>
Event Request Management <p class="text-gray-300 mb-4">
</h1> Review and manage event requests submitted by officers. Update status and
<p class="text-gray-300 mb-4"> coordinate with the team.
Review and manage event requests submitted by officers. Update </p>
status, provide feedback, and coordinate with the team. <div class="bg-base-300/50 p-4 rounded-lg text-sm text-gray-300">
</p> <p class="font-medium mb-2">As an executive officer, you can:</p>
<div class="bg-base-300/50 p-4 rounded-lg text-sm text-gray-300"> <ul class="list-disc list-inside space-y-1 ml-2">
<p class="font-medium mb-2">As an executive officer, you can:</p> <li>View all submitted event requests</li>
<ul class="list-disc list-inside space-y-1 ml-2"> <li>Update the status of requests (Pending, Completed, Declined)</li>
<li>View all submitted event requests</li> <li>Filter and sort requests by various criteria</li>
<li> </ul>
Update the status of requests (Pending, Completed, Declined)
</li>
<li>Add comments or feedback for the requesting officer</li>
<li>Filter and sort requests by various criteria</li>
</ul>
</div>
</div> </div>
</div>
{ {
error && ( error && (
<div class="alert alert-error mb-6"> <div class="alert alert-error mb-6">
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6 stroke-current shrink-0" class="h-6 w-6 stroke-current shrink-0"
fill="none" fill="none"
viewBox="0 0 24 24" viewBox="0 0 24 24"
> >
<path <path
stroke-linecap="round" stroke-linecap="round"
stroke-linejoin="round" stroke-linejoin="round"
stroke-width="2" stroke-width="2"
d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"
/> />
</svg> </svg>
<span>{error}</span> <span>{error}</span>
</div> </div>
) )
} }
{ {
!error && ( !error && (
<div class="bg-base-200 rounded-lg shadow-xl min-h-[600px] event-table-container"> <div class="bg-base-200 rounded-lg shadow-xl min-h-[600px] event-table-container">
<div class="p-4 md:p-6 h-auto"> <div class="p-4 md:p-6 h-auto">
<EventRequestManagementTable <EventRequestManagementTable
client:load client:load
eventRequests={allEventRequests} eventRequests={allEventRequests}
/> />
</div> </div>
</div> </div>
) )
} }
</div> </div>
<script> <script>
// Import the DataSyncService for client-side use // Import the DataSyncService for client-side use
import { DataSyncService } from "../../scripts/database/DataSyncService"; import { DataSyncService } from "../../scripts/database/DataSyncService";
import { Collections } from "../../schemas/pocketbase/schema"; import { Collections } from "../../schemas/pocketbase/schema";
// Remove the visibilitychange event listener that causes full page refresh // Remove the visibilitychange event listener that causes full page refresh
// Instead, we'll use a more efficient approach to refresh data only when needed // Instead, we'll use a more efficient approach to refresh data only when needed
document.addEventListener("visibilitychange", () => { document.addEventListener("visibilitychange", () => {
if (document.visibilityState === "visible") { if (document.visibilityState === "visible") {
// Instead of reloading the entire page, dispatch a custom event // Instead of reloading the entire page, dispatch a custom event
// that components can listen for to refresh their data // that components can listen for to refresh their data
document.dispatchEvent(new CustomEvent("dashboardTabVisible")); document.dispatchEvent(new CustomEvent("dashboardTabVisible"));
} }
}); });
// Handle authentication errors // Handle authentication errors
document.addEventListener("DOMContentLoaded", async () => { document.addEventListener("DOMContentLoaded", async () => {
// Initialize DataSyncService for client-side // Initialize DataSyncService for client-side
const dataSync = DataSyncService.getInstance(); const dataSync = DataSyncService.getInstance();
// Prefetch data into IndexedDB // Prefetch data into IndexedDB
try { try {
await dataSync.syncCollection( await dataSync.syncCollection(
Collections.EVENT_REQUESTS, Collections.EVENT_REQUESTS,
"", "",
"-created", "-created",
{ expand: "requested_user" } { expand: "requested_user" },
); );
console.log("Initial data sync complete"); console.log("Initial data sync complete");
} catch (err) { } catch (err) {
console.error("Error during initial data sync:", err); console.error("Error during initial data sync:", err);
} }
// Check for error message in the UI // Check for error message in the UI
const errorElement = document.querySelector(".alert-error span"); const errorElement = document.querySelector(".alert-error span");
if ( if (
errorElement && errorElement &&
errorElement.textContent?.includes("Authentication error") errorElement.textContent?.includes("Authentication error")
) { ) {
console.log( console.log(
"Authentication error detected in UI, redirecting to login..." "Authentication error detected in UI, redirecting to login...",
); );
// Redirect to login page after a short delay // Redirect to login page after a short delay
setTimeout(() => { setTimeout(() => {
window.location.href = "/login"; window.location.href = "/login";
}, 3000); }, 3000);
return; return;
} }
// Also check if we have any event requests // Also check if we have any event requests
const tableContainer = document.querySelector(".event-table-container"); const tableContainer = document.querySelector(".event-table-container");
if (tableContainer) { if (tableContainer) {
console.log( console.log(
"Event table container found, component should load normally" "Event table container found, component should load normally",
); );
} else { } else {
console.log( console.log(
"Event table container not found, might be an issue with rendering" "Event table container not found, might be an issue with rendering",
); );
} }
}); });
</script> </script>

View file

@ -12,14 +12,12 @@ interface ExtendedEventRequest extends SchemaEventRequest {
email: string; email: string;
}; };
invoice_data?: string | any; invoice_data?: string | any;
feedback?: string;
} }
interface EventRequestDetailsProps { interface EventRequestDetailsProps {
request: ExtendedEventRequest; request: ExtendedEventRequest;
onClose: () => void; onClose: () => void;
onStatusChange: (id: string, status: "submitted" | "pending" | "completed" | "declined") => Promise<void>; onStatusChange: (id: string, status: "submitted" | "pending" | "completed" | "declined") => Promise<void>;
onFeedbackChange: (id: string, feedback: string) => Promise<boolean>;
} }
// Separate component for AS Funding tab to isolate any issues // Separate component for AS Funding tab to isolate any issues
@ -225,11 +223,8 @@ const InvoiceTable: React.FC<{ invoiceData: any }> = ({ invoiceData }) => {
const EventRequestDetails = ({ const EventRequestDetails = ({
request, request,
onClose, onClose,
onStatusChange, onStatusChange
onFeedbackChange
}: EventRequestDetailsProps): React.ReactNode => { }: EventRequestDetailsProps): React.ReactNode => {
const [feedback, setFeedback] = useState<string>(request.feedback || '');
const [isSaving, setIsSaving] = useState<boolean>(false);
const [activeTab, setActiveTab] = useState<'details' | 'pr' | 'funding'>('details'); const [activeTab, setActiveTab] = useState<'details' | 'pr' | 'funding'>('details');
const [status, setStatus] = useState<"submitted" | "pending" | "completed" | "declined">(request.status); const [status, setStatus] = useState<"submitted" | "pending" | "completed" | "declined">(request.status);
const [isStatusChanging, setIsStatusChanging] = useState(false); const [isStatusChanging, setIsStatusChanging] = useState(false);
@ -269,22 +264,6 @@ const EventRequestDetails = ({
} }
}; };
// Handle saving feedback
const handleSaveFeedback = async () => {
if (feedback === request.feedback) {
toast('No changes to save', { icon: '' });
return;
}
setIsSaving(true);
const success = await onFeedbackChange(request.id, feedback);
setIsSaving(false);
if (success) {
toast.success('Feedback saved successfully');
}
};
// Handle status change // Handle status change
const handleStatusChange = async (newStatus: "submitted" | "pending" | "completed" | "declined") => { const handleStatusChange = async (newStatus: "submitted" | "pending" | "completed" | "declined") => {
setIsStatusChanging(true); setIsStatusChanging(true);
@ -479,36 +458,6 @@ const EventRequestDetails = ({
<ASFundingTab request={request} /> <ASFundingTab request={request} />
)} )}
</div> </div>
{/* Feedback section */}
<div className="p-4 border-t border-base-300">
<h4 className="text-sm font-medium text-gray-400 mb-2">Feedback for Requester</h4>
<div className="flex flex-col gap-3">
<textarea
className="textarea textarea-bordered w-full"
placeholder="Add feedback or notes for the event requester..."
rows={3}
value={feedback}
onChange={(e) => setFeedback(e.target.value)}
></textarea>
<div className="flex justify-end">
<button
className="btn btn-primary btn-sm"
onClick={handleSaveFeedback}
disabled={isSaving || feedback === request.feedback}
>
{isSaving ? (
<>
<span className="loading loading-spinner loading-xs"></span>
Saving...
</>
) : (
'Save Feedback'
)}
</button>
</div>
</div>
</div>
</motion.div> </motion.div>
</div> </div>
); );

View file

@ -25,7 +25,6 @@ interface ExtendedEventRequest extends SchemaEventRequest {
[key: string]: any; [key: string]: any;
}; };
invoice_data?: any; invoice_data?: any;
feedback?: string;
status: "submitted" | "pending" | "completed" | "declined"; status: "submitted" | "pending" | "completed" | "declined";
} }
@ -176,37 +175,6 @@ const EventRequestManagementTable = ({ eventRequests: initialEventRequests }: Ev
} }
}; };
// Add feedback to event request
const addFeedback = async (id: string, feedback: string) => {
try {
const update = Update.getInstance();
const result = await update.updateField('event_request', id, 'feedback', feedback);
// Update local state
setEventRequests(prev =>
prev.map(request =>
request.id === id ? { ...request, feedback } : request
)
);
setFilteredRequests(prev =>
prev.map(request =>
request.id === id ? { ...request, feedback } : request
)
);
// Force sync to update IndexedDB
await dataSync.syncCollection<ExtendedEventRequest>(Collections.EVENT_REQUESTS);
// Remove success toast for saving feedback
return true;
} catch (error) {
console.error('Error saving feedback:', error);
toast.error('Failed to save feedback');
return false;
}
};
// Format date for display // Format date for display
const formatDate = (dateString: string) => { const formatDate = (dateString: string) => {
if (!dateString) return 'Not specified'; if (!dateString) return 'Not specified';
@ -616,7 +584,6 @@ const EventRequestManagementTable = ({ eventRequests: initialEventRequests }: Ev
request={selectedRequest} request={selectedRequest}
onClose={closeModal} onClose={closeModal}
onStatusChange={updateEventRequestStatus} onStatusChange={updateEventRequestStatus}
onFeedbackChange={addFeedback}
/> />
</AnimatePresence> </AnimatePresence>
)} )}