Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
9f9150c
Inserted mock data
Yurika-Kan Dec 3, 2025
fedb4fc
Renamed database
Yurika-Kan Dec 3, 2025
c02886b
Restored env template
Yurika-Kan Dec 3, 2025
14469b3
Merge pull request #1 from londonjones4189/sql
Yurika-Kan Dec 3, 2025
45426b3
admin routes
micahcheng Dec 4, 2025
1278966
Designed and uploaded logo
londonjones4189 Dec 4, 2025
af032d8
Added logo without tagline
londonjones4189 Dec 4, 2025
4b159bd
Merge pull request #2 from londonjones4189/feature/logo2
londonjones4189 Dec 4, 2025
f3148fc
Added Data Analyst blueprint file
londonjones4189 Dec 4, 2025
b1b2ab4
Connected data analyst routes to mock data
londonjones4189 Dec 4, 2025
a80e856
Merge pull request #3 from londonjones4189/feature/DataAnalystBlueprint
londonjones4189 Dec 5, 2025
a0b04ac
wip: swapper files
zuhazana1 Dec 5, 2025
c37497a
stuff
micahcheng Dec 5, 2025
2f92fbf
rebase lalala
micahcheng Dec 5, 2025
ea25e40
Fix MySQL authentication and implement admin endpoints with foreign k…
micahcheng Dec 5, 2025
5720e63
Merge pull request #4 from londonjones4189/AdminFlaskBlueprint
micahcheng Dec 5, 2025
c47f27b
fixed more
micahcheng Dec 5, 2025
35bb4ec
Merge pull request #5 from londonjones4189/AdminFlaskBlueprint
micahcheng Dec 5, 2025
05b088a
deleted some stuff
micahcheng Dec 5, 2025
ff7c661
Merge pull request #6 from londonjones4189/AdminFlaskBlueprint
micahcheng Dec 5, 2025
1108662
first three quiries
zuhazana1 Dec 5, 2025
f70e249
made code more consistent
micahcheng Dec 6, 2025
aa7d4e2
consistency is key
micahcheng Dec 6, 2025
dbe7ad9
Merge pull request #7 from londonjones4189/AdminFlaskBlueprint
micahcheng Dec 6, 2025
19a9e68
added streamlit+nav+home connections?
micahcheng Dec 6, 2025
82ed3c5
Merge pull request #8 from londonjones4189/AdminFlaskBlueprint
micahcheng Dec 6, 2025
220532b
Merge pull request #10 from londonjones4189/features/swapper
zuhazana1 Dec 6, 2025
1bfa1cd
apis
micahcheng Dec 6, 2025
93d8eae
Merge branch 'main' of https://github.com/londonjones4189/FitHub into…
micahcheng Dec 6, 2025
ef7a498
Fixed main with Docker + Cleaned files
Yurika-Kan Dec 6, 2025
572e145
Merge branch 'main' of https://github.com/londonjones4189/FitHub
Yurika-Kan Dec 6, 2025
a4d1d89
Created Streamlit Homepage
londonjones4189 Dec 6, 2025
3de7ac5
admin home stuff
micahcheng Dec 6, 2025
6c40a7c
Merge branch 'main' of https://github.com/londonjones4189/FitHub into…
micahcheng Dec 6, 2025
031a84f
Tested & Patched Admin Routes
Yurika-Kan Dec 6, 2025
a1903f4
Merge pull request #11 from londonjones4189/feature/Homepage2
Yurika-Kan Dec 6, 2025
4bfd1ff
Update api/backend/admin/admin_routes.py
Yurika-Kan Dec 6, 2025
aa67ecc
Cleaned
Yurika-Kan Dec 6, 2025
409ef0a
Merge branch 'patch-routes' of https://github.com/londonjones4189/Fit…
Yurika-Kan Dec 6, 2025
413c4ec
Merge pull request #12 from londonjones4189/patch-routes
londonjones4189 Dec 6, 2025
9148c5b
corrected endpoints for ui
micahcheng Dec 6, 2025
b60b865
Merge branch 'main' of https://github.com/londonjones4189/FitHub into…
micahcheng Dec 6, 2025
4132c02
connected all routes
micahcheng Dec 6, 2025
be58fae
added styling
micahcheng Dec 7, 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
8 changes: 8 additions & 0 deletions .idea/.gitignore

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

12 changes: 12 additions & 0 deletions .idea/FitHub.iml

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

6 changes: 6 additions & 0 deletions .idea/inspectionProfiles/profiles_settings.xml

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

7 changes: 7 additions & 0 deletions .idea/misc.xml

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

8 changes: 8 additions & 0 deletions .idea/modules.xml

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

6 changes: 6 additions & 0 deletions .idea/vcs.xml

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

27 changes: 27 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
FROM python:3.11-slim

WORKDIR /appcode

# downloads
RUN apt-get update && apt-get install -y \
build-essential \
curl \
git \
libfreetype6-dev \
pkg-config \
&& rm -rf /var/lib/apt/lists/*

# RUN mkdir /requirements
# COPY ./src/requirements.txt /requirements/requirements.txt

COPY ./src/requirements.txt .

RUN pip3 install -r requirements.txt

# lists all the packages
RUN ls

EXPOSE 8501

# docker container runs streamlit
CMD ["streamlit", "run", "Home.py", "--server.port=8501", "--server.address=0.0.0.0"]
2 changes: 1 addition & 1 deletion api/.env.template
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ DB_USER=root
DB_HOST=db
DB_PORT=3306
DB_NAME=ngo_db
MYSQL_ROOT_PASSWORD=<put a good password here>
MYSQL_ROOT_PASSWORD=<put a good password here>
3 changes: 1 addition & 2 deletions api/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,4 @@ COPY . .
EXPOSE 4000

# Run Python in unbuffered mode to ensure logs are immediately visible
CMD ["python", "-u", "backend_app.py"]

CMD ["python", "-u", "backend_app.py"]
10 changes: 10 additions & 0 deletions api/backend/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#------------------------------------------------------------
# This file creates a shared DB connection resource
#------------------------------------------------------------
from flaskext.mysql import MySQL
from pymysql import cursors


# the parameter instructs the connection to return data
# as a dictionary object.
db = MySQL(cursorclass=cursors.DictCursor)
Empty file added api/backend/admin/__init__.py
Empty file.
165 changes: 165 additions & 0 deletions api/backend/admin/admin_routes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
from flask import Blueprint, request, jsonify, make_response
from backend.db_connection import db

admin = Blueprint('admin', __name__)

# USER STORY 1 — View unresolved reports
@admin.route('/reports/pending', methods=['GET'])
def get_pending_reports():
cursor = db.get_db().cursor()
cursor.execute("""
SELECT ReportID, Severity, Note, ReportedItem
FROM Reports
WHERE Resolved = 0;
""")
data = cursor.fetchall()

the_response = make_response(jsonify(data))
the_response.status_code = 200
return the_response


# USER STORY 1 — Resolve a report
@admin.route('/reports/<int:report_id>/resolve', methods=['PUT'])
def resolve_report(report_id):
cursor = db.get_db().cursor()
cursor.execute("""
UPDATE Reports
SET Resolved = 1, ResolvedAt = NOW()
WHERE ReportID = %s;
""", (report_id,))

db.get_db().commit()

the_response = make_response(jsonify({"message": "Report resolved"}))
the_response.status_code = 200
return the_response


# USER STORY 2 — Update user role
@admin.route('/users/<int:user_id>/role', methods=['PUT'])
def update_user_role(user_id):
new_role = request.json.get("role")

cursor = db.get_db().cursor()
cursor.execute("""
UPDATE Users
SET Role = %s
WHERE UserID = %s;
""", (new_role, user_id))

db.get_db().commit()

the_response = make_response(jsonify({"message": "User role updated"}))
the_response.status_code = 200
return the_response


# USER STORY 3 — Deactivate user
@admin.route('/users/<int:user_id>/deactivate', methods=['PUT'])
def deactivate_user(user_id):
cursor = db.get_db().cursor()
cursor.execute("""
UPDATE Users
SET IsActive = 0
WHERE UserID = %s;
""", (user_id,))

db.get_db().commit()

the_response = make_response(jsonify({"message": "User deactivated"}))
the_response.status_code = 200
return the_response

# USER STORY 4 — Create announcement
@admin.route('/announcements', methods=['POST'])
def create_announcement():
data = request.json
announcer = data.get("announcer_id")
message = data.get("message")

cursor = db.get_db().cursor()

cursor.execute("""
INSERT INTO Announcements (AnnouncerID, Message, AnnouncedAt)
VALUES (%s, %s, NOW());
""", (announcer, message))

announcement_id = cursor.lastrowid

cursor.execute("""
INSERT INTO AnnouncementsReceived (AnnouncementID, UserID)
SELECT %s, UserID FROM Users WHERE IsActive = 1;
""", (announcement_id,))

db.get_db().commit()

the_response = make_response(jsonify({"message": "Announcement created"}))
the_response.status_code = 201
return the_response


# USER STORY 5 — Analytics summary
@admin.route('/analytics/summary', methods=['GET'])
def analytics_summary():
cursor = db.get_db().cursor()
cursor.execute("""
SELECT
(SELECT COUNT(*) FROM Users) AS TotalUsers,
(SELECT COUNT(*) FROM Items) AS TotalListings,
(SELECT COUNT(*) FROM Reports WHERE Resolved = 0) AS OpenReports;
""")
data = cursor.fetchall()

the_response = make_response(jsonify(data))
the_response.status_code = 200
return the_response


# USER STORY 6 — Delete duplicate items
@admin.route('/items/duplicates', methods=['DELETE'])
def delete_duplicate_items():
cursor = db.get_db().cursor()
cursor.execute("""
DELETE i FROM Items i
JOIN (
SELECT Title, OwnerID, MIN(ItemID) AS KeepID
FROM Items
GROUP BY Title, OwnerID
) base
ON i.Title = base.Title
AND i.OwnerID = base.OwnerID
AND i.ItemID != base.KeepID;
""")

db.get_db().commit()

the_response = make_response(jsonify({"message": "Duplicate items removed"}))
the_response.status_code = 200
return the_response


# USER STORY 6 + 1 — Delete specific item
@admin.route('/items/<int:item_id>', methods=['DELETE'])
def delete_item(item_id):
try:
cursor = db.get_db().cursor()

cursor.execute("DELETE FROM Images WHERE ItemID = %s;", (item_id,))
cursor.execute("DELETE FROM ItemTags WHERE ItemID = %s;", (item_id,))
cursor.execute("DELETE FROM OrderItems WHERE ItemID = %s;", (item_id,))
cursor.execute("DELETE FROM Reports WHERE ReportedItem = %s;", (item_id,))
cursor.execute("DELETE FROM Items WHERE ItemID = %s;", (item_id,))

db.get_db().commit()

the_response = make_response(jsonify({"message": "Item removed"}))
the_response.status_code = 200
return the_response

except Exception as e:
db.get_db().rollback()

the_response = make_response(jsonify({"error": str(e)}))
the_response.status_code = 500
return the_response
10 changes: 10 additions & 0 deletions api/backend/dataAnalysts/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#------------------------------------------------------------
# This file creates a shared DB connection resource
#------------------------------------------------------------
from flaskext.mysql import MySQL
from pymysql import cursors


# the parameter instructs the connection to return data
# as a dictionary object.
db = MySQL(cursorclass=cursors.DictCursor)
Loading