Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
7 changes: 6 additions & 1 deletion backend/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ import cookieParser from "cookie-parser";
import dotenv from "dotenv";
import authRouter from "./routes/Auth.router.js";
import teamRouter from "./routes/Team.router.js";
import adminRouter from "./routes/admin.router.js";
import inviteRouter from "./routes/Invite.router.js";
import userRouter from "./routes/User.router.js";
import memberRouter from "./routes/Member.router.js";
import teamPageRouter from "./routes/Team.page.router.js";

import joinRouter from "./routes/Join.router.js";
import eventRouter from "./routes/Event.router.js";
import projectRouter from "./routes/Project.router.js";
Expand All @@ -22,7 +25,7 @@ app.use(cookieParser());
app.use(methodOverride("_method"));

// CORS Configuration
const allowedOrigins = process.env.FRONTEND_DOMAIN_PROD || process.env.FRONTEND_DOMAIN_DEV;
const allowedOrigins = process.env.FRONTEND_DOMAIN_PROD || process.env.FRONTEND_DOMAIN_DEV || "http://localhost:5173";
console.log(allowedOrigins);
const corsOptions = {
origin: allowedOrigins,
Expand Down Expand Up @@ -51,6 +54,8 @@ app.use('/api/teams', joinRouter);
app.use('/api/teams', memberRouter);
app.use('/api/events', eventRouter);
app.use('/api/projects', projectRouter);
app.use('/api/teampage', teamPageRouter);
app.use('/api/admin', adminRouter);

// Error handling middleware
app.use((err, req, res, next) => {
Expand Down
53 changes: 53 additions & 0 deletions backend/controllers/Team.Member.controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import TeamMember from "../models/TeamMember.model.js";

export const getTeamByYears = async (req, res) => {
try {
const years = await TeamMember.distinct("year");
years.sort((a, b) => b - a);
res.json(years);
} catch (err) {
res.status(500).json({ message: "Failed to fetch years" });
}
};

export const getCurrentTeam = async (req, res) => {
try {
const year = parseInt(req.query.year);
if (!year) return res.status(400).json({ message: "Year is required" });
const team = await TeamMember.find({ year }).sort({ order: 1 });
res.json(team);
} catch (err) {
res.status(500).json({ message: "Failed to fetch team" });
}
};

export const createTeamMember = async (req, res) => {
try {
const member = await TeamMember.create(req.body);
res.status(201).json(member);
} catch (err) {
res.status(400).json({ message: "Failed to create team member", error: err.message });
}
};

export const updateTeamMember = async (req, res) => {
try {
const { id } = req.params;
const member = await TeamMember.findByIdAndUpdate(id, req.body, { new: true });
if (!member) return res.status(404).json({ message: "Team member not found" });
res.json(member);
} catch (err) {
res.status(400).json({ message: "Failed to update team member", error: err.message });
}
};

export const deleteTeamMember = async (req, res) => {
try {
const { id } = req.params;
const member = await TeamMember.findByIdAndDelete(id);
if (!member) return res.status(404).json({ message: "Team member not found" });
res.json({ success: true });
} catch (err) {
res.status(400).json({ message: "Failed to delete team member", error: err.message });
}
};
1 change: 1 addition & 0 deletions backend/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ dotenv.config({path:'./.env'})
import connectDB from "./db/db.js"
import app from "./app.js"

// app.use(express.json())
connectDB()
.then(()=>{
const port=process.env.PORT || 3000;
Expand Down
20 changes: 20 additions & 0 deletions backend/models/TeamMember.model.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import mongoose from "mongoose";

const teamMemberSchema = new mongoose.Schema(
{
name: { type: String, required: true },
role: { type: String, required: true },
image: { type: String },
desc: { type: String },
facebook: { type: String },
twitter: { type: String },
instagram: { type: String },
year: { type: Number, required: true }, // e.g. 2025
order: { type: Number, default: 0 }, // for sorting
},
{ timestamps: true }
);

const TeamMember = mongoose.model("TeamMember", teamMemberSchema);

export default TeamMember;
15 changes: 15 additions & 0 deletions backend/routes/Team.member.router.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import express from "express";
import { getCurrentTeam, getTeamByYear, createTeamMember, updateTeamMember, deleteTeamMember } from "../controllers/Team..Member.controller.js";

const router = express.Router();

// Public endpoints
router.get("/years", getTeamByYears);
// router.get("/", getCurrentTeam);

// Admin endpoints
router.post("/create-team-member", createTeamMember);
router.put("/team/:id", updateTeamMember);
router.delete("/team/:id", deleteTeamMember);

export default router;
8 changes: 8 additions & 0 deletions backend/routes/Team.page.router.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import express from "express";
import { getTeamYears, getTeamByYear, createTeamMember, updateTeamMember, deleteTeamMember } from "../controllers/Team..Member.controller.js";

const router = express.Router();

router.get("/years", getTeamYears);
router.get("/", getTeamByYear);
export default router;
10 changes: 10 additions & 0 deletions backend/routes/admin.router.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import express from "express";
// import { getTeamYears, getTeamByYear, createTeamMember, updateTeamMember, deleteTeamMember } from "../controllers/Team..Member.controller.js";
import teamRouter from "./Team.member.router.js";

const router = express.Router();

// Public endpoints
router.use("/team", teamRouter);

export default router;
4 changes: 2 additions & 2 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions frontend/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@ import TransactionVerifyPage from "./pages/TransactionVerifyPage";
import WorkshopInfo from "./pages/WorkshopInfo";
import TeamDetailsPage from "./pages/TeamDetailsPage";
import SynapseEventPage from "./pages/SynapseEventPage";
import AdminDashBoard from "./admin/AdminDashBoard";
import UserDashboardPage from "./pages/UserDashboardPage";
import EventDetailsPage from "./pages/EventDetailsPage.jsx";
import CreateEventPage from "./pages/CreateEventPage.jsx";
import ManageEventsPage from "./pages/ManageEventsPage.jsx";
import { Toaster } from "./components/ui/toaster";
import TeamPage from "./pages/TeamPage";

const App = () => {
return (
Expand All @@ -45,6 +47,8 @@ const App = () => {
<Route path="/register" element={<RegisterPage />} />
<Route path="/login" element={<LoginPage />} />
<Route path="/forgot-password" element={<ForgotPasswordPage />} />
<Route path="/admin" element={<AdminDashBoard />} />
<Route path="/team" element={<TeamPage />} />

<Route
path="/userdashboard"
Expand Down
36 changes: 36 additions & 0 deletions frontend/src/admin/AdminDashBoard.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React, { useState } from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faUsers, faUser, faPlus } from "@fortawesome/free-solid-svg-icons";
import AdminSidebar from "./admin-comp/AdminSidebar";
import TeamManagement from "./admin-comp/TeamManagement";

const SIDEBAR_OPTIONS = [
{ name: "Team Management", icon: faUsers },
{ name: "User Management", icon: faUser },
{ name: "Event Management", icon: faUsers },
{ name: "Workshop Management", icon: faUsers },
];

export default function AdminDashBoard() {
const [activeSection, setActiveSection] = useState("Team Management");

return (
<div className="min-h-screen bg-gray-50 dark:bg-gray-900 flex flex-col md:flex-row">
<AdminSidebar
options={SIDEBAR_OPTIONS}
activeSection={activeSection}
setActiveSection={setActiveSection}
className="w-full md:w-64 bg-white dark:bg-gray-800 border-r border-gray-200 dark:border-gray-700"
/>
<main className="flex-1 p-4 md:p-10 transition-all duration-300">
{activeSection === "Team Management" && <TeamManagement />}
{activeSection !== "Team Management" && (
<div className="text-xl md:text-2xl text-gray-400 dark:text-gray-500 font-bold text-center py-10">
{activeSection} (Coming Soon)
</div>
)}
</main>
</div>
);
}

27 changes: 27 additions & 0 deletions frontend/src/admin/admin-comp/AdminSidebar.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";

export default function AdminSidebar({ options, activeSection, setActiveSection, className }) {
return (
<aside className={`w-full md:w-64 bg-white dark:bg-gray-800 shadow-lg p-4 md:p-6 flex flex-row md:flex-col gap-2 md:gap-4 border-b md:border-b-0 md:border-r border-gray-200 dark:border-gray-700 ${className || ''}`}>
<h2 className="text-lg md:text-2xl font-bold text-pink-600 dark:text-pink-400 mb-2 md:mb-6 w-full text-center md:text-left">Admin Dashboard</h2>
<div className="flex flex-row md:flex-col gap-2 md:gap-4 w-full">
{options.map((opt) => (
<button
key={opt.name}
className={`flex items-center gap-2 md:gap-3 px-2 md:px-4 py-2 rounded-lg font-semibold text-base md:text-lg transition-colors duration-200 focus:outline-none w-full justify-center md:justify-start ${
activeSection === opt.name
? "bg-pink-600 text-white dark:bg-pink-700"
: "bg-gray-100 dark:bg-gray-900 text-pink-600 dark:text-pink-400 hover:bg-pink-50 dark:hover:bg-gray-800"
}`}
onClick={() => setActiveSection(opt.name)}
>
<FontAwesomeIcon icon={opt.icon} />
<span>{opt.name}</span>
</button>
))}
</div>
</aside>
);
}

Loading