DEV Community

Patrick Mwangi
Patrick Mwangi

Posted on

Tabiya Hackathon Project

AI Powered job seeking app

File Structure for Backend and Frontend:

/hackathon-project
├── backend
│   ├── app.py
│   ├── config.py
│   ├── models.py
│   ├── routes.py
│   ├── services
│   │   ├── nlp_service.py
│   │   ├── auth_service.py
│   │   └── chatbot_service.py
│   ├── database
│   │   └── db_init.py
│   ├── requirements.txt
└── frontend
    ├── public
    │   └── index.html
    ├── src
    │   ├── components
    │   │   ├── JobMatch.js
    │   │   ├── ChatBot.js
    │   │   └── Dashboard.js
    │   ├── App.js
    │   ├── index.js
    └── package.json
Enter fullscreen mode Exit fullscreen mode

Backend Code (Flask + Python)

app.py

from flask import Flask
from routes import auth_blueprint, nlp_blueprint
from database.db_init.py import init_db

app = Flask(__name__)

# Initialize database
init_db(app)

# Register routes
app.register_blueprint(auth_blueprint)
app.register_blueprint(nlp_blueprint)

if __name__ == '__main__':
    app.run(debug=True)
Enter fullscreen mode Exit fullscreen mode

config.py

import os

class Config:
    SECRET_KEY = os.environ.get('SECRET_KEY') or 'supersecretkey'
    SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or 'sqlite:///site.db'
    SQLALCHEMY_TRACK_MODIFICATIONS = False
Enter fullscreen mode Exit fullscreen mode

models.py

from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(150), unique=True, nullable=False)
    email = db.Column(db.String(150), unique=True, nullable=False)
    password = db.Column(db.String(60), nullable=False)

class Job(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(150), nullable=False)
    description = db.Column(db.Text, nullable=False)
Enter fullscreen mode Exit fullscreen mode

routes.py

from flask import Blueprint, jsonify, request
from services.nlp_service import classify_job
from services.auth_service import login_user

auth_blueprint = Blueprint('auth', __name__)
nlp_blueprint = Blueprint('nlp', __name__)

@auth_blueprint.route('/login', methods=['POST'])
def login():
    data = request.json
    return login_user(data['username'], data['password'])

@nlp_blueprint.route('/match', methods=['POST'])
def match():
    job_desc = request.json.get('description')
    return classify_job(job_desc)
Enter fullscreen mode Exit fullscreen mode

nlp_service.py

import requests

def classify_job(description):
    url = 'https://tabiya-api.com/classify'
    response = requests.post(url, json={'description': description})
    return response.json()
Enter fullscreen mode Exit fullscreen mode

auth_service.py

from models import User

def login_user(username, password):
    user = User.query.filter_by(username=username).first()
    if user and user.password == password:
        return {'message': 'Login successful'}, 200
    return {'message': 'Invalid credentials'}, 401
Enter fullscreen mode Exit fullscreen mode

database/db_init.py

from flask_sqlalchemy import SQLAlchemy
from models import db

def init_db(app):
    app.config.from_object('config.Config')
    db.init_app(app)
    with app.app_context():
        db.create_all()
Enter fullscreen mode Exit fullscreen mode

requirements.txt

Flask==2.0.1
Flask-SQLAlchemy==2.5.1
requests==2.26.0
Enter fullscreen mode Exit fullscreen mode

Frontend Code (React + JavaScript)

src/App.js

import React from 'react';
import JobMatch from './components/JobMatch';
import ChatBot from './components/ChatBot';
import Dashboard from './components/Dashboard';

function App() {
  return (
    <div>
      <h1>Hackathon Project</h1>
      <JobMatch />
      <ChatBot />
      <Dashboard />
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

src/components/JobMatch.js

import React, { useState } from 'react';
import axios from 'axios';

const JobMatch = () => {
  const [description, setDescription] = useState('');
  const [result, setResult] = useState(null);

  const handleSubmit = async () => {
    const response = await axios.post('/match', { description });
    setResult(response.data);
  };

  return (
    <div>
      <h2>Job Matcher</h2>
      <textarea onChange={(e) => setDescription(e.target.value)} />
      <button onClick={handleSubmit}>Match Job</button>
      {result && <div>{JSON.stringify(result)}</div>}
    </div>
  );
};

export default JobMatch;
Enter fullscreen mode Exit fullscreen mode

src/components/ChatBot.js

import React from 'react';

const ChatBot = () => {
  return (
    <div>
      <h2>AI Chatbot</h2>
      <p>Chatbot will be implemented here...</p>
    </div>
  );
};

export default ChatBot;
Enter fullscreen mode Exit fullscreen mode

src/components/Dashboard.js

import React from 'react';

const Dashboard = () => {
  return (
    <div>
      <h2>Entrepreneurship Dashboard</h2>
      <p>Track your progress and business plans here...</p>
    </div>
  );
};

export default Dashboard;
Enter fullscreen mode Exit fullscreen mode

Run Instructions:

  1. Backend:

    • Install dependencies: pip install -r requirements.txt.
    • Start the server: python app.py.
  2. Frontend:

    • Navigate to the frontend folder.
    • Install dependencies: npm install.
    • Start the frontend: npm start.

Updated Backend with Error Handling and Real-time Job Matching

1. Error Handling in Backend Services

Let's first add proper error handling to the backend services, ensuring the app returns meaningful messages instead of crashing on exceptions.

services/nlp_service.py (Error handling added)

import requests

def classify_job(description):
    try:
        url = 'https://tabiya-api.com/classify'
        response = requests.post(url, json={'description': description})
        response.raise_for_status()  # Raises HTTPError for bad responses
        return response.json()
    except requests.exceptions.HTTPError as http_err:
        return {"error": f"HTTP error occurred: {http_err}"}, 500
    except Exception as err:
        return {"error": f"An error occurred: {err}"}, 500
Enter fullscreen mode Exit fullscreen mode

auth_service.py (Error handling added)

from models import User

def login_user(username, password):
    try:
        user = User.query.filter_by(username=username).first()
        if user and user.password == password:
            return {'message': 'Login successful'}, 200
        return {'message': 'Invalid credentials'}, 401
    except Exception as err:
        return {"error": f"An error occurred: {err}"}, 500
Enter fullscreen mode Exit fullscreen mode

2. Real-time Job Matching with WebSockets

To implement real-time job matching, we can use Flask-SocketIO on the backend and socket.io on the frontend for real-time communication.

Add WebSocket Support to Backend

Install Flask-SocketIO:
pip install flask-socketio
Enter fullscreen mode Exit fullscreen mode

Update app.py to support SocketIO:

from flask import Flask
from flask_socketio import SocketIO, emit
from routes import auth_blueprint, nlp_blueprint
from database.db_init import init_db

app = Flask(__name__)
socketio = SocketIO(app, cors_allowed_origins="*")  # Enable WebSockets

# Initialize database
init_db(app)

# Register routes
app.register_blueprint(auth_blueprint)
app.register_blueprint(nlp_blueprint)

# Real-time job matching with WebSockets
@socketio.on('match_job')
def handle_job_matching(data):
    job_desc = data.get('description')
    if not job_desc:
        emit('job_match_result', {'error': 'Job description is required'}, broadcast=True)
        return
    result = classify_job(job_desc)
    emit('job_match_result', result, broadcast=True)  # Broadcast result

if __name__ == '__main__':
    socketio.run(app, debug=True)
Enter fullscreen mode Exit fullscreen mode

3. Frontend Real-time Integration

Install socket.io-client for real-time communication:
npm install socket.io-client
Enter fullscreen mode Exit fullscreen mode

Update JobMatch.js for real-time communication:

import React, { useState, useEffect } from 'react';
import io from 'socket.io-client';

const socket = io('http://localhost:5000');  // Backend WebSocket URL

const JobMatch = () => {
  const [description, setDescription] = useState('');
  const [result, setResult] = useState(null);

  useEffect(() => {
    // Listen for real-time job match results from server
    socket.on('job_match_result', (data) => {
      setResult(data);
    });
  }, []);

  const handleSubmit = () => {
    // Emit job description to backend for real-time matching
    socket.emit('match_job', { description });
  };

  return (
    <div>
      <h2>Real-time Job Matcher</h2>
      <textarea onChange={(e) => setDescription(e.target.value)} />
      <button onClick={handleSubmit}>Match Job</button>
      {result && <div>{JSON.stringify(result)}</div>}
    </div>
  );
};

export default JobMatch;
Enter fullscreen mode Exit fullscreen mode

Updated Structure:

/hackathon-project
├── backend
│   ├── app.py                  # Flask backend with SocketIO
│   ├── config.py               # Configs for database, secrets
│   ├── models.py               # Database models
│   ├── routes.py               # API routes
│   ├── services
│   │   ├── nlp_service.py      # NLP matching logic with error handling
│   │   ├── auth_service.py     # Authentication logic with error handling
│   ├── database
│   │   └── db_init.py          # Database initialization
│   ├── requirements.txt        # Backend dependencies
└── frontend
    ├── src
    │   ├── components
    │   │   ├── JobMatch.js     # Frontend with real-time job matching
    │   └── App.js              # Main frontend app
    ├── package.json            # Frontend dependencies
Enter fullscreen mode Exit fullscreen mode

Instructions to Run:

  1. Backend:

    • Install dependencies: pip install -r requirements.txt
    • Run the backend: python app.py (now with WebSockets support)
  2. Frontend:

    • Navigate to the frontend folder.
    • Install dependencies: npm install.
    • Run the frontend: npm start.

Top comments (0)