From b079d8be7f48b46f9dc90036ecd0fa4e7f5f1a55 Mon Sep 17 00:00:00 2001 From: khushijain03 Date: Fri, 2 May 2025 19:58:29 -0400 Subject: [PATCH 1/8] Resolved merge conflicts with development --- package-lock.json | 83 +++++ package.json | 2 + src/components/App.jsx | 2 + .../EventManagement/EventManagementTabs.css | 48 +++ .../EventManagement/EventManagementTabs.jsx | 109 ++++++ .../EventManagement/EventPage.css | 318 ++++++++++++++++++ .../EventManagement/EventPage.jsx | 193 +++++++++++ src/routes.js | 34 ++ 8 files changed, 789 insertions(+) create mode 100644 src/components/CommunityPortal/EventManagement/EventManagementTabs.css create mode 100644 src/components/CommunityPortal/EventManagement/EventManagementTabs.jsx create mode 100644 src/components/CommunityPortal/EventManagement/EventPage.css create mode 100644 src/components/CommunityPortal/EventManagement/EventPage.jsx diff --git a/package-lock.json b/package-lock.json index ddde41d5c6..70a4b49219 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9921,6 +9921,11 @@ "@xtuc/long": "4.2.2" } }, + "@wojtekmaj/date-utils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@wojtekmaj/date-utils/-/date-utils-1.5.1.tgz", + "integrity": "sha512-+i7+JmNiE/3c9FKxzWFi2IjRJ+KzZl1QPu6QNrsgaa2MuBgXvUy4gA1TVzf/JMdIIloB76xSKikTWuyYAIVLww==" + }, "@xmldom/xmldom": { "version": "0.8.10", "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", @@ -20947,6 +20952,23 @@ "map-cache": "^0.2.2" } }, + "framer-motion": { + "version": "12.9.2", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.9.2.tgz", + "integrity": "sha512-R0O3Jdqbfwywpm45obP+8sTgafmdEcUoShQTAV+rB5pi+Y1Px/FYL5qLLRe5tPtBdN1J4jos7M+xN2VV2oEAbQ==", + "requires": { + "motion-dom": "^12.9.1", + "motion-utils": "^12.8.3", + "tslib": "^2.4.0" + }, + "dependencies": { + "tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + } + } + }, "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", @@ -21200,6 +21222,14 @@ "get-intrinsic": "^1.1.1" } }, + "get-user-locale": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/get-user-locale/-/get-user-locale-2.3.2.tgz", + "integrity": "sha512-O2GWvQkhnbDoWFUJfaBlDIKUEdND8ATpBXD6KXcbhxlfktyD/d8w6mkzM/IlQEqGZAMz/PW6j6Hv53BiigKLUQ==", + "requires": { + "mem": "^8.0.0" + } + }, "get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", @@ -24231,6 +24261,14 @@ "tmpl": "1.0.5" } }, + "map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "requires": { + "p-defer": "^1.0.0" + } + }, "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", @@ -24275,6 +24313,22 @@ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" }, + "mem": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/mem/-/mem-8.1.1.tgz", + "integrity": "sha512-qFCFUDs7U3b8mBDPyz5EToEKoAkgCzqquIgi9nkkR9bixxOVOre+09lbuH7+9Kn2NFpm56M3GUWVbU2hQgdACA==", + "requires": { + "map-age-cleaner": "^0.1.3", + "mimic-fn": "^3.1.0" + }, + "dependencies": { + "mimic-fn": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz", + "integrity": "sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==" + } + } + }, "memoize-one": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", @@ -24675,6 +24729,19 @@ "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==", "dev": true }, + "motion-dom": { + "version": "12.9.1", + "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.9.1.tgz", + "integrity": "sha512-xqXEwRLDYDTzOgXobSoWtytRtGlf7zdkRfFbrrdP7eojaGQZ5Go4OOKtgnx7uF8sAkfr1ZjMvbCJSCIT2h6fkQ==", + "requires": { + "motion-utils": "^12.8.3" + } + }, + "motion-utils": { + "version": "12.8.3", + "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.8.3.tgz", + "integrity": "sha512-GYVauZEbca8/zOhEiYOY9/uJeedYQld6co/GJFKOy//0c/4lDqk0zB549sBYqqV2iMuX+uHrY1E5zd8A2L+1Lw==" + }, "move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", @@ -27297,6 +27364,11 @@ } } }, + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==" + }, "p-each-series": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.2.0.tgz", @@ -29182,6 +29254,17 @@ "warning": "^4.0.3" } }, + "react-calendar": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/react-calendar/-/react-calendar-5.1.0.tgz", + "integrity": "sha512-09o/rQHPZGEi658IXAJtWfra1N69D1eFnuJ3FQm9qUVzlzNnos1+GWgGiUeSs22QOpNm32aoVFOimq0p3Ug9Eg==", + "requires": { + "@wojtekmaj/date-utils": "^1.1.3", + "clsx": "^2.0.0", + "get-user-locale": "^2.2.1", + "warning": "^4.0.0" + } + }, "react-chartjs-2": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-5.2.0.tgz", diff --git a/package.json b/package.json index d56bf24d48..628520c686 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "diff": "^5.0.0", "dompurify": "^3.1.3", "font-awesome": "^4.7.0", + "framer-motion": "^12.9.2", "fs-extra": "^11.2.0", "history": "^4.10.1", "html-react-parser": "^1.4.14", @@ -41,6 +42,7 @@ "react-autosuggest": "^10.1.0", "react-beautiful-dnd": "^13.1.1", "react-bootstrap": "^1.0.1", + "react-calendar": "^5.1.0", "react-chartjs-2": "^5.2.0", "react-circular-progressbar": "^2.1.0", "react-collapsible": "^2.10.0", diff --git a/src/components/App.jsx b/src/components/App.jsx index 261d1d39fa..535c33cef9 100644 --- a/src/components/App.jsx +++ b/src/components/App.jsx @@ -5,6 +5,8 @@ import { BrowserRouter as Router , useLocation} from 'react-router-dom'; import { PersistGate } from 'redux-persist/integration/react'; import routes from '../routes'; import logger from '../services/logService'; +//import EventPage from './components/EventPage'; +//import EventManagementTabs from './components/CommunityPortal/EventManagement/EventManagementTabs'; import httpService from '../services/httpService'; import { setCurrentUser, logoutUser } from '../actions/authActions'; diff --git a/src/components/CommunityPortal/EventManagement/EventManagementTabs.css b/src/components/CommunityPortal/EventManagement/EventManagementTabs.css new file mode 100644 index 0000000000..27d84b427e --- /dev/null +++ b/src/components/CommunityPortal/EventManagement/EventManagementTabs.css @@ -0,0 +1,48 @@ +.tab-buttons { + display: flex; + gap: 10px; + margin-bottom: 15px; +} + +.tab-btn { + padding: 10px 15px; + border: none; + background-color: transparent; + font-size: 16px; + cursor: pointer; + transition: all 0.2s ease-in-out; + font-weight: normal; + /* Default font weight */ +} + +.tab-btn:hover { + font-weight: bold; + /* Bold on hover */ +} + +.tab-btn.active { + font-weight: bold; + /* Keep bold when active */ + border-bottom: 2px solid black; + /* Optional: Underline active tab */ +} + +.engagement-sections { + display: flex; + gap: 10px; + margin-bottom: 10px; +} + +.section-btn { + padding: 8px 12px; + border: none; + background-color: lightgray; + cursor: pointer; + transition: all 0.2s ease-in-out; +} + +.section-btn.active { + font-weight: bold; + background-color: gray; + color: white; +} \ No newline at end of file diff --git a/src/components/CommunityPortal/EventManagement/EventManagementTabs.jsx b/src/components/CommunityPortal/EventManagement/EventManagementTabs.jsx new file mode 100644 index 0000000000..2a6a37c047 --- /dev/null +++ b/src/components/CommunityPortal/EventManagement/EventManagementTabs.jsx @@ -0,0 +1,109 @@ +import { useState, useEffect } from "react"; +import { useParams, useHistory } from "react-router-dom"; +import "./EventManagementTabs.css"; +import "./EventPage.jsx"; +import "./EventPage.css"; +//import CommentsComponent from "./Engagement/Comments"; +//import FeedbackComponent from "./Engagement/Feedback"; + +const dummyEvents = [ + { id: "1", name: "Tech Conference 2025", date: "2025-05-15", location: "San Francisco" }, + { id: "2", name: "AI Summit", date: "2025-06-20", location: "New York" }, + { id: "3", name: "Developer Meetup", date: "2025-07-10", location: "Chicago" } +]; + +const EventManagementTabs = () => { + const { activityid, tab, section } = useParams(); + const history = useHistory(); + const [event, setEvent] = useState(null); + const [activeTab, setActiveTab] = useState(tab || "description"); + const [activeSection, setActiveSection] = useState(section || "comments"); + + useEffect(() => { + const foundEvent = dummyEvents.find((e) => e.id === activityid); + setEvent(foundEvent); + }, [activityid]); + + const tabs = [ + { key: "description", label: "Description" }, + { key: "analysis", label: "Analysis" }, + { key: "resources", label: "Resources" }, + { key: "engagement", label: "Engagement" } + ]; + + const engagementSections = ["comments", "feedback"]; + + const handleTabClick = (newTab) => { + setActiveTab(newTab); + const newPath = newTab === "engagement" + ? `/communityportal/activity/${activityid}/engagement/comments` + : `/communityportal/activity/${activityid}/${newTab}`; + history.push(newPath); + }; + + const handleEngagementSectionClick = (newSection) => { + setActiveSection(newSection); + history.push(`/communityportal/activity/${activityid}/engagement/${newSection}`); + }; + + const renderContent = () => { + if (!event) return
Event details below
; + + if (activeTab === "engagement") { + return ( + +
+
+ {engagementSections.map((sec) => ( + + ))} +
+
+ {activeSection === "feedback" ?
"Feedback section"
:
"Comments Section"
} +
+
+ ); + } + + switch (activeTab) { + case "analysis": + return
Analysis for {event.name}
; + case "resources": + return
Resources for {event.name}
; + case "description": + default: + return ( +
+ +

This is a detailed description of the event.

+
+ ); + } + }; + + return ( +
+
+ {tabs.map(({ key, label }) => ( + + ))} +
+ +
{renderContent()}
+
+ ); +}; + +export default EventManagementTabs; \ No newline at end of file diff --git a/src/components/CommunityPortal/EventManagement/EventPage.css b/src/components/CommunityPortal/EventManagement/EventPage.css new file mode 100644 index 0000000000..a149c94436 --- /dev/null +++ b/src/components/CommunityPortal/EventManagement/EventPage.css @@ -0,0 +1,318 @@ +.event-page { + padding: 50px; +} + +.event-card { + display: flex; + gap: 20px; + padding: 20px; + background: var(--background); + color: var(--text-color); + border-radius: 10px; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + border: 1px solid #D3D3D3; +} + +.event-card:hover { + box-shadow: none; + transform: none; +} + +.event-card__left { + width: 20%; + height: 90%; +} + +.event-card__middle { + width: 60%; + display: flex; + flex-direction: column; + gap: 10px; +} + +.event-card__right { + width: 20%; + max-height: 90%; + padding-top: 90px; +} + +.event-card__image { + width: 100%; + height: 400px; + background: #ddd; + display: flex; + align-items: center; + justify-content: center; + border-radius: 8px; +} + +.event-card__media-upload { + width: 100%; + margin-top: 10px; +} + +.event-card__title { + text-align: center; + font-size: 1.5rem; + font-weight: bold; + border: none; + outline: none; + background: transparent; + width: 100%; +} + +.event-card_12 { + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: flex-start; + width: 100%; + max-width: 98%; + padding: 15px; + margin: 10px; + background-color: #ffffff; + border-radius: 8px; + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1); + margin-right: 10px; +} + + +.event-card__info, +.event-card__extra { + display: flex; + justify-content: space-between; + width: 100%; + margin-bottom: 15px; + padding: 10px; + background-color: #f9f9f9; + border-radius: 4px; +} + +.info-item, +.extra-item { + display: flex; + flex-direction: column; + align-items: flex-start; + flex: 1; + padding: 5px; + margin: 0 5px; + width: auto; + /* Spacing between items */ +} + +.status-active { + background-color: green; + color: white; +} + +.status-finished { + background-color: gray; + color: white; +} + +.status-participated { + background-color: blue; + color: white; +} + +.event-description { + display: flex; + flex-direction: column; + gap: 10px; + margin-top: 20px; +} + +.textarea { + width: 100%; + height: 90px; + padding: 10px; + border-radius: 5px; + border: 1px solid #ccc; +} + +.media-upload-container { + display: flex; + justify-content: space-between; + align-items: center; +} + +.description-media-upload { + margin-right: 10px; + /* Spacing between media upload and button */ + /* Optional: You can adjust the size of the input if needed. */ +} + +.post-btn { + min-height: 10px; + border-radius: 10px; + width: 250px; + padding: 10px 10px; + border: 1px solid #ccc; + background-color: #2E5061; + color: #ffffff; + cursor: pointer; + transition: background 0.3s ease; +} + +.post-btn:hover { + color: #ffffff; +} + +/* Ensure all calendar elements are visible */ +.react-calendar { + width: 100%; + max-width: 400px; + max-height: 100%; + background: var(--background, #fff); + color: var(--text-color, #000); + border-radius: 8px; + border: 1px solid #ddd; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); + padding: 10px; +} + + +/* Improve visibility of month & year navigation */ +.react-calendar__navigation { + display: flex; + justify-content: space-between; + align-items: center; + font-weight: bold; + font-size: 16px; + color: var(--text-color, #333); + padding: 5px; +} + + +.react-calendar__navigation button { + background: none; + border: none; + cursor: pointer; + font-size: 14px; + padding: 5px; + color: var(--text-color, #333); +} + + +/* Ensure all calendar dates are visible */ +.react-calendar__tile { + padding: 10px; + font-size: 14px; + text-align: center; + border-radius: 4px; + cursor: pointer; + background: var(--tile-background, #fff); + color: var(--text-color, #000); + transition: background 0.3s ease; +} + +/* Highlight the selected date */ +.react-calendar__tile--active { + background: #007bff !important; + color: white !important; + font-weight: bold; +} + +/* 🌙 Dark Mode Styling */ +.event-page-dark { + background-color: #1B2A41; + /* Oxford Blue */ + color: #ffffff; + min-height: 100%; +} + +/* Card Styling */ +.event-page-dark .event-card { + background-color: #3A506B; + /* Space Cadet */ + border: 1px solid #333; +} + + +/* Input Fields*/ +.input-dark, +.event-page-dark input, +.event-page-dark textarea { + background-color: #2c2c2c; + color: #ffffff; + border: 1px solid #444; + border-radius: 5px; +} + +.event-page-dark select { + background-color: #ffffff; + color: #2c2c2c; + border: 1px solid #444; +} + +/* Description Box */ +.description-box-dark { + background-color: #3A506B; + /* Yinmn Blue */ + color: white; + border: 1px solid #444; +} + +/* Buttons */ +.post-btn-dark { + background-color: #fff; + color: #2E5061; + border: 1px solid #666; +} + +.post-btn-dark:hover { + background-color: #2E5061; +} + +.event-card_12-dark { + background-color: #1C2541; +} + +/* Dark Mode Styling for event-card__info and event-card__extra */ +.event-card__info-dark, +.event-card__extra-dark { + background-color: #3A506B; + color: #ffffff; + border: 1px solid #444; +} + +/* Dark Mode Styles for React Calendar */ +.react-calendar.dark-mode { + background-color: #2a2a2a; + color: #ffffff; + border: 1px solid #444; +} + +.react-calendar.dark-mode .react-calendar__tile { + background: transparent; + color: #ffffff; +} + +.react-calendar.dark-mode .react-calendar__tile--active { + background: #444; + color: #fff; +} + +.react-calendar.dark-mode .react-calendar__tile--now { + background: #666; + color: #fff; +} + +.react-calendar.dark-mode .react-calendar__month-view__weekdays { + color: #bbb; +} + +.react-calendar.dark-mode .react-calendar__navigation { + background: #222; + color: #fff; + border-bottom: 1px solid #444; +} + +.react-calendar.dark-mode .react-calendar__navigation button { + color: rgb(85, 84, 84); +} + +.react-calendar.dark-mode .react-calendar__tile:hover { + background: #555; + color: #fff; +} \ No newline at end of file diff --git a/src/components/CommunityPortal/EventManagement/EventPage.jsx b/src/components/CommunityPortal/EventManagement/EventPage.jsx new file mode 100644 index 0000000000..f0a9b4c312 --- /dev/null +++ b/src/components/CommunityPortal/EventManagement/EventPage.jsx @@ -0,0 +1,193 @@ +import React, { useState, useEffect } from "react"; +import { useParams, useHistory } from "react-router-dom"; +import DatePicker from "react-datepicker"; +import "react-datepicker/dist/react-datepicker.css"; +import Calendar from "react-calendar"; +import "react-calendar/dist/Calendar.css"; +import "../../CommunityPortal/EventManagement/EventPage.css"; +import EventManagementTabs from "../../CommunityPortal/EventManagement/EventManagementTabs"; +import { useSelector } from "react-redux"; + +const EventPage = () => { + const darkMode = useSelector((state) => state.theme.darkMode); + const { activityid } = useParams(); + const history = useHistory(); + + + // Event State + const [eventName, setEventName] = useState("Event Name"); + const [eventType, setEventType] = useState("In-person"); + const [location, setLocation] = useState("San Francisco, CA 94108"); + const [eventLink, setEventLink] = useState("https://devforum.zoom.us"); + const [startDate, setStartDate] = useState(new Date()); + const [endDate, setEndDate] = useState(new Date()); + const [time, setTime] = useState("9:00 AM - 11:00 AM EDT"); + const [organizer, setOrganizer] = useState("Alex Brain"); + const [capacity, setCapacity] = useState("120/200"); + const [status, setStatus] = useState("Active"); + const [rating, setRating] = useState(4); + const [media, setMedia] = useState(null); + const [description, setDescription] = useState(""); + + // Autosave Description (Simulated) + useEffect(() => { + const timer = setTimeout(() => { + console.log("Auto-saving description:", description); + }, 1000); + return () => clearTimeout(timer); + }, [description]); + + // Media Upload Handler + const handleMediaUpload = (event) => { + const file = event.target.files[0]; + if (file) { + const reader = new FileReader(); + reader.onloadend = () => { + setMedia(reader.result); + }; + reader.readAsDataURL(file); + } + }; + + // Star Rating Display + const renderStars = () => { + return [...Array(5)].map((_, index) => ( + + ⭐ + + )); + }; + + // Date Selection Validation (Prevent Past Dates) + const handleDateChange = (dates) => { + const [start, end] = dates; + const today = new Date(); + today.setHours(0, 0, 0, 0); + if (start >= today) { + setStartDate(start); + setEndDate(end || start); + } else { + alert("Cannot select past dates."); + } + }; + + return ( +
+ {/* Top Section */} +
+ + {/* Left Section: Event Image */} +
+
+ {media ? Event Media : No Media} +
+ +
+ + {/* Middle Section: Event Details */} +
+ setEventName(e.target.value)} + /> +

+ Type: + +

+

Location: setLocation(e.target.value)} + className={darkMode ? "input-dark" : ""} />

+
+ {/* First Row */} +
+

📅 Date:

+ +
+

⏰ Time:

setTime(e.target.value)} + className={darkMode ? "input-dark" : ""} />
+

👤 Organiser:

setOrganizer(e.target.value)} + className={darkMode ? "input-dark" : ""} />
+
+ + {/* Second Row */} +
+

👥 Capacity:

setCapacity(e.target.value)} + className={darkMode ? "input-dark" : ""} />

+

⭐ Overall Rating:

{renderStars()}

+

Status:

+ +

+
+
+
+ + {/* Right Section: Calendar */} +
+ { + if (date >= new Date().setHours(0, 0, 0, 0)) { + setStartDate(date); + setEndDate(date); // Update endDate dynamically + } else { + alert("Cannot select past dates."); + } + }} + value={startDate} + minDate={new Date()} // Prevent past date selection + tileClassName={({ date, view }) => { + if (view === "month" && date < new Date().setHours(0, 0, 0, 0)) { + return "react-calendar__tile--disabled"; + } + return null; + }} + /> +
+
+ + {/* Bottom Section - Tabs */} +
+ +
+ + {/* Description Section */} +
+