From e436f9a6b084ae16249a55e8d74868c9bc4c86e1 Mon Sep 17 00:00:00 2001 From: deveshsawant05 <146441689+deveshsawant05@users.noreply.github.com> Date: Mon, 19 Aug 2024 01:02:07 +0530 Subject: [PATCH] Api fetching started for event page. (#107) * Added Navbar component to Layout * Fixed Navbar overlapping * Test Workflow * Fixed Navbar overlapping * added footer to layout. fixed navbar links prefetch * changed title,changed icon * Added Complete Events Page * Added mobile css for events page, added winners sections * fixed winners section font * fixed * Added Blogs Page * Deleted some temporary files * Blogs Page Fixes, Changed Projects to Blogs * Added Contact Us page * Jenil's Changes * Bucket env variable changed for all files. * Api fetching for Event page started, also added delete button for admin --- src/app/api/rest/v1/isUserAdmin/route.ts | 28 +++++ src/app/api/v1/create/event/route.ts | 2 +- src/app/api/v1/get/blog/route.ts | 2 +- .../event/[id]/components/checkIsAdmin.jsx | 23 ++++ src/app/event/[id]/components/event.jsx | 21 +++- .../event/[id]/components/eventDetails.jsx | 31 +++-- src/app/event/[id]/page.jsx | 106 ++++++++++-------- 7 files changed, 153 insertions(+), 60 deletions(-) create mode 100644 src/app/api/rest/v1/isUserAdmin/route.ts create mode 100644 src/app/event/[id]/components/checkIsAdmin.jsx diff --git a/src/app/api/rest/v1/isUserAdmin/route.ts b/src/app/api/rest/v1/isUserAdmin/route.ts new file mode 100644 index 0000000..6cde6c4 --- /dev/null +++ b/src/app/api/rest/v1/isUserAdmin/route.ts @@ -0,0 +1,28 @@ +import { NextRequest, NextResponse } from "next/server"; +import { createClient } from "@/utils/supabase/server"; + +export async function GET(request: NextRequest): Promise { + try { + const supabase = createClient(); + const { + data: { user }, + error: userError, + } = await supabase.auth.getUser(); + if (userError || !user) { + return NextResponse.json({ isAdmin: false }, { status: 200 }); + } + const isAdmin = await supabase + .from("users") + .select("admin") + .eq("id", user.id); + + if (isAdmin) { + return NextResponse.json({ isAdmin: true }, { status: 200 }); + } else { + return NextResponse.json({ isAdmin: false }, { status: 200 }); + } + } catch (error) { + console.error(error); + return NextResponse.json({ isAdmin: false }, { status: 200 }); + } +} diff --git a/src/app/api/v1/create/event/route.ts b/src/app/api/v1/create/event/route.ts index dd1454d..f542428 100644 --- a/src/app/api/v1/create/event/route.ts +++ b/src/app/api/v1/create/event/route.ts @@ -103,7 +103,7 @@ export async function POST(request: NextRequest): Promise { if (poster_file && poster) { const { error: posterUploadError } = await supabase.storage - .from(process.env.BUCKET || "") + .from(process.env.NEXT_PUBLIC_BUCKET || "") .upload(`/events/${eventId}/poster`, poster, { upsert: true, }); diff --git a/src/app/api/v1/get/blog/route.ts b/src/app/api/v1/get/blog/route.ts index 1fb7f51..b18b974 100644 --- a/src/app/api/v1/get/blog/route.ts +++ b/src/app/api/v1/get/blog/route.ts @@ -31,7 +31,7 @@ export async function GET(request: NextRequest): Promise { const blogFileUrl = `${getPublicUrl(`/blogs/${id}/blog`)}`; const { data: images, error: imagesError } = await supabase.storage - .from(process.env.BUCKET || "") + .from(process.env.NEXT_PUBLIC_BUCKET || "") .list(`images/${id}/`); if (imagesError) { diff --git a/src/app/event/[id]/components/checkIsAdmin.jsx b/src/app/event/[id]/components/checkIsAdmin.jsx new file mode 100644 index 0000000..6046d31 --- /dev/null +++ b/src/app/event/[id]/components/checkIsAdmin.jsx @@ -0,0 +1,23 @@ +import { useState, useEffect } from "react"; +import axios from "axios"; + +const checkIsAdmin = () => { + const [isAdmin , setIsAdmin] = useState(false) + useEffect(() => { + const fetchIsAdmin = async () => { + try { + const response = await axios.get(`/api/rest/v1/isUserAdmin`); + const result = response.data; + setIsAdmin(result.isAdmin); + } catch (error) { + console.error(error); + } + }; + + fetchIsAdmin(); + }, [isAdmin]); + + return isAdmin; +}; + +export default checkIsAdmin; diff --git a/src/app/event/[id]/components/event.jsx b/src/app/event/[id]/components/event.jsx index 05a363b..8a97f94 100644 --- a/src/app/event/[id]/components/event.jsx +++ b/src/app/event/[id]/components/event.jsx @@ -5,6 +5,8 @@ import EventPoster from "./eventPoster"; import EventDetails from "./eventDetails"; import useWindowDimensions from "./currentWindowSize"; +import { getPublicUrl } from "@/lib/utils"; + function GenerateEvent({ props: event }) { // Getting current window dimensions const { width, height } = useWindowDimensions(); @@ -18,6 +20,8 @@ function GenerateEvent({ props: event }) { const [eventPosterFixed, setEventPosterFixed] = useState(""); const [eventPosterCover, setEventPosterCover] = useState(""); + const [eventPosterAspectRatio, setEventPosterAspectRatio] = useState(1); + const handleScroll = () => { const position = window.scrollY; setScrollPosition(position); @@ -26,7 +30,7 @@ function GenerateEvent({ props: event }) { // To change classes useEffect(() => { if (width - height > 0) { - if (scrollPosition > width - height - 0.12 * (width - height)) { + if (scrollPosition > (width - height - (0.12 * (width - height)))/eventPosterAspectRatio) { // setEventDetailsFixed(""); setEventPosterFixed("event-poster-fixed"); @@ -50,7 +54,20 @@ function GenerateEvent({ props: event }) { }; }, []); - const eventPoster = "/event_poster.avif"; + const [eventPoster,setEventPoster] = useState(getPublicUrl(`/events/${event.id}/poster`)); + useEffect(()=>{ + const img = new Image(); + img.src = eventPoster; + img.onload = () => { + const ratio = img.width / img.height; + setEventPosterAspectRatio(ratio); + }; + + img.onerror = () => { + console.error('Failed to load image.'); + }; + },[]); + return (
diff --git a/src/app/event/[id]/components/eventDetails.jsx b/src/app/event/[id]/components/eventDetails.jsx index b56cb24..1d802aa 100644 --- a/src/app/event/[id]/components/eventDetails.jsx +++ b/src/app/event/[id]/components/eventDetails.jsx @@ -10,6 +10,8 @@ import EventConvenors from "./eventConvenors"; import EventVenue from "./eventVenue"; import EventWinners from "./eventWinners"; +import checkIsAdmin from "./checkIsAdmin"; + import { Montserrat } from "next/font/google"; const montserratFont = Montserrat({ weight: ["100", "400"], @@ -17,8 +19,7 @@ const montserratFont = Montserrat({ }); function EventDetails(props) { - const [isAdmin, setIsAdmin] = useState(true); //Set default to false - + const isAdmin = checkIsAdmin() || false; const [event, setEvent] = useState(props.event); const [eventName, setEventName] = useState(event.name); const [eventDescription, setEventDescription] = useState(event.description); @@ -36,6 +37,7 @@ function EventDetails(props) { CalculateDaysLeft(registerUntilDate), ); const [eventDate, setEventDate] = useState(event.date); + const [eventTime, setEventTime] = useState(event.time); const [eventDuration, setEventDuration] = useState( CalculateEventDuration(event.duration), ); @@ -47,7 +49,8 @@ function EventDetails(props) { const [eventPrizes, setEventPrizes] = useState(event.prizes); const [eventConvenors, setEventConvenors] = useState(event.convenors); const [eventWinners, setEventWinners] = useState(event.winners); - + const [eventVenueLink , setEventVenueLink ] = useState(event.venue_link); + //To update the remaining registration time each second useEffect(() => { setInterval(() => { @@ -87,7 +90,7 @@ function EventDetails(props) {

Event Time

- {new Date(eventDate).toLocaleTimeString()} + {convertTo12HourFormat(eventTime)}

@@ -126,15 +129,16 @@ function EventDetails(props) { >
-
- -
+ + :null} +
@@ -166,6 +170,8 @@ function DeleteButton() { function CalculateDaysLeft(date) { var today = new Date(); + var istOffsetInMilliseconds = 5.5 * 60 * 60 * 1000; + today = new Date(today + istOffsetInMilliseconds); var anotherDate = new Date(date); const timeInMS = anotherDate.getTime() - today.getTime(); var daysRemaining = Math.ceil(timeInMS / (1000 * 60 * 60 * 24)); @@ -192,6 +198,13 @@ function CalculateDaysLeft(date) { } } +function convertTo12HourFormat(time24) { + let [hours, minutes, seconds] = time24.split(':').map(Number); + let period = hours >= 12 ? 'PM' : 'AM'; + hours = hours % 12 || 12; + return `${hours}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')} ${period}`; +} + function CalculateEventDuration(totalmins) { var absTotal = Math.abs(totalmins); var mins = absTotal % 60; diff --git a/src/app/event/[id]/page.jsx b/src/app/event/[id]/page.jsx index 8afcda9..f8f6cd7 100644 --- a/src/app/event/[id]/page.jsx +++ b/src/app/event/[id]/page.jsx @@ -7,57 +7,69 @@ import Loading from "@/components/loading"; function Event({ params }) { const eventId = params.id; - // const { event, loading, error } = useFetchEvent(eventId); - // const router = useRouter(); + const { event, loading, error } = useFetchEvent(eventId); + const router = useRouter(); - // if (loading) { - // return <> - // - // ; - // } + if (loading) { + return <> + + ; + } - // if (error) { - // console.error(error); - // router.push('/events'); - // return null; - // } + if (error) { + console.error(error); + router.push('/events'); + return null; + } // To start calling api delete the object below and uncomment the above code - const event = { - id: 7, - name: "Codestrike v6.0", - description: `Join us for an exciting coding event organized by Coding Club IIITV, \nwhere teamwork and innovation take center stage! \nIn this unique competition, teams of three programmers will come together to \n solve complex coding challenges within a set timeframe. Participants will need to collaborate closely, leveraging each other's strengths to develop efficient and creative solutions. This event is designed to foster camaraderie, enhance problem-solving skills, and encourage effective communication among team members. Don't miss this opportunity to test your coding prowess, make new friends, and have a blast working together. Sign up now and be part of a thrilling coding adventure!`, - date: "2024-08-05T15:30:00", - duration: 60, - mode: false, - host_link: "https://www.hosted.com", - venue: "Mess Hall", - requirements: ["Laptop", "Notebook", "Pen", "Pencil"], - hosted_registration: true, - register_until: "2024-08-05T15:32:30", - registration_link: "https://www.registration.com", - creator: "b4e05b86-df08-49d8-a118-51c205216401", - prizes: [ - "Rs. 10000", - "Rs. 5000", - "Rs. 1000", - { - "Female Special": "Rs. 1000", - "FY Special": "Rs. 1000", - }, - ], - winners: { - "Web Dev": ["ABCDEGFHIJKL", "ABCDEGFHIJKL", "ABCDEGFHIJKL"], - "Cloud ": ["ABCDEGFHIJKL"], - CyberSecurity: ["ABCDEGFHIJKL", "ABCDEGFHIJKL"], - }, - convenors: [ - "Devyash Saini", - "Devyash Saini", - "Devyash Saini", - "Devyash Saini", - ], - }; +// const event = { +// "id": 46, +// "name": "CodeStrike v6.0", +// "description": "A competitive coding event", +// "date": "2024-07-30", +// "duration": 180, +// "mode": true, +// "host_link": "https://www.example.com", +// "venue": null, +// "requirements": [ +// "Laptop", +// "Notebook" +// ], +// "hosted_registration": true, +// "register_until": "2024-09-28T00:00:00", +// "registration_link": "https://www.example.com", +// "creator": "16ca184e-2872-48e0-b7c1-6425cdc66b0b", +// "venue_link": "https://maps.google.com/maps?width=100%25&height=600&hl=en&q=Indian%20Institute%20of%20Information%20Technology%20Vadodara+(IIIT%20Vadodara)&t=&z=14&ie=UTF8&iwloc=B&output=embed", +// "convenors": [ +// "devyash", +// "devyash", +// "devyash" +// ], +// "prizes": [ +// "7Cr", +// "69L", +// "3.14L", +// { +// "fy special": "150 Rupiya" +// } +// ], +// "winners": { +// "Web Dev": [ +// "ABCDEGFHIJKL", +// "ABCDEGFHIJKL", +// "ABCDEGFHIJKL" +// ], +// "Cloud ": [ +// "ABCDEGFHIJKL" +// ], +// "CyberSecurity": [ +// "ABCDEGFHIJKL", +// "ABCDEGFHIJKL" +// ] +// }, +// "time": "22:29:39" +// }; return ; }