From bee706eba82fc5de19f2a0112f5db7e201202ec1 Mon Sep 17 00:00:00 2001 From: srbhr Date: Sun, 18 Feb 2024 01:20:57 +0530 Subject: [PATCH] Shifted the WebApp to a web-app branch --- README.md | 12 - webapp/.eslintrc.json | 11 - webapp/.gitignore | 35 - webapp/README.md | 164 - webapp/app/(routes)/layout.tsx | 39 - webapp/app/(routes)/page.tsx | 26 - webapp/app/_components/button/button.tsx | 22 - .../_components/common-words/common-words.tsx | 58 - webapp/app/_components/footer/footer.tsx | 106 - webapp/app/_components/footer/footerLinks.ts | 39 - webapp/app/_components/header/header.tsx | 83 - webapp/app/_components/hero/hero.tsx | 18 - .../job-descriptions/add-jobs/add-jobs.tsx | 196 - .../job-descriptions/job-descriptions.tsx | 23 - .../processing-error/processing-error.tsx | 20 - .../resume/file-upload/file-upload.tsx | 94 - .../resume/pdf-viewer/pdf-viewer.tsx | 72 - .../resume/resume-glance/resume-glance.tsx | 23 - .../_components/suggestions/suggestions.tsx | 72 - .../third-party-services/reducer.ts | 40 - .../third-party-services/saved-keys.tsx | 128 - .../third-party-services.tsx | 57 - .../vector-scores/vector-scores.tsx | 72 - webapp/app/_stores/useGlobalStore.ts | 61 - webapp/app/_types/job-descriptions.ts | 12 - webapp/app/_types/resume-processor.ts | 25 - webapp/app/_types/service-keys.ts | 6 - webapp/app/_utils/environment.ts | 21 - webapp/app/_utils/errors.ts | 21 - webapp/app/globals.css | 31 - webapp/backend/api/index.py | 161 - webapp/backend/schemas/__init__.py | 0 webapp/backend/schemas/resume_processor.py | 44 - webapp/backend/scripts/__init__.py | 0 webapp/backend/scripts/files.py | 132 - webapp/backend/scripts/resume_processor.py | 65 - webapp/backend/scripts/service_keys.py | 75 - webapp/next.config.js | 23 - webapp/package-lock.json | 5748 ----------------- webapp/package.json | 38 - webapp/postcss.config.js | 6 - webapp/public/favicon-32x32.png | Bin 1244 -> 0 bytes webapp/public/icons/discord-light.svg | 7 - webapp/public/icons/file-description.svg | 7 - webapp/public/icons/github-light.svg | 7 - webapp/public/icons/github.svg | 5 - webapp/public/icons/link.svg | 5 - webapp/public/icons/productHunt-light.svg | 7 - webapp/public/resume_matcher_logo.png | Bin 20023 -> 0 bytes webapp/tailwind.config.ts | 20 - webapp/tsconfig.json | 32 - 51 files changed, 7969 deletions(-) delete mode 100644 webapp/.eslintrc.json delete mode 100644 webapp/.gitignore delete mode 100644 webapp/README.md delete mode 100644 webapp/app/(routes)/layout.tsx delete mode 100644 webapp/app/(routes)/page.tsx delete mode 100644 webapp/app/_components/button/button.tsx delete mode 100644 webapp/app/_components/common-words/common-words.tsx delete mode 100644 webapp/app/_components/footer/footer.tsx delete mode 100644 webapp/app/_components/footer/footerLinks.ts delete mode 100644 webapp/app/_components/header/header.tsx delete mode 100644 webapp/app/_components/hero/hero.tsx delete mode 100644 webapp/app/_components/job-descriptions/add-jobs/add-jobs.tsx delete mode 100644 webapp/app/_components/job-descriptions/job-descriptions.tsx delete mode 100644 webapp/app/_components/processing-error/processing-error.tsx delete mode 100644 webapp/app/_components/resume/file-upload/file-upload.tsx delete mode 100644 webapp/app/_components/resume/pdf-viewer/pdf-viewer.tsx delete mode 100644 webapp/app/_components/resume/resume-glance/resume-glance.tsx delete mode 100644 webapp/app/_components/suggestions/suggestions.tsx delete mode 100644 webapp/app/_components/third-party-services/reducer.ts delete mode 100644 webapp/app/_components/third-party-services/saved-keys.tsx delete mode 100644 webapp/app/_components/third-party-services/third-party-services.tsx delete mode 100644 webapp/app/_components/vector-scores/vector-scores.tsx delete mode 100644 webapp/app/_stores/useGlobalStore.ts delete mode 100644 webapp/app/_types/job-descriptions.ts delete mode 100644 webapp/app/_types/resume-processor.ts delete mode 100644 webapp/app/_types/service-keys.ts delete mode 100644 webapp/app/_utils/environment.ts delete mode 100644 webapp/app/_utils/errors.ts delete mode 100644 webapp/app/globals.css delete mode 100644 webapp/backend/api/index.py delete mode 100644 webapp/backend/schemas/__init__.py delete mode 100644 webapp/backend/schemas/resume_processor.py delete mode 100644 webapp/backend/scripts/__init__.py delete mode 100644 webapp/backend/scripts/files.py delete mode 100644 webapp/backend/scripts/resume_processor.py delete mode 100644 webapp/backend/scripts/service_keys.py delete mode 100644 webapp/next.config.js delete mode 100644 webapp/package-lock.json delete mode 100644 webapp/package.json delete mode 100644 webapp/postcss.config.js delete mode 100644 webapp/public/favicon-32x32.png delete mode 100644 webapp/public/icons/discord-light.svg delete mode 100644 webapp/public/icons/file-description.svg delete mode 100644 webapp/public/icons/github-light.svg delete mode 100644 webapp/public/icons/github.svg delete mode 100644 webapp/public/icons/link.svg delete mode 100644 webapp/public/icons/productHunt-light.svg delete mode 100644 webapp/public/resume_matcher_logo.png delete mode 100644 webapp/tailwind.config.ts delete mode 100644 webapp/tsconfig.json diff --git a/README.md b/README.md index 795f4e8a..2622b693 100644 --- a/README.md +++ b/README.md @@ -242,18 +242,6 @@ Pull Requests & Issues are not just welcomed, they're celebrated! Let's create t #### Tech Stack -Current: - -- Python webapp in Streamlit. - -![Python](https://img.shields.io/badge/Python-3776AB?style=flat-square&logo=python&color=blue&logoColor=green) - - - -In Development: - -- Check the [webapp](/webapp/) folder for a Next JS app in development. (In Development) - ![Python](https://img.shields.io/badge/Python-FFD43B?style=flat-square&logo=python&logoColor=blue) ![Tailwind CSS](https://img.shields.io/badge/Tailwind_CSS-38B2AC?style=flat-square&logo=tailwind-css&logoColor=white) ![Next JS](https://img.shields.io/badge/Next-black?style=flat-square&logo=next.js&logoColor=white) ![FastAPI](https://img.shields.io/badge/FastAPI-005571?style=flat-square&logo=fastapi) ![TypeScript](https://img.shields.io/badge/TypeScript-007ACC?style=flat-square&logo=typescript&logoColor=white) ![HTML5](https://img.shields.io/badge/HTML5-E34F26?style=flat-square&logo=html5&logoColor=white) ![CSS3](https://img.shields.io/badge/CSS3-1572B6?style=flat-square&logo=css3&logoColor=white) ![& More](https://custom-icon-badges.demolab.com/badge/And_More-white?style=flat-square&logo=plus&logoColor=black)
diff --git a/webapp/.eslintrc.json b/webapp/.eslintrc.json deleted file mode 100644 index ce6402bc..00000000 --- a/webapp/.eslintrc.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "extends": "next/core-web-vitals", - "rules": { - "no-unused-vars": [ - "warn", - { - "argsIgnorePattern": "^_" - } - ] - } -} diff --git a/webapp/.gitignore b/webapp/.gitignore deleted file mode 100644 index 8f322f0d..00000000 --- a/webapp/.gitignore +++ /dev/null @@ -1,35 +0,0 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies -/node_modules -/.pnp -.pnp.js - -# testing -/coverage - -# next.js -/.next/ -/out/ - -# production -/build - -# misc -.DS_Store -*.pem - -# debug -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# local env files -.env*.local - -# vercel -.vercel - -# typescript -*.tsbuildinfo -next-env.d.ts diff --git a/webapp/README.md b/webapp/README.md deleted file mode 100644 index 10411ded..00000000 --- a/webapp/README.md +++ /dev/null @@ -1,164 +0,0 @@ -# Resume Matcher - A Full Stack Web Application - -The Resume Matcher takes your resume and job descriptions as input, parses them using Python, and mimics the functionalities of an ATS, providing you with insights and suggestions to make your resume ATS-friendly. - -> [!WARNING] -> The results returned from through the web app are currently entirely mocked / faked. This means that the results returned are not real and are just for demonstration purposes. This will be implemented with real data results in a future release. - -## Demo - -View a brief GIF demo of the web apps' design functionality below: - -![Resume-Matcher-Web-App-UI-Quick-Demo-2](https://github.com/Sayvai/react-project-dashboard-mvp-match/assets/7581546/5bf9c4c8-a5d1-47ee-8e27-eacda0dbcac9) - -## Getting Started - -### Prerequisites - -- install [Node.js](https://nodejs.org/en/download/). The version used for this project is v18.17.0 - -- install [Python](https://www.python.org/downloads/). The version used for this project is v3.11.5 - -### Setup - -1. clone the repository -2. navigate to the project directory (e.g. `cd Resume-Matcher`) -3. Follow the [README](../README.md) instructions set out in the root of the repository to setup the Python environment and run the Python scripts. -4. navigate to the `webapp` directory (e.g. `cd webapp`) -5. run `npm install` to install the frontend client app dependencies -6. For Mac OS / Linux / WSL users: run `npm run dev` to start the web app (i.e. this script will start the frontend client and backend FastAPI servers concurrently within one terminal process inside `webapp` directory`) -7. For Windows (non-WSL) users: run `npm run dev-win` to start the web app (i.e. this script will start the frontend client and backend FastAPI servers concurrently within one terminal process inside `webapp` directory`) -8. once both servers are ready, open [http://localhost:3000](http://localhost:3000) on your browser to view and interact with the app. - -### Extra Setup Hints - -- 💡 You may also decide to run the frontend and backend servers in separate terminal processes independently of one another. To run the frontend server in isolation, run `npm run next-dev`. To run the backend FastAPI server in isolation, run `npm run fastapi-dev` (For Mac OS / Linux / WSL) or `npm run fastapi-dev-win` (For Windows non-WSL). - -## Debugging - -### VS Code Debugger - FastAPI Backend - -When working with the backend web application files, you may like to debug the backend server during runtime and have the ability to set breakpoints to pause execution on certain line(s), inspect variable values, and other runtime data using the VS Code debugger. To do so, follow the steps below: - -#### Setup VS Code Launch Configuration - -- Open the VS Code debugger tab (i.e. the bug icon on the left sidebar) - -- Click on the gear icon to open the launch.json file - -- Add the following configuration to the launch.json file, and save: - -```json -{ - "version": "0.2.0", - "configurations": [ - { - "name": "Debug FastAPI Backend", - "type": "python", - "request": "launch", - "module": "uvicorn", - "args": ["webapp.backend.api.index:app", "--reload"], - "jinja": true, - "justMyCode": true - } - ] -} -``` - -#### Start the Backend Server in Debug Mode - -1. ⚠️ IMPORTANT: Before proceeding along this set of steps, ensure the frontend server is NOT running. It will need to be running in isolation of the backend server, after the backend server has successfully completed its startup process. - -2. Open the VS Code debugger tab (i.e. the bug icon on the left sidebar) - -3. Select the "Debug FastAPI Backend" configuration from the dropdown - -4. Click on the play button to start the backend server in debug mode - -5. A new terminal window will open and the backend server will start running in debug mode - -6. You may optionally set breakpoints in the backend python files to pause execution on certain line(s), inspect variable values, and other runtime data, as you interact with the app or make requests to the backend server. - -7. Ensure the frontend server is running in isolation of the backend server, after the backend server has successfully completed its starup process. By running the following command in a separate terminal window: - -```bash -npm run next-dev -``` - -8. Once the backend server (and frontend server) is ready, open [http://localhost:3000](http://localhost:3000) on your browser to view and interact with the app. - -### Visual demonstration of running the FastAPI backend server in VS Code Debugger - -![Resume-Matcher-vs-code-debug-backend-fastapi-demo](https://github.com/srbhr/Resume-Matcher/assets/7581546/04b3b8e2-98c4-40ff-964f-8075c55091c9) - -## Troubleshooting Common Issues - -### Error: connect ECONNREFUSED 127.0.0.1:8000 - -
-You may encounter the following Error: connect ECONNREFUSED 127.0.0.1:8000 error in the terminal (and browser ui throws an exception) when running the frontend server in isolation of the backend server via npm run next-dev (👉 👀 click to reveal error snippet): - -```bash -[0] Failed to proxy http://127.0.0.1:8000/api/service-keys Error: connect ECONNREFUSED 127.0.0.1:8000 -[0] at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1495:16) { -[0] errno: -61, -[0] code: 'ECONNREFUSED', -[0] syscall: 'connect', -[0] address: '127.0.0.1', -[0] port: 8000 -[0] } -[0] Error: connect ECONNREFUSED 127.0.0.1:8000 -[0] at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1495:16) { -[0] errno: -61, -[0] code: 'ECONNREFUSED', -[0] syscall: 'connect', -[0] address: '127.0.0.1', -[0] port: 8000 -[0] } -[0] SyntaxError: Unexpected token I in JSON at position 0 -[0] at JSON.parse () -[0] at parseJSONFromBytes (node:internal/deps/undici/undici:6662:19) -[0] at successSteps (node:internal/deps/undici/undici:6636:27) -[0] at node:internal/deps/undici/undici:1236:60 -[0] at node:internal/process/task_queues:140:7 -[0] at AsyncResource.runInAsyncScope (node:async_hooks:203:9) -[0] at AsyncResource.runMicrotask (node:internal/process/task_queues:137:8) -[0] at process.processTicksAndRejections (node:internal/process/task_queues:95:5) -[0] - error node_modules/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.development.js (340:14) @ getErrorMessage -``` - -
-
- -💡 This is most likely because the backend server has not yet started in isolation. To resolve this, ensure the backend server is running in isolation of the frontend server, by running the following command in a separate terminal window, and wait for the backend server to complete its startup process, then refresh the browser window to view the app: - -```bash -npm run fastapi-dev -``` - -💡 Or, you may alternatively run the backend server using the VS Code debugger, as described in the [VS Code Debugger - FastAPI Backend](#vs-code-debugger---fastapi-backend) section above. - -## Future Improvements - -Below are some of the improvements that can be made to the web app for future consideration: - -- 👉 Replace mock response data with real data from the backend. View file; [scripts/resume_processor.py](/webapp/backend/scripts/resume_processor.py), where the `build_response()` function can be modified to hook up to other python scripts to process and return the real data from the backend. The initial python response model classes are defined in the [schemas/resume_processor.py](/webapp/backend/schemas/resume_processor.py) file, and so that should help to get started with thinking about how to structure the data to be returned from the backend. -- Add unit tests (frontend and backend) -- Add end-to-end functional tests (frontend) -- Improve the UI/UX of loading and error states as requests are made to the backend - -## Technologies Used - -This is a full stack web application, hosting the frontend UI interactive web client interface, and the backend server API. - -The application is built using the following main technologies: - -- [Next.js](https://nextjs.org/) - a React.js meta-framework for building client and server-side rendered React applications - -- [FastAPI](https://fastapi.tiangolo.com/) - a Python framework for building web APIs - -- [TailwindCSS](https://tailwindcss.com/) - a CSS framework for building responsive web applications - -- [Zustand](https://github.com/pmndrs/zustand) - a frontend client state management library - -- [react-pdf](https://projects.wojtekmaj.pl/react-pdf/) - a React component library for rendering PDF documents on the frontend ui diff --git a/webapp/app/(routes)/layout.tsx b/webapp/app/(routes)/layout.tsx deleted file mode 100644 index 622b9901..00000000 --- a/webapp/app/(routes)/layout.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import type { Metadata } from "next"; -import { Fira_Sans } from "next/font/google"; -import "@/app/globals.css"; -import Header from "@/components/header/header"; -const firaSans = Fira_Sans({ - weight: ["100", "200", "300", "400", "500", "600", "700", "800", "900"], - subsets: ["latin"], -}); - -export const metadata: Metadata = { - title: "Resume Matcher", - description: - "An AI Based Free & Open Source ATS, Resume Matcher to tailor your resume to a job description. Find the best keywords, and gain deep insights into your resume.", - keywords: ["Resume", "Matcher", "ATS", "Score"], - authors: [ - { name: "Samurize", url: "https://github.com/srbhr" }, - { name: "Sayvai", url: "https://github.com/Sayvai" }, - ], - icons: { - icon: "/favicon-32x32.png", - }, -}; - -export default function RootLayout({ - children, -}: { - children: React.ReactNode; -}) { - return ( - - -
-
- {children} -
- - - ); -} diff --git a/webapp/app/(routes)/page.tsx b/webapp/app/(routes)/page.tsx deleted file mode 100644 index dc91ddcc..00000000 --- a/webapp/app/(routes)/page.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import JobDescriptions from "@/components/job-descriptions/job-descriptions"; -import VectorScore from "@/components/vector-scores/vector-scores"; -import CommonWords from "@/components/common-words/common-words"; -import Suggestions from "@/components/suggestions/suggestions"; -import ThirdPartyServicesKeys from "@/components/third-party-services/third-party-services"; -import FileUpload from "@/components/resume/file-upload/file-upload"; -import ResumeGlance from "@/components/resume/resume-glance/resume-glance"; -import Hero from "@/components/hero/hero"; -import Footer from "../_components/footer/footer"; - -export default function Home() { - return ( -
- - - - - - - - - -
-
- ); -} diff --git a/webapp/app/_components/button/button.tsx b/webapp/app/_components/button/button.tsx deleted file mode 100644 index ae1de17b..00000000 --- a/webapp/app/_components/button/button.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import clsx from "clsx"; - -type ButtonProps = React.HTMLProps & { - type?: "button" | "submit" | "reset"; - children: React.ReactNode; -}; - -const Button = ({ children, type = "button", ...props }: ButtonProps) => { - const { className: inheritedClassNames, ...buttonProps } = props; - - return ( - - ); -}; - -export default Button; diff --git a/webapp/app/_components/common-words/common-words.tsx b/webapp/app/_components/common-words/common-words.tsx deleted file mode 100644 index bd45e6ad..00000000 --- a/webapp/app/_components/common-words/common-words.tsx +++ /dev/null @@ -1,58 +0,0 @@ -"use client"; - -import DOMPurify from "dompurify"; -import { useGlobalStore } from "@/stores/useGlobalStore"; -import ProcessingError from "@/components/processing-error/processing-error"; - -const CommonWords = () => { - const { isBackendProcessing, resumeProcessorResponse } = useGlobalStore(); - - if (!isBackendProcessing && !resumeProcessorResponse?.commonWordsSet) - return null; - - function renderCommonWords() { - const { commonWordsSet } = resumeProcessorResponse || {}; - - if (!commonWordsSet) return null; - - return ( - - ); - } - - return ( -
-

- Common Words between Job Descriptions and Resumes Highlighted -

- {isBackendProcessing &&

Processing common words...

} - -
- {renderCommonWords()} -
-
- ); -}; - -export default CommonWords; diff --git a/webapp/app/_components/footer/footer.tsx b/webapp/app/_components/footer/footer.tsx deleted file mode 100644 index 4fedfa61..00000000 --- a/webapp/app/_components/footer/footer.tsx +++ /dev/null @@ -1,106 +0,0 @@ -import Image from "next/image"; -import data from "./footerLinks"; - -const Footer = () => { - return ( -
-
-
-

Resume Matcher

- -
-
- {data.map((section, index) => ( -
-

{section.label}

- -
- ))} -
-
-
- - Discord Logo - - - Product Hunt Logo - - - GitHub Logo - -
-
- ); -}; -export default Footer; diff --git a/webapp/app/_components/footer/footerLinks.ts b/webapp/app/_components/footer/footerLinks.ts deleted file mode 100644 index eeddcc78..00000000 --- a/webapp/app/_components/footer/footerLinks.ts +++ /dev/null @@ -1,39 +0,0 @@ -const data = [ - { - isSection: true, - label: "Community", - items: [ - { title: "Dev Community Posts", link: "https://dev.to/srbhr/creating-a-game-changer-in-job-search-an-open-source-ats-resume-matcher-31g9", - shouldOpenInNewPage: true }, - ], - }, - { - isSection: true, - label: "Find Us", - items: [ - { title: "Product Hunt", link: "https://www.producthunt.com/posts/resume-matcher" , - shouldOpenInNewPage: true}, - { title: "Discord", link: "https://discord.gg/t3Y9HEuV34" , - shouldOpenInNewPage: true}, - { title: "Alternative To", link: "https://alternativeto.net/software/resume-matcher/", - shouldOpenInNewPage: true }, - { title: "Toolify AI", link: "https://www.toolify.ai/tool/resume-matcher" , - shouldOpenInNewPage: true}, - ], - }, - { - isSection: true, - label: "Github", - items: [ - { title: "Creator", link: "https://github.com/srbhr", - shouldOpenInNewPage: true }, - { title: "Contributors", link: "https://github.com/srbhr/Resume-Matcher/graphs/contributors" , - shouldOpenInNewPage: true}, - { title: "Star Gazers", link: "https://github.com/srbhr/Resume-Matcher/stargazers", - shouldOpenInNewPage: true }, - { title: "Forks", link: "https://github.com/srbhr/Resume-Matcher/forks" , - shouldOpenInNewPage: true}, - ], - }, -] -export default data diff --git a/webapp/app/_components/header/header.tsx b/webapp/app/_components/header/header.tsx deleted file mode 100644 index 85898125..00000000 --- a/webapp/app/_components/header/header.tsx +++ /dev/null @@ -1,83 +0,0 @@ -import Image from "next/image"; -import Button from "@/components/button/button"; - -const Header = () => { - return ( -
- Resume Matcher Logo - - -
- ); -}; - -export default Header; diff --git a/webapp/app/_components/hero/hero.tsx b/webapp/app/_components/hero/hero.tsx deleted file mode 100644 index b8b03dd2..00000000 --- a/webapp/app/_components/hero/hero.tsx +++ /dev/null @@ -1,18 +0,0 @@ -type HeroProps = { - children?: React.ReactNode; -}; - -const Hero = ({ children }: HeroProps) => { - return ( - <> -
-

- Free and Open Source ATS to help your resume pass the screening stage. -

- {children} -
- - ); -}; - -export default Hero; diff --git a/webapp/app/_components/job-descriptions/add-jobs/add-jobs.tsx b/webapp/app/_components/job-descriptions/add-jobs/add-jobs.tsx deleted file mode 100644 index 773c6f49..00000000 --- a/webapp/app/_components/job-descriptions/add-jobs/add-jobs.tsx +++ /dev/null @@ -1,196 +0,0 @@ -"use client"; - -import { useState } from "react"; -import Image from "next/image"; -import { JobDescription } from "@/types/job-descriptions"; -import Button from "@/components/button/button"; -import { useGlobalStore } from "@/stores/useGlobalStore"; - -type AddJobsProps = { - numMaxJobs?: number; -}; - -const JOB_DETAIL_TYPE = { - LINK: "link", - DESCRIPTION: "description", -}; - -const AddJobs = ({ numMaxJobs = 1 }: AddJobsProps) => { - const { - setJobDescriptions, - processData, - resumeProcessorResponse, - clearResumeProcessorResponse, - } = useGlobalStore(); - const [jobs, setJobs] = useState([]); - - const handleAddJobDetail = (e: React.MouseEvent) => { - const jobDetailType = e.currentTarget.dataset.jobDetailType; - - const randomId = crypto.randomUUID(); - - handleClearOutdatedResults(); - - if (jobDetailType === JOB_DETAIL_TYPE.LINK) { - return addEmptyJobDetailLink(randomId); - } - - return addEmptyJobDetailDescription(randomId); - }; - - function addEmptyJobDetailLink(id: string) { - setJobs((jobs) => [...jobs, { id, link: "" }]); - } - - function addEmptyJobDetailDescription(id: string) { - setJobs((jobs) => [...jobs, { id, description: "" }]); - } - - function removeJobDetail(id: string) { - setJobs((jobs) => jobs.filter((job) => job.id !== id)); - handleClearOutdatedResults(); - } - - function handleClearOutdatedResults() { - if (resumeProcessorResponse) { - clearResumeProcessorResponse(); - } - } - - function renderJobs() { - return jobs.map((job, index) => { - const jobNumber = index + 1; - const inputName = `job_${jobNumber.toString()}`; - const jobDetailType = - "link" in job ? JOB_DETAIL_TYPE.LINK : JOB_DETAIL_TYPE.DESCRIPTION; - - return ( -
-
- - -
- - (id:{" "} - - {job.id} - - ) - - {"link" in job && ( - - )} - {"description" in job && ( -