updated create events and event details
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
import React, { useState, useEffect } from "react";
|
||||||
import { Button } from "@nextui-org/react";
|
import { Button } from "@nextui-org/react";
|
||||||
import { Formik, Form } from "formik";
|
import { Formik, Form } from "formik";
|
||||||
import * as Yup from "yup";
|
import * as Yup from "yup";
|
||||||
@@ -8,6 +9,7 @@ import NextUIFormikTextarea from "../components/NextUIFormikTextarea";
|
|||||||
import config from "../config";
|
import config from "../config";
|
||||||
import { ArrowUTurnLeftIcon } from "../icons";
|
import { ArrowUTurnLeftIcon } from "../icons";
|
||||||
|
|
||||||
|
// Validation schema
|
||||||
const validationSchema = Yup.object({
|
const validationSchema = Yup.object({
|
||||||
title: Yup.string()
|
title: Yup.string()
|
||||||
.trim()
|
.trim()
|
||||||
@@ -40,8 +42,22 @@ const validationSchema = Yup.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const CreateEventsPage = () => {
|
const CreateEventsPage = () => {
|
||||||
|
const [townCouncils, setTownCouncils] = useState<string[]>([]);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchTownCouncils = async () => {
|
||||||
|
try {
|
||||||
|
const res = await axios.get(`${config.serverAddress}/users/town-councils-metadata`);
|
||||||
|
setTownCouncils(JSON.parse(res.data).townCouncils);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to fetch town councils:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fetchTownCouncils();
|
||||||
|
}, []);
|
||||||
|
|
||||||
const initialValues = {
|
const initialValues = {
|
||||||
title: "",
|
title: "",
|
||||||
description: "",
|
description: "",
|
||||||
@@ -100,7 +116,7 @@ const CreateEventsPage = () => {
|
|||||||
validationSchema={validationSchema}
|
validationSchema={validationSchema}
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
>
|
>
|
||||||
{({ isValid, dirty, isSubmitting }) => (
|
{({ isValid, dirty, isSubmitting, setFieldValue }) => (
|
||||||
<Form className="flex flex-col gap-5">
|
<Form className="flex flex-col gap-5">
|
||||||
<NextUIFormikInput
|
<NextUIFormikInput
|
||||||
label="Title"
|
label="Title"
|
||||||
@@ -128,13 +144,21 @@ const CreateEventsPage = () => {
|
|||||||
placeholder="Enter event time"
|
placeholder="Enter event time"
|
||||||
labelPlacement="inside"
|
labelPlacement="inside"
|
||||||
/>
|
/>
|
||||||
<NextUIFormikInput
|
<div>
|
||||||
label="Location"
|
<label className="block text-gray-700">Location</label>
|
||||||
name="location"
|
<select
|
||||||
type="text"
|
name="location"
|
||||||
placeholder="Enter event location"
|
className="form-select mt-1 block w-full"
|
||||||
labelPlacement="inside"
|
onChange={(e) => setFieldValue("location", e.target.value)}
|
||||||
/>
|
>
|
||||||
|
<option value="">Select a town council</option>
|
||||||
|
{townCouncils.map((townCouncil, index) => (
|
||||||
|
<option key={index} value={townCouncil}>
|
||||||
|
{townCouncil}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
<NextUIFormikInput
|
<NextUIFormikInput
|
||||||
label="Category"
|
label="Category"
|
||||||
name="category"
|
name="category"
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { useParams, useNavigate } from "react-router-dom";
|
import { useParams, useNavigate } from "react-router-dom";
|
||||||
import instance from "../security/http";
|
import instance from "../security/http";
|
||||||
import config from "../config";
|
import config from "../config";
|
||||||
import { Card, CardHeader, CardBody, Button } from "@nextui-org/react";
|
import { Card, CardHeader, CardBody, Button, CardFooter } from "@nextui-org/react";
|
||||||
import { ArrowUTurnLeftIcon } from "../icons"; // Make sure this path is correct
|
import { ArrowUTurnLeftIcon } from "../icons"; // Make sure this path is correct
|
||||||
|
|
||||||
const EventDetailsPage = () => {
|
const EventDetailsPage = () => {
|
||||||
const { id } = useParams<{ id: string }>(); // Get the event ID from the URL
|
const { id } = useParams<{ id: string }>(); // Get the event ID from the URL
|
||||||
const [event, setEvent] = useState<any>(null); // State to store event details
|
const [event, setEvent] = useState<any>(null); // State to store event details
|
||||||
|
const [similarEvents, setSimilarEvents] = useState<any[]>([]); // State to store similar events
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -17,6 +18,18 @@ const EventDetailsPage = () => {
|
|||||||
const res = await instance.get(`${config.serverAddress}/events/${id}`);
|
const res = await instance.get(`${config.serverAddress}/events/${id}`);
|
||||||
console.log("Fetched event details:", res.data); // Log the fetched data
|
console.log("Fetched event details:", res.data); // Log the fetched data
|
||||||
setEvent(res.data);
|
setEvent(res.data);
|
||||||
|
|
||||||
|
// Fetch all events to find similar ones
|
||||||
|
const allEventsRes = await instance.get(`${config.serverAddress}/events`);
|
||||||
|
const allEvents = allEventsRes.data;
|
||||||
|
|
||||||
|
// Find similar events based on location and category, excluding the current event
|
||||||
|
const similar = allEvents.filter((e: any) =>
|
||||||
|
e.id !== Number(id) && // Make sure to exclude the current event
|
||||||
|
(e.location === res.data.location || e.category === res.data.category)
|
||||||
|
);
|
||||||
|
|
||||||
|
setSimilarEvents(similar);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to fetch event details:", error);
|
console.error("Failed to fetch event details:", error);
|
||||||
}
|
}
|
||||||
@@ -31,7 +44,7 @@ const EventDetailsPage = () => {
|
|||||||
<div className="w-full h-full p-8">
|
<div className="w-full h-full p-8">
|
||||||
<Button
|
<Button
|
||||||
className="mb-4 bg-gray-200 text-black rounded px-4 py-2 hover:bg-gray-300"
|
className="mb-4 bg-gray-200 text-black rounded px-4 py-2 hover:bg-gray-300"
|
||||||
onClick={() => navigate(-1)}
|
onClick={() => navigate('/events')} // Navigate directly to the events page
|
||||||
>
|
>
|
||||||
<ArrowUTurnLeftIcon />
|
<ArrowUTurnLeftIcon />
|
||||||
Back to Events
|
Back to Events
|
||||||
@@ -65,13 +78,48 @@ const EventDetailsPage = () => {
|
|||||||
<strong>Slots Available:</strong> {event.slotsAvailable}
|
<strong>Slots Available:</strong> {event.slotsAvailable}
|
||||||
</p>
|
</p>
|
||||||
<Button
|
<Button
|
||||||
className="mt-4 bg-red-500 text-white rounded px-4 py-2 hover:red"
|
className="mt-4 bg-red-500 text-white rounded px-4 py-2 hover:bg-red-600"
|
||||||
onClick={() => navigate(`/register/${id}`)}
|
onClick={() => navigate(`/register/${id}`)}
|
||||||
>
|
>
|
||||||
Register for Event
|
Register for Event
|
||||||
</Button>
|
</Button>
|
||||||
</CardBody>
|
</CardBody>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
{/* Similar Events Section */}
|
||||||
|
<div className="mt-8">
|
||||||
|
<h2 className="text-2xl font-semibold mb-4">Similar Events You Might Be Interested In</h2>
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
|
{similarEvents.length === 0 ? (
|
||||||
|
<p className="text-gray-600">No similar events available.</p>
|
||||||
|
) : (
|
||||||
|
similarEvents.map((similarEvent: any) => (
|
||||||
|
<Card key={similarEvent.id} className="bg-white rounded-lg overflow-hidden border">
|
||||||
|
<CardHeader className="pb-0 pt-2 px-4 flex-col items-start">
|
||||||
|
<h4 className="font-bold text-large">{similarEvent.title}</h4>
|
||||||
|
</CardHeader>
|
||||||
|
<CardBody className="pb-0 pt-2 px-4 flex-col items-start">
|
||||||
|
<img
|
||||||
|
alt={similarEvent.title}
|
||||||
|
className="object-cover rounded-xl"
|
||||||
|
src={similarEvent.imageUrl}
|
||||||
|
width="100%"
|
||||||
|
height={180}
|
||||||
|
/>
|
||||||
|
</CardBody>
|
||||||
|
<CardFooter className="flex flex-col items-start p-4">
|
||||||
|
<Button
|
||||||
|
className="bg-primary-600 text-white rounded px-4 py-2 hover:bg-primary-700"
|
||||||
|
onClick={() => navigate(`/event/${similarEvent.id}`)}
|
||||||
|
>
|
||||||
|
View event details
|
||||||
|
</Button>
|
||||||
|
</CardFooter>
|
||||||
|
</Card>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user