From 7c7bdd5824e055d5d4d2b6081c33106dec6f5d73 Mon Sep 17 00:00:00 2001 From: Akash <akashsingh2210670@gmail.com> Date: Thu, 21 Nov 2024 20:44:08 +0530 Subject: [PATCH 1/4] feat: removed firebase calls from frontend, fixed events page --- app/(default)/achievements/page.tsx | 9 +- app/(default)/api/admin/route.ts | 48 ++ app/(default)/api/events/route.ts | 135 +++++ app/(default)/events/EventCard.css | 215 ------- .../{myevents => events}/page.module.css | 0 app/(default)/events/page.tsx | 524 ++++++------------ app/(default)/myevents/page.tsx | 224 -------- components/EventForm.tsx | 12 +- components/EventUpdateForm.tsx | 2 +- components/ui/footer.tsx | 2 +- components/ui/header.tsx | 4 +- package-lock.json | 15 +- package.json | 3 +- 13 files changed, 377 insertions(+), 816 deletions(-) create mode 100644 app/(default)/api/admin/route.ts create mode 100644 app/(default)/api/events/route.ts delete mode 100644 app/(default)/events/EventCard.css rename app/(default)/{myevents => events}/page.module.css (100%) delete mode 100644 app/(default)/myevents/page.tsx diff --git a/app/(default)/achievements/page.tsx b/app/(default)/achievements/page.tsx index ad0866f..bdb4505 100644 --- a/app/(default)/achievements/page.tsx +++ b/app/(default)/achievements/page.tsx @@ -4,9 +4,6 @@ import { useEffect, useState } from "react"; import axios from "axios"; import { onAuthStateChanged } from "firebase/auth"; import { auth } from "@/Firebase"; -import { db } from "@/Firebase"; -import { doc, getDoc } from "firebase/firestore"; -import Image from "next/image"; import AchievementCard from "@/components/AchievementCard"; interface Achiever { @@ -40,9 +37,9 @@ export default function AchievementsPage() { if (user) { const uid = user.uid; try { - const adminDocRef = await doc(db, "admin", uid); - const adminDocSnap = await getDoc(adminDocRef); - if (adminDocSnap.exists()) { + const resp = await fetch(`/api/admin?uid=${uid}`); + const data = await resp.json(); + if (data.isAdmin) { setIsAdmin(true); } } catch (error) { diff --git a/app/(default)/api/admin/route.ts b/app/(default)/api/admin/route.ts new file mode 100644 index 0000000..58772a2 --- /dev/null +++ b/app/(default)/api/admin/route.ts @@ -0,0 +1,48 @@ +import { db } from "@/Firebase"; +import { + doc, + getDoc, +} from "firebase/firestore"; +import { NextResponse } from "next/server"; + + +export async function GET(request: Request) { + try { + const { searchParams } = new URL(request.url); + const uid = searchParams.get("uid"); + if (!uid) { + return NextResponse.json( + { error: "UID is required" }, + { status: 400 } + ); + } + const adminDocRef = doc(db, "admin", uid); + const adminDocSnap = await getDoc(adminDocRef); + if (!adminDocSnap.exists()) { + return NextResponse.json( + { error: "User is not an admin" , isAdmin: false }, + { status: 403 } + ); + } + else { + return NextResponse.json( + { message: "User is an admin" , isAdmin: true }, + { status: 200 } + ); + } + } catch (error) { + if (error instanceof Error) { + console.error("Error details:", error.message); + return NextResponse.json( + { error: "An error occurred", details: error.message }, + { status: 500 } + ); + } else { + console.error("Unknown error:", error); + return NextResponse.json( + { error: "An unknown error occurred" }, + { status: 500 } + ); + } + } +} diff --git a/app/(default)/api/events/route.ts b/app/(default)/api/events/route.ts new file mode 100644 index 0000000..ae75b3a --- /dev/null +++ b/app/(default)/api/events/route.ts @@ -0,0 +1,135 @@ +import { db } from "@/Firebase"; +import { + getDocs, + query, + collection, + orderBy, + addDoc, + updateDoc, + doc, + deleteDoc, +} from "firebase/firestore"; +import { NextResponse } from "next/server"; + + +export async function GET(request: Request) { + try { + const eventsCollection = collection(db, "events"); + const eventSnapshot = await getDocs(eventsCollection); + const data = eventSnapshot.docs.map((doc) => doc.data()); + const eventsList = data.map((event : any) => { + console.log("event id in backend is", event.id); + return { + id: event.id, + eventName: event.eventName, + description: event.description, + eventDate: event.eventDate, + lastDateOfRegistration: event.lastDateOfRegistration, + dateCreated: event.dateCreated, + dateModified: event.dateModified, + imageURL: event.imageURL, + registrationLink: event.registrationLink, + }; + }); + return NextResponse.json({ events: eventsList }, { status: 200 }); + } catch (error) { + if (error instanceof Error) { + console.error("Error details:", error.message); + return NextResponse.json( + { error: "An error occurred", details: error.message }, + { status: 500 } + ); + } else { + console.error("Unknown error:", error); + return NextResponse.json( + { error: "An unknown error occurred" }, + { status: 500 } + ); + } + } +} + +export async function POST(request: Request) { + try { + const newEvent = await request.json(); + const docRef = await addDoc(collection(db, "events"), newEvent); + return NextResponse.json({ id: docRef.id }, { status: 201 }); + } catch (error) { + if (error instanceof Error) { + console.error("Error details:", error.message); + return NextResponse.json( + { error: "An error occurred", details: error.message }, + { status: 500 } + ); + } else { + console.error("Unknown error:", error); + return NextResponse.json( + { error: "An unknown error occurred" }, + { status: 500 } + ); + } + } +} + +export async function PUT(request: Request) { + try{ + const { searchParams } = new URL(request.url); + const eventid = searchParams.get("eventid"); + if (!eventid) { + return NextResponse.json( + { error: "Event ID is required" }, + { status: 400 } + ); + } + const updatedEvent = await request.json(); + await updateDoc(doc(db, "events", eventid), updatedEvent); + + }catch (error) { + if (error instanceof Error) { + console.error("Error details:", error.message); + return NextResponse.json( + { error: "An error occurred", details: error.message }, + { status: 500 } + ); + } else { + console.error("Unknown error:", error); + return NextResponse.json( + { error: "An unknown error occurred" }, + { status: 500 } + ); + } + } +} + +export async function DELETE(request: Request) { + try{ + const { searchParams } = new URL(request.url); + const eventid = searchParams.get("eventid"); + if (!eventid) { + return NextResponse.json( + { error: "Event ID is required" }, + { status: 400 } + ); + } + await deleteDoc(doc(db, "events", eventid)); + } + catch (error) { + if (error instanceof Error) { + console.error("Error details:", error.message); + return NextResponse.json( + { error: "An error occurred", details: error.message }, + { status: 500 } + ); + } else { + console.error("Unknown error:", error); + return NextResponse.json( + { error: "An unknown error occurred" }, + { status: 500 } + ); + } + } +} + + + + diff --git a/app/(default)/events/EventCard.css b/app/(default)/events/EventCard.css deleted file mode 100644 index 449977a..0000000 --- a/app/(default)/events/EventCard.css +++ /dev/null @@ -1,215 +0,0 @@ -h2 { - font-family: 'Arial Narrow Bold', sans-serif; - margin-top: 60px; - padding-bottom: 30px; - font-size: 2.5em; - color: #00c853; - text-align: center; -} - -.event-cards-container { - display: flex; - flex-wrap: wrap; - justify-content: space-around; -} - -.event-card { - width: 300px; - height: 400px; - perspective: 1000px; - margin: 20px; -} - -.event-card-inner { - width: 100%; - height: 100%; - position: relative; - transform-style: preserve-3d; - transition: transform 0.8s; -} - -.event-card:hover .event-card-inner { - transform: rotateY(180deg); -} - -.event-card-front, -.event-card-back { - width: 100%; - height: 100%; - position: absolute; - backface-visibility: hidden; - background-color: black; - color: white; - border-radius: 10px; - box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); - border: 2px solid #00c853; -} - -.event-card-front { - display: flex; - justify-content: center; - align-items: center; -} - -.event-card-back { - padding: 20px; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - position: relative; - transform: rotateY(180deg); -} - -.event-card-back img { - width: 100%; - height: auto; - max-height: 150px; - opacity: 0.2; - object-fit: cover; - position: absolute; - top: 0; - left: 0; - z-index: 0; -} - -.event-card-back p { - z-index: 1; - position: relative; - color: white; - font-size: 1.2em; - text-align: center; -} - -.event-poster-container { - position: relative; - width: 280px; - padding-bottom: 75%; - display: flex; - justify-content: center; - align-items: center; -} - -.event-poster { - position: absolute; - top: -40px; - left: 0; - width: 100%; - height: 100%; - object-fit: cover; - border-radius: 10px; -} - -.event-content-container { - text-align: center; -} - -.event-content-container h3 { - margin-bottom: 0; - font-size: 1.4em; -} - -.event-content-container p { - margin-top: 0px; - margin-bottom: 25px; - font-size: 1em; -} - -/* Updated button styles */ -.toggle-form-button, -.toggle-edit-button, -.submit-event-button, -.update-event-button, -.remove-event-button { - margin-top: 70px !important; - background-color: black; - color: yellow; - border: 2px solid yellow; - border-radius: 5px; - padding: 10px 20px; - font-size: 1em; - cursor: pointer; - transition: background-color 0.3s, color 0.3s; - margin: 10px; -} - -.toggle-form-button:hover, -.toggle-edit-button:hover, -.submit-event-button:hover, -.update-event-button:hover, -.remove-event-button:hover { - background-color: yellow; - color: black; -} - -form { - background-color: black; - color: white; - padding: 20px; - border-radius: 10px; - box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3); - border: 2px solid yellow; - width: 80%; - margin: 40px auto; -} - -form label { - color: yellow; - font-weight: bold; - display: block; - margin-bottom: 10px; -} - -form input, -form textarea, -form select { - width: 100%; - padding: 10px; - margin-bottom: 20px; - border: 2px solid yellow; - border-radius: 5px; - background-color: black !important; - color: white !important; - font-size: 1em; -} - -form input::placeholder, -form textarea::placeholder { - color: grey !important; - opacity: 1; -} - -form input:focus, -form textarea:focus, -form select:focus { - border-color: yellow; - outline: none; -} - -input[type="text"], -input[type="date"], -textarea { - background-color: black !important; - color: white !important; -} - -input[type="text"]::placeholder, -input[type="date"]::placeholder, -textarea::placeholder { - color: grey !important; - opacity: 1; -} - -form button { - margin-top: 20px; -} - -section { - margin-bottom: 40px; -} - -.upcoming-events, -.ongoing-events, -.past-events { - margin-top: 60px; -} diff --git a/app/(default)/myevents/page.module.css b/app/(default)/events/page.module.css similarity index 100% rename from app/(default)/myevents/page.module.css rename to app/(default)/events/page.module.css diff --git a/app/(default)/events/page.tsx b/app/(default)/events/page.tsx index 17f25ef..66f8f1d 100644 --- a/app/(default)/events/page.tsx +++ b/app/(default)/events/page.tsx @@ -1,396 +1,200 @@ "use client"; -import React, { useState, useEffect } from "react"; -import { db, auth, storage } from "@/Firebase"; -import { - collection, - addDoc, - getDocs, - orderBy, - query, - updateDoc, - doc, - deleteDoc, - getDoc, -} from "firebase/firestore"; -import { ref, uploadBytes, getDownloadURL } from "firebase/storage"; +import { useState, useEffect } from "react"; +import { auth } from "../../../Firebase"; import { onAuthStateChanged } from "firebase/auth"; -import "./EventCard.css"; -import Image from "next/image"; +import EventForm from "../../../components/EventForm"; +import EventUpdateForm from "../../../components/EventUpdateForm"; +import EventCard from "../../../components/EventCard"; +import Sidebar from "../../../components/Sidebar"; + + +const EventsPage = () => { + const [showForm, setShowForm] = useState(false); + const [isAdminLoggedIn, setIsAdminLoggedIn] = useState(false); + const [events, setEvents] = useState< + { + id: string; + eventName: string; + description: string; + eventDate: string; + lastDateOfRegistration: string; + dateCreated: string; + dateModified: string; + imageURL: string; + registrationLink: string; + }[] + >([]); + + const [selectedEvent, setSelectedEvent] = useState<{ + id: string; + eventName: string; + description: string; + eventDate: string; + lastDateOfRegistration: string; + dateCreated: string; + dateModified: string; + imageURL: string; + registrationLink: string; + } | null>(null); + + const [isSidebarOpen, setIsSidebarOpen] = useState(false); -interface Event { - eventName: string; - description: string; - imageUrl: string; - startDate: string; - endDate: string; - id?: string; -} - -const EventCard: React.FC = () => { - const [events, setEvents] = useState<Event[]>([]); - const [eventName, setEventName] = useState(""); - const [description, setDescription] = useState(""); - const [imageUrl, setImageUrl] = useState(""); - const [imageFile, setImageFile] = useState<File | null>(null); - const [startDate, setStartDate] = useState(""); - const [endDate, setEndDate] = useState(""); - const [formVisible, setFormVisible] = useState(false); - const [editFormVisible, setEditFormVisible] = useState(false); - const [eventToEdit, setEventToEdit] = useState(""); - const [eventDataToEdit, setEventDataToEdit] = useState<Event | null>(null); - const [isAdmin, setIsAdmin] = useState<boolean>(false); - - // Fetch admin status useEffect(() => { - const checkAdminStatus = async () => { - onAuthStateChanged(auth, async (user) => { - if (user) { - const uid = user.uid; - try { - const adminDocRef = doc(db, "admin", uid); - const adminDocSnap = await getDoc(adminDocRef); - if (adminDocSnap.exists()) { - setIsAdmin(true); - } - } catch (error) { - console.log("Error getting document:", error); + onAuthStateChanged(auth, async (user) => { + if (user) { + const uid = user.uid; + try { + const resp = await fetch(`/api/admin?uid=${uid}`); + const data = await resp.json(); + if (data.isAdmin) { + setIsAdminLoggedIn(true); } + } catch (error) { + console.log("Error getting document:", error); } - }); - }; - - checkAdminStatus(); - }, []); + } + }); + }); + + const fetchEvents = async () => { + const resp = await fetch("/api/events"); + const data = await resp.json(); + const eventsList = data.events; + setEvents(eventsList); + }; - // Fetch events from Firestore - useEffect(() => { - const fetchEvents = async () => { - const q = query(collection(db, "events"), orderBy("startDate")); - const querySnapshot = await getDocs(q); - const eventsList: Event[] = querySnapshot.docs.map((doc) => ({ - ...doc.data(), - id: doc.id, - })) as Event[]; - setEvents(eventsList); - }; + useEffect(() => { fetchEvents(); }, []); - const uploadImage = async (file: File) => { - const imageRef = ref(storage, `eventImages/${file.name}`); - await uploadBytes(imageRef, file); - return await getDownloadURL(imageRef); - }; - - const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => { - e.preventDefault(); - - try { - const imageUrl = imageFile ? await uploadImage(imageFile) : ""; - const newEvent: Event = { - eventName, - description, - imageUrl, - startDate, - endDate, - }; - - const docRef = await addDoc(collection(db, "events"), newEvent); - setEvents((prevEvents) => - [...prevEvents, { ...newEvent, id: docRef.id }].sort( - (a, b) => new Date(a.startDate).getTime() - new Date(b.startDate).getTime() - ) - ); - - resetForm(); - } catch (error) { - console.error("Error adding document: ", error); - } - }; - - const handleEditSubmit = async (e: React.FormEvent<HTMLFormElement>) => { - e.preventDefault(); - if (!eventDataToEdit || !eventDataToEdit.id) return; - - try { - const updatedImageUrl = imageFile ? await uploadImage(imageFile) : eventDataToEdit.imageUrl; - const updatedEvent = { - eventName, - description, - imageUrl: updatedImageUrl, - startDate, - endDate, - }; - - await updateDoc(doc(db, "events", eventDataToEdit.id), updatedEvent); - setEvents((prevEvents) => - prevEvents - .map((event) => - event.id === eventDataToEdit.id ? { ...updatedEvent, id: event.id } : event - ) - .sort((a, b) => new Date(a.startDate).getTime() - new Date(b.startDate).getTime()) - ); - - setEditFormVisible(false); - resetForm(); - } catch (error) { - console.error("Error updating document: ", error); - } - }; - - const handleRemoveEvent = async () => { - if (!eventDataToEdit || !eventDataToEdit.id) return; - + // Deleting an event + const deleteEvent = async (eventId: string , event : any) => { + console.log("Deleting event ", event); + console.log("Deleting event with id: ", eventId); try { - await deleteDoc(doc(db, "events", eventDataToEdit.id)); - setEvents((prevEvents) => prevEvents.filter((event) => event.id !== eventDataToEdit.id)); - setEditFormVisible(false); + await fetch(`/api/events/?eventid=${eventId}`, { + method: "DELETE", + }); + setEvents((prevEvents) => prevEvents.filter((event) => event.id !== eventId)); } catch (error) { console.error("Error deleting document: ", error); } + fetchEvents(); // Refresh event list }; - const handleEventToEditChange = (eventName: string) => { - const selectedEvent = events.find((event) => event.eventName === eventName); - if (selectedEvent) { - setEventDataToEdit(selectedEvent); - setEventName(selectedEvent.eventName); - setDescription(selectedEvent.description); - setImageUrl(selectedEvent.imageUrl); - setStartDate(selectedEvent.startDate); - setEndDate(selectedEvent.endDate); - } else { - setEventDataToEdit(null); - } + const handleEventSelect = (event: { + id: string; + eventName: string; + description: string; + eventDate: string; + lastDateOfRegistration: string; + dateCreated: string; + dateModified: string; + imageURL: string; + registrationLink: string; // Ensure registrationLink is included + }) => { + setSelectedEvent(event); + setIsSidebarOpen(true); }; - const resetForm = () => { - setEventName(""); - setDescription(""); - setImageFile(null); - setImageUrl(""); - setStartDate(""); - setEndDate(""); - setFormVisible(false); + const handleSidebarClose = () => { + setIsSidebarOpen(false); }; - const currentDate = new Date(); - const upcomingEvents = events.filter((event) => new Date(event.startDate) > currentDate); - const ongoingEvents = events.filter( - (event) => new Date(event.startDate) <= currentDate && new Date(event.endDate) >= currentDate - ); - const pastEvents = events.filter((event) => new Date(event.endDate) < currentDate); - - const renderEventCards = (events: Event[]) => { - if (!events || events.length === 0) return <p>No events to display</p>; + // Dividing events into Past, Present, and Future based on eventDate + const today = new Date(); - return ( - <div className="event-cards-container"> - {events.map((event) => ( - <div key={event.id} className="event-card"> - <div className="event-card-inner"> - <div className="event-card-front"> - <div className="event-container"> - <div className="event-poster-container"> - <Image - width={300} - height={300} - src={event.imageUrl} - alt={event.eventName} - className="event-poster" - /> - </div> - <div className="event-content-container"> - <h3>{event.eventName}</h3> - <p> - {event.startDate} {event.endDate && ` - ${event.endDate}`} - </p> - </div> - </div> - </div> - <div className="event-card-back"> - <Image - src={event.imageUrl || "https://via.placeholder.com/150"} - alt={event.eventName || "Event image"} - width={300} - height={200} - /> - <p>{event.description || "No description available"}</p> - </div> - </div> - </div> - ))} - </div> - ); - }; + const pastEvents = events.filter( + (event) => new Date(event.eventDate) < today + ); + const presentEvents = events.filter( + (event) => new Date(event.eventDate).toDateString() === today.toDateString() + ); + const futureEvents = events.filter( + (event) => new Date(event.eventDate) > today + ); return ( - <div> - {isAdmin && ( - <> + <div className="p-4 pt-20 relative"> + <h1 className="text-5xl font-bold mb-2 pl-5 pt-2 text-center">Events</h1> + <div className="flex justify-end"> + {isAdminLoggedIn && ( <button - className="toggle-form-button" - onClick={() => setFormVisible(!formVisible)} + onClick={() => setShowForm(!showForm)} // Toggles the form visibility + className="bg-blue-600 text-white py-2 px-4 rounded-md mb-4" > - {formVisible ? "Hide Event Form" : "Add New Event"} + Add Event </button> + )} + </div> - {formVisible && ( - <form onSubmit={handleSubmit} style={{ marginBottom: "20px" }}> - {/* Form fields */} - <div> - <label>Event Name:</label> - <input - type="text" - value={eventName} - onChange={(e) => setEventName(e.target.value)} - required - /> - </div> - <div> - <label>Description:</label> - <textarea - value={description} - onChange={(e) => setDescription(e.target.value)} - required - /> - </div> - <div> - <label>Image Upload:</label> - <input - type="file" - accept="image/*" - onChange={(e) => { - if (e.target.files) { - setImageFile(e.target.files[0]); - } - }} - required - /> - </div> - <div> - <label>Start Date:</label> - <input - type="date" - value={startDate} - onChange={(e) => setStartDate(e.target.value)} - required - /> - </div> - <div> - <label>End Date:</label> - <input - type="date" - value={endDate} - onChange={(e) => setEndDate(e.target.value)} - required - /> - </div> - <button type="submit" className="submit-event-button"> - Add Event - </button> - </form> - )} - - <button - className="toggle-edit-button" - onClick={() => setEditFormVisible(!editFormVisible)} - > - {editFormVisible ? "Hide Edit Form" : "Edit Event"} - </button> + {/* Event Form to Add New Event */} + {isAdminLoggedIn && showForm && <EventForm />} + + {/* Displaying the Events */} + <div className="mt-2"> + {/* Present Events */} + + + {/* Future Events */} + {/* <h2 className="text-2xl font-bold mb-4 mt-8">CurreEvents</h2> */} + {futureEvents.length > 0 ? ( + <div className="flex justify-around"> + {futureEvents.map((event) => ( + <EventCard + key={event.id} + event={event} + isAdminLoggedIn={isAdminLoggedIn} + onDelete={() => deleteEvent(event.id , event)} + onSelect={handleEventSelect} + /> + ))} + </div> + ) : ( + <p>No presents events available.</p> + )} + </div> - {editFormVisible && ( - <form onSubmit={handleEditSubmit} style={{ marginBottom: "20px" }}> - <div> - <label>Select Event to Edit:</label> - <select - value={eventToEdit} - onChange={(e) => { - setEventToEdit(e.target.value); - handleEventToEditChange(e.target.value); - }} - > - <option value="">Select Event</option> - {events.map((event) => ( - <option key={event.id} value={event.eventName}> - {event.eventName} - </option> - ))} - </select> - </div> - <div> - <label>Event Name:</label> - <input - type="text" - value={eventName} - onChange={(e) => setEventName(e.target.value)} - required - /> - </div> - <div> - <label>Description:</label> - <textarea - value={description} - onChange={(e) => setDescription(e.target.value)} - required - /> - </div> - <div> - <label>Image Upload:</label> - <input - type="file" - accept="image/*" - onChange={(e) => { - if (e.target.files) { - setImageFile(e.target.files[0]); - } - }} - /> - </div> - <div> - <label>Start Date:</label> - <input - type="date" - value={startDate} - onChange={(e) => setStartDate(e.target.value)} - required - /> - </div> - <div> - <label>End Date:</label> - <input - type="date" - value={endDate} - onChange={(e) => setEndDate(e.target.value)} - required - /> - </div> - <button type="submit" className="update-event-button"> - Update Event - </button> - <button - type="button" - className="remove-event-button" - onClick={handleRemoveEvent} - > - Remove Event - </button> - </form> - )} - </> + {/* Past Events */} + <h2 className="text-3xl font-bold mb-8 mt-16 ml-4 text-center">Past Events</h2> + {pastEvents.length > 0 ? ( + <div className="sm:flex justify-around"> + {pastEvents.map((event) => ( + <EventCard + key={event.id} + event={event} + isAdminLoggedIn={isAdminLoggedIn} + onDelete={() => deleteEvent(event.id , event)} + onSelect={handleEventSelect} + /> + ))} + </div> + ) : ( + <p>No past events available.</p> )} - <h2>Upcoming Events</h2> - {renderEventCards(upcomingEvents)} - - <h2>Ongoing Events</h2> - {renderEventCards(ongoingEvents)} + {/* Sidebar for Event Details */} + {isSidebarOpen && selectedEvent && ( + <Sidebar + event={selectedEvent} + onClose={handleSidebarClose} + registrationLink={selectedEvent.registrationLink} // Pass registrationLink explicitly + /> + )} - <h2>Past Events</h2> - {renderEventCards(pastEvents)} + {/* Event Update Form */} + {isAdminLoggedIn && selectedEvent && ( + <div className="mt-8 z-50"> + <h2 className="text-2xl font-bold mb-4">Update Event</h2> + <EventUpdateForm + eventId={selectedEvent.id} + initialEventData={selectedEvent} + /> + </div> + )} </div> ); }; -export default EventCard; +export default EventsPage; diff --git a/app/(default)/myevents/page.tsx b/app/(default)/myevents/page.tsx deleted file mode 100644 index ed5f9b2..0000000 --- a/app/(default)/myevents/page.tsx +++ /dev/null @@ -1,224 +0,0 @@ -"use client"; - -import { useState, useEffect } from "react"; -import { db, auth } from "../../../Firebase"; // Firebase setup -import { - collection, - getDocs, - doc, - deleteDoc, - getDoc, -} from "firebase/firestore"; -import { onAuthStateChanged } from "firebase/auth"; -import EventForm from "../../../components/EventForm"; -import EventUpdateForm from "../../../components/EventUpdateForm"; -import EventCard from "../../../components/EventCard"; // Import new EventCard component -import Sidebar from "../../../components/Sidebar"; // Import Sidebar component -// import Image from "next/image"; - -const EventsPage = () => { - const [showForm, setShowForm] = useState(false); // For toggling form visibility - const [isAdminLoggedIn, setIsAdminLoggedIn] = useState(false); - const [events, setEvents] = useState< - { - id: string; - eventName: string; - description: string; - eventDate: string; - lastDateOfRegistration: string; - dateCreated: string; - dateModified: string; - imageURL: string; // Adding imageURL field - registrationLink: string; - }[] - >([]); - - const [selectedEvent, setSelectedEvent] = useState<{ - id: string; - eventName: string; - description: string; - eventDate: string; - lastDateOfRegistration: string; - dateCreated: string; - dateModified: string; - imageURL: string; - registrationLink: string; - } | null>(null); // For sidebar details - - const [isSidebarOpen, setIsSidebarOpen] = useState(false); // Track sidebar state - - useEffect(() => { - const checkAdmin = async (uid: string) => { - try { - const docRef = doc(db, "admin", uid); - const docSnap = await getDoc(docRef); - if (docSnap.exists()) { - setIsAdminLoggedIn(true); - } else { - setIsAdminLoggedIn(false); - } - } catch (error) { - console.error("Error checking admin status:", error); - setIsAdminLoggedIn(false); - } - }; - - const unsubscribe = onAuthStateChanged(auth, (user) => { - if (user) { - checkAdmin(user.uid); - } else { - setIsAdminLoggedIn(false); - } - }); - - return () => unsubscribe(); - }, []); - - // Fetching data from Firebase - const fetchEvents = async () => { - const eventsCollection = collection(db, "myEvents"); - const eventSnapshot = await getDocs(eventsCollection); - - const eventList = eventSnapshot.docs.map((doc) => { - const data = doc.data(); - return { - id: doc.id, - eventName: data.eventName || "", - description: data.description || "", - eventDate: data.eventDate || "", - lastDateOfRegistration: data.lastDateOfRegistration || "", - dateCreated: data.dateCreated || "", - dateModified: data.dateModified || "", - imageURL: data.imageURL || "", - registrationLink: data.registrationLink || "", // Include registrationLink - }; - }); - - setEvents(eventList); - }; - - useEffect(() => { - fetchEvents(); - }, []); - - // Deleting an event - const deleteEvent = async (eventId: string) => { - await deleteDoc(doc(db, "myEvents", eventId)); - fetchEvents(); // Refresh event list - }; - - const handleEventSelect = (event: { - id: string; - eventName: string; - description: string; - eventDate: string; - lastDateOfRegistration: string; - dateCreated: string; - dateModified: string; - imageURL: string; - registrationLink: string; // Ensure registrationLink is included - }) => { - setSelectedEvent(event); - setIsSidebarOpen(true); - }; - - const handleSidebarClose = () => { - setIsSidebarOpen(false); - }; - - // Dividing events into Past, Present, and Future based on eventDate - const today = new Date(); - - const pastEvents = events.filter( - (event) => new Date(event.eventDate) < today - ); - const presentEvents = events.filter( - (event) => new Date(event.eventDate).toDateString() === today.toDateString() - ); - const futureEvents = events.filter( - (event) => new Date(event.eventDate) > today - ); - - return ( - <div className="p-4 pt-20 relative"> - <h1 className="text-5xl font-bold mb-2 pl-5 pt-2 text-center">Events</h1> - <div className="flex justify-end"> - {isAdminLoggedIn && ( - <button - onClick={() => setShowForm(!showForm)} // Toggles the form visibility - className="bg-blue-600 text-white py-2 px-4 rounded-md mb-4" - > - Add Event - </button> - )} - </div> - - {/* Event Form to Add New Event */} - {isAdminLoggedIn && showForm && <EventForm />} - - {/* Displaying the Events */} - <div className="mt-2"> - {/* Present Events */} - - - {/* Future Events */} - {/* <h2 className="text-2xl font-bold mb-4 mt-8">CurreEvents</h2> */} - {futureEvents.length > 0 ? ( - <div className="flex justify-around"> - {futureEvents.map((event) => ( - <EventCard - key={event.id} - event={event} - isAdminLoggedIn={isAdminLoggedIn} - onDelete={deleteEvent} - onSelect={handleEventSelect} - /> - ))} - </div> - ) : ( - <p>No presents events available.</p> - )} - </div> - - {/* Past Events */} - <h2 className="text-3xl font-bold mb-8 mt-16 ml-4 text-center">Past Events</h2> - {pastEvents.length > 0 ? ( - <div className="sm:flex justify-around"> - {pastEvents.map((event) => ( - <EventCard - key={event.id} - event={event} - isAdminLoggedIn={isAdminLoggedIn} - onDelete={deleteEvent} - onSelect={handleEventSelect} // Pass handleEventSelect to open sidebar - /> - ))} - </div> - ) : ( - <p>No past events available.</p> - )} - - {/* Sidebar for Event Details */} - {isSidebarOpen && selectedEvent && ( - <Sidebar - event={selectedEvent} - onClose={handleSidebarClose} - registrationLink={selectedEvent.registrationLink} // Pass registrationLink explicitly - /> - )} - - {/* Event Update Form */} - {isAdminLoggedIn && selectedEvent && ( - <div className="mt-8 z-50"> - <h2 className="text-2xl font-bold mb-4">Update Event</h2> - <EventUpdateForm - eventId={selectedEvent.id} - initialEventData={selectedEvent} - /> - </div> - )} - </div> - ); -}; - -export default EventsPage; diff --git a/components/EventForm.tsx b/components/EventForm.tsx index ad903dc..8ec66fc 100644 --- a/components/EventForm.tsx +++ b/components/EventForm.tsx @@ -1,6 +1,8 @@ import { useState } from "react"; import { db } from "../Firebase"; -import { addDoc, collection } from "firebase/firestore"; +import { doc, setDoc, collection } from "firebase/firestore"; +import { v4 as uuidv4 } from 'uuid'; + const EventForm = () => { const [eventName, setEventName] = useState(""); @@ -13,10 +15,10 @@ const EventForm = () => { const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); try { - const eventsCollection = collection(db, "myEvents"); - const currentDate = new Date().toISOString(); // Get current date/time in ISO format - - await addDoc(eventsCollection, { + const currentDate = new Date().toISOString(); + const eventId = uuidv4(); + await setDoc( doc(db , "events" , eventId), { + id: eventId, eventName, eventDate, lastDateOfRegistration, diff --git a/components/EventUpdateForm.tsx b/components/EventUpdateForm.tsx index b5f35c9..3e98eca 100644 --- a/components/EventUpdateForm.tsx +++ b/components/EventUpdateForm.tsx @@ -30,7 +30,7 @@ const EventUpdateForm = ({ const handleUpdate = async (e: React.FormEvent) => { e.preventDefault(); try { - const eventDocRef = doc(db, "myEvents", eventId); + const eventDocRef = doc(db, "events", eventId); const currentDate = new Date().toISOString(); // Set dateModified to the current date/time await updateDoc(eventDocRef, { diff --git a/components/ui/footer.tsx b/components/ui/footer.tsx index ed80e11..960499a 100644 --- a/components/ui/footer.tsx +++ b/components/ui/footer.tsx @@ -11,7 +11,7 @@ export default function Footer() { <div className="mx-auto max-w-screen-xl text-center"> <ul className="flex flex-wrap justify-center items-center mb-6 text-white"> <li><Link href="/" className="mr-4 hover:underline md:mr-6">Home</Link></li> - <li><Link href="/myevents" className="mr-4 hover:underline md:mr-6">Events</Link></li> + <li><Link href="/events" className="mr-4 hover:underline md:mr-6">Events</Link></li> <li><Link href="/leads" className="mr-4 hover:underline md:mr-6">Leads</Link></li> <li><Link href="/members" className="mr-4 hover:underline md:mr-6">Members</Link></li> <li><Link href="/achievements" className="mr-4 hover:underline md:mr-6">Achievements</Link></li> diff --git a/components/ui/header.tsx b/components/ui/header.tsx index 80b9b44..dcfb7b9 100644 --- a/components/ui/header.tsx +++ b/components/ui/header.tsx @@ -49,8 +49,8 @@ export default function Header() { <nav className="hidden md:flex md:grow"> <ul className="flex grow justify-end flex-wrap items-center"> <li> - <Link href="/myevents"> - <p className={`font-medium ${pathname === '/myevents' ? 'font-extrabold text-white' : 'text-gray-300'} hover:text-white px-2 lg:px-5 py-3 flex items-center transition duration-150 ease-in-out`}>Events</p> + <Link href="/events"> + <p className={`font-medium ${pathname === '/events' ? 'font-extrabold text-white' : 'text-gray-300'} hover:text-white px-2 lg:px-5 py-3 flex items-center transition duration-150 ease-in-out`}>Events</p> </Link> </li> <li> diff --git a/package-lock.json b/package-lock.json index db69062..2e0fab2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -46,7 +46,8 @@ "sharp": "^0.33.5", "tailwind-merge": "^2.5.4", "tailwindcss-animate": "^1.0.7", - "typescript": "^5.3.3" + "typescript": "^5.3.3", + "uuid": "^11.0.3" }, "devDependencies": { "@tailwindcss/forms": "^0.5.7", @@ -17279,6 +17280,18 @@ "node": ">= 0.4.0" } }, + "node_modules/uuid": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.3.tgz", + "integrity": "sha512-d0z310fCWv5dJwnX1Y/MncBAqGMKEzlBb1AOf7z9K8ALnd0utBX/msg/fA0+sbyN1ihbMsLhrBlnl1ak7Wa0rg==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/package.json b/package.json index 6b01c10..680a9cb 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,8 @@ "sharp": "^0.33.5", "tailwind-merge": "^2.5.4", "tailwindcss-animate": "^1.0.7", - "typescript": "^5.3.3" + "typescript": "^5.3.3", + "uuid": "^11.0.3" }, "devDependencies": { "@tailwindcss/forms": "^0.5.7", From 25134ac2fdadd2110f202c961742f8ff85bb86e1 Mon Sep 17 00:00:00 2001 From: Akash <akashsingh2210670@gmail.com> Date: Thu, 21 Nov 2024 21:16:06 +0530 Subject: [PATCH 2/4] feat : removed more firebase calls from frontend --- app/(default)/api/events/route.ts | 25 +++++++++++++----- app/(default)/pbctf/page.tsx | 16 ------------ components/EventForm.tsx | 31 +++++++++++----------- components/EventUpdateForm.tsx | 32 ++++++++++++----------- components/leadspage.tsx | 43 ++++++++++++------------------- 5 files changed, 67 insertions(+), 80 deletions(-) diff --git a/app/(default)/api/events/route.ts b/app/(default)/api/events/route.ts index ae75b3a..665e12d 100644 --- a/app/(default)/api/events/route.ts +++ b/app/(default)/api/events/route.ts @@ -1,15 +1,14 @@ import { db } from "@/Firebase"; import { getDocs, - query, collection, - orderBy, - addDoc, updateDoc, doc, deleteDoc, + setDoc } from "firebase/firestore"; import { NextResponse } from "next/server"; +import { v4 as uuidv4 } from 'uuid'; export async function GET(request: Request) { @@ -18,7 +17,6 @@ export async function GET(request: Request) { const eventSnapshot = await getDocs(eventsCollection); const data = eventSnapshot.docs.map((doc) => doc.data()); const eventsList = data.map((event : any) => { - console.log("event id in backend is", event.id); return { id: event.id, eventName: event.eventName, @@ -52,8 +50,22 @@ export async function GET(request: Request) { export async function POST(request: Request) { try { const newEvent = await request.json(); - const docRef = await addDoc(collection(db, "events"), newEvent); - return NextResponse.json({ id: docRef.id }, { status: 201 }); + const eventId = uuidv4(); + + const currentDate = new Date().toISOString(); + const { eventName, eventDate, lastDateOfRegistration, description, imageURL, registrationLink } = newEvent; + await setDoc( doc(db , "events" , eventId), { + id : eventId, + eventName, + eventDate, + lastDateOfRegistration, + description, + imageURL, + registrationLink, + dateCreated: currentDate, + dateModified: currentDate, + }); + return NextResponse.json({ id: eventId }, { status: 201 }); } catch (error) { if (error instanceof Error) { console.error("Error details:", error.message); @@ -83,6 +95,7 @@ export async function PUT(request: Request) { } const updatedEvent = await request.json(); await updateDoc(doc(db, "events", eventid), updatedEvent); + return NextResponse.json({ id: eventid }, { status: 200 }); }catch (error) { if (error instanceof Error) { diff --git a/app/(default)/pbctf/page.tsx b/app/(default)/pbctf/page.tsx index d3e2176..3a421ff 100644 --- a/app/(default)/pbctf/page.tsx +++ b/app/(default)/pbctf/page.tsx @@ -2,24 +2,8 @@ import PBCTFForm from "@/components/forms/pbctfForm"; import DotPattern from "@/components/magicui/dot-pattern"; import { cn } from "@/lib/server/utils"; -import { onAuthStateChanged } from "firebase/auth"; -import { auth } from "@/Firebase"; -import { useEffect } from "react"; -import { useRouter } from "next/navigation"; -import Script from "next/script"; -import Head from "next/head"; const PBCTFRegisterPage = () => { - const router = useRouter(); - - // useEffect(() => { - // onAuthStateChanged(auth, (user) => { - // if (!user) { - // router.push("/login"); - // } - // }); - // }, [router]); - return ( <> diff --git a/components/EventForm.tsx b/components/EventForm.tsx index 8ec66fc..739630c 100644 --- a/components/EventForm.tsx +++ b/components/EventForm.tsx @@ -1,8 +1,4 @@ import { useState } from "react"; -import { db } from "../Firebase"; -import { doc, setDoc, collection } from "firebase/firestore"; -import { v4 as uuidv4 } from 'uuid'; - const EventForm = () => { const [eventName, setEventName] = useState(""); @@ -15,19 +11,21 @@ const EventForm = () => { const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); try { - const currentDate = new Date().toISOString(); - const eventId = uuidv4(); - await setDoc( doc(db , "events" , eventId), { - id: eventId, - eventName, - eventDate, - lastDateOfRegistration, - description, - imageURL, - registrationLink, - dateCreated: currentDate, - dateModified: currentDate, + await fetch ("/api/events", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + eventName, + eventDate, + lastDateOfRegistration, + description, + imageURL, + registrationLink, + }), }); + alert("Event added successfully!"); @@ -38,6 +36,7 @@ const EventForm = () => { setDescription(""); setImageURL(""); setRegistrationLink(""); + window.location.reload(); } catch (error) { console.error("Error adding event:", error); } diff --git a/components/EventUpdateForm.tsx b/components/EventUpdateForm.tsx index 3e98eca..82ed0ba 100644 --- a/components/EventUpdateForm.tsx +++ b/components/EventUpdateForm.tsx @@ -1,6 +1,4 @@ import { useState } from "react"; -import { db } from "../Firebase"; -import { doc, updateDoc } from "firebase/firestore"; interface EventUpdateFormProps { eventId: string; @@ -10,7 +8,7 @@ interface EventUpdateFormProps { lastDateOfRegistration: string; description: string; imageURL: string; - registrationLink: string; // Add this field to your initial data structure + registrationLink: string; }; } @@ -18,6 +16,7 @@ const EventUpdateForm = ({ eventId, initialEventData, }: EventUpdateFormProps) => { + const [eventName, setEventName] = useState(initialEventData.eventName); const [eventDate, setEventDate] = useState(initialEventData.eventDate); const [lastDateOfRegistration, setLastDateOfRegistration] = useState( @@ -30,20 +29,23 @@ const EventUpdateForm = ({ const handleUpdate = async (e: React.FormEvent) => { e.preventDefault(); try { - const eventDocRef = doc(db, "events", eventId); - const currentDate = new Date().toISOString(); // Set dateModified to the current date/time - - await updateDoc(eventDocRef, { - eventName, - eventDate, - lastDateOfRegistration, - description, - imageURL, - registrationLink, // Include the registration link in the update - dateModified: currentDate, + await fetch(`/api/events/?eventid=${eventId}`, { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + eventId, + eventName, + eventDate, + lastDateOfRegistration, + description, + imageURL, + registrationLink, + }), }); - alert("Event updated successfully!"); + window.location.reload(); } catch (error) { console.error("Error updating event:", error); } diff --git a/components/leadspage.tsx b/components/leadspage.tsx index f60b186..ce65422 100644 --- a/components/leadspage.tsx +++ b/components/leadspage.tsx @@ -1,10 +1,8 @@ "use client"; import React, { useState, useEffect } from "react"; -import { getAuth, onAuthStateChanged } from "firebase/auth"; +import { onAuthStateChanged } from "firebase/auth"; import { - getFirestore, - doc, getDoc, getDocs, collection, @@ -60,36 +58,27 @@ const Leads: React.FC = () => { setLoading(false); } }; - useEffect(() => { - const checkAdmin = async (uid: string) => { - try { - const docRef = doc(db, "admin", uid); - const docSnap = await getDoc(docRef); - if (docSnap.exists()) { - setIsAdminLoggedIn(true); - } else { - setIsAdminLoggedIn(false); - } - } catch (error) { - console.error("Error checking admin status:", error); - setIsAdminLoggedIn(false); - } - }; - - const unsubscribe = onAuthStateChanged(auth, (user) => { + onAuthStateChanged(auth, async (user) => { if (user) { - checkAdmin(user.uid); - } else { - setIsAdminLoggedIn(false); + const uid = user.uid; + try { + const resp = await fetch(`/api/admin?uid=${uid}`); + const data = await resp.json(); + if (data.isAdmin) { + setIsAdminLoggedIn(true); + } + } catch (error) { + console.log("Error getting document:", error); + } } }); + }); - fetchLeads(); // Call fetchLeads when component mounts - - return () => unsubscribe(); + useEffect(() => { + fetchLeads(); }, []); - + const handleAddOrEditLead = async (selectedLead:Lead) => { if (!selectedLead?.name || !selectedLead?.position) { console.error( From 3de2b4650a791220e161affa5d45f76d7aa11aaa Mon Sep 17 00:00:00 2001 From: Akash <akashsingh2210670@gmail.com> Date: Thu, 21 Nov 2024 23:02:33 +0530 Subject: [PATCH 3/4] feat: REMOVED MORE DB CALLS FROM FRONTEND --- app/(default)/achievements/page.tsx | 1 - app/(default)/api/admin/route.ts | 23 +++ app/(default)/api/leads/route.ts | 151 ++++++++++++++++++ app/(default)/api/leads/upload/route.ts | 60 +++++++ app/(default)/api/registration/pbctf/route.ts | 1 - .../api/registration/recruitment/route.ts | 3 - app/(default)/api/registration/sih/route.ts | 7 - app/(default)/events/page.tsx | 4 +- components/Members.tsx | 35 ++-- components/Signup.tsx | 16 +- components/forms/pbctfForm.tsx | 18 ++- components/forms/recruitmentForm.tsx | 2 - components/leadspage.tsx | 76 ++++----- 13 files changed, 305 insertions(+), 92 deletions(-) create mode 100644 app/(default)/api/leads/route.ts create mode 100644 app/(default)/api/leads/upload/route.ts diff --git a/app/(default)/achievements/page.tsx b/app/(default)/achievements/page.tsx index bdb4505..abdb2b7 100644 --- a/app/(default)/achievements/page.tsx +++ b/app/(default)/achievements/page.tsx @@ -165,7 +165,6 @@ export default function AchievementsPage() { } const response = await axios.put("/api/achievements", formData); - console.log(response.data); setIsEditModalOpen(false); } catch (error) { console.error("Error updating achievements:", error); diff --git a/app/(default)/api/admin/route.ts b/app/(default)/api/admin/route.ts index 58772a2..56e3018 100644 --- a/app/(default)/api/admin/route.ts +++ b/app/(default)/api/admin/route.ts @@ -2,6 +2,7 @@ import { db } from "@/Firebase"; import { doc, getDoc, + setDoc } from "firebase/firestore"; import { NextResponse } from "next/server"; @@ -46,3 +47,25 @@ export async function GET(request: Request) { } } } + +export async function POST(request: Request) { + const { email, role , userId} = await request.json(); + try{await setDoc(doc(db, 'admin', userId), { + email, + role, + });}catch (error) { + if (error instanceof Error) { + console.error("Error details:", error.message); + return NextResponse.json( + { error: "An error occurred", details: error.message }, + { status: 500 } + ); + } else { + console.error("Unknown error:", error); + return NextResponse.json( + { error: "An unknown error occurred" }, + { status: 500 } + ); + } + } + } diff --git a/app/(default)/api/leads/route.ts b/app/(default)/api/leads/route.ts new file mode 100644 index 0000000..d4f2870 --- /dev/null +++ b/app/(default)/api/leads/route.ts @@ -0,0 +1,151 @@ +import { db } from "@/Firebase"; +import { + getDocs, + collection, + updateDoc, + doc, + deleteDoc, + setDoc, +} from "firebase/firestore"; +import { NextResponse } from "next/server"; +import { v4 as uuidv4 } from 'uuid'; + +interface Lead { + id: string; + name: string; + position: string; + organization: string; + additionalInfo: string; + imageUrl: string; + } + + +export async function GET(request: Request) { + try { + const leadsRef = collection(db, "leads"); + const querySnapshot = await getDocs(leadsRef); + const currentLeads: Lead[] = []; + const alumniLeads: Lead[] = []; + + querySnapshot.forEach((doc) => { + const leadData = doc.data() as Lead; + if (leadData.position === "Current") { + currentLeads.push({ ...leadData, id: doc.id }); + } else { + alumniLeads.push({ ...leadData, id: doc.id }); + } + }); + return NextResponse.json({ currentLeads, alumniLeads }, { status: 200 }); + + } catch (error) { + if (error instanceof Error) { + console.error("Error details:", error.message); + return NextResponse.json( + { error: "An error occurred", details: error.message }, + { status: 500 } + ); + } else { + console.error("Unknown error:", error); + return NextResponse.json( + { error: "An unknown error occurred" }, + { status: 500 } + ); + } + } +} + +export async function POST(request: Request) { + try { + const leadData = await request.json(); + const leadID = uuidv4(); + await setDoc(doc(db, "leads" , leadID), { + ...leadData, + imageUrl: leadData.imageUrl, // Use the imageUrl from Firebase Storage + }); + return NextResponse.json({ id: leadID }, { status: 201 }); + } catch (error) { + if (error instanceof Error) { + console.error("Error details:", error.message); + return NextResponse.json( + { error: "An error occurred", details: error.message }, + { status: 500 } + ); + } else { + console.error("Unknown error:", error); + return NextResponse.json( + { error: "An unknown error occurred" }, + { status: 500 } + ); + } + } +} + +export async function PUT(request: Request) { + try{ + const leadData = await request.json(); + const { imageUrl } = leadData; + const { searchParams } = new URL(request.url); + const id = searchParams.get("id"); + if (!id) { + return NextResponse.json( + { error: "Event ID is required" }, + { status: 400 } + ); + } + + await updateDoc(doc(db, "leads", id), { + ...leadData, + imageUrl: imageUrl, + }); + return NextResponse.json({ id: id }, { status: 200 }); + + }catch (error) { + if (error instanceof Error) { + console.error("Error details:", error.message); + return NextResponse.json( + { error: "An error occurred", details: error.message }, + { status: 500 } + ); + } else { + console.error("Unknown error:", error); + return NextResponse.json( + { error: "An unknown error occurred" }, + { status: 500 } + ); + } + } +} + +export async function DELETE(request: Request) { + try{ + const { searchParams } = new URL(request.url); + const id = searchParams.get("id"); + if (!id) { + return NextResponse.json( + { error: "Event ID is required" }, + { status: 400 } + ); + } + await deleteDoc(doc(db, "leads", id)); + return NextResponse.json({ id: id }, { status: 200 }); + } + catch (error) { + if (error instanceof Error) { + console.error("Error details:", error.message); + return NextResponse.json( + { error: "An error occurred", details: error.message }, + { status: 500 } + ); + } else { + console.error("Unknown error:", error); + return NextResponse.json( + { error: "An unknown error occurred" }, + { status: 500 } + ); + } + } +} + + + + diff --git a/app/(default)/api/leads/upload/route.ts b/app/(default)/api/leads/upload/route.ts new file mode 100644 index 0000000..576c9fc --- /dev/null +++ b/app/(default)/api/leads/upload/route.ts @@ -0,0 +1,60 @@ +import { getStorage, ref, uploadBytes, getDownloadURL } from "firebase/storage"; +import { NextResponse } from "next/server"; +import { db, storage} from "@/Firebase"; + + +export async function POST(request: Request) { + try { + const storage = getStorage(); + const selectedLead = await request.json(); + const imageRef = ref(storage, `images/${selectedLead.name}`); + let imageUrl; + + try { + const imageBlob = await fetch(selectedLead.imageUrl).then((r) => r.blob()); + console.log("Image blob fetched:", imageBlob); + try { + await uploadBytes(imageRef, imageBlob); + console.log("Image uploaded to storage"); + try { + imageUrl = await getDownloadURL(imageRef); + console.log("Image URL obtained:", imageUrl); + } catch (error: any) { + console.error("Error getting image URL:", error); + return NextResponse.json( + { error: "An error occurred", details: error.message }, + { status: 500 } + ); + } + } catch (error: any) { + console.error("Error uploading image:", error); + return NextResponse.json( + { error: "An error occurred", details: error.message }, + { status: 500 } + ); + } + } catch (error: any) { + console.error("Error fetching image blob:", error); + return NextResponse.json( + { error: "An error occurred", details: error.message }, + { status: 500 } + ); + } + + return NextResponse.json({ imageUrl: imageUrl }, { status: 201 }); + } catch (error) { + if (error instanceof Error) { + console.error("Error details:", error.message); + return NextResponse.json( + { error: "An error occurred", details: error.message }, + { status: 500 } + ); + } else { + console.error("Unknown error:", error); + return NextResponse.json( + { error: "An unknown error occurred" }, + { status: 500 } + ); + } + } +} \ No newline at end of file diff --git a/app/(default)/api/registration/pbctf/route.ts b/app/(default)/api/registration/pbctf/route.ts index cdef1b5..f13446c 100644 --- a/app/(default)/api/registration/pbctf/route.ts +++ b/app/(default)/api/registration/pbctf/route.ts @@ -51,7 +51,6 @@ export async function POST(request: Request) { ); const recaptchaResult = await recaptchaResponse.json(); - console.log(recaptchaResult.riskAnalysis.score); if (recaptchaResult.riskAnalysis.score < 0.7) { return NextResponse.json({ message: "reCAPTCHA validation failed", diff --git a/app/(default)/api/registration/recruitment/route.ts b/app/(default)/api/registration/recruitment/route.ts index 76b6885..92117db 100644 --- a/app/(default)/api/registration/recruitment/route.ts +++ b/app/(default)/api/registration/recruitment/route.ts @@ -45,7 +45,6 @@ export async function POST(request: Request) { getDocs(collegeIdQuery), ]); - console.log(!emailSnapshot.empty); if (!emailSnapshot.empty) { return NextResponse.json( @@ -116,7 +115,6 @@ export async function POST(request: Request) { ); const recaptchaResult = await recaptchaResponse.json(); - console.log(recaptchaResult.riskAnalysis.score); if (recaptchaResult.riskAnalysis.score < 0.7) { return NextResponse.json({ message: "reCAPTCHA validation failed", @@ -138,7 +136,6 @@ export async function POST(request: Request) { try { const docRef = await addDoc(collection(db, "recruitment2024"), data); - console.log("Document written with ID: ", docRef.id); } catch (error) { console.error(error); return NextResponse.json( diff --git a/app/(default)/api/registration/sih/route.ts b/app/(default)/api/registration/sih/route.ts index f06ebce..e7c7fa2 100644 --- a/app/(default)/api/registration/sih/route.ts +++ b/app/(default)/api/registration/sih/route.ts @@ -8,9 +8,6 @@ export async function POST(request: Request) { const formData = await request.json(); const { recaptcha_token, ...data } = formData; - console.log(formData); - - // Only one Registration per Email const { team_info: { team_leader: { email } } } = data; @@ -20,8 +17,6 @@ export async function POST(request: Request) { ); const querySnapshot = await getDocs(q); - console.log(!querySnapshot.empty); - if (!querySnapshot.empty) { return NextResponse.json( { @@ -56,7 +51,6 @@ export async function POST(request: Request) { ); const recaptchaResult = await recaptchaResponse.json(); - console.log(recaptchaResult); if (!recaptchaResult.success) { return NextResponse.json( { @@ -78,7 +72,6 @@ export async function POST(request: Request) { try { // Save to Firebase const docRef = await addDoc(collection(db, "sih2024"), data); - console.log("Document written with ID: ", docRef.id); } catch (error) { console.error(error); return NextResponse.json({ message: "An error occurred", error }); diff --git a/app/(default)/events/page.tsx b/app/(default)/events/page.tsx index 66f8f1d..276fcd9 100644 --- a/app/(default)/events/page.tsx +++ b/app/(default)/events/page.tsx @@ -70,8 +70,6 @@ const EventsPage = () => { // Deleting an event const deleteEvent = async (eventId: string , event : any) => { - console.log("Deleting event ", event); - console.log("Deleting event with id: ", eventId); try { await fetch(`/api/events/?eventid=${eventId}`, { method: "DELETE", @@ -80,7 +78,7 @@ const EventsPage = () => { } catch (error) { console.error("Error deleting document: ", error); } - fetchEvents(); // Refresh event list + fetchEvents(); }; const handleEventSelect = (event: { diff --git a/components/Members.tsx b/components/Members.tsx index c665fca..4d37290 100644 --- a/components/Members.tsx +++ b/components/Members.tsx @@ -5,8 +5,7 @@ import ClipLoader from "react-spinners/ClipLoader"; import { FaRegBell, FaEllipsisV } from "react-icons/fa"; import { onAuthStateChanged } from "firebase/auth"; import { auth } from "@/Firebase"; -import { db, storage } from "@/Firebase"; -import { doc, getDoc } from "firebase/firestore"; +import {storage } from "@/Firebase"; import { ref, uploadBytes, getDownloadURL } from 'firebase/storage'; import Image from 'next/image'; import Card from "./ui/Card"; @@ -61,25 +60,21 @@ export default function Members() { const [isAdmin, setIsAdmin] = useState(false); useEffect(() => { - const unsubscribe = onAuthStateChanged(auth, async (user) => { - if (user) { - const uid = user.uid; - try { - const adminDocRef = doc(db, "admin", uid); - const adminDocSnap = await getDoc(adminDocRef); - console.log("Admin document exists:", adminDocSnap.exists()); - setIsAdmin(adminDocSnap.exists()); - } catch (error) { - console.log("Error getting document:", error); - } - } else { - setIsAdmin(false); // Reset if user is not logged in + onAuthStateChanged(auth, async (user) => { + if (user) { + const uid = user.uid; + try { + const resp = await fetch(`/api/admin?uid=${uid}`); + const data = await resp.json(); + if (data.isAdmin) { + setIsAdmin(true); + } + } catch (error) { + console.log("Error getting document:", error); } + } }); - - // Cleanup subscription on unmount - return () => unsubscribe(); - }, []); // Empty dependency array + }); const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => { @@ -100,8 +95,6 @@ export default function Members() { const downloadURL = await getDownloadURL(snapshot.ref); setNewMember((prev) => ({ ...prev, imageUrl: downloadURL })); - - console.log('File uploaded successfully. Download URL:', downloadURL); } catch (error) { console.error('Error uploading file:', error); } diff --git a/components/Signup.tsx b/components/Signup.tsx index f7481f4..164481e 100644 --- a/components/Signup.tsx +++ b/components/Signup.tsx @@ -2,9 +2,10 @@ import React, { useState } from 'react'; import { useRouter } from 'next/navigation'; import { createUserWithEmailAndPassword } from 'firebase/auth'; -import { auth, db } from '../Firebase'; // Firestore initialized +import { auth } from '../Firebase'; import { doc, setDoc } from 'firebase/firestore'; import '../app/globals.css'; +import { method } from 'lodash'; const Signup = () => { @@ -39,9 +40,16 @@ const Signup = () => { if (role === 'admin') { try { - await setDoc(doc(db, 'admin', user.uid), { - email, - role, + await fetch ('/api/admin', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + email, + role, + userId: user.uid, + }), }); setSuccess('Successfully signed up!'); diff --git a/components/forms/pbctfForm.tsx b/components/forms/pbctfForm.tsx index 8096478..6a9f541 100644 --- a/components/forms/pbctfForm.tsx +++ b/components/forms/pbctfForm.tsx @@ -8,8 +8,17 @@ import { db } from "@/Firebase"; import { branches } from "@/lib/constants/dropdownOptions"; import { Press_Start_2P } from "next/font/google"; import toast from "react-hot-toast"; -import Head from "next/head"; -import Script from "next/script"; + + +// NOTE TO ANYONE WHO IS WANDERING HERE IN HOPES OF PBCTF 4.0 +// THIS FORM DIRECTLY CALLS THE DB FROM THE CLIENT SIDE +// THIS IS NOT A GOOD PRACTICE +// PLEASE DO NOT USE THIS AS A REFERENCE +// KINDLY CONTACT SKY SINGH TO FIX THIS +// WHENVEVER THE NEXT CTF IS +// PARAGATI RAJ ARE YOU READING THIS +// I MISS YOU + const pressStart2P = Press_Start_2P({ weight: "400", @@ -69,14 +78,11 @@ const PBCTFForm: React.FC = () => { } = useForm<FormData>(); const getRecaptcha = async () => { - console.log("func called"); grecaptcha.enterprise.ready(async () => { const Rtoken = await grecaptcha.enterprise.execute( process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY ); - console.log(Rtoken); setToken(Rtoken); - console.log(token); }); }; @@ -132,7 +138,6 @@ const PBCTFForm: React.FC = () => { try { const recaptcha_token = token; - console.log(recaptcha_token); if (recaptcha_token) { const response = await fetch("/api/registration/pbctf", { method: "POST", @@ -146,7 +151,6 @@ const PBCTFForm: React.FC = () => { return; } - console.log(recaptcha_token); // Check if USNs are the same for duo participation if ( diff --git a/components/forms/recruitmentForm.tsx b/components/forms/recruitmentForm.tsx index 778161d..61f0634 100644 --- a/components/forms/recruitmentForm.tsx +++ b/components/forms/recruitmentForm.tsx @@ -73,7 +73,6 @@ const RecruitmentForm: React.FC = () => { const onSubmit: SubmitHandler<any> = async (data: any) => { - console.log(token); if (isSubmitting) return; setIsSubmitting(true); try { @@ -87,7 +86,6 @@ const RecruitmentForm: React.FC = () => { const res = await response.json(); if (!response.ok || res.error) { - console.log(response.json); toast.error(res.message); return; } diff --git a/components/leadspage.tsx b/components/leadspage.tsx index ce65422..087ba06 100644 --- a/components/leadspage.tsx +++ b/components/leadspage.tsx @@ -1,19 +1,9 @@ "use client"; - import React, { useState, useEffect } from "react"; import { onAuthStateChanged } from "firebase/auth"; -import { - getDoc, - getDocs, - collection, - addDoc, - updateDoc, - deleteDoc, -} from "firebase/firestore"; import { getStorage, ref, uploadBytes, getDownloadURL } from "firebase/storage"; + import { auth } from "@/Firebase"; -import { db } from "@/Firebase"; -import { ClipLoader } from "react-spinners"; // If you're using react-spinners interface Lead { id: string; @@ -36,20 +26,10 @@ const Leads: React.FC = () => { // Fetch leads from Firestore const fetchLeads = async () => { try { - const leadsRef = collection(db, "leads"); - const querySnapshot = await getDocs(leadsRef); - const currentLeads: Lead[] = []; - const alumniLeads: Lead[] = []; - - querySnapshot.forEach((doc) => { - const leadData = doc.data() as Lead; - if (leadData.position === "Current") { - currentLeads.push({ ...leadData, id: doc.id }); - } else { - alumniLeads.push({ ...leadData, id: doc.id }); - } - }); - + const resp = await fetch("/api/leads"); + const data = await resp.json(); + const currentLeads = data.currentLeads + const alumniLeads = data.alumniLeads setCurrentLeads(currentLeads); setAlumniLeads(alumniLeads); setLoading(false); @@ -78,7 +58,7 @@ const Leads: React.FC = () => { useEffect(() => { fetchLeads(); }, []); - + const handleAddOrEditLead = async (selectedLead:Lead) => { if (!selectedLead?.name || !selectedLead?.position) { console.error( @@ -89,8 +69,6 @@ const Leads: React.FC = () => { } try { - console.log("Preparing lead data for submission:", selectedLead); - const leadData = { ...selectedLead }; const storage = getStorage(); @@ -112,27 +90,39 @@ const Leads: React.FC = () => { if (selectedLead.id) { // Update lead in Firestore - console.log("Updating existing lead with ID:", selectedLead.id); - await updateDoc(doc(db, "leads", selectedLead.id), { - ...leadData, - imageUrl: imageUrl, // Use the imageUrl from Firebase Storage - }); - console.log("Lead updated successfully in Firestore:", selectedLead.id); + try { + await fetch(`/api/leads/?id=${selectedLead.id}`, { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(leadData), + }); + } + catch (error) { + console.error("Error updating lead:", error); + alert("An error occurred while updating the lead. Check the console for details."); + } alert("Lead updated successfully"); } else { // Add new lead to Firestore - console.log("Adding new lead to Firestore..."); - await addDoc(collection(db, "leads"), { - ...leadData, - imageUrl: imageUrl, // Use the imageUrl from Firebase Storage + try { await fetch("/api/leads", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(leadData), }); - console.log("New lead added successfully."); alert("Lead added successfully"); + }catch (error) { + console.error("Error adding lead:", error); + alert("An error occurred while adding the lead. Check the console for details."); + } } setShowForm(false); setSelectedLead(null); - await fetchLeads(); // Refresh leads after adding/editing + await fetchLeads(); } catch (error) { console.error("Error in handleAddOrEditLead:", error); alert( @@ -148,7 +138,9 @@ const Leads: React.FC = () => { const handleDeleteLead = async (id: string) => { try { - await deleteDoc(doc(db, "leads", id)); + await fetch(`/api/leads/?id=${id}`, { + method: "DELETE", + }); alert("Lead deleted successfully"); await fetchLeads(); // Refresh leads after deleting } catch (error) { @@ -351,12 +343,10 @@ const LeadForm: React.FC<LeadFormProps> = ({ > ) => { const { name, value } = e.target; - console.log(`Updating field ${name} with value ${value}`); // Add logging here to verify form updates setLead((prevLead) => ({ ...prevLead, [name]: value, // Dynamically update the field based on input 'name' })); - // console.log("Hi"+selectedLead.organization) }; const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => { From c62b33542c089dd260b4118660b3d28009de6874 Mon Sep 17 00:00:00 2001 From: Akash <akashsingh2210670@gmail.com> Date: Thu, 21 Nov 2024 23:04:40 +0530 Subject: [PATCH 4/4] feat: removed pb recruitment page --- app/(default)/page.tsx | 4 ++-- app/(default)/recruitment/page.tsx | 8 +++----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/app/(default)/page.tsx b/app/(default)/page.tsx index 6f786a2..e6c788c 100644 --- a/app/(default)/page.tsx +++ b/app/(default)/page.tsx @@ -27,7 +27,7 @@ export default function Home() { <Hero /> <WhatWeDo /> <Domains /> - <div className="flex flex-col justify-center items-center py-10 px-5"> + {/* <div className="flex flex-col justify-center items-center py-10 px-5"> <SparklesText text="Upcoming Events" className="text-4xl font-bold text-center text-gray-200 mb-4" /> <Image src={"/images/recruitment.png"} @@ -43,7 +43,7 @@ export default function Home() { </button> </a> </div> - </div> + </div> */} <div className="-mt-20"> {/* Adjusted margin for Activities section */} <Activities /> diff --git a/app/(default)/recruitment/page.tsx b/app/(default)/recruitment/page.tsx index d6e53ac..baa7fdc 100644 --- a/app/(default)/recruitment/page.tsx +++ b/app/(default)/recruitment/page.tsx @@ -1,8 +1,6 @@ "use client"; import RecruitmentForm from "@/components/forms/recruitmentForm"; -import DotPattern from "@/components/magicui/dot-pattern"; import "../../css/additional-styles/form.css"; -import { cn } from "@/lib/server/utils"; import { onAuthStateChanged } from "firebase/auth"; import { auth } from "@/Firebase"; import { useEffect } from "react"; @@ -21,9 +19,9 @@ const RegisterPage = () => { }); }); - // useEffect(() => { - // router.push("/"); - // }) + useEffect(() => { + router.push("/"); + }) return ( <>