diff --git a/README.md b/README.md
index 0e1211217..399994ab1 100644
--- a/README.md
+++ b/README.md
@@ -1,49 +1,137 @@
-# [your app name here]
+# PlayPal
CodePath WEB103 Final Project
-Designed and developed by: [your names here]
+Designed and developed by: [Abil Shrestha & Aashil Ahmad]
π Link to deployed app:
## About
+PlayPal is a web app tailored for avid gamers and casual players. It acts as your one-stop shop to uncover new games, receive personalized game suggestions, and stay current on the latest gaming news. With an intuitive interface, PlayPal simplifies exploring a universe of new gaming adventures.
+
### Description and Purpose
-[text goes here]
+The app features a robust database of games spanning all genres and platforms. Users can browse and search for games by title, genre, platform, and more. Staying current with the gaming world is a breeze with PlayPal. Peruse the latest gaming headlines, previews, and reviews. PlayPal takes the hassle out of game discovery. Its clean interface and wealth of gaming info empowers users to effortlessly find their next favorite game and connect with other gaming enthusiasts.
+
+The purpose of PlayPal is to be the go-to platform for gamers to discover new game titles to play. Key goals include:
+
+
+
Provide an extensive database of games across all platforms & genres to enable discovery
+
Offer powerful browsing, searching, and filtering to easily find games matching interests
+
Showcase key game details and metadata to learn about games before playing
+
Deliver personalized recommendations for new games based on past gameplay data
+
Keep users updated on news, releases, discussions, and trends in the gaming world
+
Cultivate an engaged community of gamers discussing games & recommendations
+
Continually expand and refine game database and discovery/recommendation features
+
### Inspiration
-[text goes here]
+Rawg.io
## Tech Stack
-Frontend:
+Frontend: ReactJs, Redux, Axios, Tailwind
-Backend:
+Backend: Node.js, Express, Passport.js, Postgresql
## Features
-### [Name of Feature 1]
+### Use Passport.js for GitHub OAuth login to restrict profile and favorites pages to logged in users
+
+Allow users to login via GitHub OAuth using Passport.js to restrict access to profile and favorites pages. [gif goes here]
+
+[gif goes here]
+
+### PostgreSQL database with tables for games, platforms, genres, etc.
+
+Setup a PostgreSQL database with structured tables to store game data.
+
+[gif goes here]
+
+### Create RESTful API routes for games, platforms, and genres that support GET, POST, PATCH, and DELETE requests
+
+Implement REST API endpoints for CRUD operations on games, platforms, genres. [gif goes here]
+
+[gif goes here]
+
+### Validate game data entered in forms before creating/updating in database
+
+Validate game info entered by user before inserting or updating in the database.
+
+[gif goes here]
+
+### React Router for dynamic routing to pages like Home, Games, Genres, Platforms, etc.
+
+Use React Router to handle routing between app pages.
+
+[gif goes here]
+
+### Redirect user to Login page if not authenticated when trying to access profile
+
+Redirect to login page if user tries to access profile when unauthenticated.
+
+[gif goes here]
+
+### Break components into pages, containers, and presentational components
-[short description goes here]
+Organize components into pages, containers, and presentational components.
[gif goes here]
-### [Name of Feature 2]
+### Use component hierarchy for clean structure and separation of concerns
-[short description goes here]
+Structure components hierarchically for clean code and separation of concerns.
[gif goes here]
-### [Name of Feature 3]
+### Game search, filter, and sort functionality
-[short description goes here]
+Allow searching, filtering, and sorting the games list.
+
+[gif goes here]
+
+### Add a slide-out navigation pane for navigation links
+
+Implement slide out navigation drawer for navigation links.
+
+[gif goes here]
+
+### Display toast notifications when games are favorited, deleted, added, etc.
+
+Show toast notifications when games are favorited, deleted, added, etc.
+
+[gif goes here]
+
+### Show loading spinner for game images and other page elements while loading
+
+Display loading spinner for game images and page elements.
+
+[gif goes here]
+
+### Disable action buttons while form is submitting to prevent duplicate submits
+
+Disable form buttons during submission to prevent duplicates.
+
+[gif goes here]
+
+### Display toast notifications when games are favorited, deleted, added, etc.
+
+Show toast notifications when games are favorited, deleted, added, etc.
[gif goes here]
-### [ADDITIONAL FEATURES GO HERE - ADD ALL FEATURES HERE IN THE FORMAT ABOVE; you will check these off and add gifs as you complete them]
## Installation Instructions
-[instructions go here]
+All commands are run from the root of the project, from a terminal:
+
+| Command | Action |
+| :------------------------ | :----------------------------------------------- |
+| `npm install` | Installs dependencies |
+| `npm run dev` | Starts local dev server at `localhost:3000` |
+| `npm run build` | Build your production site to `./dist/` |
+| `npm run preview` | Preview your build locally, before deploying |
+
+
diff --git a/client/.eslintrc.cjs b/client/.eslintrc.cjs
new file mode 100644
index 000000000..5bb07c2a5
--- /dev/null
+++ b/client/.eslintrc.cjs
@@ -0,0 +1,20 @@
+module.exports = {
+ root: true,
+ env: { browser: true, es2020: true },
+ extends: [
+ "eslint:recommended",
+ "plugin:@typescript-eslint/recommended",
+ "plugin:react-hooks/recommended",
+ ],
+ ignorePatterns: ["dist", ".eslintrc.cjs"],
+ parser: "@typescript-eslint/parser",
+ plugins: ["react-refresh"],
+ rules: {
+ "react-refresh/only-export-components": [
+ "warn",
+ { allowConstantExport: true },
+ ],
+ "no-unused-vars": "off",
+ "@typescript-eslint/no-unused-vars": "off",
+ },
+};
diff --git a/client/.gitignore b/client/.gitignore
new file mode 100644
index 000000000..a547bf36d
--- /dev/null
+++ b/client/.gitignore
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/client/.prettierrc.json b/client/.prettierrc.json
new file mode 100644
index 000000000..cae18c3a2
--- /dev/null
+++ b/client/.prettierrc.json
@@ -0,0 +1,6 @@
+{
+ "trailingComma": "es5",
+ "tabWidth": 4,
+ "semi": false,
+ "singleQuote": true
+ }
\ No newline at end of file
diff --git a/client/README.md b/client/README.md
new file mode 100644
index 000000000..1ebe379f5
--- /dev/null
+++ b/client/README.md
@@ -0,0 +1,27 @@
+# React + TypeScript + Vite
+
+This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
+
+Currently, two official plugins are available:
+
+- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
+- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
+
+## Expanding the ESLint configuration
+
+If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
+
+- Configure the top-level `parserOptions` property like this:
+
+```js
+ parserOptions: {
+ ecmaVersion: 'latest',
+ sourceType: 'module',
+ project: ['./tsconfig.json', './tsconfig.node.json'],
+ tsconfigRootDir: __dirname,
+ },
+```
+
+- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked`
+- Optionally add `plugin:@typescript-eslint/stylistic-type-checked`
+- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list
diff --git a/client/components/NavBar.tsx b/client/components/NavBar.tsx
new file mode 100644
index 000000000..e04603cf7
--- /dev/null
+++ b/client/components/NavBar.tsx
@@ -0,0 +1,16 @@
+import React from 'react';
+import { Link } from 'react-router-dom';
+import SearchBar from './SearchBar';
+
+const NavBar = () => {
+ return (
+
+ >
+ )
+}
+
+export default App
diff --git a/client/src/assets/react.svg b/client/src/assets/react.svg
new file mode 100644
index 000000000..6c87de9bb
--- /dev/null
+++ b/client/src/assets/react.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/src/index.css b/client/src/index.css
new file mode 100644
index 000000000..a7608e636
--- /dev/null
+++ b/client/src/index.css
@@ -0,0 +1,7 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+html{
+ background-color: black;
+}
\ No newline at end of file
diff --git a/client/src/main.tsx b/client/src/main.tsx
new file mode 100644
index 000000000..31364b045
--- /dev/null
+++ b/client/src/main.tsx
@@ -0,0 +1,12 @@
+import React from 'react'
+import ReactDOM from 'react-dom/client'
+import App from './App.tsx'
+import './index.css'
+import { RouterProvider } from 'react-router-dom'
+import router from './routes'
+
+ReactDOM.createRoot(document.getElementById('root')!).render(
+
+
+ ,
+)
diff --git a/client/src/routes.tsx b/client/src/routes.tsx
new file mode 100644
index 000000000..990bf1df3
--- /dev/null
+++ b/client/src/routes.tsx
@@ -0,0 +1,19 @@
+import { createBrowserRouter } from "react-router-dom";
+// import ErrorPage from "./pages/ErrorPage";
+// import GameDetailPage from "./pages/GameDetailPage";
+// import HomePage from "./pages/HomePage";
+import Layout from "../pages/Layout";
+
+const router = createBrowserRouter([
+ {
+ path: '/',
+ element: ,
+ // errorElement: ,
+ // children: [
+ // { index: true, element: },
+ // { path: 'games/:slug', element: }
+ // ]
+ }
+]);
+
+export default router;
\ No newline at end of file
diff --git a/client/src/store.ts b/client/src/store.ts
new file mode 100644
index 000000000..92df66c1e
--- /dev/null
+++ b/client/src/store.ts
@@ -0,0 +1,40 @@
+import { create } from 'zustand';
+
+interface GameQuery {
+ genreId?: number;
+ platformId?: number;
+ sortOrder?: string;
+ searchText?: string;
+}
+
+interface GameQueryStore {
+ gameQuery: GameQuery;
+ setSearchText: (searchText: string) => void;
+ setGenreId: (genreId: number) => void;
+ setPlatformId: (platformId: number) => void;
+ setSortOrder: (sortOrder: string) => void;
+}
+
+const useGameQueryStore = create((set) => ({
+ gameQuery: {},
+ setSearchText: (searchText) =>
+ set(() => ({ gameQuery: { searchText } })),
+ setGenreId: (genreId) =>
+ set((store) => ({
+ gameQuery: { ...store.gameQuery, genreId, searchText: undefined },
+ })),
+ setPlatformId: (platformId) =>
+ set((store) => ({
+ gameQuery: {
+ ...store.gameQuery,
+ platformId,
+ searchText: undefined,
+ },
+ })),
+ setSortOrder: (sortOrder) =>
+ set((store) => ({
+ gameQuery: { ...store.gameQuery, sortOrder },
+ })),
+}));
+
+export default useGameQueryStore;
diff --git a/client/src/vite-env.d.ts b/client/src/vite-env.d.ts
new file mode 100644
index 000000000..11f02fe2a
--- /dev/null
+++ b/client/src/vite-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/client/tailwind.config.js b/client/tailwind.config.js
new file mode 100644
index 000000000..2c6b495cf
--- /dev/null
+++ b/client/tailwind.config.js
@@ -0,0 +1,9 @@
+/** @type {import('tailwindcss').Config} */
+export default {
+ content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}", ],
+ theme: {
+ extend: {},
+ },
+ plugins: [],
+}
+
diff --git a/client/tsconfig.json b/client/tsconfig.json
new file mode 100644
index 000000000..54de499fa
--- /dev/null
+++ b/client/tsconfig.json
@@ -0,0 +1,25 @@
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "jsx": "react-jsx",
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": false,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true
+ },
+ "include": ["src"],
+ "references": [{ "path": "./tsconfig.node.json" }]
+}
diff --git a/client/tsconfig.node.json b/client/tsconfig.node.json
new file mode 100644
index 000000000..42872c59f
--- /dev/null
+++ b/client/tsconfig.node.json
@@ -0,0 +1,10 @@
+{
+ "compilerOptions": {
+ "composite": true,
+ "skipLibCheck": true,
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "allowSyntheticDefaultImports": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/client/vite.config.ts b/client/vite.config.ts
new file mode 100644
index 000000000..5a33944a9
--- /dev/null
+++ b/client/vite.config.ts
@@ -0,0 +1,7 @@
+import { defineConfig } from 'vite'
+import react from '@vitejs/plugin-react'
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [react()],
+})
diff --git a/images/1.png b/images/1.png
new file mode 100644
index 000000000..a0121d9cf
Binary files /dev/null and b/images/1.png differ
diff --git a/images/2.png b/images/2.png
new file mode 100644
index 000000000..d57fd6636
Binary files /dev/null and b/images/2.png differ
diff --git a/images/3.png b/images/3.png
new file mode 100644
index 000000000..abad3e1b4
Binary files /dev/null and b/images/3.png differ
diff --git a/images/ERD.png b/images/ERD.png
new file mode 100644
index 000000000..7c6fa2994
Binary files /dev/null and b/images/ERD.png differ
diff --git a/milestones/milestone1.md b/milestones/milestone1.md
index a8f086378..571e2fea0 100644
--- a/milestones/milestone1.md
+++ b/milestones/milestone1.md
@@ -6,26 +6,33 @@ This document should be completed and submitted during **Unit 5** of this course
This unit, be sure to complete all tasks listed below. To complete a task, place an `x` between the brackets.
-- [ ] Read and understand all required features
- - [ ] Understand you **must** implement **all** baseline features and **two** custom features
-- [ ] In `readme.md`: update app name
-- [ ] In `readme.md`: add all group members' names
-- [ ] In `readme.md`: complete the **Description and Purpose** section
-- [ ] In `readme.md`: complete the **Inspiration** section
-- [ ] In `readme.md`: list all features you intend to include in your app (in future units, you will check off features as you complete them and add GIFs demonstrating the features)
-- [ ] In `planning/user_stories.md`: add all user stories
-- [ ] In this document, complete the **Reflection** section below
+- [X] Read and understand all required features
+ - [X] Understand you **must** implement **all** baseline features and **two** custom features
+- [X] In `readme.md`: update app name
+- [X] In `readme.md`: add all group members' names
+- [X] In `readme.md`: complete the **Description and Purpose** section
+- [X] In `readme.md`: complete the **Inspiration** section
+- [X] In `readme.md`: list all features you intend to include in your app (in future units, you will check off features as you complete them and add GIFs demonstrating the features)
+- [X] In `planning/user_stories.md`: add all user stories
+- [X] In this document, complete the **Reflection** section below
## Reflection
### 1. What went well during this unit?
-[ππΎππΎππΎ your answer here]
+Our team worked really well together during this unit to come up with an exciting web app concept - a game discovery app for gamers. We took inspiration from successful existing platforms like Rawg.io to make sure our app would fill a real need and have an engaged user base.
+
+By brainstorming the app purpose and core features as a team, we were able to get aligned on the direction for this project. We clearly outlined the goals and user experiences we want our app to provide. Breaking these down into detailed user stories gave us a solid framework to build off of as we move into the next development stages.
+
+We believe that the strategic planning and user-centric design principles we focused on this unit have set us up for success. Moving forward, we want to maintain this momentum of working together to bring an innovative web app from concept to reality.
### 2. What were some challenges your group faced in this unit?
-[ππΎππΎππΎ your answer here]
+We learned the importance of prioritizing core features and intentionally defining an MVP to make the project achievable within our timeline and skills. This discussion brought valuable collaboration as we aligned on the most essential user stories and functionality
### 3. What additional support will you need in upcoming units as you continue to work on your final project?
-[ππΎππΎππΎ your answer here]
+ We need support on how to improve website performance and responsiveness. We could use some guidance on best practices for modeling these relationships in our database and setting them up in our backend. We have questions around:
+ 1. How to properly structure the tables and foreign keys to define one-to-many relationships in our schema?
+ 2. What is the ideal way to implement joins and junction tables to enable many-to-many connections between certain data types in our app?
+ 3. What are some pitfalls to avoid when designing and querying these types of relationships on the backend?
diff --git a/milestones/milestone2.md b/milestones/milestone2.md
index 7d7687f1e..2c2aebae2 100644
--- a/milestones/milestone2.md
+++ b/milestones/milestone2.md
@@ -6,22 +6,22 @@ This document should be completed and submitted during **Unit 6** of this course
This unit, be sure to complete all tasks listed below. To complete a task, place an `x` between the brackets.
-- [ ] In `planning/wireframes.md`: add wireframes for at least three pages in your web app
-- [ ] In `planning/entity_relationship_diagram.md`: add the entity relationship diagram you developed for your database
-- [ ] Prepare your three-minute pitch presentation, to be presented during Unit 7 (the next unit)
- - [ ] You do **not** need to submit any materials in advance of your pitch
-- [ ] In this document, complete the **Reflection** section below
+- [X] In `planning/wireframes.md`: add wireframes for at least three pages in your web app
+- [X] In `planning/entity_relationship_diagram.md`: add the entity relationship diagram you developed for your database
+- [X] Prepare your three-minute pitch presentation, to be presented during Unit 7 (the next unit)
+ - [X] You do **not** need to submit any materials in advance of your pitch
+- [X] In this document, complete the **Reflection** section below
## Reflection
### 1. What went well during this unit?
-[ππΎππΎππΎ your answer here]
+Designing many to many and one to many relationship for the database went really well.
### 2. What were some challenges your group faced in this unit?
-[ππΎππΎππΎ your answer here]
+Designing Wireframe and learning how to use Figma was challenging.
### 3. What additional support will you need in upcoming units as you continue to work on your final project?
-[ππΎππΎππΎ your answer here]
+We would need feeback on our databse schema.
diff --git a/milestones/milestone3.md b/milestones/milestone3.md
index 74f5aa99a..8f8924bcb 100644
--- a/milestones/milestone3.md
+++ b/milestones/milestone3.md
@@ -23,11 +23,7 @@ You will need to reference the GitHub Project Management guide in the course por
[ππΎππΎππΎ your answer here]
-### 2. What were some challenges your group faced in this unit?
-
-[ππΎππΎππΎ your answer here]
-
-### Did you finish all of your tasks in your sprint plan for this week? If you did not finish all of the planned tasks, how would you prioritize the remaining tasks on your list?
+### 2. What were some challenges your group faced on your list?
[ππΎππΎππΎ your answer here]
diff --git a/planning/entity_relationship_diagram.md b/planning/entity_relationship_diagram.md
index 12c25f62c..9c4641d0d 100644
--- a/planning/entity_relationship_diagram.md
+++ b/planning/entity_relationship_diagram.md
@@ -1,17 +1,42 @@
# Entity Relationship Diagram
-Reference the Creating an Entity Relationship Diagram final project guide in the course portal for more information about how to complete this deliverable.
## Create the List of Tables
-[ππΎππΎππΎ List each table in your diagram]
+| User | Type | Description |
+|-------------|------|-------------|
+| id | integer | primary key |
+| name | text | name of the user |
+| email | text | email of the user |
+| username |text | username of the user |
+| password | text | password of the user |
-## Add the Entity Relationship Diagram
-[ππΎππΎππΎ Include an image or images of the diagram below. You may also wish to use the following markdown syntax to outline each table, as per your preference.]
+| Game | Type | Description |
+|-------------|------|-------------|
+| id | integer | primary key |
+| name | text | name of the Game |
+| Description | text | Description of the Game |
+| Rating |text | Rating of the Game |
-| Column Name | Type | Description |
+| Genre | Type | Description |
|-------------|------|-------------|
| id | integer | primary key |
-| name | text | name of the shoe model |
-| ... | ... | ... |
+| name | text | name of the Game |
+| Game_id | integer | Foreign key |
+
+
+| Platform | Type | Description |
+|-------------|------|-------------|
+| id | integer | primary key |
+| name | text | Platform of the Game |
+
+
+| GamePlatform | Type | Description |
+|-------------|------|-------------|
+| Game_id | integer | Foreign key |
+| platform_id | integer | Foreign key |
+
+## Add the Entity Relationship Diagram
+
+
\ No newline at end of file
diff --git a/planning/user_stories.md b/planning/user_stories.md
index 1e55ecbcd..bae830f99 100644
--- a/planning/user_stories.md
+++ b/planning/user_stories.md
@@ -1,13 +1,23 @@
# User Stories
-Reference the Writing User Stories final project guide in the course portal for more information about how to complete each of the sections below.
+As you plan, it's tempting to jump straight into thinking in terms of implementation: what cool features you'll build and what technologies you will use to achieve your vision. However, starting out this way narrows your thinking about the design of your app and limit its possibilities. You'll need to get coding eventually, but it's important to remember: technology exists to solve problems for people. The balance between design and implementation will be a give and take. Sometimes you will have to make compromises due to technical and time constraints. However, the implementation should always serve the design, not the other way around.
-## Outline User Roles
+This guide will give you an overview of one common technique for designing technology that's actually useful: writing user stories. User stories are short, straightforward descriptions of an app's functionality expressed from the perspective of the end user. By focusing on users' needs and experiences, user stories help developers prioritize features, create more user-centered products, and ultimately build technology that truly benefits its users.
-[ππΎππΎππΎ Include at least at least 1, but no more than 3, user roles.]
+## User Roles
-## Draft User Stories
+1. Regular User : A use who can search games, view details.Basic usage.
+2. Registered User : Same as regular + can create account, save favorites, get recommendations, like games etc.
-[ππΎππΎππΎ Include at least at least 10 user stories in this format:]
+## User Stories
-1. As a [user role], I want to [what], so that [why].
+1. As a user I want to be able to search for games by title, genre, platform, etc. so I can easily find new games to play.
+2. As a user I want the ability to create an account and log in so I can save games to a favorites list.
+3. As a user I want to be able to sort and filter searches by criteria like platform, genre, and rating so I can customize results.
+4. As a user I want to view descriptions, images, videos, and other details about a game so I can learn more before playing.
+5. As a user I want the interface to be intuitive and easy to navigate so I can use the app with minimal effort.
+6. As a user I want the app to have a responsive design that adapts across devices like mobile, tablet, desktop
+7. As a user I want my account information and data to be kept private and secure.
+8. As a user I want the app to load quickly and be stable so I can seamlessly discover new games.
+9. As a user, I want to be able to easily view new and upcoming game releases so I can stay up-to-date on what's coming out.
+10. As a user, I want the option to subscribe to an email newsletter so I can receive regular updates about new games and content.
diff --git a/planning/wireframes.md b/planning/wireframes.md
index fbcd15a0c..9ccb079df 100644
--- a/planning/wireframes.md
+++ b/planning/wireframes.md
@@ -1,21 +1,25 @@
# Wireframes
-Reference the Creating an Entity Relationship Diagram final project guide in the course portal for more information about how to complete this deliverable.
## List of Pages
-[ππΎππΎππΎ List the pages you expect to have in your app, with a β next to pages you have wireframed]
+
+
Profileβ
+
Home Pageβ
+
Landing Pageβ
+
Login/Signup Page
+
About Us
+
-## Wireframe 1: [page title]
+## Wireframe 1: Home Page
-[ππΎππΎππΎ include wireframe 1]
+
-## Wireframe 2: [page title]
+## Wireframe 2: Profile Page
-[ππΎππΎππΎ include wireframe 2]
+
-## Wireframe 3: [page title]
+## Wireframe 3: Landing Page
-[ππΎππΎππΎ include wireframe 3]
+
-[ππΎππΎππΎ include more wireframes as desired]
diff --git a/server/.env b/server/.env
new file mode 100644
index 000000000..4396e46a6
--- /dev/null
+++ b/server/.env
@@ -0,0 +1,5 @@
+DB_USER=your_username
+DB_PASSWORD=your_password
+DB_HOST=localhost
+DB_PORT=5432
+DB_DATABASE=your_database
\ No newline at end of file
diff --git a/server/config/database.js b/server/config/database.js
new file mode 100644
index 000000000..d0caed340
--- /dev/null
+++ b/server/config/database.js
@@ -0,0 +1,11 @@
+import pg from 'pg'
+
+const config = {
+ user: process.env.PGUSER,
+ password: process.env.PGPASSWORD,
+ database: process.env.PGDATABASE,
+ host: process.env.PGHOST,
+ port: process.env.PGPORT
+}
+
+export const pool = new pg.Pool(config)
\ No newline at end of file
diff --git a/server/config/dotenv.js b/server/config/dotenv.js
new file mode 100644
index 000000000..4a88978e3
--- /dev/null
+++ b/server/config/dotenv.js
@@ -0,0 +1,3 @@
+import dotenv from 'dotenv'
+
+dotenv.config({ path: '../.env' })
\ No newline at end of file
diff --git a/server/config/reset.js b/server/config/reset.js
new file mode 100644
index 000000000..58d200029
--- /dev/null
+++ b/server/config/reset.js
@@ -0,0 +1,56 @@
+import { pool } from '../config/database.js';
+import '../config/dotenv.js';
+import gamesData from '../data/games.js';
+
+const createGamesTable = async () => {
+ const createTableQuery = `
+ DROP TABLE IF EXISTS games;
+
+ CREATE TABLE IF NOT EXISTS games (
+ id SERIAL PRIMARY KEY,
+ title VARCHAR(255) NOT NULL,
+ developer VARCHAR(255) NOT NULL,
+ publisher VARCHAR(255) NOT NULL,
+ release_date DATE NOT NULL,
+ genre VARCHAR(50) NOT NULL,
+ platform VARCHAR(50) NOT NULL,
+ price NUMERIC(6,2) NOT NULL
+ )
+ `;
+
+ try {
+ await pool.query(createTableQuery);
+ console.log('π Games table created successfully');
+ } catch (err) {
+ console.error('β οΈ Error creating games table', err);
+ }
+};
+
+const seedGamesTable = async () => {
+ await createGamesTable();
+
+ gamesData.forEach((game) => {
+ const insertQuery = {
+ text: 'INSERT INTO games (title, developer, publisher, release_date, genre, platform, price) VALUES ($1, $2, $3, $4, $5, $6, $7)',
+ values: [
+ game.title,
+ game.developer,
+ game.publisher,
+ new Date(game.releaseDate),
+ game.genre,
+ game.platform,
+ game.price
+ ]
+ };
+
+ pool.query(insertQuery.text, insertQuery.values, (err, res) => {
+ if (err) {
+ console.error('β οΈ Error inserting game', err);
+ } else {
+ console.log(`β ${game.title} added successfully`);
+ }
+ });
+ });
+};
+
+seedGamesTable();
diff --git a/server/controllers/games.js b/server/controllers/games.js
new file mode 100644
index 000000000..e145cd2b6
--- /dev/null
+++ b/server/controllers/games.js
@@ -0,0 +1,60 @@
+import pool from '../config/database.js';
+
+const getAllGames = async (req, res) => {
+ try {
+ const results = await pool.query('SELECT * FROM games');
+ res.status(200).json(results.rows);
+ } catch (err) {
+ res.status(500).send(err.message);
+ }
+};
+
+const getGameById = async (req, res) => {
+ try {
+ const { id } = req.params;
+ const results = await pool.query('SELECT * FROM games WHERE id = $1', [id]);
+ if (results.rows.length === 0) {
+ return res.status(404).json({ message: "Game not found" });
+ }
+ res.status(200).json(results.rows[0]);
+ } catch (err) {
+ res.status(500).send(err.message);
+ }
+};
+const createGame = async (req, res) => {
+ try {
+ const { title, developer, publisher, release_date, genre, platform, price } = req.body;
+ const results = await pool.query('INSERT INTO games (title, developer, publisher, release_date, genre, platform, price) VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING *', [title, developer, publisher, release_date, genre, platform, price]);
+ res.status(201).json(results.rows[0]);
+ } catch (err) {
+ res.status(500).send(err.message);
+ }
+};
+
+const updateGame = async (req, res) => {
+ try {
+ const { id } = req.params;
+ const { title, developer, publisher, release_date, genre, platform, price } = req.body;
+ const results = await pool.query('UPDATE games SET title = $1, developer = $2, publisher = $3, release_date = $4, genre = $5, platform = $6, price = $7 WHERE id = $8 RETURNING *', [title, developer, publisher, release_date, genre, platform, price, id]);
+ res.status(200).json(results.rows[0]);
+ } catch (err) {
+ res.status(500).send(err.message);
+ }
+};
+const deleteGame = async (req, res) => {
+ try {
+ const { id } = req.params;
+ await pool.query('DELETE FROM games WHERE id = $1', [id]);
+ res.status(200).json({ message: "Game deleted" });
+ } catch (err) {
+ res.status(500).send(err.message);
+ }
+};
+
+export {
+ getAllGames,
+ getGameById,
+ createGame,
+ updateGame,
+ deleteGame
+}
diff --git a/server/data/games.js b/server/data/games.js
new file mode 100644
index 000000000..4ec8d714a
--- /dev/null
+++ b/server/data/games.js
@@ -0,0 +1,33 @@
+const gamesData = [
+ {
+ title: 'The Legend of Zelda: Breath of the Wild',
+ developer: 'Nintendo EPD',
+ publisher: 'Nintendo',
+ releaseDate: '2017-03-03',
+ genre: 'Action-adventure',
+ platform: 'Nintendo Switch',
+ price: 59.99
+ },
+ {
+ title: 'God of War',
+ developer: 'Santa Monica Studio',
+ publisher: 'Sony Interactive Entertainment',
+ releaseDate: '2018-04-20',
+ genre: 'Action-adventure',
+ platform: 'PlayStation 4',
+ price: 39.99
+ },
+ {
+ title: 'Red Dead Redemption 2',
+ developer: 'Rockstar Games',
+ publisher: 'Rockstar Games',
+ releaseDate: '2018-10-26',
+ genre: 'Action-adventure',
+ platform: 'Multiplatform',
+ price: 59.99
+ },
+
+ ];
+
+ export default gamesData;
+
\ No newline at end of file
diff --git a/server/routes/games.js b/server/routes/games.js
new file mode 100644
index 000000000..1ac728413
--- /dev/null
+++ b/server/routes/games.js
@@ -0,0 +1,14 @@
+import express from 'express';
+
+import GamesContoller from '../controllers/gamesController.js';
+
+
+const router = express.Router();
+
+router.get('/', GamesContoller.getAllGames);
+router.get('/:id', GamesContoller.getGameById);
+router.post('/', GamesContoller.createGame);
+router.put('/:id', GamesContoller.updateGame);
+router.delete('/:id', GamesContoller.deleteGame);
+
+export default router;
\ No newline at end of file
diff --git a/server/server.js b/server/server.js
new file mode 100644
index 000000000..d4aaa4429
--- /dev/null
+++ b/server/server.js
@@ -0,0 +1,32 @@
+import express from "express";
+import path from "path";
+import favicon from "serve-favicon";
+import dotenv from "dotenv";
+import cors from "cors";
+
+import gamesRouter from "../routes/games.js";
+dotenv.config();
+
+const PORT = process.env.PORT || 3000;
+const app = express();
+
+app.use(cors());
+app.use(express.json());
+
+// if (process.env.NODE_ENV === "development") {
+// app.use(favicon(path.resolve("../", "client", "public", "party.png")));
+// } else if (process.env.NODE_ENV === "production") {
+// app.use(favicon(path.resolve("public", "party.png")));
+// app.use(express.static("public"));
+// }
+
+
+app.use("/games", gamesRouter);
+
+// if (process.env.NODE_ENV === "production") {
+// app.get("/*", (_, res) => res.sendFile(path.resolve("public", "index.html")));
+// }
+
+app.listen(PORT, () => {
+ console.log(`Server listening on http://localhost:${PORT}`);
+});