From eb4b026e18974cbb8056c389571dbdf5c403eaf7 Mon Sep 17 00:00:00 2001 From: Harini312821 Date: Fri, 19 Jul 2024 22:53:10 +0800 Subject: [PATCH] editpage --- client/src/App.tsx | 2 + client/src/pages/EditEventsPage.tsx | 186 ++++++++++++++++++++++++++ client/src/pages/ManageEventsPage.tsx | 15 ++- server/models/Events.js | 4 - 4 files changed, 197 insertions(+), 10 deletions(-) create mode 100644 client/src/pages/EditEventsPage.tsx diff --git a/client/src/App.tsx b/client/src/App.tsx index ee66cdd..f26e763 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -14,6 +14,7 @@ import EventsPage from "./pages/EventsPage"; import CreateEventsPage from "./pages/CreateEventsPage"; import ManageEventsPage from "./pages/ManageEventsPage"; import AdministratorSpringboard from "./pages/AdministratorSpringboard"; +import EditEventsPage from "./pages/EditEventsPage"; function App() { return ( @@ -33,6 +34,7 @@ function App() { } path="/events" /> } path="/createEvent" /> } path="/manageEvent" /> + } path="/editEvent/:id" /> ); } diff --git a/client/src/pages/EditEventsPage.tsx b/client/src/pages/EditEventsPage.tsx new file mode 100644 index 0000000..b7cd688 --- /dev/null +++ b/client/src/pages/EditEventsPage.tsx @@ -0,0 +1,186 @@ +import React, { useState, useEffect } from 'react'; +import DefaultLayout from "../layouts/default"; +import { Button } from "@nextui-org/react"; +import { Formik, Form } from "formik"; +import * as Yup from "yup"; +import axios from "axios"; +import { useNavigate, useParams } from "react-router-dom"; +import NextUIFormikInput from "../components/NextUIFormikInput"; +import NextUIFormikTextarea from "../components/NextUIFormikTextarea"; +import config from "../config"; +import { ArrowUTurnLeftIcon } from "../icons"; + +const validationSchema = Yup.object({ + title: Yup.string() + .trim() + .min(3, "Title must be at least 3 characters") + .max(200, "Title must be at most 200 characters") + .matches( + /^[a-zA-Z0-9\s]+$/, + "Title can only contain letters, numbers, and spaces" + ) + .required("Title is required"), + description: Yup.string() + .trim() + .min(3, "Description must be at least 3 characters") + .max(500, "Description must be at most 500 characters") + .matches( + /^[a-zA-Z0-9,\s!"'-]*$/, + "Only letters, numbers, commas, spaces, exclamation marks, quotations, and common symbols are allowed" + ) + .required("Description is required"), + date: Yup.date().required("Date is required"), + time: Yup.string().required("Time is required"), + location: Yup.string().required("Location is required"), + category: Yup.string().required("Category is required"), + slotsAvailable: Yup.number().integer().required("Slots Available is required"), + imageUrl: Yup.string().url("Invalid URL format").required("Image URL is required") +}); + +const EditEventsPage = () => { + const navigate = useNavigate(); + const { id } = useParams<{ id: string }>(); + const [initialValues, setInitialValues] = useState({ + title: "", + description: "", + date: "", + time: "", + location: "", + category: "", + slotsAvailable: "", + imageUrl: "" + }); + + useEffect(() => { + const fetchEvent = async () => { + try { + const response = await axios.get(`${config.serverAddress}/events/${id}`); + console.log("Fetched event data:", response.data); // Debug log + setInitialValues(response.data); + } catch (error) { + console.error("Failed to fetch event data:", error); + } + }; + + fetchEvent(); + }, [id]); + + const handleSubmit = async ( + values: any, + { setSubmitting, resetForm, setFieldError }: any + ) => { + console.log("Submitting form with values:", values); // Debug log + try { + const response = await axios.put(`${config.serverAddress}/events/${id}`, values); + console.log("Server response:", response); // Debug log + if (response.status === 200 || response.status === 201) { + console.log("Event updated successfully:", response.data); + resetForm(); // Clear form after successful submit + navigate("/manageEvent"); + } else { + console.error("Error updating event:", response.statusText); + } + } catch (error: any) { + if (error.response && error.response.data && error.response.data.field) { + setFieldError(error.response.data.field, error.response.data.error); + } else { + console.error("Unexpected error:", error); + } + } finally { + setSubmitting(false); + } + }; + + return ( + +
+ +
+
+ + {({ isValid, dirty, isSubmitting }) => ( +
+ + + + + + + + +
+ +
+ + )} +
+
+
+ ); +}; + +export default EditEventsPage; diff --git a/client/src/pages/ManageEventsPage.tsx b/client/src/pages/ManageEventsPage.tsx index 09ecd3a..1f1a485 100644 --- a/client/src/pages/ManageEventsPage.tsx +++ b/client/src/pages/ManageEventsPage.tsx @@ -1,8 +1,8 @@ +import React, { useEffect, useState } from 'react'; import DefaultLayout from "../layouts/default"; import { Table, TableHeader, TableColumn, TableBody, TableRow, TableCell, Avatar, Button } from "@nextui-org/react"; import { useNavigate } from "react-router-dom"; import { PencilSquareIcon, TrashIcon } from "../icons"; -import { useEffect, useState } from "react"; import axios from "axios"; import config from "../config"; @@ -25,14 +25,16 @@ const ManageEventsPage = () => { }, []); const handleEdit = (id: string) => { - navigate(`/edit-event/${id}`); + navigate(`/editEvent/${id}`); }; - const handleDelete = (id: string) => { - // Add delete functionality here - axios.delete(`${config.serverAddress}/events/${id}`).then((res) => { + const handleDelete = async (id: string) => { + try { + await axios.delete(`${config.serverAddress}/events/${id}`); setEvents(events.filter((event) => event.id !== id)); - }); + } catch (error) { + console.error("Failed to delete event:", error); + } }; return ( @@ -99,3 +101,4 @@ const ManageEventsPage = () => { }; export default ManageEventsPage; + diff --git a/server/models/Events.js b/server/models/Events.js index 1b4690f..71186f6 100644 --- a/server/models/Events.js +++ b/server/models/Events.js @@ -27,10 +27,6 @@ module.exports = (sequelize) => { type: DataTypes.STRING, allowNull: false, }, - Events: { - type: DataTypes.BLOB("long"), - allowNull: true, - }, slotsAvailable: { type: DataTypes.INTEGER, allowNull: false,