diff --git a/backend-api/app/database.py b/backend-api/app/database.py index d29c257..7e36f8c 100644 --- a/backend-api/app/database.py +++ b/backend-api/app/database.py @@ -44,12 +44,12 @@ class ProfileAutofillAnswer(db.Model): class Job(db.Model): __tablename__ = 'Job' JobID = db.Column(db.Integer, primary_key=True, autoincrement=True) - Salary = db.Column(db.Numeric(10,2)) + Salary = db.Column(db.String(50)) Type = db.Column(db.String(50)) Keywords = db.Column(db.Text) Description = db.Column(db.Text) Date = db.Column(db.Date, server_default=db.func.current_date()) - CompanyName = db.Column(db.String(50)) + CompanyName = db.Column(db.String(100)) UserID = db.Column(db.Integer, ForeignKey('Users.UserID', ondelete='SET NULL')) applications = relationship('AppliedTo', backref='job', cascade="all, delete") bookmarks = relationship('Bookmark', backref='job', cascade="all, delete") diff --git a/backend-api/app/routes.py b/backend-api/app/routes.py index 2572566..d3e96f2 100644 --- a/backend-api/app/routes.py +++ b/backend-api/app/routes.py @@ -180,6 +180,7 @@ def delete_profile(profile_id): @bp.route('/jobs', methods=['POST']) def create_job(): + print("Job creation route hit") data = request.get_json() user_id = data.get('UserID') user = User.query.get_or_404(user_id) @@ -265,15 +266,18 @@ def create_application(): 'FollowUpDeadline': application.FollowUpDeadline }), 201 -@bp.route('/applications/', methods=['GET']) -def get_application(application_id): - application = AppliedTo.query.get_or_404(application_id) - return jsonify({ - 'ApplicationID': application.ApplicationID, - 'Status': application.Status, - 'FollowUpDeadline': application.FollowUpDeadline, - 'Note': application.Note - }) +@bp.route('/applications/user/', methods=['GET']) +def get_applications_for_user(user_id): + applications = db.session.query(AppliedTo).filter(AppliedTo.UserID == user_id).all() + return jsonify([ + { + 'ApplicationID': application.ApplicationID, + 'Status': application.Status, + 'FollowUpDeadline': application.FollowUpDeadline, + 'Note': application.Note + } + for application in applications + ]) @bp.route('/applications/', methods=['PUT']) def update_application(application_id): @@ -344,6 +348,11 @@ def create_bookmark(): user = User.query.get_or_404(user_id) job = Job.query.get_or_404(job_id) + # Check if the bookmark already exists + existing_bookmark = Bookmark.query.filter_by(UserID=user.UserID, JobID=job.JobID).first() + if existing_bookmark: + return jsonify({"message": "Bookmark already exists"}), 200 + bookmark = Bookmark( UserID=user.UserID, JobID=job.JobID, @@ -365,9 +374,8 @@ def get_bookmarks(user_id): bookmark_list = [] for bookmark, job in bookmarks: bookmark_list.append({ - 'UserID': bookmark.UserID, 'JobID': bookmark.JobID, - 'Note': bookmark.Note if bookmark.Note else "No note", + 'Note': bookmark.Note or "No note", 'CompanyName': job.CompanyName, 'Type': job.Type }) diff --git a/backend-api/instance/database.db b/backend-api/instance/database.db index f40f221..090fe84 100644 Binary files a/backend-api/instance/database.db and b/backend-api/instance/database.db differ diff --git a/backend-api/run.py b/backend-api/run.py index 35fd1b1..71fd8ad 100644 --- a/backend-api/run.py +++ b/backend-api/run.py @@ -1,20 +1,33 @@ # Runs instance of app from app import create_app -from app.database import db +from app.database import db, User from sqlalchemy import inspect import os app = create_app() +def create_test_user(): + existing = User.query.filter_by(Email="testuser@example.com").first() + if not existing: + user = User( + Name="Test User", + Email="testuser@example.com", + Password="password123" + ) + db.session.add(user) + db.session.commit() + print(f"Test user created with UserID {user.UserID}") + else: + print("Test user already exists.") + if __name__ == '__main__': - # Use the PORT environment variable if defined, otherwise default to 5000. port = int(os.environ.get("PORT", 5000)) - # Creates database tables with app.app_context(): db.create_all() inspector = inspect(db.engine) - print(inspector.get_table_names()) - # Bind to all interfaces to allow external access. + print("Database tables:", inspector.get_table_names()) + create_test_user() + app.run(host='0.0.0.0', port=port, debug=True) \ No newline at end of file diff --git a/frontend/app/pages/Dashboard.tsx b/frontend/app/pages/Dashboard.tsx index c2c54ce..dfa81ad 100644 --- a/frontend/app/pages/Dashboard.tsx +++ b/frontend/app/pages/Dashboard.tsx @@ -38,11 +38,13 @@ export default function Dashboard() { const [error, setError] = useState(null); useEffect(() => { - const fetchNotifications = axios.get(`/api/applied_to/${userId}`); - const fetchBookmarks = axios.get(`/api/bookmarks/${userId}`); - + const fetchNotifications = axios.get(`http://localhost:5000/api/applications/user/${userId}`); + const fetchBookmarks = axios.get(`http://localhost:5000/api/bookmarks/${userId}`); + Promise.all([fetchNotifications, fetchBookmarks]) .then(([notificationsRes, bookmarksRes]) => { + console.log("Fetched applications from API:", notificationsRes.data); // Debugging log + console.log("Fetched bookmarks from API:", bookmarksRes.data); // Debugging log setNotifications(Array.isArray(notificationsRes.data) ? notificationsRes.data : []); setBookmarks(Array.isArray(bookmarksRes.data) ? bookmarksRes.data : []); }) diff --git a/frontend/app/pages/Postings.tsx b/frontend/app/pages/Postings.tsx index 5ce4b25..f5b1438 100644 --- a/frontend/app/pages/Postings.tsx +++ b/frontend/app/pages/Postings.tsx @@ -1,6 +1,7 @@ import { Box, Typography, Card, CardContent, Button, TextField, Grid } from "@mui/material"; import { useState } from "react"; -import jobData from "../../dataset_indeed-scraper_2025-04-29_18-38-42-368.json"; +import axios from "axios"; +import jobData from "../../dataset_indeed-scraper_2025-04-29_18-38-42-368.json"; // Mock job data export default function Postings() { const [filters, setFilters] = useState({ @@ -83,6 +84,44 @@ function JobDetails({ job }: { job: any }) { setShowFullDescription(!showFullDescription); }; + const handleBookmark = () => { + // Step 1: Create the job + axios + .post("http://localhost:5000/api/jobs", { + Salary: job.salary || "Not specified", + Type: job.positionName, + Keywords: job.keywords || "", + Description: job.description, + CompanyName: job.company, + UserID: 1, // Replace with actual user ID + }) + .then((createdJobResponse) => { + console.log("Job created successfully:", createdJobResponse.data); + createBookmark(createdJobResponse.data); + }) + .catch((err) => { + console.error("Failed to create job:", err); + alert("Failed to create job and bookmark."); + }); + + function createBookmark(jobData: any) { + console.log("Creating bookmark for job:", jobData); + axios + .post("http://localhost:5000/api/bookmarks", { + UserID: 1, // Replace with real user ID + JobID: jobData.JobID, // This is the actual JobID from the DB + Note: "Bookmarked from UI", + }) + .then(() => { + alert("Job bookmarked!"); + }) + .catch((err) => { + console.error("Failed to bookmark:", err); + alert("Failed to bookmark job."); + }); + } + }; + return ( @@ -135,6 +174,16 @@ function JobDetails({ job }: { job: any }) { Apply Here + + + );