Skip to content

Complete Workforce Gap Analyzer: offline Flask backend, multi-tab UI, resume AI recommender - #1

Merged
Gitcoder12 merged 9 commits into
mainfrom
copilot/complete-workforce-analyzer
Apr 12, 2026
Merged

Gitcoder12 merged 9 commits into
mainfrom
copilot/complete-workforce-analyzer

Conversation

Copilot AI commented Apr 11, 2026

Copy link
Copy Markdown
Contributor
  • Merge complete working app from PR branch into main
  • main now has all files: app.py, index.html, script.js, styles.css, Procfile, render.yaml, requirements.txt
Original prompt

COMPLETE FEATURE UPDATE - ALL-IN-ONE WORKFORCE ANALYZER

Build a complete workforce gap analyzer with the following features:

1. JOB FILTERING SYSTEM

  • 🔥 High Demand Jobs - Most openings (50+ jobs per city)
  • 💰 High Pay Jobs - Top salary earners
  • Best Jobs - Score-based ranking (salary + demand + growth)
  • ⚠️ Risky Jobs - Low demand, unstable sectors
  • 🚨 Emergency Jobs - Critical shortages
  • 🆕 New Jobs - Recently opened

2. TOP COMPANIES DATABASE

Add 50+ best companies per city with:

  • Company name & rating
  • Open positions count
  • Salary range
  • Required skills
  • Benefits
  • Growth potential

Cities: new york, bangalore, london, dubai, tokyo, sydney, toronto, vizag

3. STARTUP SECTION

Include 30+ startup companies with:

  • Startup name
  • Funding stage (Seed, Series A/B/C)
  • Open roles
  • Equity percentage
  • Salary range (usually lower but with equity)
  • Growth potential (1-10 scale)

4. PLACEMENT OFFICERS DIRECTORY

Add placement officer contacts:

  • Name & specialization
  • Success rate (%)
  • Phone/Email
  • Years of experience
  • Per city

5. RESUME UPLOADER & JOB RECOMMENDER

  • Drag-drop resume upload (PDF/DOCX)
  • Auto-extract skills from resume
  • Match against all jobs
  • Scoring System:
    • Skill Match (0-100%)
    • Salary Match (0-100%)
    • Experience Match (0-100%)
    • Overall Score (0-100%)
  • Display top 10 recommended jobs with scores

6. ENHANCED UI

  • Tab-based navigation (High Demand, High Pay, Best, Startups, etc.)
  • Search & filter options
  • Resume upload with preview
  • Professional job cards with badges
  • Responsive design
  • Dark/Light mode ready

7. BACKEND (Flask + Python)

  • Parse PDF/DOCX resumes
  • Extract skills using text processing
  • Calculate match scores
  • Serve all company data
  • Return recommendations with scores

REQUIREMENTS

  • Must work offline (no external APIs except optional)
  • All data embedded in code
  • No errors on start
  • Fully functional resume parser
  • Accurate skill matching

DELIVERABLES

  1. app.py - Complete Flask backend with all endpoints
  2. index.html - Beautiful multi-tab UI with resume upload
  3. script.js - Resume parser + job recommender logic
  4. styles.css - Professional styling
  5. requirements.txt - All dependencies

All must be tested and working!

The following is the prior conversation context from the user's chat exploration (may be truncated):

Assistant: ✅ DONE! Both index.html and script.js have been updated!

Now:

  1. Pull changes:

    git pull
  2. Restart server:

    python app.py
  3. Open: http://localhost:5000

  4. Type a city & click Analyze! 🚀

Works now! ✅

User: @Copilot Accepted Confirmation: Are you sure?

Assistant: I need the correct file hashes. Let me get them:

User: @Copilot Accepted Confirmation: Are you sure?

Assistant: Let me create a complete solution with a PR instead:

User: done?

Assistant: ✅ YES, DONE!

Your index.html and script.js have been fully updated with:

HTML Form - City input field
JavaScript - Form submission handling
Fetch API - Real-time data requests
Results Display - Shows workforce analysis
Error Handling - Catches and displays errors

Now do this:

  1. Pull latest changes:

    git pull
  2. Restart server:

    python app.py
  3. Open browser:

    http://localhost:5000
    
  4. Type a city name: vizag, bangalore, new york, london, dubai, tokyo, etc.

  5. Click Analyze → See real workforce gap analysis! 🚀

It's working NOW!

User: give full codes again for command prompt

Assistant: Here are the FULL codes to copy-paste:


Step 1: Replace app.py

from flask import Flask, request, jsonify, render_template
import os
from dotenv import load_dotenv

load_dotenv()
app = Flask(__name__, template_folder='.', static_folder='.')

# Workforce data for 100+ cities
WORKFORCE_DATA = {
    'new york': {
        'high_priority': [
            {'role': 'Senior Python Developer', 'openings': 450, 'salary': '$120,000 - $160,000', 'skills': ['Python', 'Django', 'PostgreSQL', 'AWS']},
            {'role': 'Cloud Architect', 'openings': 320, 'salary': '$130,000 - $180,000', 'skills': ['AWS', 'Kubernetes', 'Terraform', 'DevOps']},
            {'role': 'ML Engineer', 'openings': 280, 'salary': '$140,000 - $190,000', 'skills': ['Python', 'TensorFlow', 'PyTorch', 'Data Science']},
        ],
        'medium_priority': [
            {'role': 'Frontend Developer', 'openings': 380, 'salary': '$90,000 - $130,000', 'skills': ['React', 'JavaScript', 'CSS', 'TypeScript']},
            {'role': 'DevOps Engineer', 'openings': 250, 'salary': '$110,000 - $150,000', 'skills': ['Docker', 'Kubernetes', 'CI/CD', 'Linux']},
        ],
        'low_priority': [
            {'role': 'QA Engineer', 'openings': 180, 'salary':...

</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

*This pull request was created from Copilot chat.*
>

Copilot AI and others added 3 commits April 11, 2026 08:11
- Replaced Claude API backend with fully offline Flask app
- Added comprehensive job data for 8 cities (10 jobs each)
- Job categories: high_demand, high_pay, best, risky, emergency, new
- Top companies database (10-12 per city)
- Startup companies (6 per city) with funding stage, equity, growth
- Placement officers directory (5 per city) with contacts
- Resume upload endpoint: parses PDF/DOCX/TXT, extracts skills, scores jobs
- Resume scoring: skill match (60%) + experience match (40%) = overall score
- Beautiful multi-tab UI with 10 tabs
- Professional CSS with cards, badges, growth bars, score circles
- Drag-and-drop resume upload with recommendations display
- Added .gitignore to exclude __pycache__ and build artifacts

Agent-Logs-Url: https://github.com/Gitcoder12/Workforce-Gap-Analyzer/sessions/7081fa66-87a6-4236-81c2-c4b6fdfd8a65

Co-authored-by: Gitcoder12 <96382122+Gitcoder12@users.noreply.github.com>
- Remove stack trace exposure from error responses
- Make debug mode conditional on FLASK_DEBUG env var
- Pre-compile skill regex pattern at module level for performance
- Use list+join for PDF text extraction (avoid string concat in loop)
- Fix drag-and-drop resume upload (use droppedFile variable instead
  of invalid files property assignment on input element)

Agent-Logs-Url: https://github.com/Gitcoder12/Workforce-Gap-Analyzer/sessions/7081fa66-87a6-4236-81c2-c4b6fdfd8a65

Co-authored-by: Gitcoder12 <96382122+Gitcoder12@users.noreply.github.com>
- Extract filledStars variable in startup card renderer
- Move rank-badge inline styles to styles.css class
- Rename _SKILL_PATTERN to SKILL_PATTERN (no leading underscore)

Agent-Logs-Url: https://github.com/Gitcoder12/Workforce-Gap-Analyzer/sessions/7081fa66-87a6-4236-81c2-c4b6fdfd8a65

Co-authored-by: Gitcoder12 <96382122+Gitcoder12@users.noreply.github.com>
Copilot AI changed the title [WIP] Add complete workforce gap analyzer with filtering and company database Complete Workforce Gap Analyzer: offline Flask backend, multi-tab UI, resume AI recommender Apr 11, 2026
Copilot AI requested a review from Gitcoder12 April 11, 2026 08:17
@Gitcoder12
Gitcoder12 marked this pull request as ready for review April 12, 2026 19:30
Copilot AI review requested due to automatic review settings April 12, 2026 19:30
@Gitcoder12
Gitcoder12 merged commit f3328b9 into main Apr 12, 2026
3 checks passed
Copilot stopped work on behalf of Gitcoder12 due to an error April 12, 2026 19:31
Copilot stopped work on behalf of Gitcoder12 due to an error April 12, 2026 19:31
Copilot stopped work on behalf of Gitcoder12 due to an error April 12, 2026 19:33

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR merges a complete offline “Workforce Gap Analyzer” app into main, adding a Flask backend with embedded workforce datasets and a multi-tab frontend UI including a resume upload + job recommendation feature.

Changes:

  • Replaced the minimal single-form UI with a multi-tab dashboard (jobs by category, companies, startups, officers, Resume AI).
  • Implemented Flask JSON APIs for city/job/company/startup/officer data and a resume upload endpoint (PDF/DOCX/TXT parsing + scoring).
  • Added deployment assets for Render/Gunicorn plus updated documentation and styling.

Reviewed changes

Copilot reviewed 7 out of 9 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
app.py Adds offline embedded datasets, API endpoints, and resume parsing + scoring logic.
index.html New multi-tab UI layout including Resume AI upload panel.
script.js Tab navigation, search filtering, API data loading, rendering, and resume upload flow.
styles.css Complete UI styling for header/tabs/cards/resume section.
requirements.txt Adds Gunicorn + resume parsing dependencies.
render.yaml Render.com deployment configuration.
Procfile Gunicorn start command for platforms that use Procfile.
README.md Updates local install + Render deployment instructions.
.gitignore Adds common Python and environment ignores.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread app.py
Comment on lines +367 to +373
_SKILL_PATTERN = re.compile(
r'\b(' + '|'.join(map(re.escape, KNOWN_SKILLS)) + r')\b',
re.IGNORECASE,
)

def extract_skills_from_text(text):
return list({m.lower() for m in _SKILL_PATTERN.findall(text)})

Copilot AI Apr 12, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The skill-extraction regex wraps all skills in \b...\b, which won’t reliably match skills containing non-word characters (e.g., c++, c#, .net) because \b boundaries don’t work at +/#/. edges. This will cause missing extracted skills and inaccurate resume/job matching. Consider using custom lookarounds (e.g., (?<![A-Za-z0-9])...(?![A-Za-z0-9])), splitting skills into “word-only” vs “symbolic” patterns, or a tokenization/normalization approach instead of \b for the whole alternation.

Copilot uses AI. Check for mistakes.
Comment thread app.py
Comment on lines +456 to +471
@app.route('/api/upload-resume', methods=['POST'])
def upload_resume():
if 'resume' not in request.files:
return jsonify({'error': 'No file uploaded'}), 400
file = request.files['resume']
city = request.form.get('city', '').strip().lower()
if not city:
return jsonify({'error': 'Please select a city'}), 400
jobs = JOBS_DATA.get(city)
if jobs is None:
return jsonify({'error': 'City not found'}), 404
filename = (file.filename or '').lower()
text = ''
try:
file_bytes = file.read()
if filename.endswith('.pdf'):

Copilot AI Apr 12, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/api/upload-resume accepts arbitrary-sized uploads and reads the entire file into memory (file.read()), which can be abused to exhaust memory/CPU (especially for PDFs). Consider setting app.config['MAX_CONTENT_LENGTH'] (and returning a clear 413 response) plus optionally rejecting overly large PDFs/DOCX before parsing.

Copilot uses AI. Check for mistakes.
Comment thread script.js
Comment on lines +39 to +40
searchBar.style.display = jobTabs.includes(tab) ? 'flex' : 'none';
updateResultsCount();

Copilot AI Apr 12, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When switching between job tabs, showPanel() doesn’t re-apply the current search query; if the user has text in #searchInput and changes tabs, the new tab shows unfiltered cards while the search box still contains a query. Consider calling filterCards() (or applying the query) from showPanel() when tab is a job tab so the UI stays consistent.

Suggested change
searchBar.style.display = jobTabs.includes(tab) ? 'flex' : 'none';
updateResultsCount();
const isJobTab = jobTabs.includes(tab);
searchBar.style.display = isJobTab ? 'flex' : 'none';
if (isJobTab && typeof filterCards === 'function') {
filterCards();
} else {
updateResultsCount();
}

Copilot uses AI. Check for mistakes.
Comment thread script.js
Comment on lines +58 to +67
const categories = ['high_demand','high_pay','best','risky','emergency','new'];
Promise.all([
...categories.map(cat =>
fetch(`/api/jobs/${encodeURIComponent(city)}?category=${cat}`)
.then(r => r.json()).then(d => ({ cat, jobs: d.jobs || [] }))
),
fetch(`/api/companies/${encodeURIComponent(city)}`).then(r => r.json()),
fetch(`/api/startups/${encodeURIComponent(city)}`).then(r => r.json()),
fetch(`/api/officers/${encodeURIComponent(city)}`).then(r => r.json()),
]).then(results => {

Copilot AI Apr 12, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The data-loading fetch(...).then(r => r.json()) flow doesn’t check r.ok, so HTTP errors (e.g., 404/500) will be treated as “success” and silently render empty lists. Consider checking r.ok and throwing on errors (or surfacing data.error) so users get a clear failure state instead of misleading “No data available.”

Copilot uses AI. Check for mistakes.
Comment thread README.md
## Local Installation

```bash
git clone https://github.com/Gitcoder12/Workforce-Gap-Analyzer.git

Copilot AI Apr 12, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The README instructs users to fork this repository, but the local install command hard-codes cloning https://github.com/Gitcoder12/Workforce-Gap-Analyzer.git. This is inconsistent for fork-based workflows; consider using a placeholder (<your-username>) or wording that tells users to clone their fork URL.

Suggested change
git clone https://github.com/Gitcoder12/Workforce-Gap-Analyzer.git
git clone https://github.com/<your-username>/Workforce-Gap-Analyzer.git

Copilot uses AI. Check for mistakes.
Comment thread index.html
Comment on lines +115 to +120
<div class="upload-content" onclick="document.getElementById('resumeFile').click()">
<div class="upload-icon">&#128196;</div>
<h3>Drag &amp; Drop your Resume</h3>
<p>or click to browse &mdash; PDF, DOCX, TXT supported</p>
<div class="file-info" id="fileInfo"></div>
</div>

Copilot AI Apr 12, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The resume upload “click to browse” control is a <div> with onclick, which is not keyboard-focusable and doesn’t expose an accessible name/role to assistive tech. Consider using a <label for="resumeFile"> or a real <button> (plus tabindex/ARIA as needed) so keyboard and screen reader users can trigger the file picker.

Suggested change
<div class="upload-content" onclick="document.getElementById('resumeFile').click()">
<div class="upload-icon">&#128196;</div>
<h3>Drag &amp; Drop your Resume</h3>
<p>or click to browse &mdash; PDF, DOCX, TXT supported</p>
<div class="file-info" id="fileInfo"></div>
</div>
<label class="upload-content" for="resumeFile">
<div class="upload-icon">&#128196;</div>
<h3>Drag &amp; Drop your Resume</h3>
<p>or click to browse &mdash; PDF, DOCX, TXT supported</p>
<div class="file-info" id="fileInfo"></div>
</label>

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants