-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added Events Page, API fetching is currently stopped (#80)
event page
- Loading branch information
1 parent
71b5510
commit ba56fb5
Showing
19 changed files
with
1,076 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> | ||
</> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> | ||
); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
Oops, something went wrong.
ba56fb5
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Deploy preview for iiitvcc ready!
✅ Preview
https://iiitvcc-ju17xebql-iiitv-coding-clubs-projects.vercel.app
Built with commit ba56fb5.
This pull request is being automatically deployed with vercel-action