Skip to content

Commit

Permalink
interest form
Browse files Browse the repository at this point in the history
  • Loading branch information
shahdivyank committed Nov 5, 2023
1 parent fd8d10f commit 49ca380
Show file tree
Hide file tree
Showing 9 changed files with 304 additions and 0 deletions.
18 changes: 18 additions & 0 deletions src/app/admin/interests/page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import ProtectedPage from "@/components/dynamic/ProtectedPage";
import Interests from "@/components/dynamic/admin/dashboards/Interests";

const Page = () => {
return (
<ProtectedPage
title="Admin | Interests"
restrictions={{
admins: 1,
committees: 1,
}}
>
<Interests />
</ProtectedPage>
);
};

export default Page;
114 changes: 114 additions & 0 deletions src/app/api/interests/route.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import { NextResponse } from "next/server";
import { db } from "../../../../firebase";
import {
collection,
getDocs,
doc,
updateDoc,
Timestamp,
query,
where,
} from "firebase/firestore";
import { authenticate } from "@/utils/auth";
import { AUTH } from "@/data/dynamic/admin/Feedback";

export async function POST() {
const res = NextResponse;
const { auth, uid } = await authenticate(AUTH.POST);

if (auth !== 200) {
return res.json(
{ message: `Authentication Error: ${message}` },
{ status: auth }
);
}

try {
await updateDoc(doc(db, "users", uid), {
"roles.interests": 0,
timestamp: Timestamp.now(),
});
return res.json({ message: "OK" }, { status: 200 });
} catch (err) {
return res.json(
{ message: `Internal Server Error: ${err}` },
{ status: 500 }
);
}
}

export async function GET() {
const res = NextResponse;
const { auth, message } = await authenticate(AUTH.GET);

if (auth !== 200) {
return res.json(
{ message: `Authentication Error: ${message}` },
{ status: auth }
);
}

const output = [];

try {
const snapshot = await getDocs(
query(collection(db, "users"), where("roles.interests", "in", [-1, 0, 1]))
);
snapshot.forEach((doc) => {
const { name, email, timestamp, roles } = doc.data();
output.push({
uid: doc.id,
name,
email,
status: roles.interests,
timestamp: timestamp,
});
});

const sorted = output.sort((a, b) =>
a.timestamp.seconds < b.timestamp.seconds ? 1 : -1
);

return res.json({ message: "OK", items: sorted }, { status: 200 });
} catch (err) {
return res.json(
{ message: `Internal Server Error: ${err}` },
{ status: 500 }
);
}
}

export async function PUT(req) {
const res = NextResponse;
const { auth, message } = await authenticate(AUTH.PUT);

if (auth !== 200) {
return res.json(
{ message: `Authentication Error: ${message}` },
{ status: auth }
);
}

const { objects, attribute, status } = await req.json();

try {
objects.forEach(async (object) => {
if (attribute === "role") {
await updateDoc(doc(db, "users", object.uid), {
"roles.interests": deleteField(),
});
} else if (attribute === "status") {
await updateDoc(doc(db, "users", object.uid), {
"roles.interests": status,
});
}
});

return res.json({ message: "OK" }, { status: 200 });
} catch (err) {
return res.json(
{ message: `Internal Server Error: ${err}` },
{ status: 500 }
);
}
}
12 changes: 12 additions & 0 deletions src/app/form/interest/page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import Interest from "@/components/dynamic/form/Interest";
import ProtectedPage from "@/components/dynamic/ProtectedPage";

const Page = () => {
return (
<ProtectedPage title="Form | Interest" restrictions={{}}>
<Interest />
</ProtectedPage>
);
};

export default Page;
1 change: 1 addition & 0 deletions src/components/dynamic/admin/Table.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ const Table = ({
})
);
};

return !objects ? (
<Loading />
) : (
Expand Down
23 changes: 23 additions & 0 deletions src/components/dynamic/admin/dashboards/Interests.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"use client";
import {
FILTERS,
HEADERS,
STATUSES,
TAGS,
} from "@/data/dynamic/admin/Interest";
import Dashboard from "../Dashboard";

const Feedback = () => {
return (
<Dashboard
title="Interests"
page="interests"
empty="No Interests Available"
filter={FILTERS}
header={HEADERS}
statuses={STATUSES}
tags={TAGS}
/>
);
};
export default Feedback;
44 changes: 44 additions & 0 deletions src/components/dynamic/form/Interest.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"use client";

import { useState } from "react";
import Form from "@/components/dynamic/form/Form.jsx";
import axios from "axios";
import toast from "react-hot-toast";
import { FIELDS, ATTRIBUTES } from "@/data/dynamic/form/Interest";
import { useSession } from "next-auth/react";
import { STATUSES } from "@/data/dynamic/admin/Interest";

const Interest = () => {
const { data: session } = useSession();
const [interest, setInterest] = useState({
...ATTRIBUTES,
name: session.user.name,
email: session.user.email,
roles: session.user.roles,
form: "interests",
});

const onSubmit = (setLoading, setState) => {
axios
.post("/api/interests", interest)
.then(() => toast(`✅ Submitted successfully!`))
.catch(() => toast(`❌ Internal Server Error`))
.finally(() => {
setLoading(false);
setState(2);
});
};

return (
<Form
fields={FIELDS}
object={interest}
setObject={setInterest}
header="INTEREST APPLICATION"
onSubmit={onSubmit}
statuses={STATUSES}
/>
);
};

export default Interest;
6 changes: 6 additions & 0 deletions src/data/dynamic/Navigation.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
FaLock,
FaCalendarDay,
FaMedal,
FaExclamation,
} from "react-icons/fa";
import { AiOutlineQrcode } from "react-icons/ai";
import { signOut } from "next-auth/react";
Expand Down Expand Up @@ -61,6 +62,11 @@ export const TABS = {
link: "/admin/committees",
icon: <SiHandshake className={iconStyle} />,
},
{
name: "interests",
link: "/admin/interest",
icon: <FaExclamation className={iconStyle} />,
},
{
name: "feedback",
link: "/admin/feedback",
Expand Down
51 changes: 51 additions & 0 deletions src/data/dynamic/admin/Interest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
export const FILTERS = {
unnotified: {
state: true,
value: 0,
},
notified: {
state: true,
value: 1,
},
};

export const TAGS = [
{
text: "notified",
value: 1,
},
{
text: "unnotified",
value: 0,
},
];

export const HEADERS = [
{ text: "name", size: "w-5/12", icon: true, sort: "off" },
{ text: "email", size: "w-5/12", icon: true, sort: "off" },
{
text: "status",
size: "w-2/12",
icon: true,
sort: "off",
hasTag: true,
},
];

export const AUTH = {
POST: {},
GET: {
admins: 1,
},
PUT: {
admins: 1,
},
DELETE: {
admins: 1,
},
};

export const STATUSES = {
1: "notified",
0: "unnotified",
};
35 changes: 35 additions & 0 deletions src/data/dynamic/form/Interest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
export const FIELDS = {
description: {
input: "description",
width: 12,
texts: [
"Welcome to HACKATHON_NAME. Thank you for taking interestin in HACKAHTON_NAME, we appreciate your efforts to help support HACKATHON_NAME. HACKATHON_NAME is a DESCRIPTION hackathon spanning HACKATHON_LENGTH on HACKATHON_DATE.",
"This is simply an interest form, once applications are released, you will be notified immediately and will be required to register again. We hope to see you there!",
],
},
name: {
input: "input",
name: "name",
type: "text",
title: "Name",
maxLength: 50,
width: 12,
editable: false,
required: true,
},
email: {
input: "input",
name: "email",
type: "email",
title: "Email Address",
maxLength: 50,
width: 12,
editable: false,
required: true,
},
};

export const ATTRIBUTES = {
name: "",
email: "",
};

0 comments on commit 49ca380

Please sign in to comment.