fix changes
This commit is contained in:
parent
4065105bab
commit
28822129ef
4 changed files with 87 additions and 17 deletions
|
@ -54,7 +54,19 @@ import EventRequestForm from "./Officer_EventRequestForm/EventRequestForm";
|
||||||
const formView = document.getElementById("form-view");
|
const formView = document.getElementById("form-view");
|
||||||
const previewView = document.getElementById("preview-view");
|
const previewView = document.getElementById("preview-view");
|
||||||
|
|
||||||
formTab?.addEventListener("click", () => {
|
// Prevent form submission when clicking tabs
|
||||||
|
document.querySelectorAll(".tab").forEach((tab) => {
|
||||||
|
tab.addEventListener("click", (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
formTab?.addEventListener("click", (e) => {
|
||||||
|
// Prevent default behavior to avoid form submission
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
formTab.classList.add("tab-active");
|
formTab.classList.add("tab-active");
|
||||||
previewTab?.classList.remove("tab-active");
|
previewTab?.classList.remove("tab-active");
|
||||||
formView?.classList.remove("hidden");
|
formView?.classList.remove("hidden");
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { motion } from 'framer-motion';
|
import { motion } from 'framer-motion';
|
||||||
|
import toast from 'react-hot-toast';
|
||||||
import type { EventRequestFormData } from './EventRequestForm';
|
import type { EventRequestFormData } from './EventRequestForm';
|
||||||
import InvoiceBuilder from './InvoiceBuilder';
|
import InvoiceBuilder from './InvoiceBuilder';
|
||||||
import type { InvoiceData } from './InvoiceBuilder';
|
import type { InvoiceData } from './InvoiceBuilder';
|
||||||
|
@ -40,32 +41,47 @@ const ASFundingSection: React.FC<ASFundingSectionProps> = ({ formData, onDataCha
|
||||||
const handleMultipleInvoiceFilesChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleMultipleInvoiceFilesChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
if (e.target.files && e.target.files.length > 0) {
|
if (e.target.files && e.target.files.length > 0) {
|
||||||
const files = Array.from(e.target.files);
|
const files = Array.from(e.target.files);
|
||||||
setInvoiceFiles(prevFiles => [...prevFiles, ...files]);
|
|
||||||
onDataChange({ invoice_files: [...formData.invoice_files, ...files] });
|
// Check file sizes
|
||||||
|
const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB limit per file
|
||||||
|
const oversizedFiles = files.filter(file => file.size > MAX_FILE_SIZE);
|
||||||
|
|
||||||
|
if (oversizedFiles.length > 0) {
|
||||||
|
toast.error(`Some files exceed the 10MB size limit: ${oversizedFiles.map(f => f.name).join(', ')}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update state with new files
|
||||||
|
const updatedFiles = [...invoiceFiles, ...files];
|
||||||
|
setInvoiceFiles(updatedFiles);
|
||||||
|
onDataChange({ invoice_files: updatedFiles });
|
||||||
|
|
||||||
// Also set the first file as the main invoice file for backward compatibility
|
// Also set the first file as the main invoice file for backward compatibility
|
||||||
if (files.length > 0 && !formData.invoice) {
|
if (files.length > 0 && !formData.invoice) {
|
||||||
setInvoiceFile(files[0]);
|
setInvoiceFile(files[0]);
|
||||||
onDataChange({ invoice: files[0] });
|
onDataChange({ invoice: files[0] });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toast.success(`Added ${files.length} file${files.length > 1 ? 's' : ''} successfully`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Remove an invoice file
|
// Remove an invoice file
|
||||||
const handleRemoveInvoiceFile = (index: number) => {
|
const handleRemoveInvoiceFile = (index: number) => {
|
||||||
const updatedFiles = [...invoiceFiles];
|
const updatedFiles = [...invoiceFiles];
|
||||||
|
const removedFileName = updatedFiles[index].name;
|
||||||
updatedFiles.splice(index, 1);
|
updatedFiles.splice(index, 1);
|
||||||
setInvoiceFiles(updatedFiles);
|
setInvoiceFiles(updatedFiles);
|
||||||
onDataChange({ invoice_files: updatedFiles });
|
onDataChange({ invoice_files: updatedFiles });
|
||||||
|
|
||||||
// Update the main invoice file if needed
|
// Update the main invoice file if needed
|
||||||
if (index === 0 && updatedFiles.length > 0) {
|
if (invoiceFile && invoiceFile.name === removedFileName) {
|
||||||
setInvoiceFile(updatedFiles[0]);
|
const newMainFile = updatedFiles.length > 0 ? updatedFiles[0] : null;
|
||||||
onDataChange({ invoice: updatedFiles[0] });
|
setInvoiceFile(newMainFile);
|
||||||
} else if (updatedFiles.length === 0) {
|
onDataChange({ invoice: newMainFile });
|
||||||
setInvoiceFile(null);
|
|
||||||
onDataChange({ invoice: null });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toast.success(`Removed ${removedFileName}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle invoice data change
|
// Handle invoice data change
|
||||||
|
|
|
@ -247,16 +247,22 @@ const EventRequestForm: React.FC = () => {
|
||||||
await fileManager.uploadFile('event_request', record.id, 'room_booking', formData.room_booking);
|
await fileManager.uploadFile('event_request', record.id, 'room_booking', formData.room_booking);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Upload the main invoice file (for backward compatibility)
|
|
||||||
if (formData.invoice) {
|
|
||||||
toast.loading('Uploading invoice file...', { id: submittingToast });
|
|
||||||
await fileManager.uploadFile('event_request', record.id, 'invoice', formData.invoice);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Upload multiple invoice files
|
// Upload multiple invoice files
|
||||||
if (formData.invoice_files && formData.invoice_files.length > 0) {
|
if (formData.invoice_files && formData.invoice_files.length > 0) {
|
||||||
toast.loading('Uploading invoice files...', { id: submittingToast });
|
toast.loading('Uploading invoice files...', { id: submittingToast });
|
||||||
await fileManager.uploadFiles('event_request', record.id, 'invoice_files', formData.invoice_files);
|
|
||||||
|
// Use appendFiles instead of uploadFiles to ensure we're adding files, not replacing them
|
||||||
|
await fileManager.appendFiles('event_request', record.id, 'invoice_files', formData.invoice_files);
|
||||||
|
|
||||||
|
// For backward compatibility, also upload the first file as the main invoice
|
||||||
|
if (formData.invoice || formData.invoice_files[0]) {
|
||||||
|
const mainInvoice = formData.invoice || formData.invoice_files[0];
|
||||||
|
await fileManager.uploadFile('event_request', record.id, 'invoice', mainInvoice);
|
||||||
|
}
|
||||||
|
} else if (formData.invoice) {
|
||||||
|
// If there are no invoice_files but there is a main invoice, upload it
|
||||||
|
toast.loading('Uploading invoice file...', { id: submittingToast });
|
||||||
|
await fileManager.uploadFile('event_request', record.id, 'invoice', formData.invoice);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear form data from localStorage
|
// Clear form data from localStorage
|
||||||
|
@ -754,7 +760,28 @@ const EventRequestForm: React.FC = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Toaster position="top-right" />
|
<Toaster
|
||||||
|
position="top-right"
|
||||||
|
toastOptions={{
|
||||||
|
duration: 4000,
|
||||||
|
style: {
|
||||||
|
background: '#333',
|
||||||
|
color: '#fff',
|
||||||
|
},
|
||||||
|
success: {
|
||||||
|
duration: 3000,
|
||||||
|
style: {
|
||||||
|
background: 'green',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
error: {
|
||||||
|
duration: 5000,
|
||||||
|
style: {
|
||||||
|
background: 'red',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<motion.div
|
<motion.div
|
||||||
variants={containerVariants}
|
variants={containerVariants}
|
||||||
initial="hidden"
|
initial="hidden"
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { motion } from 'framer-motion';
|
import { motion } from 'framer-motion';
|
||||||
|
import toast from 'react-hot-toast';
|
||||||
|
|
||||||
// Animation variants
|
// Animation variants
|
||||||
const itemVariants = {
|
const itemVariants = {
|
||||||
|
@ -128,6 +129,7 @@ const InvoiceBuilder: React.FC<InvoiceBuilderProps> = ({ invoiceData, onChange }
|
||||||
|
|
||||||
if (isDuplicate) {
|
if (isDuplicate) {
|
||||||
setErrors({ description: 'An item with this description already exists' });
|
setErrors({ description: 'An item with this description already exists' });
|
||||||
|
toast.error('An item with this description already exists');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,6 +151,9 @@ const InvoiceBuilder: React.FC<InvoiceBuilderProps> = ({ invoiceData, onChange }
|
||||||
items: [...invoiceData.items, item]
|
items: [...invoiceData.items, item]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Show success toast
|
||||||
|
toast.success(`Added ${item.description} to invoice`);
|
||||||
|
|
||||||
// Reset new item form
|
// Reset new item form
|
||||||
setNewItem({
|
setNewItem({
|
||||||
description: '',
|
description: '',
|
||||||
|
@ -162,10 +167,15 @@ const InvoiceBuilder: React.FC<InvoiceBuilderProps> = ({ invoiceData, onChange }
|
||||||
|
|
||||||
// Remove an item
|
// Remove an item
|
||||||
const handleRemoveItem = (id: string) => {
|
const handleRemoveItem = (id: string) => {
|
||||||
|
const itemToRemove = invoiceData.items.find(item => item.id === id);
|
||||||
onChange({
|
onChange({
|
||||||
...invoiceData,
|
...invoiceData,
|
||||||
items: invoiceData.items.filter(item => item.id !== id)
|
items: invoiceData.items.filter(item => item.id !== id)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (itemToRemove) {
|
||||||
|
toast.success(`Removed ${itemToRemove.description} from invoice`);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Update tax rate
|
// Update tax rate
|
||||||
|
@ -192,6 +202,11 @@ const InvoiceBuilder: React.FC<InvoiceBuilderProps> = ({ invoiceData, onChange }
|
||||||
...invoiceData,
|
...invoiceData,
|
||||||
vendor: e.target.value
|
vendor: e.target.value
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Clear vendor error if it exists
|
||||||
|
if (errors.vendor && e.target.value.trim()) {
|
||||||
|
setErrors({ ...errors, vendor: undefined });
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Format currency
|
// Format currency
|
||||||
|
|
Loading…
Reference in a new issue