Skip to content

Commit

Permalink
Added Events Page, API fetching is currently stopped (#80)
Browse files Browse the repository at this point in the history
event page
  • Loading branch information
deveshsawant05 authored Aug 5, 2024
1 parent 71b5510 commit ba56fb5
Show file tree
Hide file tree
Showing 19 changed files with 1,076 additions and 12 deletions.
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

1 comment on commit ba56fb5

@github-actions
Copy link

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

Please sign in to comment.