diff --git a/package-lock.json b/package-lock.json index 0f1ba87b..150f4c14 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,8 @@ "devdisplay": "file:", "flag": "^5.0.1", "framer-motion": "^12.7.4", + "html2canvas": "^1.4.1", + "jspdf": "^3.0.1", "lucide-react": "^0.507.0", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -4319,6 +4321,12 @@ "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.18.tgz", "integrity": "sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==" }, + "node_modules/@types/raf": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/@types/raf/-/raf-3.4.3.tgz", + "integrity": "sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==", + "optional": true + }, "node_modules/@types/range-parser": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", @@ -5280,6 +5288,17 @@ "node": ">= 4.0.0" } }, + "node_modules/atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } + }, "node_modules/autoprefixer": { "version": "10.4.21", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz", @@ -5612,6 +5631,14 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "node_modules/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", @@ -5781,6 +5808,17 @@ "node-int64": "^0.4.0" } }, + "node_modules/btoa": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz", + "integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==", + "bin": { + "btoa": "bin/btoa.js" + }, + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -5923,6 +5961,25 @@ } ] }, + "node_modules/canvg": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.11.tgz", + "integrity": "sha512-5ON+q7jCTgMp9cjpu4Jo6XbvfYwSB2Ow3kzHKfIyJfaCAOHLbdKPQqGKgfED/R5B+3TFFfe8pegYA+b423SRyA==", + "optional": true, + "dependencies": { + "@babel/runtime": "^7.12.5", + "@types/raf": "^3.4.0", + "core-js": "^3.8.3", + "raf": "^3.4.1", + "regenerator-runtime": "^0.13.7", + "rgbcolor": "^1.0.1", + "stackblur-canvas": "^2.0.0", + "svg-pathdata": "^6.0.3" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/case-sensitive-paths-webpack-plugin": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", @@ -6436,6 +6493,14 @@ "postcss": "^8.4" } }, + "node_modules/css-line-break": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", + "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==", + "dependencies": { + "utrie": "^1.0.2" + } + }, "node_modules/css-loader": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", @@ -7113,6 +7178,15 @@ "url": "https://github.com/fb55/domhandler?sponsor=1" } }, + "node_modules/dompurify": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.5.tgz", + "integrity": "sha512-mLPd29uoRe9HpvwP2TxClGQBzGXeEC/we/q+bFlmPPmj2p2Ugl3r6ATu/UU1v77DXNcehiBg9zsr1dREyA/dJQ==", + "optional": true, + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, "node_modules/domutils": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", @@ -8306,6 +8380,11 @@ "bser": "2.1.1" } }, + "node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==" + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -9248,6 +9327,18 @@ } } }, + "node_modules/html2canvas": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz", + "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==", + "dependencies": { + "css-line-break": "^2.1.0", + "text-segmentation": "^1.0.3" + }, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/htmlparser2": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", @@ -12136,6 +12227,23 @@ "node": ">=0.10.0" } }, + "node_modules/jspdf": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/jspdf/-/jspdf-3.0.1.tgz", + "integrity": "sha512-qaGIxqxetdoNnFQQXxTKUD9/Z7AloLaw94fFsOiJMxbfYdBbrBuhWmbzI8TVjrw7s3jBY1PFHofBKMV/wZPapg==", + "dependencies": { + "@babel/runtime": "^7.26.7", + "atob": "^2.1.2", + "btoa": "^1.2.1", + "fflate": "^0.8.1" + }, + "optionalDependencies": { + "canvg": "^3.0.11", + "core-js": "^3.6.0", + "dompurify": "^3.2.4", + "html2canvas": "^1.0.0-rc.5" + } + }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", @@ -15434,6 +15542,15 @@ "node": ">=0.10.0" } }, + "node_modules/rgbcolor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz", + "integrity": "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==", + "optional": true, + "engines": { + "node": ">= 0.8.15" + } + }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -16202,6 +16319,15 @@ "node": ">=8" } }, + "node_modules/stackblur-canvas": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.7.0.tgz", + "integrity": "sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==", + "optional": true, + "engines": { + "node": ">=0.1.14" + } + }, "node_modules/stackframe": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", @@ -16756,6 +16882,15 @@ "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" }, + "node_modules/svg-pathdata": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz", + "integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==", + "optional": true, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/svgo": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", @@ -17089,6 +17224,14 @@ "node": ">=8" } }, + "node_modules/text-segmentation": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", + "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==", + "dependencies": { + "utrie": "^1.0.2" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -17365,16 +17508,16 @@ } }, "node_modules/typescript": { - "version": "5.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", - "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=14.17" + "node": ">=4.2.0" } }, "node_modules/unbox-primitive": { @@ -17567,6 +17710,14 @@ "node": ">= 0.4.0" } }, + "node_modules/utrie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz", + "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==", + "dependencies": { + "base64-arraybuffer": "^1.0.2" + } + }, "node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", diff --git a/package.json b/package.json index 9c2c5516..a4ba38a6 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,8 @@ "devdisplay": "file:", "flag": "^5.0.1", "framer-motion": "^12.7.4", + "html2canvas": "^1.4.1", + "jspdf": "^3.0.1", "lucide-react": "^0.507.0", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/src/App.js b/src/App.js index 5d9e9e0b..12627283 100644 --- a/src/App.js +++ b/src/App.js @@ -15,7 +15,9 @@ import IdeaSubmission from './Page/IdeaSubmission.jsx'; import PortfolioIdeas from './Page/PortfolioIdeas/PortfolioIdeas.jsx'; import PortfolioBuilder from './Page/PortfolioBuilder.jsx'; import ProjectShowcase from './Page/ProjectShowcase.jsx'; -import ResumeBuilder from './Page/ResumeBuilder.jsx'; +import Resume from './Page/Resume.jsx'; +import ResumeBuilder from './components/ResumeBuilder/ResumeBuilder.jsx'; +import ResumeAnalyzer from './components/ResumeAnalyzer/ResumeAnalyzer.jsx'; import Discussions from './Page/Discussions.jsx'; import IndustryTrends from './Page/IndustryTrends.jsx'; import JourneyPage from './Page/JourneyPage.jsx'; @@ -50,6 +52,7 @@ import DevShare from './Page/ResoucesHub/DevShare.jsx'; import PageNotFound from './Page/PageNotFound.jsx'; import ProfilePage from './components/Profile/ProfilePage'; +import { ResumeProvider } from './components/ResumeBuilder/context/ResumeContext.jsx'; function App() { React.useEffect(() => { @@ -110,7 +113,16 @@ function App() { } /> } /> } /> - } /> + } /> + + + + } + /> + } /> } /> } /> } /> diff --git a/src/Page/Home.jsx b/src/Page/Home.jsx index a45d9dc6..c929246e 100644 --- a/src/Page/Home.jsx +++ b/src/Page/Home.jsx @@ -475,7 +475,7 @@ const TechFeatures = () => { { { - window.location.href = 'https://resume-builder-pro.vercel.app/'; + window.location.href = '/Resume'; window.open('_blank'); }} > diff --git a/src/Page/Resume.jsx b/src/Page/Resume.jsx new file mode 100644 index 00000000..f2dcc2f2 --- /dev/null +++ b/src/Page/Resume.jsx @@ -0,0 +1,638 @@ +import { useState, useEffect } from 'react'; +import { ArrowLeft, Search, FileText, Sparkles, Zap, Edit, Eye, Download, Share2, TrendingUp } from 'lucide-react'; +import styled from 'styled-components'; +import Marquee from 'react-fast-marquee'; +import { Routes, Route, useNavigate } from 'react-router-dom'; +import { Footer } from '../components/Footer/Footer'; +import ResumeBuilder from '../components/ResumeBuilder/ResumeBuilder'; +import ResumeAnalyzer from '../components/ResumeAnalyzer/ResumeAnalyzer'; + +const ResumeProvider = ({ children }) =>
{children}
; + +const Navbar = () => { + return ( +
+ ); +}; + +const Hero = () => { + return ( +
+
+
+ +
+
+
+
Resume Builder
+
+
+
+ {['AQliM', 'WCb99', 'dBNZV', 'tiisO', 're9B7', 'BKG4G', 'NaoVe', 'pwIlv', 'QmcAd', 'VG2eL'].map( + (id, index) => ( +
+ + + +
+ ), + )} +
+
+
+
+
+ ); +}; + +const Tags = () => { + const tags = [ + 'Professional Templates', + 'ATS Friendly', + 'Modern Designs', + 'Easy Editor', + 'PDF Export', + 'Real-time Preview', + 'Custom Sections', + 'Mobile Responsive', + 'Industry Specific', + 'Career Focused', + 'Clean Layouts', + 'Print Ready', + 'Quick Build', + 'Professional Look', + 'Customizable', + 'Modern Styling', + 'Expert Approved', + 'Job Ready', + 'Stand Out', + 'Get Hired', + ]; + + return ( +
+

+ Create Professional Resumes That Get You Hired +

+ +
+ {[...tags, ...tags, ...tags].map((text, index) => ( + + {text} + + ))} +
+
+
+ +
+ {[...tags, ...tags, ...tags].map((text, index) => ( + + {text} + + ))} +
+
+ +
+ ); +}; + +const ResumeBuilderCards = () => { + const [searchTerm, setSearchTerm] = useState(''); + + const ResumeFeatures = [ + { + title: 'Quick Builder', + description: 'Create your professional resume in minutes with our intuitive builder.', + icon: , + tags: ['Quick', 'Easy', 'Intuitive', 'Professional'], + }, + { + title: 'Live Preview', + description: 'See your resume come to life with real-time preview as you build.', + icon: , + tags: ['Real-time', 'Preview', 'WYSIWYG', 'Visual'], + }, + { + title: 'PDF Export', + description: 'Download your resume as a high-quality PDF ready for applications.', + icon: , + tags: ['PDF', 'Download', 'Export', 'Print Ready'], + }, + { + title: 'ATS Friendly', + description: 'Optimized templates that pass through Applicant Tracking Systems.', + icon: , + tags: ['ATS', 'Optimized', 'Tracking', 'Systems'], + }, + { + title: 'Share & Collaborate', + description: 'Share your resume link or collaborate with career counselors.', + icon: , + tags: ['Share', 'Collaborate', 'Link', 'Feedback'], + }, + { + title: 'AI Assistant', + description: 'Get AI-powered suggestions to improve your resume content.', + icon: , + tags: ['AI', 'Assistant', 'Suggestions', 'Improve', 'Coming Soon'], + }, + ]; + + const filteredFeatures = ResumeFeatures.filter((feature) => { + const searchContent = `${feature.title} ${feature.description} ${feature.tags.join(' ')}`.toLowerCase(); + return searchContent.includes(searchTerm.toLowerCase()); + }); + + const handleSearch = (value) => { + setSearchTerm(value); + }; + + return ( +
+
+
+
+
+ + handleSearch(e.target.value)} + className="w-full rounded-full border border-[#00a6fb] bg-[rgba(15,27,53,0.9)] py-3 pl-12 pr-4 text-white placeholder-gray-400 outline-none ring-2 ring-transparent transition-all focus:ring-[#00a6fb]" + /> +
+
+
+
+ {filteredFeatures.length === 0 ? ( +
+

No features found matching your search.

+
+ ) : ( +
+ {filteredFeatures.map((feature, index) => ( + +
+ +
+
+
{feature.icon}
+

{feature.title}

+

{feature.description}

+
+ {feature.tags.map((tag, tagIndex) => ( + + {tag} + + ))} +
+
+
+
+
+ + ))} +
+ )} +
+ ); +}; + +const ActionSection = () => { + const navigate = useNavigate(); + + const handleStartBuilding = () => { + console.log('Start Building Now clicked, navigating to /ResumeBuilder'); + navigate('/ResumeBuilder'); + }; + + const handleAnalyzeResume = () => { + console.log('Analyzing resume...'); + navigate('/ResumeAnalyzer'); + }; + + return ( +
+
+

Ready to Build Your Resume?

+

+ Choose your path to creating a professional resume that gets you noticed by employers. +

+
+ +
+
Start Building Now
+ + +
+
+ + + AI Resume Analyzer + +
+ +
+
+
+ ); +}; + +const StyledButton = styled.button` + cursor: pointer; + font-size: 1rem; + border-radius: 12px; + border: none; + padding: 1px; + background: radial-gradient(circle 80px at 80% -10%, #ffffff, #181b1b); + position: relative; + transition: + background 0.3s, + transform 0.3s; + animation: zoom 3s ease-in-out infinite; + + &:hover { + transform: scale(0.98); + animation-play-state: paused; + } + + &:disabled { + opacity: 0.7; + cursor: not-allowed; + } + + &::after { + content: ''; + position: absolute; + width: 65%; + height: 60%; + border-radius: 120px; + top: 0; + right: 0; + box-shadow: 0 0 20px #ffffff38; + z-index: -1; + transition: box-shadow 0.3s; + } + + &:hover::after { + box-shadow: 0 0 10px #ffffff18; + } + + .blob1 { + position: absolute; + width: 50px; + height: 100%; + border-radius: 16px; + bottom: 0; + left: 0; + background: radial-gradient(circle 60px at 0% 100%, #3fe9ff, #0000ff80, transparent); + box-shadow: -10px 10px 30px #0051ff2d; + transition: + background 0.3s, + box-shadow 0.3s; + } + + &:hover .blob1 { + box-shadow: -5px 5px 20px #000; + } + + .inner { + padding: 10px 20px; + border-radius: 12px; + color: #fff; + z-index: 3; + position: relative; + background: radial-gradient(circle 80px at 80% -50%, #777777, #0f1111); + transition: background 0.3s; + } + + &:hover .inner { + background: radial-gradient(circle 80px at 80% -50%, #333333, #0f0f0f); + } + + .inner::before { + content: ''; + width: 100%; + height: 100%; + left: 0; + top: 0; + border-radius: 12px; + background: radial-gradient(circle 60px at 0% 100%, #00e1ff1a, #0000ff11, transparent); + position: absolute; + transition: opacity 0.3s; + } + + &:hover .inner::before { + opacity: 0; + } + + @keyframes zoom { + 0%, + 100% { + transform: scale(1); + } + 50% { + transform: scale(1.05); + } + } +`; + +const StyledDot = styled.div` + .dot { + width: 5px; + aspect-ratio: 1; + position: absolute; + background-color: #fff; + box-shadow: 0 0 10px #ffffff; + border-radius: 100px; + z-index: 2; + right: 0; + top: 0; + animation: moveDot 6s linear infinite; + } + + @keyframes moveDot { + 0% { + top: 0; + right: 0; + } + 25% { + top: 0; + right: calc(100% - 5px); + } + 50% { + top: calc(100% - 5px); + right: calc(100% - 5px); + } + 75% { + top: calc(100% - 5px); + right: 0; + } + 100% { + top: 0; + right: 0; + } + } +`; + +const StyledWrapper = styled.div` + .relative { + position: relative; + } + + .inline-block { + display: inline-block; + } + + .py-3 { + padding-top: 0.75rem; + padding-bottom: 0.75rem; + } + + .pointer-events-none { + pointer-events: none; + } + + .absolute { + position: absolute; + } + + .inset-0 { + inset: 0; + } + + button { + font-family: inherit; + font-feature-settings: inherit; + font-variation-settings: inherit; + font-size: 100%; + font-weight: inherit; + line-height: inherit; + color: inherit; + margin: 0; + padding: 0; + width: 300px !important; + } + + button { + text-transform: none; + cursor: pointer; + } + + .inline-flex { + display: inline-flex; + } + + .justify-center { + justify-content: center; + } + + .rounded-lg { + border-radius: 0.5rem; + } + + .bg-primary { + --tw-bg-opacity: 1; + background-color: rgba(15, 27, 53, 0); + } + + .text-white { + --tw-text-opacity: 1; + color: rgb(255 255 255 / var(--tw-text-opacity)); + } + + .px-18 { + padding-left: 4.5rem; + padding-right: 4.5rem; + } + + .py-5 { + padding-top: 1.25rem; + padding-bottom: 1.25rem; + } + + .text-6xl { + font-size: 3.75rem; + line-height: 1; + } + + .font-bold { + font-weight: 700; + } + + .transition-all { + transition-property: all; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; + } + + .focus\:outline-none:focus { + outline specials: 2px solid transparent; + outline-offset: 2px; + } + + .enabled\:hover\:shadow-md:hover:enabled { + --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1); + --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); + } + + .disabled\:opacity-50:disabled { + opacity: 0.5; + } + + .animate-magic-sparkle { + animation: magic-sparkle 3s infinite; + } + + .style-AQliM { + top: 10%; + left: 5%; + } + + .style-WCb99 { + top: 20%; + right: 10%; + } + + .style-dBNZV { + bottom: 15%; + left: 15%; + } + + .style-tiisO { + top: 30%; + left: 25%; + } + + .style-re9B7 { + bottom: 25%; + right: 20%; + } + + .style-BKG4G { + top: 15%; + right: 30%; + } + + .style-NaoVe { + bottom: 10%; + left: 35%; + } + + .style-pwIlv { + top: 25%; + right: 15%; + } + + .style-QmcAd { + bottom: 20%; + left: 10%; + } + + .style-VG2eL { + top: 35%; + right: 25%; + } + + .animate-spin-slow { + animation: spin 8s linear infinite; + } + + @keyframes magic-sparkle { + 0% { + opacity: 0; + transform: scale(0.5); + } + 50% { + opacity: 1; + transform: scale(1); + } + 100% { + opacity: 0; + transform: scale(0.5); + } + } + + @keyframes spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } + } +`; + +const Home = () => { + return ( +
+ + + + + +
+
+ ); +}; + +const App = () => { + return ( + + + } /> + } /> + } /> + + + ); +}; + +export default App; diff --git a/src/Page/ResumeBuilder.jsx b/src/Page/ResumeBuilder.jsx deleted file mode 100644 index 5730e27c..00000000 --- a/src/Page/ResumeBuilder.jsx +++ /dev/null @@ -1,693 +0,0 @@ -// import React, { useState } from 'react'; -// import { Tab, Tabs, TabList, TabPanel } from 'react-tabs'; -// import 'react-tabs/style/react-tabs.css'; -// import { saveAs } from 'file-saver'; -// import { toast, ToastContainer } from 'react-toastify'; -// import 'react-toastify/dist/ReactToastify.css'; - -// // Libraries for text extraction -// import mammoth from 'mammoth'; // For DOCX files -// import * as pdfjsLib from 'pdfjs-dist'; // For PDF files - -// const ResumeBuilder = () => { -// const [resumeText, setResumeText] = useState(''); -// const [feedback, setFeedback] = useState(''); -// const [score, setScore] = useState(''); -// const [jobDescription, setJobDescription] = useState(''); -// const [tabIndex, setTabIndex] = useState(0); - -// // File upload and text extraction -// const handleFileUpload = (event) => { -// const file = event.target.files[0]; -// if (!file) return; - -// const fileType = file.name.split('.').pop(); -// if (fileType === 'pdf') { -// extractTextFromPDF(file); -// } else if (fileType === 'docx') { -// extractTextFromDOCX(file); -// } else { -// toast.error('Unsupported file type. Please upload a PDF or DOCX file.'); -// } -// }; - -// const extractTextFromPDF = (file) => { -// const fileReader = new FileReader(); -// fileReader.onload = async () => { -// const typedArray = new Uint8Array(fileReader.result); -// const pdf = await pdfjsLib.getDocument(typedArray).promise; -// let text = ''; -// for (let i = 0; i < pdf.numPages; i++) { -// const page = await pdf.getPage(i + 1); -// const content = await page.getTextContent(); -// text += content.items.map((item) => item.str).join(' '); -// } -// setResumeText(text); -// toast.success('PDF text extracted successfully!'); -// }; -// fileReader.readAsArrayBuffer(file); -// }; - -// const extractTextFromDOCX = (file) => { -// const fileReader = new FileReader(); -// fileReader.onload = async () => { -// const result = await mammoth.extractRawText({ arrayBuffer: fileReader.result }); -// setResumeText(result.value); -// toast.success('DOCX text extracted successfully!'); -// }; -// fileReader.readAsArrayBuffer(file); -// }; - -// // Mock AI responses -// const analyzeResume = () => { -// if (!resumeText) { -// toast.error('Please upload a resume first.'); -// return; -// } -// setFeedback(`Analysis of resume: ${resumeText.substring(0, 100)}...`); -// toast.success('Resume analyzed successfully!'); -// }; - -// const getResumeScore = () => { -// if (!resumeText) { -// toast.error('Please upload a resume first.'); -// return; -// } -// setScore('Your resume score is 85/100. Great job!'); -// toast.success('Resume scored successfully!'); -// }; - -// const downloadImprovedResume = () => { -// const blob = new Blob([resumeText], { type: 'text/plain;charset=utf-8' }); -// saveAs(blob, 'Improved_Resume.txt'); -// toast.success('Resume downloaded successfully!'); -// }; - -// return ( -//
-// -//

๐Ÿš€ AI ResumeXpert Analyst

-//

Upload your resume to get detailed AI feedback, ATS analysis, and job match insights!

- -// -// {resumeText && ( -//
-//

Resume Text Extracted:

-// -//
-// )} - -// setTabIndex(index)}> -// -// ๐Ÿ“‚ Upload Resume -// ๐Ÿ“Š Job Match Analysis -// ๐Ÿš€ AI Project Suggestions -// ๐Ÿคทโ€โ™‚ ATS Score Checker -// ๐Ÿ“Š AI-Powered Resume Ranking -// - -// {/* Tab 1: Resume Upload and Analysis */} -// -// -// -// -// {feedback && ( -//

-// Feedback: {feedback} -//

-// )} -// {score && ( -//

-// Score: {score} -//

-// )} -//
- -// {/* Tab 2: Job Match Analysis */} -// -// -// -// - -// {/* Tab 3: AI Project Suggestions */} -// -// -// - -// {/* Tab 4: ATS Score Checker */} -// -// -// - -// {/* Tab 5: AI-Powered Resume Ranking */} -// -// -// -//
-//
-// ); -// }; - -// export default ResumeBuilder; - -// https://github.com/abhishekkumar62000/AI-ResumeXpert-Analyst/blob/main/App.py -// # Import Important Library -// import streamlit as st -// import google.generativeai as genai -// import webbrowser -// from PyPDF2 import PdfReader -// from docx import Document -// from reportlab.pdfgen import canvas -// from reportlab.lib.pagesizes import letter - -// # Set page configuration -// st.set_page_config(page_title="AI Resume Reviewer", page_icon="๐Ÿ“„", layout="wide") - -// # Fetch API key from Streamlit Secrets -// GEMINI_API_KEY = st.secrets["GEMINI_API_KEY"] - -// # Ensure the API key is set -// if not GEMINI_API_KEY: -// st.error("โš  GEMINI API Key is missing. Set it in Streamlit Secrets!") -// else: -// genai.configure(api_key=GEMINI_API_KEY) - -// import google.api_core.exceptions # Add this import - -// # List available models to verify the model name -// try: -// available_models = genai.list_models() -// model_names = [model.name for model in available_models] - -// # Verify if the desired model is in the list -// desired_model_name = "models/gemini-1.5-flash-latest" # Replace with the correct model name -// if desired_model_name in model_names: -// model = genai.GenerativeModel(desired_model_name) -// else: -// st.error(f"โš  Model '{desired_model_name}' not found. Available models: {model_names}") -// st.stop() -// except google.api_core.exceptions.PermissionDenied as e: -// st.error("โš  Permission denied. Please check your API key permissions.") -// st.stop() -// except google.api_core.exceptions.InvalidArgument as e: -// st.error("โš  Invalid argument. Please check the model name and API key.") -// st.stop() -// except Exception as e: -// st.error(f"โš  An unexpected error occurred: {e}") -// st.stop() - -// def chat_with_gemini(prompt): -// try: -// response = model.generate_content(prompt) -// return response.text if response else "No response received." -// except google.api_core.exceptions.NotFound as e: -// st.error("โš  Model not found. Please check the model name and API key.") -// return "Model not found." -// except google.api_core.exceptions.PermissionDenied as e: -// st.error("โš  Permission denied. Please check your API key permissions.") -// return "Permission denied." -// except google.api_core.exceptions.InvalidArgument as e: -// st.error("โš  Invalid argument. Please check the model name and API key.") -// return "Invalid argument." -// except Exception as e: -// st.error(f"โš  An unexpected error occurred: {e}") -// return f"An unexpected error occurred: {e}" - -// # Your other code remains the same -// import asyncio - -// try: -// asyncio.get_running_loop() -// except RuntimeError: -// asyncio.run(asyncio.sleep(0)) # โœ… Ensure a running event loop - -// # UI Improvements -// st.title("๐Ÿš€AI ResumeXpert Analyst ๐Ÿค–") -// st.markdown("Upload your resume to get detailed AI feedback, ATS analysis, and job match insights!๐Ÿง ") -// st.caption("๐Ÿ“ Rewrite. ๐Ÿš€ Rank. ๐ŸŽฏ Recruit โ€“ AI ResumeXpert at Your Service!๐Ÿ‘จโ€๐Ÿ’ป") - -// AI_path = "AI.png" # Ensure this file is in the same directory as your script -// try: -// st.sidebar.image(AI_path) -// except FileNotFoundError: -// st.sidebar.warning("AI.png file not found. Please check the file path.") - -// image_path = "image.png" # Ensure this file is in the same directory as your script -// try: -// st.sidebar.image(image_path) -// except FileNotFoundError: -// st.sidebar.warning("image.png file not found. Please check the file path.") - -// # Sidebar Navigation -// with st.sidebar: -// st.header("โš™ App Features") - -// tab_selection = st.radio("Select a Feature:", [ -// "๐Ÿ“„ Resume Analysis", -// "๐Ÿ“Š ATS Score & Fixes", -// "๐Ÿ’ผ Job Fit Analysis", -// "๐Ÿš€ AI Project Suggestions", -// "๐Ÿ’ก Best Career Path", -// "๐Ÿ›  Missing Skills & Learning Guide", -// "๐ŸŽ“ Certifications & Courses", -// "๐Ÿ’ฐ Expected Salaries & Job Roles", -// "๐Ÿ“Š AI Resume Ranking", -// "๐Ÿ” Personalized Job Alerts", -// "โœ‰ AI Cover Letter Generator", -// "๐ŸŽค AI Mock Interviews" -// ]) - -// st.markdown("๐Ÿ‘จ๐Ÿ‘จโ€๐Ÿ’ปDeveloper:- Abhishek๐Ÿ’–Yadav") - -// developer_path = "pic.jpg" # Ensure this file is in the same directory as your script -// try: -// st.sidebar.image(developer_path) -// except FileNotFoundError: -// st.sidebar.warning("pic.jpg file not found. Please check the file path.") - -// def extract_text(file): -// if file.name.endswith(".pdf"): -// pdf_reader = PdfReader(file) -// return "\n".join([page.extract_text() for page in pdf_reader.pages if page.extract_text()]) -// elif file.name.endswith(".docx"): -// doc = Document(file) -// return "\n".join([para.text for para in doc.paragraphs]) -// else: -// return "โŒ Unsupported file format. Upload a PDF or DOCX." - -// def analyze_resume(text): -// prompt = f""" -// You are an expert AI Resume Reviewer. Analyze the following resume thoroughly and provide structured insights on: -// 0๏ธโƒฃ first Full Detail Analysis of Resume Files and Display all details of the resume -// 1๏ธโƒฃ Strengths: What makes this resume stand out? Identify key skills, achievements, and formatting positives. -// 2๏ธโƒฃ Areas for Improvement: Highlight missing elements, weak points, and vague descriptions that need enhancement. -// 3๏ธโƒฃ Formatting Suggestions: Provide recommendations for a more professional and ATS-compliant structure. -// 4๏ธโƒฃ ATS Compliance Check: Analyze the resume for ATS-friendliness, including keyword optimization and readability. -// 5๏ธโƒฃ Overall Rating: Score the resume on a scale of 1 to 10 with justification. - -// Resume: -// {text} -// """ -// return chat_with_gemini(prompt) - -// def match_job_description(resume_text, job_desc): -// prompt = f""" -// You are an AI Job Fit Analyzer. Compare the given resume with the provided job description and generate a structured report: - -// โœ… Matching Skills: Identify skills in the resume that match the job description. -// โŒ Missing Skills: Highlight missing key skills that the candidate needs to acquire. -// ๐Ÿ“Š Fit Percentage: Provide a percentage match score based on skillset, experience, and qualifications. -// ๐Ÿ† Final Verdict: Clearly state whether the candidate is a "Good Fit" or "Needs Improvement" with reasons. - -// Resume: -// {resume_text} - -// Job Description: -// {job_desc} -// """ -// return chat_with_gemini(prompt) - -// def get_resume_score(resume_text): -// prompt = f""" -// As an AI Resume Scorer, evaluate the resume across different factors and provide a structured breakdown: - -// ๐ŸŽฏ Skills Match: XX% (How well the skills align with industry requirements) -// ๐Ÿ“ˆ Experience Level: XX% (Assessment of experience depth and relevance) -// โœจ Formatting Quality: XX% (Resume structure, clarity, and ATS compliance) -// ๐Ÿ” Overall Strength: XX% (General effectiveness of the resume) - -// Provide the final Resume Score (0-100) with a breakdown and actionable insights for improvement. - -// Resume: -// {resume_text} -// """ -// return chat_with_gemini(prompt) - -// def get_improved_resume(resume_text): -// prompt = f""" -// Optimize the following resume to enhance its professionalism, clarity, and ATS compliance: - -// - โœ… Fix grammar and spelling errors -// - ๐Ÿ”ฅ Improve clarity, conciseness, and professionalism -// - โœจ Optimize formatting for readability and ATS-friendliness -// - ๐Ÿ“Œ Ensure keyword optimization to improve job match chances -// - ๐Ÿ† Enhance overall presentation while maintaining content integrity - -// Resume: -// {resume_text} - -// Provide only the improved resume text. -// """ -// return chat_with_gemini(prompt) - -// def create_pdf(text, filename="Optimized_Resume.pdf"): -// c = canvas.Canvas(filename, pagesize=letter) -// c.drawString(50, 750, text) -// c.save() -// return filename - -// # Create Section-wise Tabs -// tab1, tab2, tab3, tab4, tab5 = st.tabs(["๐Ÿ“‚ Upload Resume", "๐Ÿ“Š Job Match Analysis", "๐Ÿš€ AI Project Suggestions", "๐Ÿคทโ€โ™‚ ATS Score Checker", "๐Ÿ“Š AI-Powered Resume Ranking"]) - -// # Tab 1: Resume Upload and Analysis -// with tab1: -// uploaded_file = st.file_uploader("Upload Resume (PDF/DOCX)", type=["pdf", "docx"]) -// if uploaded_file: -// st.success("โœ… Resume Uploaded Successfully!") -// resume_text = extract_text(uploaded_file) - -// # AI Resume Analysis -// feedback = analyze_resume(resume_text) -// score_feedback = get_resume_score(resume_text) - -// st.subheader("๐Ÿ“ AI Feedback") -// st.write(feedback) - -// st.subheader("โญ Resume Score & ATS Breakdown") -// st.write(score_feedback) - -// if st.button("๐Ÿš€ Improve Resume & Download"): -// improved_resume_text = get_improved_resume(resume_text) -// updated_pdf = create_pdf(improved_resume_text) -// st.success("๐ŸŽ‰ Resume Improved Successfully!") -// st.download_button("โฌ‡ Download Optimized Resume", open(updated_pdf, "rb"), file_name="Optimized_Resume.pdf") - -// # Tab 2: Job Match Analysis -// with tab2: -// job_desc = st.text_area("๐Ÿ“Œ Paste Job Description Here:") -// if job_desc and 'resume_text' in locals(): -// st.write("๐Ÿ” Analyzing job fit...") -// job_fit_feedback = match_job_description(resume_text, job_desc) -// st.subheader("๐Ÿ“Š Job Fit Analysis") -// st.write(job_fit_feedback) - -// # Function to Generate AI-Based Project Suggestions (5 per level) -// def suggest_projects(resume_text): -// prompt = f""" -// You are a project mentor Expert. Based on the resume below, suggest 5 projects for each level: - -// Basic Level (For Beginners): 5 easy projects to get started. -// Intermediate Level (For Practitioners): 5 projects requiring more expertise. -// Advanced Level (For Experts): 5 complex projects showcasing deep skills. - -// ๐Ÿ”น For Each Project: Provide a brief description and the required tech stack (tools, frameworks, technologies). -// ๐Ÿ”น Make sure the projects align with the user's skills, experience, and domain. - -// Resume: -// {resume_text} -// """ -// return chat_with_gemini(prompt) - -// # Tab 3: AI Project Suggestions -// with tab3: -// st.subheader("๐Ÿš€ AI-Powered Project Suggestions") -// if uploaded_file and 'resume_text' in locals(): -// if st.button("๐Ÿ“Œ Get Project Ideas Based on Resume"): -// project_suggestions = suggest_projects(resume_text) -// st.write(project_suggestions) - -// # Function to Calculate ATS Score & Provide Feedback -// def check_ats_score(resume_text): -// prompt = f""" -// You are an ATS resume evaluator. Based on the resume below, analyze its ATS compatibility on a scale of 100. - -// Scoring Criteria: -// - โœ… Proper Formatting & Readability (20%) -// - โœ… Use of Correct Keywords (30%) -// - โœ… Section Organization (20%) -// - โœ… No Unnecessary Graphics or Tables (15%) -// - โœ… Proper Contact Info & Structure (15%) - -// Provide Output as: -// - ATS Score (out of 100) -// - Improvement Suggestions to improve 100 ATS Score - -// Resume: -// {resume_text} -// """ -// response = chat_with_gemini(prompt) -// try: -// ats_score = int(response.split("ATS Score:")[1].split("/100")[0].strip()) -// except (IndexError, ValueError): -// ats_score = 0 # Default to 0 if parsing fails -// ats_feedback = response.split("Improvement Suggestions to improve 100 ATS Score")[1].strip() if "Improvement Suggestions to improve 100 ATS Score" in response else "No feedback available." -// return ats_score, ats_feedback - -// # Tab 4: ATS Score Checker -// with tab4: -// st.subheader("๐Ÿคทโ€โ™‚ ATS Score Checker") - -// if uploaded_file and 'resume_text' in locals(): -// if st.button("๐Ÿ” Check ATS Score"): -// ats_score, ats_feedback = check_ats_score(resume_text) -// st.markdown(f"### โœ… Your ATS Score: {ats_score}/100") -// if ats_score < 80: -// st.warning("โš  Your resume needs improvement!") -// st.write(ats_feedback) -// else: -// st.success("๐ŸŽ‰ Your resume is ATS-friendly!") - -// # Tab 5: AI-Powered Resume Ranking -// with tab5: -// st.subheader("๐Ÿ“Š AI-Powered Resume Ranking") - -// # Upload multiple resume files -// uploaded_files = st.file_uploader("Upload Multiple Resumes (PDF/DOCX)", type=["pdf", "docx"], accept_multiple_files=True) - -// # Process resumes if uploaded -// if uploaded_files: -// resume_texts = [] -// file_names = [] - -// for file in uploaded_files: -// text = extract_text(file) # Function to extract text from PDF/DOCX -// if text.startswith("โŒ"): # Error handling -// st.error(f"โŒ Unable to process: {file.name}") -// else: -// resume_texts.append(text) -// file_names.append(file.name) - -// if len(resume_texts) > 0: -// if st.button("๐Ÿš€ Rank Resumes"): # Button to rank resumes -// ranked_resumes = [] - -// for i, text in enumerate(resume_texts): -// rank_prompt = f""" -// You are an AI Resume Evaluator. Assess the following resume based on: -// โœ… *ATS Compatibility* -// โœ… *Readability & Formatting* -// โœ… *Job Fit & Skills Alignment* - -// Give a *score out of 100* and a brief analysis. - -// Resume: -// {text} -// """ -// score_response = chat_with_gemini(rank_prompt) # AI function to analyze resume -// try: -// score = int(score_response.split("Score:")[-1].split("/")[0].strip()) # Extract score -// except (IndexError, ValueError): -// score = 0 # Default to 0 if parsing fails -// ranked_resumes.append((file_names[i], score)) - -// # Sort resumes by score (Highest to Lowest) -// ranked_resumes.sort(key=lambda x: x[1], reverse=True) - -// # Display ranked results -// st.subheader("๐Ÿ† Ranked Resumes") -// for i, (name, score) in enumerate(ranked_resumes, start=1): -// st.write(f"{i}. {name}** - *Score: {score}/100*") - -// # Creating multiple tabs together -// tab6, tab7, tab8, tab9, tab10, tab11, tab12 = st.tabs([ -// "๐Ÿ’ก AI Career Roadmap & Skills Guide", -// "๐Ÿ›  Missing Skills & How to Learn Them", -// "๐Ÿ“œ Certifications & Course Recommendations", -// "๐Ÿ’ฐ Expected Salaries & Job Roles", -// "๐Ÿ“ข Resume Feedback via AI Chat", -// "๐Ÿ“ข Personalized Job Alerts", -// "๐Ÿ’ก Soft Skills Analysis & Improvement" -// ]) - -// # Tab 6: Best Career Path -// with tab6: -// st.subheader("๐Ÿ’ก AI Career Roadmap & Skills Guide") -// if uploaded_file and 'resume_text' in locals(): -// if st.button("๐Ÿš€ Get Career Insights"): -// def generate_career_roadmap(resume_text): -// prompt = f""" -// You are an AI Career Advisor. Based on the following resume, suggest the best career path: - -// โœ… Current Strengths & Skills: Identify the user's key strengths. -// ๐Ÿš€ Best Career Path: Recommend an ideal career direction. -// ๐Ÿ“ˆ Career Growth Roadmap: -// - ๐Ÿ”น Entry-Level Roles -// - ๐Ÿ”ธ Mid-Level Roles -// - ๐Ÿ”บ Senior-Level Roles -// ๐Ÿ”ฎ Future Industry Trends: Emerging trends & opportunities. - -// Resume: -// {resume_text} -// """ -// return chat_with_gemini(prompt) - -// career_guidance = generate_career_roadmap(resume_text) -// st.write(career_guidance) - -// # Tab 7: Missing Skills -// with tab7: -// st.subheader("๐Ÿ›  Missing Skills & How to Learn Them") -// if uploaded_file and 'resume_text' in locals(): -// if st.button("๐Ÿ“š Identify Missing Skills"): -// def find_missing_skills(resume_text): -// prompt = f""" -// You are an AI Skill Analyzer. Analyze the following resume and provide missing skills: - -// โœ… Existing Skills: List the current skills of the user. -// โŒ Missing Skills: Identify skills required for industry standards. -// ๐ŸŽฏ How to Learn Them: Provide learning resources (courses, books, projects). -// ๐Ÿ”ฅ Importance of These Skills: Explain how these skills will improve job opportunities. - -// Resume: -// {resume_text} -// """ -// return chat_with_gemini(prompt) - -// missing_skills = find_missing_skills(resume_text) -// st.write(missing_skills) - -// # Tab 8: Certifications & Courses -// with tab8: -// st.subheader("๐Ÿ“œ Certifications & Course Recommendations") -// if uploaded_file and 'resume_text' in locals(): -// if st.button("๐ŸŽ“ Get Course Recommendations"): -// def recommend_certifications(resume_text): -// prompt = f""" -// You are an AI Career Coach. Analyze the following resume and suggest relevant certifications & courses: - -// โœ… Top 5 Certifications: Industry-recognized certifications that align with the userโ€™s skills and career path. -// ๐Ÿ“š Top 5 Online Courses: From platforms like Coursera, Udemy, LinkedIn Learning, or edX. -// ๐Ÿ”ฅ Why These Certifications?: Explain why these certifications/courses will boost their career. -// ๐Ÿ›  Preparation Resources: Provide book or website recommendations. - -// Resume: -// {resume_text} -// """ -// return chat_with_gemini(prompt) - -// courses = recommend_certifications(resume_text) -// st.write(courses) - -// # Tab 9: Expected Salaries & Job Roles -// with tab9: -// st.subheader("๐Ÿ’ฐ Expected Salaries & Job Roles") -// if uploaded_file and 'resume_text' in locals(): -// if st.button("๐Ÿ’ผ Get Salary & Job Role Insights"): -// def get_salary_and_jobs(resume_text): -// prompt = f""" -// You are an AI Career Consultant. Analyze the following resume and provide structured salary insights: - -// ๐Ÿ’ผ Best Job Roles: Suggest top job roles based on userโ€™s skills, experience, and industry trends. -// ๐ŸŒŽ Salary Estimates by Region: -// - USA: $XX,XXX - $XX,XXX per year -// - UK: ยฃXX,XXX - ยฃXX,XXX per year -// - India: โ‚นXX,XX,XXX - โ‚นXX,XX,XXX per year -// - Remote/Global: $XX,XXX per year (varies based on employer) -// ๐Ÿ“ˆ Career Growth Insights: How salaries and opportunities increase with upskilling. -// ๐Ÿ”ฅ Top Industries Hiring: Which industries are in demand for the user's skills? - -// Resume: -// {resume_text} -// """ -// return chat_with_gemini(prompt) - -// salary_and_jobs = get_salary_and_jobs(resume_text) -// st.write(salary_and_jobs) - -// # Tab 10: Interactive Resume Q&A -// with tab10: -// st.subheader("๐Ÿ“ข Ask AI About Your Resume") -// st.markdown("๐Ÿ’ฌ Type any question about your resume, and AI will provide detailed guidance!") - -// if uploaded_file: -// user_question = st.text_input("โ“ Ask anything about your resume:") - -// if user_question: -// with st.spinner("๐Ÿค– AI is analyzing your resume..."): -// prompt = f""" -// You are an expert AI Resume Consultant. A user has uploaded their resume and is asking the following question: - -// Question: {user_question} - -// Resume: -// {resume_text} - -// Provide a detailed, structured, and insightful response, including: -// - Key observations from their resume. -// - Actionable improvements tailored to their experience. -// - Industry best practices for better job opportunities. -// """ -// response = chat_with_gemini(prompt) -// st.write("๐Ÿ’ก AI Response:") -// st.write(response) - -// # Tab 11: Personalized Job Alerts -// with tab11: -// st.subheader("๐Ÿ”” Personalized Job Alerts") - -// # Input fields for user preferences -// job_title = st.text_input("๐ŸŽฏ Enter Job Title (e.g., Data Scientist, Software Engineer)") -// location = st.text_input("๐Ÿ“ Preferred Location (e.g., Remote, New York, Bangalore)") - -// if st.button("๐Ÿ” Find Jobs Now"): -// if job_title and location: -// st.success(f"๐Ÿ”— Here are job links for *{job_title}* in *{location}*:") - -// # Dynamic job search URLs -// indeed_url = f"https://www.indeed.com/jobs?q={job_title.replace(' ', '+')}&l={location.replace(' ', '+')}" -// linkedin_url = f"https://www.linkedin.com/jobs/search?keywords={job_title.replace(' ', '%20')}&location={location.replace(' ', '%20')}" -// naukri_url = f"https://www.naukri.com/{job_title.replace(' ', '-')}-jobs-in-{location.replace(' ', '-')}" -// google_jobs_url = f"https://www.google.com/search?q={job_title.replace(' ', '+')}+jobs+in+{location.replace(' ', '+')}" - -// # Display clickable job links -// st.markdown(f"[๐ŸŸข Indeed Jobs]({indeed_url})") -// st.markdown(f"[๐Ÿ”ต LinkedIn Jobs]({linkedin_url})") -// st.markdown(f"[๐ŸŸ  Naukri Jobs]({naukri_url})") -// st.markdown(f"[๐Ÿ”ด Google Jobs]({google_jobs_url})") - -// # Open default browser with job search links -// webbrowser.open(indeed_url) -// webbrowser.open(linkedin_url) -// webbrowser.open(naukri_url) -// webbrowser.open(google_jobs_url) -// else: -// st.error("โš  Please enter both job title and location to get job alerts.") - -// # Tab 12: Soft Skills Analysis & Improvement Tips -// with tab12: -// st.subheader("๐Ÿ’ก Soft Skills Analysis & Improvement") - -// if uploaded_file: -// resume_text = extract_text(uploaded_file) # Ensure resume_text is defined -// soft_skills_prompt = f""" -// You are an AI Soft Skills Analyzer. Based on the resume, identify the candidate's *soft skills* and suggest ways to improve them: - -// โœ… *Identified Soft Skills* -// โœ… *Why these skills are important* -// โœ… *Recommended activities to strengthen them* -// โœ… *Online courses or books to improve them* - -// Resume: -// {resume_text} -// """ -// if st.button("๐Ÿ“š Get Soft Skills Insights"): -// soft_skills_analysis = chat_with_gemini(soft_skills_prompt) -// st.write(soft_skills_analysis) -// else: -// st.warning("Please upload a resume to analyze soft skills.") diff --git a/src/components/ResumeAnalyzer/ResumeAnalyzer.jsx b/src/components/ResumeAnalyzer/ResumeAnalyzer.jsx new file mode 100644 index 00000000..f20c021d --- /dev/null +++ b/src/components/ResumeAnalyzer/ResumeAnalyzer.jsx @@ -0,0 +1,40 @@ +import React from 'react'; +import { Construction, ArrowLeft } from 'lucide-react'; +import { useNavigate } from 'react-router-dom'; + +const ResumeAnalyzer = () => { + const navigate = useNavigate(); + + return ( +
+ + +
+ +

Resume Analyzer

+

This feature is currently under construction.

+

+ We're working hard to bring you an amazing AI-powered resume analysis tool. Please check back soon! +

+
+
+ ); +}; + +export default ResumeAnalyzer; diff --git a/src/components/ResumeBuilder/ResumeBuilder.jsx b/src/components/ResumeBuilder/ResumeBuilder.jsx new file mode 100644 index 00000000..34c416a7 --- /dev/null +++ b/src/components/ResumeBuilder/ResumeBuilder.jsx @@ -0,0 +1,79 @@ +'use client'; + +import { useState } from 'react'; +import { FaUser, FaBriefcase, FaCode, FaBook, FaGraduationCap, FaUsers, FaAward, FaFileAlt } from 'react-icons/fa'; + +import Sidebar from './Sidebar'; +import BasicInfo from './Sections/BasicInfo'; +import Experience from './Sections/Experience'; +import Projects from './Sections/Projects'; +import Skills from './Sections/Skills'; +import Education from './Sections/Education'; +import Leadership from './Sections/Leadership'; +import Achievement from './Sections/Achievement'; +import Resume from './Sections/Resume'; + +import './styles/ResumeBuilder.css'; + +const sections = [ + { id: 'basic-info', label: 'Basic Info', icon: FaUser }, + { id: 'experience', label: 'Experience', icon: FaBriefcase }, + { id: 'projects', label: 'Projects', icon: FaCode }, + { id: 'skills', label: 'Skills', icon: FaBook }, + { id: 'education', label: 'Education', icon: FaGraduationCap }, + { id: 'leadership', label: 'Leadership', icon: FaUsers }, + { id: 'achievement', label: 'Achievement', icon: FaAward }, + { id: 'resume', label: 'Resume', icon: FaFileAlt }, +]; + +function ResumeBuilder() { + const [activeSection, setActiveSection] = useState('basic-info'); + + const getStepStatus = (sectionId) => { + const currentIndex = sections.findIndex((section) => section.id === activeSection); + const sectionIndex = sections.findIndex((section) => section.id === sectionId); + + if (sectionIndex < currentIndex) return 'completed'; + if (sectionIndex === currentIndex) return 'active'; + return 'pending'; + }; + + const renderSection = () => { + switch (activeSection) { + case 'basic-info': + return setActiveSection('experience')} />; + case 'experience': + return setActiveSection('basic-info')} onNext={() => setActiveSection('projects')} />; + case 'projects': + return setActiveSection('experience')} onNext={() => setActiveSection('skills')} />; + case 'skills': + return setActiveSection('projects')} onNext={() => setActiveSection('education')} />; + case 'education': + return setActiveSection('skills')} onNext={() => setActiveSection('leadership')} />; + case 'leadership': + return ( + setActiveSection('education')} onNext={() => setActiveSection('achievement')} /> + ); + case 'achievement': + return setActiveSection('leadership')} onNext={() => setActiveSection('resume')} />; + case 'resume': + return setActiveSection('achievement')} />; + default: + return setActiveSection('experience')} />; + } + }; + + return ( +
+ +
{renderSection()}
+
+ ); +} + +export default ResumeBuilder; diff --git a/src/components/ResumeBuilder/Sections/Achievement.jsx b/src/components/ResumeBuilder/Sections/Achievement.jsx new file mode 100644 index 00000000..c05e98d6 --- /dev/null +++ b/src/components/ResumeBuilder/Sections/Achievement.jsx @@ -0,0 +1,110 @@ +'use client'; + +import { useState, useEffect } from 'react'; +import { Award, ArrowLeft, ArrowRight } from 'lucide-react'; +import { useResume } from '../context/ResumeContext'; +import '../styles/FormSections.css'; + +function Achievement({ onPrev, onNext }) { + const { resumeData, updateAchievements } = useResume(); + const [achievements, setAchievements] = useState(resumeData.achievements); + + useEffect(() => { + setAchievements(resumeData.achievements); + }, [resumeData.achievements]); + + const handleChange = (field, value) => { + setAchievements((prev) => ({ + ...prev, + [field]: value, + })); + }; + + const handleSubmit = (e) => { + e.preventDefault(); + updateAchievements(achievements); + onNext(); + }; + + return ( +
+
+
+

+ Achievements +

+

Add your notable achievements and recognitions

+
+ +
+
+
+ +
+ + handleChange('achievement1', e.target.value)} + placeholder="Any Hackathon wins or participations" + /> +
+
+ +
+ +
+ + handleChange('achievement2', e.target.value)} + placeholder="Any Coding Contest Achievements" + /> +
+
+
+ +
+
+ +
+ + handleChange('achievement3', e.target.value)} + placeholder="Any Hackathon wins or participations" + /> +
+
+ +
+ +
+ + handleChange('achievement4', e.target.value)} + placeholder="Any Coding Contest Achievements" + /> +
+
+
+ +
+ + +
+
+
+
+ ); +} + +export default Achievement; diff --git a/src/components/ResumeBuilder/Sections/BasicInfo.jsx b/src/components/ResumeBuilder/Sections/BasicInfo.jsx new file mode 100644 index 00000000..abe17842 --- /dev/null +++ b/src/components/ResumeBuilder/Sections/BasicInfo.jsx @@ -0,0 +1,194 @@ +'use client'; + +import { useState, useEffect } from 'react'; +import { User, Linkedin, Github, Mail, Phone, ArrowRight } from 'lucide-react'; +import { useResume } from '../context/ResumeContext'; +import '../styles/FormSections.css'; + +function BasicInfo({ onNext }) { + const { resumeData, updateBasicInfo } = useResume(); + const [formData, setFormData] = useState(resumeData.basicInfo); + const [errors, setErrors] = useState({}); + + useEffect(() => { + setFormData(resumeData.basicInfo); + }, [resumeData.basicInfo]); + + const handleChange = (e) => { + const { name, value } = e.target; + setFormData((prev) => ({ ...prev, [name]: value })); + + // Clear error when user types + if (errors[name]) { + setErrors((prev) => { + const newErrors = { ...prev }; + delete newErrors[name]; + return newErrors; + }); + } + }; + + const validateForm = () => { + const newErrors = {}; + + if (!formData.firstName.trim()) { + newErrors.firstName = 'First name is required'; + } + + if (!formData.linkedinLink.trim()) { + newErrors.linkedinLink = 'LinkedIn link is required'; + } + + if (!formData.email.trim()) { + newErrors.email = 'Email is required'; + } else if (!/\S+@\S+\.\S+/.test(formData.email)) { + newErrors.email = 'Email is invalid'; + } + + if (!formData.phoneNumber.trim()) { + newErrors.phoneNumber = 'Phone number is required'; + } + + setErrors(newErrors); + return Object.keys(newErrors).length === 0; + }; + + const handleSubmit = (e) => { + e.preventDefault(); + + if (validateForm()) { + updateBasicInfo(formData); + onNext(); + } + }; + + return ( +
+
+
+

+ Basic Information +

+

Enter your personal details to get started with your resume

+
+ +
+
+
+ +
+ + +
+ {errors.firstName &&

{errors.firstName}

} +
+ +
+ +
+ + +
+
+
+ +
+
+ +
+ + +
+ {errors.linkedinLink &&

{errors.linkedinLink}

} +
+ +
+ +
+ + +
+
+
+ +
+
+ +
+ + +
+ {errors.email &&

{errors.email}

} +
+ +
+ +
+ + +
+ {errors.phoneNumber &&

{errors.phoneNumber}

} +
+
+ +
+ +
+
+
+
+ ); +} + +export default BasicInfo; diff --git a/src/components/ResumeBuilder/Sections/Education.jsx b/src/components/ResumeBuilder/Sections/Education.jsx new file mode 100644 index 00000000..335af395 --- /dev/null +++ b/src/components/ResumeBuilder/Sections/Education.jsx @@ -0,0 +1,157 @@ +'use client'; + +import { useState, useEffect } from 'react'; +import { GraduationCap, CalendarDays, MapPin, Trash2, Plus, ArrowLeft, ArrowRight } from 'lucide-react'; +import { useResume } from '../context/ResumeContext'; +import '../styles/FormSections.css'; + +function Education({ onPrev, onNext }) { + const { resumeData, updateEducation } = useResume(); + const [educations, setEducations] = useState( + resumeData.education.length > 0 + ? resumeData.education + : [ + { + title: '', + schoolName: '', + duration: '', + location: '', + }, + ], + ); + + useEffect(() => { + if (resumeData.education.length > 0) { + setEducations(resumeData.education); + } + }, [resumeData.education]); + + const handleChange = (index, field, value) => { + const updatedEducations = [...educations]; + updatedEducations[index] = { + ...updatedEducations[index], + [field]: value, + }; + setEducations(updatedEducations); + }; + + const addEducation = () => { + setEducations([ + ...educations, + { + title: '', + schoolName: '', + duration: '', + location: '', + }, + ]); + }; + + const removeEducation = (index) => { + if (educations.length > 1) { + const updatedEducations = [...educations]; + updatedEducations.splice(index, 1); + setEducations(updatedEducations); + } + }; + + const handleSubmit = (e) => { + e.preventDefault(); + updateEducation(educations); + onNext(); + }; + + return ( +
+
+
+

+ Education +

+

Add your educational background

+
+ +
+ {educations.map((education, index) => ( +
+ {educations.length > 1 && ( + + )} + +
+ +
+ + handleChange(index, 'title', e.target.value)} + placeholder="eg: Bachelors of Technology in Computer Science" + /> +
+
+ +
+ +
+ + handleChange(index, 'schoolName', e.target.value)} + placeholder="e.g. University of California, Berkeley" + /> +
+
+ +
+
+ +
+ + handleChange(index, 'duration', e.target.value)} + placeholder="e.g. 2018 - 2022" + /> +
+
+ +
+ +
+ + handleChange(index, 'location', e.target.value)} + placeholder="Location eg: Patna, Bihar" + /> +
+
+
+
+ ))} + + + +
+ + +
+
+
+
+ ); +} + +export default Education; diff --git a/src/components/ResumeBuilder/Sections/Experience.jsx b/src/components/ResumeBuilder/Sections/Experience.jsx new file mode 100644 index 00000000..d2e088c9 --- /dev/null +++ b/src/components/ResumeBuilder/Sections/Experience.jsx @@ -0,0 +1,172 @@ +'use client'; + +import { useState, useEffect } from 'react'; +import { Building2, CalendarDays, MapPin, Trash2, Plus, ArrowLeft, ArrowRight } from 'lucide-react'; +import { useResume } from '../context/ResumeContext'; +import '../styles/FormSections.css'; + +function Experience({ onPrev, onNext }) { + const { resumeData, updateExperience } = useResume(); + const [experiences, setExperiences] = useState( + resumeData.experience.length > 0 + ? resumeData.experience + : [ + { + designation: '', + companyName: '', + duration: '', + location: '', + workDescription: '', + }, + ], + ); + + useEffect(() => { + if (resumeData.experience.length > 0) { + setExperiences(resumeData.experience); + } + }, [resumeData.experience]); + + const handleChange = (index, field, value) => { + const updatedExperiences = [...experiences]; + updatedExperiences[index] = { + ...updatedExperiences[index], + [field]: value, + }; + setExperiences(updatedExperiences); + }; + + const addExperience = () => { + setExperiences([ + ...experiences, + { + designation: '', + companyName: '', + duration: '', + location: '', + workDescription: '', + }, + ]); + }; + + const removeExperience = (index) => { + if (experiences.length > 1) { + const updatedExperiences = [...experiences]; + updatedExperiences.splice(index, 1); + setExperiences(updatedExperiences); + } + }; + + const handleSubmit = (e) => { + e.preventDefault(); + updateExperience(experiences); + onNext(); + }; + + return ( +
+
+
+

+ Work Experience +

+

Add your professional work experience

+
+ +
+ {experiences.map((experience, index) => ( +
+ {experiences.length > 1 && ( + + )} + +
+
+ +
+ + handleChange(index, 'designation', e.target.value)} + placeholder="e.g. Software Engineer" + /> +
+
+ +
+ +
+ + handleChange(index, 'companyName', e.target.value)} + placeholder="e.g. Acme Inc." + /> +
+
+
+ +
+
+ +
+ + handleChange(index, 'duration', e.target.value)} + placeholder="e.g. Jan 2020 - Present" + /> +
+
+ +
+ +
+ + handleChange(index, 'location', e.target.value)} + placeholder="e.g. San Francisco, CA" + /> +
+
+
+ +
+ +