Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
109 commits
Select commit Hold shift + click to select a range
ce92597
add all necessary dependencies and libraries
jszor Aug 19, 2025
f658577
set up libraries and foundation for the backend
jszor Aug 20, 2025
732c4f1
add rest of backend skeleton and boilerplate
jszor Aug 20, 2025
f4fcd32
add user model
jszor Aug 20, 2025
515dfd1
set up authentication controllers
jszor Aug 21, 2025
c250a84
add authentication middleware
jszor Aug 21, 2025
4c851ae
set up auth routes and import to server.js
jszor Aug 21, 2025
cbc0444
add pet schema to models
jszor Aug 21, 2025
ba22603
add petRoutes
jszor Aug 21, 2025
32bdd84
add lastupdated to petschema to allow for automatic expiration
jszor Aug 22, 2025
f08a800
modify petschema to include conditions
jszor Aug 22, 2025
c6dca03
tweak pet decay util function
jszor Aug 23, 2025
041c8b3
add getPet controller to petController
jszor Aug 23, 2025
9a602d5
add petCreate controller function in petController
jszor Aug 23, 2025
9b1cff5
mount petRoutes to server.js
jszor Aug 23, 2025
aa7edcf
add pet inventory controller functions
jszor Aug 23, 2025
9cdf2c6
add useItem controller to petController to make use-item route work, …
jszor Aug 23, 2025
ee393fa
updated applyPetDecay to work with cron job and lazy evaluation
jszor Aug 24, 2025
6a332d4
add statTimers to pet model to keep track of updated stats individually
jszor Aug 24, 2025
598ed83
update applyPetDecay function to correct bug where cycles never reach…
jszor Aug 24, 2025
df01d34
create cron job to update pets every hour
jszor Aug 24, 2025
1470d70
import cron job to server.js
jszor Aug 24, 2025
4f7216b
correct useItem controller so that items only consumed if they have a…
jszor Aug 24, 2025
15d056d
modify pet model to remove sicknessTime and PoopTime timestamps, as w…
jszor Aug 24, 2025
4a44528
add nextPoopTime and nextSicknessTime timestamps to pet model to allo…
jszor Aug 24, 2025
6146508
add poop and sickness randomization logic to applyPetDecay controller
jszor Aug 24, 2025
f6d43d3
add useItem route to petRoutes.js
jszor Aug 25, 2025
78aa188
create addCoins, addXP and getLeaderboardcontrollers in petController…
jszor Aug 25, 2025
f583055
add routes for addXP, addCoins and getLeaderboard to petRoutes.js
jszor Aug 25, 2025
42102d7
add seedItems.js to seed DB with items
jszor Aug 25, 2025
fcb371e
tweak user model for better performance
jszor Aug 25, 2025
6d3a89a
add node-cron to dependencies, change stats for effects in items.js m…
jszor Aug 25, 2025
f4aff01
added type: module to package.json
jszor Aug 25, 2025
1fee6e6
correct syntax error in importing Item to seedItems.js, and make powe…
jszor Aug 25, 2025
358d2f2
change powerup.default to equal an empty object since powerup is an o…
jszor Aug 25, 2025
5b38ef9
tweak sickness and poop logic so that times get rescheduled even if s…
jszor Aug 25, 2025
a2f6475
tweaked item price in seedItems.js
jszor Aug 25, 2025
8b20285
add store routes to petRoutes.js
jszor Aug 25, 2025
df6e336
create storeRoutes.js and storeController.js to house store related l…
jszor Aug 25, 2025
62d707a
import storeRoutes to server.js and tweak path names on storeRoutes.js
jszor Aug 25, 2025
ecaaeb9
add exercise model, exercise controller, exercise routes and extract …
jszor Aug 26, 2025
bf89407
add seedExercises.js to add exercises to DB
jszor Aug 26, 2025
0fa1db1
correct error in seedExercises.js, -are verbs, question 4
jszor Aug 26, 2025
715b2b9
create login route and add to __root.tsx
jszor Aug 26, 2025
35b0000
map out structure
jszor Aug 26, 2025
6eaa8b6
add custom colors and fonts to index.css
jszor Aug 27, 2025
4be56c0
add global styles
jszor Aug 27, 2025
e0e8744
create d.ts. file and add to tsconfig.json, create components for lan…
jszor Aug 27, 2025
0942946
add _redirects to solve netlify deployment issue
jszor Aug 27, 2025
8dfe258
delete _redirects from public folder
jszor Aug 27, 2025
a21f6e1
tweak footer padding
jszor Aug 27, 2025
935456c
add Features.tsx to index route, tweak landing page layout
jszor Aug 27, 2025
5100279
styling log in page
jszor Aug 27, 2025
1dc345b
fine tune login logic
jszor Aug 27, 2025
91d56bf
momentarily change scripts.start in package.json to node_env=development
jszor Aug 27, 2025
2e207dd
add deployed backend to login fetch function as env variable
jszor Aug 27, 2025
f5a75be
fix issue where app routes do not render
jszor Aug 28, 2025
30960a0
conditionally render landing header and footer on landing routes only…
jszor Aug 28, 2025
83d3aad
add app header, and redirect to login when click logout
jszor Aug 28, 2025
a7068e8
tweak login error message when invalid credentials
jszor Aug 28, 2025
3afce68
set up panels for game ui
jszor Aug 28, 2025
616aef2
add app menu links
jszor Aug 28, 2025
db51413
minor correction
jszor Aug 28, 2025
9fc9860
create inventory routes also dynamic ones
jszor Aug 28, 2025
6a1bd42
minor fix
jszor Aug 28, 2025
fc053c2
add backlink from inventory back to main menu
jszor Aug 28, 2025
172060c
tweak petGet function in petController to only return pet that is alive
jszor Aug 28, 2025
279e17e
tweak general logic to only apply to a user's only living pet
jszor Aug 28, 2025
7bb9212
add cond render on inventory menu when in subroutes. add logic to map…
jszor Aug 28, 2025
f8310ac
tweak backlink to menu on inventory.tsx
jszor Aug 28, 2025
00fae48
fix issue with backlinks not working correctly
jszor Aug 28, 2025
3fc2156
create store store and dynamically render individual food item detail…
jszor Aug 28, 2025
6cd1191
change message response in useItem
jszor Aug 29, 2025
e6f2398
tweak food item detail layout
jszor Aug 29, 2025
d20a53d
minor styling changes to menu
jszor Aug 29, 2025
3f827e5
add sprite, coins and stat icons with bars to console
jszor Aug 29, 2025
a1c47c3
add _redirects to prevent error 404 when refreshing deployed site
jszor Aug 29, 2025
c228418
move redirects to dist folder
jszor Aug 29, 2025
7366d86
move redirects to public folder to solve netlify refresh page not fou…
jszor Aug 29, 2025
531409c
minor styling tweaks, button hovers, panel borders, etc
jszor Aug 29, 2025
02ad7fb
delete console log from beforeLoad function in app.tsx
jszor Aug 30, 2025
d39271d
add error message for user navigating to inventory item that they don…
jszor Aug 30, 2025
bf5728e
change highlight color in index.css
jszor Aug 30, 2025
320f729
add logic for inventory medicine
jszor Aug 30, 2025
812e39c
add logic for inventory toys
jszor Aug 30, 2025
a0fe2cc
add logic for inventory powerups
jszor Aug 30, 2025
8eda5f9
styling tweaks for inventory message displays
jszor Aug 30, 2025
af03340
tweak buyItem in storeController to find item by name, as per fronten…
jszor Aug 31, 2025
c4b7e1e
tweak success message when buying item in storeController
jszor Aug 31, 2025
2447f80
tweak messages on storeController
jszor Aug 31, 2025
925c952
try fix for db not updating after successfully buying item in store
jszor Aug 31, 2025
e2abea9
add status alive to buyItem in storeController.js
jszor Aug 31, 2025
8581299
add logic for pet shop, specifically food shop
jszor Aug 31, 2025
c4e672b
add logic for pet shop, specifically toy shop
jszor Aug 31, 2025
4a21699
add logic for pet shop, specifically medicine shop
jszor Aug 31, 2025
1935779
add logic for pet shop, specifically powerup shop
jszor Aug 31, 2025
13af784
limit project scope, remove superfluous code
jszor Nov 9, 2025
71d02c7
add responsiveness
jszor Nov 9, 2025
08d4ce2
make about lead home for now
jszor Nov 9, 2025
6dde5c0
edit readme
jszor Nov 9, 2025
375fa12
Update README to specify web app format
jszor Nov 9, 2025
3ff330f
Revise project description and technology sections
jszor Nov 9, 2025
b331711
edit layout readme file
jszor Nov 9, 2025
1453b7f
Update README with approval note for navigation
jszor Nov 9, 2025
cb079db
fix responsiveness issue in item descriptions
jszor Nov 17, 2025
d7b891e
landing page responsiveness
jszor Nov 18, 2025
3ac8eb6
responsiveness log in page
jszor Nov 18, 2025
8e01271
disable footer links
jszor Nov 18, 2025
52878ee
return user-friendly error message on pet expiration
jszor Nov 27, 2025
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
23 changes: 18 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
# Final Project

Replace this readme with your own information about your project.
BrainPet is a tamagotchi-like web app where the goal is to keep your virtual pet alive by tending to its needs.

Start by briefly describing the assignment in a sentence or two. Keep it short and to the point.
## The idea

## The problem
My goal was to create a virtual pet app that could integrate a learning aspect that allowed my students to solve exercises and gain coins and experience for their pets. The scope was a little ambitious for the given time frame, so it ended up just being a regular tamagotchi app for the hand-in, but I intend on developing the original idea later down the line.

Describe how you approached to problem, and what tools and techniques you used to solve it. How did you plan? What technologies did you use? If you had more time, what would be next?
## Technologies used

- Frontend: React + TypeScript, TailwindCSS
- Backend: Node.js + Express
- Database: MongoDB + mongoose
- Authentication: JWT
- Navigation: TanStack Router (approved by Matilda)
- State management: Zustand
- External libraries: Framer Motion + node-cron + bcrypt
- Extracurricular hooks: useNavigate, useLocation.
- Additional tools: Figma, Postman, Lighthouse, Trello.

The application is responsive for mobile, tablet and desktop (320px - 1600px) and supported on Chrome, Safari and Firefox. It follows accessibility standards, clean code practices and has a 100% score on Lighthouse.

## View it live

Every project should be deployed somewhere. Be sure to include the link to the deployed project so that the viewer can click around and see what it's all about.
- Deployed frontend: https://brainpet.netlify.app/
- Deployed backend: https://project-final-wgeu.onrender.com/
14 changes: 14 additions & 0 deletions backend/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Node modules
node_modules

# MacOS
.DS_Store

# Environment variables
.env
.env.local
.env.*.local

# Misc

todo.md
19 changes: 19 additions & 0 deletions backend/config/db.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import mongoose from "mongoose";

const connectDB = async () => {
try {
const uri =
process.env.NODE_ENV === "production"
? process.env.MONGODB_URI_PROD
: process.env.MONGODB_URI_DEV;

await mongoose.connect(uri);

console.log(`✅ MongoDB connected to ${uri}`);
} catch (err) {
console.error("❌ MongoDB connection error:", err.message);
process.exit(1);
}
};

export default connectDB;
94 changes: 94 additions & 0 deletions backend/controllers/authController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { User } from "../models/user.js";
import bcrypt from "bcrypt";
import jwt from "jsonwebtoken";

// Helper to generate JWT
const generateToken = (id) => {
return jwt.sign({ id }, process.env.JWT_SECRET, { expiresIn: "30d" });
};

// Register a new user
// POST /api/auth/register
// Public access

export const registerUser = async (req, res) => {
const { initials, email, password, classroomCode } = req.body;

try {
// Check if user exists
const userExists = await User.findOne({ email });
if (userExists) {
return res.status(400).json({ error: "User already exists" });
}

// Hash password
const salt = await bcrypt.genSalt(10);
const hashedPassword = await bcrypt.hash(password, salt);

// Create user
const user = await User.create({
initials,
email,
password: hashedPassword,
classroomCode,
});

// Respond with token
res.status(201).json({
_id: user._id,
initials: user.initials,
email: user.email,
classroomCode: user.classroomCode,
token: generateToken(user._id),
});

} catch (error) {
res.status(400).json({ error: error.message });
}
};

// Log in an existing user
// POST api/auth/login
// Public access

export const loginUser = async (req, res) => {
const { email, password } = req.body;

try {
// Find user
const user = await User.findOne({ email });
if (!user) {
return res.status(401).json({ error: "Invalid credentials" });
}

// Compare password
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) {
return res.status(401).json({ error: "Invalid credentials" });
}

// Respond with token
res.json({
_id: user._id,
initials: user.initials,
email: user.email,
classroomCode: user.classroomCode,
token: generateToken(user._id),
});
} catch (error) {
res.status(500).json({ error: error.message });
}
};

// Get user profile info (minus password)
// GET api/auth/profile
// Private access

export const getUserProfile = async (req, res) => {
try {
const user = await User.findById(req.user.id).select("-password");
res.json(user);
} catch (error) {
res.status(500).json({ error: error.message });
}
};
Loading