diff --git a/backend/controllers/userController.js b/backend/controllers/userController.js index 0677b91d..8d8c241e 100644 --- a/backend/controllers/userController.js +++ b/backend/controllers/userController.js @@ -532,4 +532,4 @@ export const deleteUserAccount = async (req, res, next) => { } catch (error) { return next(error) } -} \ No newline at end of file +} diff --git a/backend/routes/Blog.js b/backend/routes/Blog.js index d3d81315..74b6c4e9 100644 --- a/backend/routes/Blog.js +++ b/backend/routes/Blog.js @@ -6,7 +6,7 @@ const router = Router() // Function to validate required fields with enhanced rules const validateBlogFields = (title, content, author) => { const errors = {} - + if (!title) { errors.title = 'Title is required.' } else if (title.length < 5) { @@ -18,7 +18,7 @@ const validateBlogFields = (title, content, author) => { } else if (content.length < 10) { errors.content = 'Content must be at least 10 characters long.' } - + if (!author) { errors.author = 'Author is required.' } else if (author.trim().length === 0) { @@ -37,9 +37,9 @@ router.post('/add', async (req, res) => { const errors = validateBlogFields(title, content, author) if (Object.keys(errors).length) { // Return a structured response showing all validation errors - return res.status(400).json({ + return res.status(400).json({ message: 'Validation failed. Please fix the errors below.', - errors + errors, }) } @@ -96,9 +96,9 @@ router.put('/update/:id', async (req, res) => { const errors = validateBlogFields(title, content, author) if (Object.keys(errors).length) { // Return a structured response showing all validation errors - return res.status(400).json({ + return res.status(400).json({ message: 'Validation failed. Please fix the errors below.', - errors + errors, }) } diff --git a/frontend/src/Components/ConfirmationModalDelete.jsx b/frontend/src/Components/ConfirmationModalDelete.jsx index 15c333ed..83b1f28e 100644 --- a/frontend/src/Components/ConfirmationModalDelete.jsx +++ b/frontend/src/Components/ConfirmationModalDelete.jsx @@ -1,13 +1,24 @@ -import React from 'react'; +import React from 'react' -const ConfirmationModalDelete = ({ isOpen, onClose, onConfirm, confirmationText, setConfirmationText }) => { - if (!isOpen) return null; +const ConfirmationModalDelete = ({ + isOpen, + onClose, + onConfirm, + confirmationText, + setConfirmationText, +}) => { + if (!isOpen) return null return (
-

Confirm Account Deletion

-

Type "I want to delete my account" to confirm:

+

+ Confirm Account Deletion +

+

+ Type "I want to delete my account" to + confirm: +

- -
- ); -}; + ) +} -export default ConfirmationModalDelete; +export default ConfirmationModalDelete diff --git a/frontend/src/Components/DeleteAccountButton.jsx b/frontend/src/Components/DeleteAccountButton.jsx index afb0154a..19bbd7de 100644 --- a/frontend/src/Components/DeleteAccountButton.jsx +++ b/frontend/src/Components/DeleteAccountButton.jsx @@ -1,30 +1,32 @@ -import React, { useState } from 'react'; -import { toast } from 'react-hot-toast'; -import axios from 'axios'; -import { useNavigate } from 'react-router-dom'; -import ConfirmationModal from './ConfirmationModalDelete'; // Import the modal component +import React, { useState } from 'react' +import { toast } from 'react-hot-toast' +import axios from 'axios' +import { useNavigate } from 'react-router-dom' +import ConfirmationModal from './ConfirmationModalDelete' // Import the modal component const DeleteAccountButton = () => { - const [isModalOpen, setIsModalOpen] = useState(false); - const [confirmationText, setConfirmationText] = useState(''); - const navigate = useNavigate(); + const [isModalOpen, setIsModalOpen] = useState(false) + const [confirmationText, setConfirmationText] = useState('') + const navigate = useNavigate() const handleDeleteAccount = async () => { if (confirmationText !== 'I want to delete my account') { - toast.error('Please type "I want to delete my account" to confirm.'); - return; + toast.error('Please type "I want to delete my account" to confirm.') + return } try { - const response = await axios.delete('/api/users'); // Adjust the endpoint as necessary - toast.success(response.data.message); - + const response = await axios.delete('/api/users') // Adjust the endpoint as necessary + toast.success(response.data.message) + // Redirect to the registration page after deletion - navigate('/register'); // Adjust the path as necessary + navigate('/register') // Adjust the path as necessary } catch (error) { - toast.error(error.response?.data?.message || 'Failed to delete account'); + toast.error( + error.response?.data?.message || 'Failed to delete account' + ) } - }; + } return (
@@ -43,7 +45,7 @@ const DeleteAccountButton = () => { setConfirmationText={setConfirmationText} />
- ); -}; + ) +} -export default DeleteAccountButton; +export default DeleteAccountButton diff --git a/frontend/src/Components/Home/ShopList.jsx b/frontend/src/Components/Home/ShopList.jsx index 059ed611..d7afe8e4 100644 --- a/frontend/src/Components/Home/ShopList.jsx +++ b/frontend/src/Components/Home/ShopList.jsx @@ -14,9 +14,7 @@ const ShopList = () => { const fetchShops = async () => { try { // Use the VITE_API_URL environment variable from .env file - const { data } = await axios.get( - `/api/shops/all-shops` - ) + const { data } = await axios.get(`/api/shops/all-shops`) setShops(data) // Set shop data in state setLoading(false) // Turn off loading } catch (error) { diff --git a/frontend/src/Pages/Admin/AaddCoupons.jsx b/frontend/src/Pages/Admin/AaddCoupons.jsx index 1b91bd4d..f5b0666b 100644 --- a/frontend/src/Pages/Admin/AaddCoupons.jsx +++ b/frontend/src/Pages/Admin/AaddCoupons.jsx @@ -5,36 +5,36 @@ import Swal from 'sweetalert2' import Sidebar from '../../Components/Admin/AsideBar' const AddCoupon = () => { - const navigate = useNavigate(); + const navigate = useNavigate() const [formData, setFormData] = useState({ couponCode: '', discount: '', expiryDate: '', - }); - const [loading, setLoading] = useState(false); + }) + const [loading, setLoading] = useState(false) const [errors, setErrors] = useState({ couponCode: '', discount: '', expiryDate: '', - }); + }) // Handle input change with validation const handleChange = (e) => { - const { name, value } = e.target; - let error = ''; + const { name, value } = e.target + let error = '' // Coupon Code validation: Ensure it's not empty if (name === 'couponCode' && value === '') { - error = 'Coupon code cannot be empty'; + error = 'Coupon code cannot be empty' } // Discount validation: Must be a number and <= 100 if (name === 'discount') { - const discountValue = parseInt(value, 10); + const discountValue = parseInt(value, 10) if (isNaN(discountValue) || discountValue < 0) { - error = 'Discount must be a positive number'; + error = 'Discount must be a positive number' } else if (discountValue > 100) { - error = 'Discount cannot be more than 100'; + error = 'Discount cannot be more than 100' } } // Expiry date validation: Must be today or a future date @@ -48,45 +48,45 @@ const AddCoupon = () => { } // Update form data and errors - setFormData({ ...formData, [name]: value }); - setErrors({ ...errors, [name]: error }); - }; + setFormData({ ...formData, [name]: value }) + setErrors({ ...errors, [name]: error }) + } // Handle form submission const handleSubmit = async (e) => { - e.preventDefault(); + e.preventDefault() // Check if any validation errors exist if (Object.values(errors).some((err) => err)) { - Swal.fire('Validation Error', 'Please fix the errors', 'error'); - return; + Swal.fire('Validation Error', 'Please fix the errors', 'error') + return } try { - setLoading(true); + setLoading(true) await axios.post('/coupon', formData, { headers: { Authorization: `Bearer ${localStorage.getItem('token')}`, }, - }); + }) - Swal.fire('Success', 'Coupon created successfully', 'success'); - navigate('/coupons'); + Swal.fire('Success', 'Coupon created successfully', 'success') + navigate('/coupons') } catch (err) { - console.error('Error creating coupon:', err); + console.error('Error creating coupon:', err) Swal.fire( 'Error', 'Error creating coupon, please try again', 'error' - ); + ) } finally { - setLoading(false); + setLoading(false) } - }; + } const handleCancel = () => { - navigate('/coupons'); - }; + navigate('/coupons') + } return (
@@ -137,8 +137,14 @@ const AddCoupon = () => { value={formData.discount} onChange={handleChange} onBlur={() => { - if (parseInt(formData.discount, 10) > 100) { - setFormData({ ...formData, discount: '100' }); + if ( + parseInt(formData.discount, 10) > + 100 + ) { + setFormData({ + ...formData, + discount: '100', + }) } }} required @@ -161,7 +167,7 @@ const AddCoupon = () => { onChange={handleChange} required min="2024-10-15" - max="2030-10-15" + max="2030-10-15" /> {errors.expiryDate && (

@@ -190,7 +196,7 @@ const AddCoupon = () => {

- ); -}; + ) +} -export default AddCoupon; +export default AddCoupon diff --git a/frontend/src/Pages/Admin/Astaff.jsx b/frontend/src/Pages/Admin/Astaff.jsx index c8549e6d..e35a31cf 100644 --- a/frontend/src/Pages/Admin/Astaff.jsx +++ b/frontend/src/Pages/Admin/Astaff.jsx @@ -110,30 +110,29 @@ const Staff = () => { } const generatePDF = () => { - const doc = new jsPDF(); - const img = new Image(); - const img1 = new Image(); - img.src = logo; - img1.src = image; + const doc = new jsPDF() + const img = new Image() + const img1 = new Image() + img.src = logo + img1.src = image // Add logo - doc.addImage(img, 'PNG', 20, 20, 35, 10); // Adjust x, y, width, height as needed + doc.addImage(img, 'PNG', 20, 20, 35, 10) // Adjust x, y, width, height as needed // Get the width of the PDF page - const pdfWidth = doc.internal.pageSize.getWidth(); - const imgWidth = 60; // Width of the image - const imgHeight = 25; // Height of the image - + const pdfWidth = doc.internal.pageSize.getWidth() + const imgWidth = 60 // Width of the image + const imgHeight = 25 // Height of the image + // Adjustments for moving the image higher and left - const xPosition = pdfWidth - imgWidth - 10; // Move left by 10 units - const yPosition = 20; // Move up on the Y-axis (reduce from 35 to 20) - + const xPosition = pdfWidth - imgWidth - 10 // Move left by 10 units + const yPosition = 20 // Move up on the Y-axis (reduce from 35 to 20) + // Position the image - doc.addImage(img1, 'PNG', xPosition, yPosition, imgWidth, imgHeight); - + doc.addImage(img1, 'PNG', xPosition, yPosition, imgWidth, imgHeight) // Add title below the logo - doc.setFontSize(15); - doc.text('Staff List', 105, 40, null, null, 'center'); // Centered below logo - + doc.setFontSize(15) + doc.text('Staff List', 105, 40, null, null, 'center') // Centered below logo + // Prepare the table data const tableColumn = [ 'Id', @@ -143,9 +142,9 @@ const Staff = () => { 'Birth Day', 'Address', 'Role', - ]; - const tableRows = []; - + ] + const tableRows = [] + filteredStaff.forEach((member, index) => { const memberData = [ index + 1, @@ -155,11 +154,10 @@ const Staff = () => { member.birthday.split('T')[0], `${member.Address.home} ${member.Address.street} ${member.Address.city}`, member.role, - ]; - tableRows.push(memberData); - }); - - + ] + tableRows.push(memberData) + }) + // Add table to PDF doc.autoTable({ head: [tableColumn], @@ -168,25 +166,29 @@ const Staff = () => { styles: { fontSize: 9, // Adjust this value to make the table content smaller }, - }); - + }) + // Get the final Y position after the table - const finalY = doc.lastAutoTable.finalY; - + const finalY = doc.lastAutoTable.finalY + // Add current date and time below the table, aligned to the left - const currentDate = new Date(); - const dateString = currentDate.toLocaleDateString(); // Format: MM/DD/YYYY or local format - const timeString = currentDate.toLocaleTimeString(); // Format: HH:MM:SS AM/PM or local format - - doc.setFontSize(8); // Smaller font for date and time - doc.text(`Generated on: ${dateString} at ${timeString}`, 20, finalY + 10, null, null, 'left'); // Left side of the document - + const currentDate = new Date() + const dateString = currentDate.toLocaleDateString() // Format: MM/DD/YYYY or local format + const timeString = currentDate.toLocaleTimeString() // Format: HH:MM:SS AM/PM or local format + + doc.setFontSize(8) // Smaller font for date and time + doc.text( + `Generated on: ${dateString} at ${timeString}`, + 20, + finalY + 10, + null, + null, + 'left' + ) // Left side of the document + // Save the PDF - doc.save('staff-list.pdf'); - }; - - - + doc.save('staff-list.pdf') + } if (loading) { return ( diff --git a/frontend/src/Pages/Customer/Settings.jsx b/frontend/src/Pages/Customer/Settings.jsx index b6833895..763db217 100644 --- a/frontend/src/Pages/Customer/Settings.jsx +++ b/frontend/src/Pages/Customer/Settings.jsx @@ -377,8 +377,8 @@ function Settings() {
-
- +
+
diff --git a/frontend/src/Pages/HomePage.jsx b/frontend/src/Pages/HomePage.jsx index c29ef0b0..ae566072 100644 --- a/frontend/src/Pages/HomePage.jsx +++ b/frontend/src/Pages/HomePage.jsx @@ -12,7 +12,7 @@ const Homepage = () => { document.title = 'FarmCart : Home' }, []) - const user = JSON.parse(localStorage.getItem('user')) + const user = JSON.parse(localStorage.getItem('user')) // Handle the case where user is null or undefined const customer = user diff --git a/frontend/src/Pages/blog manage/AddBlog.jsx b/frontend/src/Pages/blog manage/AddBlog.jsx index a6945c74..17d134f4 100644 --- a/frontend/src/Pages/blog manage/AddBlog.jsx +++ b/frontend/src/Pages/blog manage/AddBlog.jsx @@ -161,9 +161,7 @@ function AddNews() {