Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Events Page, API fetching is currently stopped #80

Merged
merged 14 commits into from
Aug 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions src/app/event/[id]/components/currentWindowSize.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { useState, useEffect } from 'react';

export default function useWindowDimensions() {

const hasWindow = typeof window !== 'undefined';

function getWindowDimensions() {
const width = hasWindow ? window.innerWidth : null;
const height = hasWindow ? window.innerHeight : null;
return {
width,
height,
};
}

const [windowDimensions, setWindowDimensions] = useState(getWindowDimensions());

useEffect(() => {
if (hasWindow) {
function handleResize() {
setWindowDimensions(getWindowDimensions());
}

window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}
}, [hasWindow]);

return windowDimensions;
}
71 changes: 71 additions & 0 deletions src/app/event/[id]/components/event.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import React, { useState, useEffect } from 'react';
import "@/styles/event.css";

import EventPoster from "./eventPoster";
import EventDetails from "./eventDetails";
import useWindowDimensions from "./currentWindowSize";


function GenerateEvent({props:event}){
// Getting current window dimensions
const {width , height} = useWindowDimensions();

// console.log(width-height);

const [scrollPosition, setScrollPosition] = useState(0);
const [eventDetailsFixed ,setEventDetailsFixed] = useState("event-details-fixed");
const [eventPosterFixed ,setEventPosterFixed] = useState("");
const [eventPosterCover, setEventPosterCover] = useState("");

const handleScroll = () => {
const position = window.scrollY;
setScrollPosition(position);
};

// To change classes
useEffect(()=>{
if(width-height>0) {
if((scrollPosition>(width-height-(0.12*(width-height)))) ){ //
setEventDetailsFixed("");
setEventPosterFixed("event-poster-fixed");
}
else{
setEventPosterFixed("");
setEventDetailsFixed("event-details-fixed");
}
setEventPosterCover("event-poster-cover");
}
else{

setEventPosterFixed("");
setEventDetailsFixed("");
}
},[scrollPosition,width,height]);

// To track scroll position
useEffect(() => {
window.addEventListener('scroll', handleScroll, { passive: true });

return () => {
window.removeEventListener('scroll', handleScroll);
};
}, []);

const eventPoster = "https://media.licdn.com/dms/image/D4D22AQHTRDh3tAk0wA/feedshare-shrink_800/0/1713529970610?e=1725494400&v=beta&t=1BamLpGDgW7rWUcYBUFRkm_35Y1wseXAE9VZS80XbtE";
return (
<div className="event-div">
<div className={`event-poster ${eventPosterFixed}`}>
<EventPoster posterUrl = {eventPoster}/>
</div>

<div className={`${eventPosterCover}`}> </div>
<div className= {`event-details ${eventDetailsFixed}`}>
<EventDetails
event = {event}
/>
</div>
</div>
)
}

export default GenerateEvent;
15 changes: 15 additions & 0 deletions src/app/event/[id]/components/eventConvenors.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from "react";
export default function EventConvenors(props) {
return (
<>
<div className="event-convenors-container rounded-lg border shadow-sm bg-secondary border-none p-6 gap-6">
<p className="event-convenors-title bold">Convenors</p>
<ul className="event-convenors">
{props.eventConvenors.map((item,index) => {
return <li key={index}>{item}</li>;
})}
</ul>
</div>
</>
);
}
199 changes: 199 additions & 0 deletions src/app/event/[id]/components/eventDetails.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
'use client'
import React, { useEffect, useState } from "react";
import Link from "next/link";
import { useRouter } from "next/navigation";
import EventMode from "./eventMode"
import EventDuration from "./eventDuration";
import EventRequirements from "./eventRequirements";
import EventPrizes from "./eventPrizes";
import EventConvenors from "./eventConvenors";
import EventVenue from "./eventVenue";
import { Montserrat } from "next/font/google";
const montserratFont = Montserrat({weight: ["100","400"], subsets: ["latin"]});


function EventDetails(props){

const [isAdmin,setIsAdmin] = useState(true); //Set default to false

const [event,setEvent] = useState(props.event);
const [eventName,setEventName] = useState(event.name);
const [eventDescription,setEventDescription] = useState(event.description);
const [registerUntilDate,setRegisterUntilDate] = useState(event.register_until);
const [registrationLink , setRegistrationLink] = useState(event.registration_link);
const [hostedRegistration , setHostedRegistration] = useState(event.hosted_registration);
const [hostLink, setHostLink] = useState(event.host_link);
const [daysLeftToRegister,setDaysLeftToRegister]= useState(CalculateDaysLeft(registerUntilDate));
const [eventDate,setEventDate] = useState(event.date);
const [eventDuration , setEventDuration]=useState((CalculateEventDuration(event.duration)));
const [eventMode ,setEventMode] = useState(event.mode);
const [eventVenue ,setEventVenue] = useState(event.venue);
const [eventRequirements, setEventRequirements] = useState(event.requirements);
const [eventPrizes , setEventPrizes] = useState(event.prizes);
const [eventConvenors,setEventConvenors] = useState(event.convenors);
//To update the remaining registration time each second
useEffect(()=>{
setInterval(()=>{
setDaysLeftToRegister(CalculateDaysLeft(registerUntilDate))
},1000)
},[daysLeftToRegister])



return <>
<div className="event-cover-details grid grid-cols-2 lg:grid-cols-12 gap-2 ">
<p className="col-span-2 lg:col-span-6 event-title ">{eventName}</p>

<div className="col-span-2 lg:col-span-6 ">
<p className="event-days-left " suppressHydrationWarning>{daysLeftToRegister}</p>
<Link className={((CalculateDaysLeft(registerUntilDate)==="Registration closed")?"disabled-link ":null)+"col-span-1 inline-flex h-10 items-center justify-center rounded-md bg-primary text-primary-foreground px-8 text-sm font-medium shadow transition-colors hover:bg-primary-hover focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50"}
href={hostedRegistration?registrationLink:hostLink} target="_blank" >
Register
</Link>
{isAdmin ? DeleteButton() : null}
</div>
</div>
<div className= {`event-date-time-container ${montserratFont.className}`}>
<div className="event-date-container rounded-lg border shadow-sm bg-secondary border-none px-4 py-2 gap-6">
<p className="event-date-title ">Event Date</p>
<p className="event-date">{formatDate(new Date(eventDate))}</p>
</div>
<div className="event-time-container rounded-lg border shadow-sm bg-secondary border-none px-4 py-2 gap-6">
<p className="event-time-title">Event Time</p>
<p className="event-time">{new Date(eventDate).toLocaleTimeString()}</p>
</div>
</div>

<hr style={{width : "100%"}}/>

<div className={`event-details-description ${montserratFont.className}`}>
<p className="event-description-title">About Event</p>
<pre className={`event-description ${montserratFont.className}`}>{eventDescription}</pre>
</div>

<div className= {`event-mode-duration-container ${montserratFont.className}`}>
<EventMode
eventMode = {eventMode}
eventVenue = {eventVenue}
/>
<EventDuration eventDuration ={eventDuration} />
</div>
<div className="event-grid-container grid grid-cols-1 lg:grid-cols-2 gap-5 items-stretch justify-stretch">
<div style={{width:"100%"}} className= {`lg:col-span-1 lg:row-span-1 ${montserratFont.className}`}>
<EventRequirements eventRequirements = {eventRequirements}/>
</div>
<div style={{width:"100%"}} className= {`lg:col-span-1 lg:row-span-2 ${montserratFont.className}`}>
<EventPrizes eventPrizes = {eventPrizes}/>
</div>
<div style={{width:"100%"}} className= {`lg:col-span-1 lg:row-start-2 lg:row-span-2 order-last ${montserratFont.className}`}>
<EventVenue />
</div>
<div style={{width:"100%"}} className= {`lg:col-span-1 lg:row-span-1 ${montserratFont.className}`}>
<EventConvenors eventConvenors = {eventConvenors}/>
</div>
</div>
</>
}

function DeleteButton(){
const router = useRouter();

function onDeleteButtonClicked(){
if(confirm("Are you sure you want to delete this event?")){
router.push("/events");
}else{
return false;
}
}

return(
<button className="inline-flex h-10 items-center justify-center rounded-md px-8 text-sm font-medium shadow transition-colors hover:bg-muted hover:text-primary-foreground border focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50"
onClick={onDeleteButtonClicked}>
Delete
</button>
)
}



function CalculateDaysLeft(date){
var today = new Date();
var anotherDate = new Date(date);
const timeInMS = anotherDate.getTime() - today.getTime();
var daysRemaining = Math.ceil(timeInMS / (1000 * 60 * 60 * 24));

var hoursRemaining = (Math.ceil(timeInMS / (1000 * 60 * 60 )));
var minutesRemaining = (Math.ceil(timeInMS / (1000 * 60)));
var secondsRemaining = (Math.ceil(timeInMS / (1000)));
if(daysRemaining>3){
return (daysRemaining+" days left")
}
else{
if(hoursRemaining>1){
return (hoursRemaining+" hours left");
}
else{
if(minutesRemaining>2){
return(minutesRemaining+" minutes left");
}
else{
if(secondsRemaining>0){
return(secondsRemaining+" seconds left");
}
else{
return("Registration closed");
}
}
}
}
}

function CalculateEventDuration (totalmins) {

var absTotal= Math.abs(totalmins);
var mins= absTotal % 60;
var hours = Math.floor(absTotal / 60);
var days= Math.floor(hours / 24);
var hourss = hours % 24;
var duration ="";
if(days>0){
;
if(days==1){duration = duration+days+" Day"}
else{duration = duration+days+" Day"};
if(hourss || mins){duration = duration+", ";}
}
if(hourss){
if(hourss==1){duration = duration+hourss+" Hour"}
else{duration = duration+hourss+" Hours"};
if(mins){duration = duration+", ";}
}
if(mins){
duration = duration+mins+" Minutes";
}

return duration;

}

function formatDate(date) {
// Array of month names
const monthNames = [
"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
];

// Array of day names
const dayNames = [
"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
];

// Extract day, month, and year from the date
const day = date.getDate();
const month = monthNames[date.getMonth()];
const year = date.getFullYear();
const dayName = dayNames[date.getDay()];

// Format the date
return `${day < 10 ? '0' + day : day}-${month}-${year}, ${dayName}`;
}
export default EventDetails;
25 changes: 25 additions & 0 deletions src/app/event/[id]/components/eventDuration.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React from "react";
export default function EventDuration(props) {
return (
<>
<div className="event-mode rounded-lg border bg-card text-card-foreground shadow-sm flex gap-2">
<div style={{color:"var(--primary)"}}><DurationIcon/></div>
<p className="event-mode-icon">{props.eventDuration}</p>
</div>
</>
);
}

const DurationIcon = () => (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
viewBox="0 0 64 64"
id="stopwatch"
width={"32px"}
height={"32px"}
>
<path d="M34 10.09c-.66-.09-1.32-.09-2-.09s-1.34 0-2 .09a22 22 0 1 0 4 0zM32 50a18 18 0 1 1 18-18 18 18 0 0 1-18 18zm18.76-34a2 2 0 0 1-1.44-.62 23.9 23.9 0 0 0-8.07-5.54 2 2 0 1 1 1.54-3.69 27.87 27.87 0 0 1 9.42 6.46A2 2 0 0 1 50.76 16zm-37.52 0a2 2 0 0 1-1.44-3.38 27.87 27.87 0 0 1 9.42-6.46 2 2 0 1 1 1.54 3.69 23.9 23.9 0 0 0-8.07 5.54 2 2 0 0 1-1.45.61z"></path>
<path d="M38 6a2 2 0 0 1-2 2h-2v2.09c-.66-.09-1.32-.09-2-.09s-1.34 0-2 .09V8h-2a2 2 0 0 1 0-4h8a2 2 0 0 1 2 2zm2 28h-8a2 2 0 0 1-2-2V20a2 2 0 0 1 4 0v10h6a2 2 0 0 1 0 4z"></path>
</svg>
);
38 changes: 38 additions & 0 deletions src/app/event/[id]/components/eventMode.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from "react";
export default function EventMode(props) {
return <>
<div className="event-mode rounded-lg border bg-card text-card-foreground shadow-sm flex gap-2">
<div style={{color:"var(--primary)"}} >{props.eventMode ? <OnlineIcon /> : <OfflineIcon/>}</div>
<p className="event-mode-icon">{props.eventMode ? "Online" : props.eventVenue}</p>
</div>
</>
}

const OnlineIcon = ({ width = 24, height = 24}) => (
<svg
xmlns="http://www.w3.org/2000/svg"
width={width}
height={height}
id="wifi"
fill="currentColor"
>
<path d="M13.414 19.412a1.994 1.994 0 0 0 0-2.826 1.994 1.994 0 0 0-2.828-.002 2 2 0 1 0 2.828 2.828zm7.071-7.897a1.99 1.99 0 0 1-1.414-.586c-3.899-3.899-10.243-3.898-14.143 0A2 2 0 0 1 2.099 8.1c5.459-5.458 14.341-5.458 19.799 0a2 2 0 0 1-1.413 3.415zM7.757 15.757a2 2 0 0 1-1.414-3.414c3.118-3.119 8.194-3.119 11.313 0a2 2 0 0 1-2.829 2.829 4.005 4.005 0 0 0-5.657 0 1.99 1.99 0 0 1-1.413.585z" transform="matrix(0.9999999999999999, 0, 0, 0.9999999999999999, 0, 0)" />
</svg>
);


const OfflineIcon = ({ width = 32, height = 32}) => (
<svg
xmlns="http://www.w3.org/2000/svg"
width={width}
height={height}
id="gps"
fill="currentColor"
>
<g>
<path d="M16 6.781c4.008 0 7.25 3.225 7.25 7.23 0 1.812-.674 3.455-1.773 4.727l-.288.37-3.668 4.154-.292.373-1.208 1.355-1.189-1.353-.289-.375-3.56-4.024a.512.512 0 0 0-.03-.029c-.018-.017-.041-.043-.074-.076a7.22 7.22 0 0 1-2.129-5.121c0-4.006 3.242-7.23 7.25-7.23zm.002 3.71a3.532 3.532 0 0 0-3.525 3.525 3.534 3.534 0 0 0 3.525 3.527 3.536 3.536 0 0 0 3.527-3.527 3.534 3.534 0 0 0-3.527-3.526zm0 1a2.519 2.519 0 0 1 2.527 2.525 2.52 2.52 0 0 1-2.527 2.527 2.519 2.519 0 0 1-2.525-2.527 2.517 2.517 0 0 1 2.525-2.526z" >

</path></g>
</svg>
);

9 changes: 9 additions & 0 deletions src/app/event/[id]/components/eventPoster.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React from "react";

function EventPoster(props){
return <>
<img style={props.style} src={props.posterUrl}></img>
</>
}

export default EventPoster;
Loading