ieeeucsd-org/src/components/dashboard/Officer_EventRequestForm.astro
2025-02-20 01:46:56 -08:00

274 lines
9 KiB
Text

---
import { Authentication } from "../../scripts/pocketbase/Authentication";
import { Update } from "../../scripts/pocketbase/Update";
import { FileManager } from "../../scripts/pocketbase/FileManager";
// Form sections
import PRSection from "./Officer_EventRequestForm/PRSection";
import EventDetailsSection from "./Officer_EventRequestForm/EventDetailsSection";
import TAPSection from "./Officer_EventRequestForm/TAPSection";
import ASFundingSection from "./Officer_EventRequestForm/ASFundingSection";
const auth = Authentication.getInstance();
const update = Update.getInstance();
const fileManager = FileManager.getInstance();
---
<div class="w-full max-w-4xl mx-auto p-6">
<h1
class="text-3xl font-bold mb-8 bg-gradient-to-r from-primary to-secondary bg-clip-text text-transparent"
>
Event Request Form
</h1>
<form id="eventRequestForm" class="space-y-8">
<div class="card bg-base-100/95 backdrop-blur-md shadow-lg">
<div class="card-body">
<h2 class="card-title text-xl">
Do you need graphics from our design team?
</h2>
<div class="space-y-4 mt-4">
<label class="label cursor-pointer justify-start gap-3">
<input
type="radio"
name="needsGraphics"
value="yes"
class="radio radio-primary"
/>
<span class="label-text">Yes (Continue to PR Section)</span>
</label>
<label class="label cursor-pointer justify-start gap-3">
<input
type="radio"
name="needsGraphics"
value="no"
class="radio radio-primary"
/>
<span class="label-text">No (Skip to Event Details)</span>
</label>
</div>
</div>
</div>
<div id="prSection" class="hidden">
<PRSection client:load />
</div>
<div id="eventDetailsSection">
<EventDetailsSection client:load />
</div>
<div id="tapSection">
<TAPSection client:load>
<ASFundingSection client:load />
</TAPSection>
</div>
<div class="flex justify-end space-x-4 mt-8">
<button
type="button"
id="saveAsDraft"
class="btn btn-ghost hover:bg-base-200 gap-2"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
d="M7.707 10.293a1 1 0 10-1.414 1.414l3 3a1 1 0 001.414 0l3-3a1 1 0 00-1.414-1.414L11 11.586V6h5a2 2 0 012 2v7a2 2 0 01-2 2H4a2 2 0 01-2-2V8a2 2 0 012-2h5v5.586l-1.293-1.293zM9 4a1 1 0 012 0v2H9V4z"
></path>
</svg>
Save as Draft
</button>
<button
type="submit"
class="btn btn-primary gap-2 shadow-md hover:shadow-lg transition-all duration-300"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
d="M10.894 2.553a1 1 0 00-1.788 0l-7 14a1 1 0 001.169 1.409l5-1.429A1 1 0 009 15.571V11a1 1 0 112 0v4.571a1 1 0 00.725.962l5 1.428a1 1 0 001.17-1.408l-7-14z"
></path>
</svg>
Submit Request
</button>
</div>
</form>
</div>
<script>
import { Authentication } from "../../scripts/pocketbase/Authentication";
import { Update } from "../../scripts/pocketbase/Update";
import { FileManager } from "../../scripts/pocketbase/FileManager";
// Form visibility logic
const form = document.getElementById("eventRequestForm") as HTMLFormElement;
const prSection = document.getElementById("prSection");
const needsGraphicsRadios = document.getElementsByName("needsGraphics");
// Show/hide PR section based on radio selection
needsGraphicsRadios.forEach((radio) => {
radio.addEventListener("change", (e) => {
const target = e.target as HTMLInputElement;
if (target.value === "yes" && prSection) {
prSection.classList.remove("hidden");
} else if (prSection) {
prSection.classList.add("hidden");
}
});
});
// Form submission handler
form?.addEventListener("submit", async (e) => {
e.preventDefault();
// Collect form data
const formData = new FormData(form);
const data: Record<string, any> = {};
// Convert FormData to a proper object with correct types
formData.forEach((value, key) => {
if (value instanceof File) {
// Skip file fields as they'll be handled separately
return;
}
data[key] = value;
});
try {
// Create event request record
const auth = Authentication.getInstance();
const update = Update.getInstance();
// Add user ID to the request
const userId = auth.getUserId();
if (userId) {
data.requested_user = userId;
}
// Create the record
const record = await update.updateFields(
"event_request",
data.id || "",
data,
);
// Handle file uploads if any
const fileManager = FileManager.getInstance();
const fileFields = ["room_booking", "invoice", "other_logos"];
for (const field of fileFields) {
const files = formData
.getAll(field)
.filter((f): f is File => f instanceof File);
if (files.length > 0) {
await fileManager.uploadFiles(
"event_request",
record.id,
field,
files,
);
}
}
// Show success message using a toast
const toast = document.createElement("div");
toast.className = "toast toast-end";
toast.innerHTML = `
<div class="alert alert-success">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<span>Event request submitted successfully!</span>
</div>
`;
document.body.appendChild(toast);
setTimeout(() => toast.remove(), 3000);
// Redirect to events management page
window.location.href = "/dashboard/events";
} catch (error) {
console.error("Error submitting form:", error);
// Show error toast
const toast = document.createElement("div");
toast.className = "toast toast-end";
toast.innerHTML = `
<div class="alert alert-error">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
<span>Error submitting form. Please try again.</span>
</div>
`;
document.body.appendChild(toast);
setTimeout(() => toast.remove(), 3000);
}
});
// Save as draft handler
document
.getElementById("saveAsDraft")
?.addEventListener("click", async () => {
// Similar to submit but mark as draft
const formData = new FormData(form);
const data: Record<string, any> = {};
// Convert FormData to a proper object with correct types
formData.forEach((value, key) => {
if (value instanceof File) {
// Skip file fields as they'll be handled separately
return;
}
data[key] = value;
});
data.status = "draft";
try {
const auth = Authentication.getInstance();
const update = Update.getInstance();
const userId = auth.getUserId();
if (userId) {
data.requested_user = userId;
}
await update.updateFields("event_request", data.id || "", data);
// Show success toast
const toast = document.createElement("div");
toast.className = "toast toast-end";
toast.innerHTML = `
<div class="alert alert-success">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<span>Draft saved successfully!</span>
</div>
`;
document.body.appendChild(toast);
setTimeout(() => toast.remove(), 3000);
} catch (error) {
console.error("Error saving draft:", error);
// Show error toast
const toast = document.createElement("div");
toast.className = "toast toast-end";
toast.innerHTML = `
<div class="alert alert-error">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
<span>Error saving draft. Please try again.</span>
</div>
`;
document.body.appendChild(toast);
setTimeout(() => toast.remove(), 3000);
}
});
</script>