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
30 changes: 15 additions & 15 deletions pr_template.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
# [YOUR FULL NAME]'s Submission
**Date**: [date here]
# Daniel Thomas's Submission
**Date**: 12/1/2025

**BU Email**: [email here]
**BU Email**: diggyzar@bu.edu

**Class Year**: [year here]
**Class Year**: 2027

**Favorite Hobby**: [hobby here]
**Favorite Hobby**: Martial Arts (specifically karate!)

## Requirements
Please check off which features you have implemented:
- [ ] A catchy name and title with a cool font!
- [ ] An interesting and beautiful frontend design with a catchy title and cool fonts and colors that looks good on any screen size.
- [ ] A home page with a summary about the interesting thing you want to teach me about. I was originally planning for this to be purely academic (e.g. math, CS, physics, engineering) topics but I am expanding it to include anything. However, you should be able to teach about whatever you choose in a clear way and go in-depth about it. If your subject matter is particularly engaging, that will reflect positively on your application.
- [ ] Extra pages with more detailed information on certain topics. Make your website intuitive to navigate through, both within the pages themselves and in your choice of pages. You can structure your website however you see fit.
- [ ] A poll/quiz feature where you can check that the user is aborbing the information your website teaches about well. These quiz questions should be scattered throughout the website, and they should tell the user whether they got the answer right or not once they select it. Additionally, it should show a live count of results (like a social media poll) with the names of the users who have voted for each option. You should take time to make sure your UI for this component is intuitive to use while still including all of the features listed. A user should be able to change their result if they want, and this should be reflected in the result count.
- [ ] A comment feature on each page where users can offer feedback or ask questions based on the lesson on the page. The home page does not need a comment section, but every other page should have one.
- [ ] Deploy the frontend and backend if you can using some of the free deployment tools we talked about in the workshops!
- [x] A catchy name and title with a cool font!
- [x] An interesting and beautiful frontend design with a catchy title and cool fonts and colors that looks good on any screen size.
- [x] A home page with a summary about the interesting thing you want to teach me about. I was originally planning for this to be purely academic (e.g. math, CS, physics, engineering) topics but I am expanding it to include anything. However, you should be able to teach about whatever you choose in a clear way and go in-depth about it. If your subject matter is particularly engaging, that will reflect positively on your application.
- [x] Extra pages with more detailed information on certain topics. Make your website intuitive to navigate through, both within the pages themselves and in your choice of pages. You can structure your website however you see fit.
- [x] A poll/quiz feature where you can check that the user is aborbing the information your website teaches about well. These quiz questions should be scattered throughout the website, and they should tell the user whether they got the answer right or not once they select it. Additionally, it should show a live count of results (like a social media poll) with the names of the users who have voted for each option. You should take time to make sure your UI for this component is intuitive to use while still including all of the features listed. A user should be able to change their result if they want, and this should be reflected in the result count.
- [x] A comment feature on each page where users can offer feedback or ask questions based on the lesson on the page. The home page does not need a comment section, but every other page should have one.
- [x] Deploy the frontend and backend if you can using some of the free deployment tools we talked about in the workshops!

## Screen Recording
**Link**: [paste it here]
**Link**: https://youtu.be/cr-lHbyddJI

## Written Portion
1. **How did the project go? What parts of it did you most enjoy / find yourself good at?**

[answer here]
I thought the project was really fun to implement. Even though I have been using Next.js and Typescript for past projects and websites, I still found myself very engaged and I still was able to learn more about how React worked through this assessment. That said, I found it enjoyable trying to figure out what eaxctly to use in order to implement the name feature, especially without authentication. Since I realized that authentication could be overkill for this website, I tried to figure out how to save variables across multiple pages, which is how I came across useContext. Using that was certainly interesting to figure out and I can definitely see myself use this feature more often in future projects. I also had prior experience with MongoDB, so I used that extensively to implement the comment and quiz/poll features. But this project in particular made me put a little more thought into how I should structure my database, especially if I want to retrieve multiple comments to one person or generate a randomized question.

2. **Was this technical assessment what you expected? If you had another two weeks to work on it, what would you add or change?**

[answer here]
Not really. I moreso expected something a little more than a portfolio website (imagine this exact assessment but removing the comment and quiz/poll feature entirely). But I'm glad this included aspects that were not entirely covered in the JDT workshops, so I could explore the features I specifically wanted to put in my website. If I had an extra two weeks, I would also add more transitions to each of the pages, to make sure that the user experience is improved a little it. I would also experiment with more creative layouts for each of the pages. I would also figure out a way to add user-specific stats (e.g. You answered 75% of the questions right). I would also try to implement a system where I could point users to the nearest karate dojos based on their geolocation so they could start training (or if they're unable to, point them to a bunch of online content where they start training).
41 changes: 41 additions & 0 deletions src/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# env files (can opt-in for committing if needed)
.env*

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
36 changes: 36 additions & 0 deletions src/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).

## Getting Started

First, run the development server:

```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.

This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.

## Learn More

To learn more about Next.js, take a look at the following resources:

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!

## Deploy on Vercel

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.

Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
19 changes: 19 additions & 0 deletions src/app/actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
"use server";

import client from "@/app/lib/mongodb";

export async function testDatabaseConnection() {
let isConnected = false;
try {
const mongoClient = await client.connect();
// Send a ping to confirm a successful connection
await mongoClient.db("admin").command({ ping: 1 });
console.log(
"Pinged your deployment. You successfully connected to MongoDB!",
); // because this is a server action, the console.log will be outputted to your terminal not in the browser
return !isConnected;
} catch (e) {
console.error(e);
return isConnected;
}
}
27 changes: 27 additions & 0 deletions src/app/api/add_comment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { clientPromise } from "../lib/mongodb"

export default async function handler(req, res) {

const client = await clientPromise;

const name = req.query.name;
const comment = req.query.comment;
const path = req.query.path;

try {

await client.connect();

const db = client.db("feedback");
db.collection("comments").insertOne({name: name, comment: comment, path: path})
res.status(200).json(data);
}
catch (error) {
console.error("API Error:", error);
res.status(500).json({ message: error });
}
finally {
await client.close();
}

}
43 changes: 43 additions & 0 deletions src/app/api/add_comment/route.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import client from "../../lib/mongodb"

export async function POST(request) {
try {
const { searchParams } = new URL(request.url)
const name = searchParams.get("name");
const comment = searchParams.get("comment")
const path = searchParams.get("path");

console.log("Adding comment:", { name, comment, path });

if (!name || !comment || !path) {
return Response.json(
{ error: "Missing required fields" },
{ status: 400 }
);
}

await client.connect();

const database = client.db("feedback");
const collection = database.collection("comments");

const result = await collection.insertOne({
name,
comment,
path,
createdAt: new Date()
});

return Response.json({
success: true,
insertedId: result.insertedId
});

} catch (error) {
console.error("API Error:", error);
return Response.json(
{ error: "Failed to add comment: " + error.message },
{ status: 500 }
);
}
}
34 changes: 34 additions & 0 deletions src/app/api/get_comments/route.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import client from "../../lib/mongodb"

export async function GET(request) {
try {

const { searchParams } = new URL(request.url);
const path = searchParams.get("path");

if (!path) {
return Response.json(
{ error: "Path parameter is required" },
{ status: 400 }
);
}

// Make sure client is connected
await client.connect();

const database = client.db("feedback");
const collection = database.collection("comments");

const data = await collection.find({ path: path }).sort({createdAt: -1}).toArray();

console.log(`Found ${data.length} comments for path: ${path}`);
return Response.json(data);

} catch (error) {
console.error("API Error:", error);
return Response.json(
{ error: "Failed to fetch comments: " + error.message },
{ status: 500 }
);
}
}
34 changes: 34 additions & 0 deletions src/app/api/get_questions/route.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import client from "../../lib/mongodb"

export async function GET(request) {
try {

const { searchParams } = new URL(request.url);
const path = searchParams.get("path");

if (!path) {
return Response.json(
{ error: "Path parameter is required" },
{ status: 400 }
);
}

// Make sure client is connected
await client.connect();

const database = client.db("feedback");
const collection = database.collection("results");

const data = await collection.find({ topic: path }).toArray();

console.log(`Found ${data.length} questions for path: ${path}`);
return Response.json(data);

} catch (error) {
console.error("API Error:", error);
return Response.json(
{ error: "Failed to fetch questions: " + error.message },
{ status: 500 }
);
}
}
84 changes: 84 additions & 0 deletions src/app/api/save_answer/route.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { MongoClient } from 'mongodb';
import { ObjectId } from "mongodb";


export async function POST(request) {

const client = new MongoClient(process.env.MONGODB_URI);

try {
const { searchParams } = new URL(request.url)
const id = searchParams.get("id");
const name = searchParams.get("name");
const choice = searchParams.get("choice");
let answerId = searchParams.get("answer_id");

await client.connect();

const db = client.db("feedback");
const collection = db.collection("results")

if (answerId === "undefined") {
answerId = new ObjectId();
console.log("New objectid created!", answerId)
}
else {
answerId = new ObjectId(answerId)
}

// First, try to update an existing answer inside the answers array
const updateExisting = await collection.updateOne(
{
_id: new ObjectId(id),
"answers.id": answerId,
},
{
$set: {
"answers.$.choice": choice,
"answers.$.updatedAt": new Date(),
},
}
);

let operationType = "updated";

// If no existing answer was matched, add a new one
if (updateExisting.matchedCount === 0) {
await collection.updateOne(
{ _id: new ObjectId(id) },
{
$addToSet: {
answers: {
id: answerId,
name,
choice,
createdAt: new Date(),
},
},
},
{ upsert: true }
);
operationType = "inserted";
}

const updatedDoc = await collection.findOne({ _id: new ObjectId(id) });
console.log("Updated document:", updatedDoc);

return Response.json({
success: true,
operation: operationType,
answerId: answerId.toString(),
});
}
catch (error) {
console.error("API Error:", error);
return Response.json(
{ error: "Failed to add comment: " + error.message },
{ status: 500 }
)
}
finally {
await client.close();
}

}
Loading