diff --git a/frontend/AIPT/package-lock.json b/frontend/AIPT/package-lock.json index 01d3e2e..5edc75d 100644 --- a/frontend/AIPT/package-lock.json +++ b/frontend/AIPT/package-lock.json @@ -9,6 +9,7 @@ "version": "0.0.0", "dependencies": { "@radix-ui/react-icons": "^1.3.2", + "@radix-ui/react-label": "^2.1.0", "@radix-ui/react-select": "^2.1.2", "@radix-ui/react-slot": "^1.1.0", "@shadcn/ui": "^0.0.4", @@ -954,6 +955,28 @@ } } }, + "node_modules/@radix-ui/react-label": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.0.tgz", + "integrity": "sha512-peLblDlFw/ngk3UWq0VnYaOLy6agTZZ+MUO/WhVfm14vJGML+xH4FAl2XQGLqdefjNb7ApRg6Yn7U42ZhmYXdw==", + "dependencies": { + "@radix-ui/react-primitive": "2.0.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-popper": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.0.tgz", diff --git a/frontend/AIPT/package.json b/frontend/AIPT/package.json index 5bde615..17c3087 100644 --- a/frontend/AIPT/package.json +++ b/frontend/AIPT/package.json @@ -11,6 +11,7 @@ }, "dependencies": { "@radix-ui/react-icons": "^1.3.2", + "@radix-ui/react-label": "^2.1.0", "@radix-ui/react-select": "^2.1.2", "@radix-ui/react-slot": "^1.1.0", "@shadcn/ui": "^0.0.4", diff --git a/frontend/AIPT/src/App.tsx b/frontend/AIPT/src/App.tsx index 4e53516..e5d8bdb 100644 --- a/frontend/AIPT/src/App.tsx +++ b/frontend/AIPT/src/App.tsx @@ -12,6 +12,7 @@ import Assignments from './pages/Candidate/Assignments'; import CandidateProfile from './pages/Candidate/CandidateProfile'; import Settings from './pages/Candidate/Settings'; import CandidateHome from './pages/Candidate/CandidateHome'; +import JobApplicationForm from './pages/Candidate/JobDetails'; const App: React.FC = () => { @@ -86,6 +87,15 @@ const App: React.FC = () => { } /> + + + + } + /> + = ({ title }) => { const [isDropdownOpen, setIsDropdownOpen] = useState(false); + const [isScrolled, setIsScrolled] = useState(false); const location = useLocation(); @@ -42,6 +44,7 @@ const CandidateHeader: React.FC = ({ title }) => { console.log("Is scrolled?", isScrolled); return ( +
diff --git a/frontend/AIPT/src/components/Candidate/Footer.tsx b/frontend/AIPT/src/components/Candidate/Footer.tsx new file mode 100644 index 0000000..6b50d85 --- /dev/null +++ b/frontend/AIPT/src/components/Candidate/Footer.tsx @@ -0,0 +1,114 @@ +import React from 'react'; + +import { AiFillInstagram,AiOutlineWhatsApp,AiFillFacebook ,AiOutlineMail, AiOutlinePhone } from "react-icons/ai"; +import { BsArrowUpCircleFill } from "react-icons/bs"; +import { BiSolidMap } from "react-icons/bi"; +import './footer.css'; + +const Footer = () => { + const scrollToTop = () => { + window.scrollTo({ top: 0, behavior: 'smooth' }); + }; + + return ( +
+
+ {/* Main Footer Content */} +
+ {/* Company Info */} +
+

+ AIPT +

+

+ Crafting digital experiences that inspire and innovate. We're committed to excellence in everything we do. +

+
+ + {/* Quick Links, Stay Updated, and Contact Us */} +
+ {/* Quick Links */} +
+

Quick Links

+
    + {['About Us', 'Services', 'Portfolio', 'Careers', 'Contact'].map((item) => ( +
  • + + {item} + +
  • + ))} +
+
+ + {/* Stay Updated */} +
+

Stay Updated

+
+

Subscribe to our newsletter for updates and insights.

+
+ + +
+
+
+ + {/* Contact Us */} +
+

Contact Us

+
+
+ + info@AIPT.com +
+
+ + +94 (76) 123-4567 +
+
+ + 123 Malabe, Malabe
Sri Lanaka, SL 10001
+
+
+
+
+
+ + {/* Social Links & Copyright */} +
+
+
+ {[AiFillFacebook , AiOutlineWhatsApp, AiFillInstagram].map((Icon, index) => ( + + + + ))} +
+
+ © {new Date().getFullYear()} AIPT. All rights reserved. +
+ +
+
+
+
+ ); +}; + +export default Footer; diff --git a/frontend/AIPT/src/components/Candidate/candidateHeader.css b/frontend/AIPT/src/components/Candidate/candidateHeader.css index 103df0b..1b9da61 100644 --- a/frontend/AIPT/src/components/Candidate/candidateHeader.css +++ b/frontend/AIPT/src/components/Candidate/candidateHeader.css @@ -13,6 +13,7 @@ width: 100%; box-sizing: border-box; transition: background-color 0.3s ease, box-shadow 0.3s ease; + left: 0; } @@ -24,8 +25,8 @@ } .header-scrolled { - background-color: #d3d3d3; - transition: background-color 0.3s ease; + background: linear-gradient(to right, #28025c, #00313f); + transition: background-color 0.5s ease; } diff --git a/frontend/AIPT/src/components/Candidate/footer.css b/frontend/AIPT/src/components/Candidate/footer.css new file mode 100644 index 0000000..92ddcbd --- /dev/null +++ b/frontend/AIPT/src/components/Candidate/footer.css @@ -0,0 +1,243 @@ +footer { + background: linear-gradient(to right, #1e293b, #1f2937); + color: #e2e8f0; + font-family: 'Arial', sans-serif; + display: flex; + flex-direction: column; + justify-content: space-between; /* Ensure content is spaced properly */ + height: 100%; + } + + footer .container { + max-width: 1200px; + margin: 0 auto; + display: flex; + flex-direction: column; /* Stack the content vertically */ + padding: 2rem 0; /* Adjusted padding */ + } + + footer .footer-content { + flex-grow: 1; /* This will take up all available space, pushing the social section to the bottom */ + } + + footer h3, + footer h4 { + font-weight: bold; + } + + footer a { + color: #94a3b8; + text-decoration: none; + transition: color 0.3s ease-in-out; + } + + footer a:hover { + color: #ffffff; + } + + footer ul { + list-style: none; + padding: 0; + margin: 0; + } + + footer li { + margin: 0; + } + + footer input[type="email"] { + width: 100%; + max-width: 300px; + padding: 10px; + border-radius: 6px; + border: none; + background-color: #2d3748; + color: #ffffff; + } + + footer input[type="email"]::placeholder { + color: #a0aec0; + } + + footer button { + padding: 10px 20px; + border: none; + border-radius: 6px; + background-color: #3b82f6; + color: #ffffff; + cursor: pointer; + font-weight: bold; + transition: background-color 0.3s ease-in-out; + } + + footer button:hover { + background-color: #2563eb; + } + + footer svg { + fill: currentColor; + } + + footer .flex { + display: flex; + flex-wrap: wrap; + } + + footer .gap-3 { + gap: 0.75rem; + } + + footer .gap-6 { + gap: 1.5rem; + } + + footer .text-gray-400 { + color: #94a3b8; + } + + footer .topBtn{ + color: #ffffff; + } + + footer .SocialIcon{ + color: #ffffff; + } + + footer .hover\:text-white:hover { + color: #2563eb; + } + + footer .hover\:SocialIcon:hover { + color: #dadada; + } + + + footer .text-sm { + font-size: 0.875rem; + } + + footer .border-t { + border-top: 1px solid #374151; + } + + footer .py-12 { + padding-top: 3rem; + padding-bottom: 3rem; + } + + footer .pt-8 { + padding-top: 2rem; + } + + footer .space-y-2 > * + * { + margin-top: 0.5rem; + } + + footer .space-y-4 > * + * { + margin-top: 1rem; + } + + footer .grid { + display: grid; + } + + footer .grid-cols-1 { + grid-template-columns: 1fr; + } + + footer .md\:grid-cols-2 { + grid-template-columns: repeat(2, 1fr); + } + + footer .lg\:grid-cols-3 { + grid-template-columns: repeat(3, 1fr); /* Ensure 3 columns */ + } + + footer .gap-12 { + gap: 3rem; + } + + footer .rounded-lg { + border-radius: 0.5rem; + } + + footer .focus\:outline-none:focus { + outline: none; + } + + footer .focus\:ring-2:focus { + box-shadow: 0 0 0 2px #3b82f6; + } + + footer .bg-gradient-to-r { + background: linear-gradient(to right, var(--tw-gradient-stops)); + } + + footer .from-blue-400 { + --tw-gradient-from: #60a5fa; + --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to, rgba(96, 165, 250, 0)); + } + + footer .to-purple-500 { + --tw-gradient-to: #a78bfa; + } + + footer .bg-clip-text { + background-clip: text; + -webkit-background-clip: text; + } + + footer .text-transparent { + color: transparent; + } + + + footer .footer-content { + display: flex; + flex-direction: column; + gap: 2rem; + } + + footer .footer-social { + margin-top: 3rem; + display: flex; + flex-direction: column; + align-items: center; + } + + footer .footer-social .flex { + justify-content: center; + gap: 1.5rem; + } + + footer .footer-social button { + margin-top: 1.5rem; + } + + footer .footer-social svg { + width: 30px; /* Adjust the icon size */ + height: 30px; + fill: #ffffff; /* Adjust the color of the icon */ + } + + footer .footer-social button { + background-color: #3b82f6; /* Change background color */ + color: #ffffff; + border-radius: 50%; /* Make it round */ + padding: 12px; /* Adjust the button size */ + border: none; + cursor: pointer; + transition: background-color 0.3s ease-in-out; + } + + footer .footer-social button:hover { + background-color: #2563eb; /* Adjust the hover background color */ + } + + footer .footer-social button svg { + width: 24px; /* Adjust the icon size inside the button */ + height: 24px; + } + + + \ No newline at end of file diff --git a/frontend/AIPT/src/components/ui/select.tsx b/frontend/AIPT/src/components/ui/select.tsx index dd94d30..ecd5ea1 100644 --- a/frontend/AIPT/src/components/ui/select.tsx +++ b/frontend/AIPT/src/components/ui/select.tsx @@ -36,12 +36,13 @@ const SelectContent = React.forwardRef< {children} -)) +)); SelectItem.displayName = SelectPrimitive.Item.displayName export { diff --git a/frontend/AIPT/src/images/header.png b/frontend/AIPT/src/images/header.png new file mode 100644 index 0000000..669be4e Binary files /dev/null and b/frontend/AIPT/src/images/header.png differ diff --git a/frontend/AIPT/src/pages/Candidate/CandidateHome.tsx b/frontend/AIPT/src/pages/Candidate/CandidateHome.tsx index 72c819b..8befafa 100644 --- a/frontend/AIPT/src/pages/Candidate/CandidateHome.tsx +++ b/frontend/AIPT/src/pages/Candidate/CandidateHome.tsx @@ -1,22 +1,40 @@ -import React, { useState } from 'react'; +import React, { useState, useEffect } from 'react'; import '../Styles/CandidateHome.css'; import Header from '../../components/Candidate/CandidateHeader'; +import Footer from '../../components/Candidate/Footer'; import { Search, Calendar, ArrowUpDown, Filter } from 'lucide-react'; import { Card, CardHeader, CardContent, CardFooter } from "../../components/ui/card"; import { Input } from "../../components/ui/input"; import { Button } from "../../components/ui/button"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../../components/ui/select"; +import axios from 'axios'; +import { useNavigate } from "react-router-dom"; + + + const CandidateHome: React.FC = () => { { Header } - const jobPosts = [ - { id: 1, title: "Frontend Developer", description: "Create beautiful, responsive user interfaces with React and TypeScript.", company: "TechCorp", date: "2021-09-01", type: "full-time" }, - { id: 2, title: "Backend Developer", description: "Build scalable backend systems using Python, Django, and SQL.", company: "TechCorp", date: "2021-09-05", type: "full-time" }, - { id: 3, title: "Full Stack Developer", description: "Join our team to work on both front-end and back-end development.", company: "TechCorp", date: "2021-09-10", type: "full-time" }, - { id: 4, title: "UX/UI Designer", description: "Design and improve the user experience and interface of the platform.", company: "TechCorp", date: "2021-09-15", type: "full-time" }, - { id: 5, title: "Data Scientist", description: "Analyze data and build predictive models to guide business decisions.", company: "TechCorp", date: "2021-09-20", type: "full-time" }, - { id: 6, title: "DevOps Engineer", description: "Manage and improve our deployment pipelines and infrastructure.", company: "TechCorp", date: "2021-09-25", type: "full-time" }, - ]; + const navigate = useNavigate(); + const [jobPosts, setJobPosts] = useState([]); + useEffect(() => { + axios.get('http://localhost:5000/api/jobs/all') + .then(response => { + setJobPosts(response.data); + }) + .catch(error => { + console.error("There was an error fetching the jobs:", error); + }); + }, []); + + // const jobPosts = [ + // { jobID: 1, jobRole: "Frontend Developer", description: "Create beautiful, responsive user interfaces with React and TypeScript.", company: "TechCorp", location: "New York", salary: 90000, jobType: "Full-time", date: "2021-09-01" }, + // { jobID: 2, jobRole: "Backend Developer", description: "Build scalable backend systems using Python, Django, and SQL.", company: "TechCorp", location: "San Francisco", salary: 95000, jobType: "Full-time", date: "2021-09-05" }, + // { jobID: 3, jobRole: "Full Stack Developer", description: "Join our team to work on both front-end and back-end development.", company: "TechCorp", location: "Chicago", salary: 105000, jobType: "Full-time", date: "2021-09-10" }, + // { jobID: 4, jobRole: "UX/UI Designer", description: "Design and improve the user experience and interface of the platform.", company: "TechCorp", location: "Los Angeles", salary: 85000, jobType: "Full-time", date: "2021-09-15" }, + // { jobID: 5, jobRole: "Data Scientist", description: "Analyze data and build predictive models to guide business decisions.", company: "TechCorp", location: "Austin", salary: 120000, jobType: "Full-time", date: "2021-09-20" }, + // { jobID: 6, jobRole: "DevOps Engineer", description: "Manage and improve our deployment pipelines and infrastructure.", company: "TechCorp", location: "Dallas", salary: 110000, jobType: "Full-time", date: "2021-09-25" }, + // ]; const [searchQuery, setSearchQuery] = useState(''); const [dateFilter, setDateFilter] = useState('all'); @@ -25,7 +43,7 @@ const CandidateHome: React.FC = () => { const filteredJobPosts = jobPosts .filter((job) => - job.title.toLowerCase().includes(searchQuery.toLowerCase()) || + job.jobRole.toLowerCase().includes(searchQuery.toLowerCase()) || job.description.toLowerCase().includes(searchQuery.toLowerCase()) ) .filter((job) => { @@ -37,7 +55,7 @@ const CandidateHome: React.FC = () => { if (dateFilter === 'month') return (today.getTime() - jobDate.getTime()) / (1000 * 60 * 60 * 24) <= 30; return true; }) - .filter((job) => (typeFilter === 'all' ? true : job.type === typeFilter)) + .filter((job) => (typeFilter === 'all' ? true : job.jobType === typeFilter)) .sort((a, b) => { if (orderBy === 'newest') return new Date(b.date).getTime() - new Date(a.date).getTime(); if (orderBy === 'oldest') return new Date(a.date).getTime() - new Date(b.date).getTime(); @@ -46,14 +64,15 @@ const CandidateHome: React.FC = () => { return (
-
+
{/* Header Banner Section */}

Find your dream job and kickstart your career with us today.

Welcome to Our Job Portal

- + +
{/* Main content area */} @@ -124,10 +143,9 @@ const CandidateHome: React.FC = () => { All Types - Full Time - Part Time - Contract - Internship + Full Time + Part Time + Contract
@@ -141,12 +159,14 @@ const CandidateHome: React.FC = () => { {filteredJobPosts.length > 0 ? (
{filteredJobPosts.map((job) => ( -
-
{job.title}
+
+
{job.jobRole}
{job.company}

{job.description}

+

{job.location}

+

${job.salary}

@@ -154,7 +174,12 @@ const CandidateHome: React.FC = () => {
- +
@@ -164,9 +189,9 @@ const CandidateHome: React.FC = () => {

No jobs found. Try adjusting your filters.

)}
-
+