2025-03-30 11:52:59 +00:00
< script setup >
import JobCard from './components/JobCard.vue'
import SideNav from './components/SideNav.vue'
import Dashboard from './components/Dashboard.vue'
import Applications from './components/Applications.vue'
import SavedJobs from './components/SavedJobs.vue'
import JobDetail from './components/JobDetail.vue'
import JobFilters from './components/JobFilters.vue'
2025-04-02 04:50:03 +00:00
import Profile from './components/Profile.vue'
2025-03-30 11:52:59 +00:00
import { ref , provide , onMounted , computed } from 'vue'
// Current active section
const activeSection = ref ( 'dashboard' )
// Selected job for detail view
const selectedJobId = ref ( null )
const showJobDetail = ref ( false )
// Theme state
const isDarkMode = ref ( false )
// Initialize theme on mount
onMounted ( ( ) => {
// Check for saved preference in localStorage
const savedTheme = localStorage . getItem ( 'theme' )
if ( savedTheme ) {
isDarkMode . value = savedTheme === 'dark'
} else {
// Use system preference as fallback
isDarkMode . value = window . matchMedia ( '(prefers-color-scheme: dark)' ) . matches
}
// Apply initial theme
applyTheme ( isDarkMode . value )
} )
// Apply theme to document
const applyTheme = ( dark ) => {
document . documentElement . classList . toggle ( 'dark-mode' , dark )
document . documentElement . classList . toggle ( 'light-mode' , ! dark )
localStorage . setItem ( 'theme' , dark ? 'dark' : 'light' )
}
// Handle theme toggle from SideNav
const handleThemeToggle = ( dark ) => {
isDarkMode . value = dark
applyTheme ( dark )
}
// Provide theme state to components
provide ( 'isDarkMode' , isDarkMode )
provide ( 'toggleTheme' , handleThemeToggle )
// Provide navigation state to components
provide ( 'activeSection' , activeSection )
// Handle navigation
const handleNavigation = ( section ) => {
activeSection . value = section
console . log ( ` Navigated to: ${ section } ` )
}
// Sample job listings data
const allJobListings = [
{
id : 1 ,
title : 'Frontend Developer' ,
company : 'Tech Innovations Inc.' ,
location : 'San Francisco, CA' ,
salary : '$120,000 - $150,000' ,
employmentType : 'Full-time' ,
experience : '3+ years' ,
description : 'We are looking for an experienced Frontend Developer proficient in Vue.js to join our growing team. You will be responsible for building user interfaces and implementing new features.' ,
applied : false ,
tags : [ 'Vue.js' , 'JavaScript' , 'CSS' , 'UI/UX' ]
} ,
{
id : 2 ,
title : 'Backend Engineer' ,
company : 'DataSystems Co.' ,
location : 'Remote' ,
salary : '$130,000 - $160,000' ,
employmentType : 'Full-time' ,
experience : '4+ years' ,
description : 'Join our backend team to develop scalable APIs and services. Experience with Node.js and database design required.' ,
applied : false ,
tags : [ 'Node.js' , 'API' , 'Backend' , 'Databases' ]
} ,
{
id : 3 ,
title : 'Full Stack Developer' ,
company : 'WebSolutions Ltd.' ,
location : 'New York, NY' ,
salary : '$140,000 - $170,000' ,
employmentType : 'Full-time' ,
experience : '5+ years' ,
description : 'Looking for a versatile developer who can work across the entire stack. Experience with Vue.js and Node.js is a plus.' ,
applied : true ,
tags : [ 'Full Stack' , 'Vue.js' , 'Node.js' , 'JavaScript' ]
} ,
{
id : 4 ,
title : 'UX/UI Designer' ,
company : 'Creative Design Studio' ,
location : 'Chicago, IL' ,
salary : '$110,000 - $135,000' ,
employmentType : 'Full-time' ,
experience : '2+ years' ,
description : 'Join our design team to create beautiful and intuitive user interfaces for web and mobile applications.' ,
applied : false ,
tags : [ 'UI/UX' , 'Design' , 'Figma' , 'Prototyping' ]
} ,
{
id : 5 ,
title : 'DevOps Engineer' ,
company : 'CloudTech Solutions' ,
location : 'Remote' ,
salary : '$135,000 - $165,000' ,
employmentType : 'Full-time' ,
experience : '4+ years' ,
description : 'Looking for a skilled DevOps engineer to help us build and maintain our cloud infrastructure and CI/CD pipelines.' ,
applied : false ,
tags : [ 'AWS' , 'Docker' , 'Kubernetes' , 'CI/CD' ]
} ,
{
id : 6 ,
title : 'Product Manager' ,
company : 'Tech Innovations Inc.' ,
location : 'San Francisco, CA' ,
salary : '$150,000 - $180,000' ,
employmentType : 'Full-time' ,
experience : '5+ years' ,
description : 'Lead product development initiatives and work closely with engineering, design, and marketing teams to deliver exceptional products.' ,
applied : false ,
tags : [ 'Product' , 'Agile' , 'Leadership' , 'Strategy' ]
} ,
{
id : 7 ,
title : 'Data Scientist' ,
company : 'DataSystems Co.' ,
location : 'Boston, MA' ,
salary : '$140,000 - $170,000' ,
employmentType : 'Full-time' ,
experience : '3+ years' ,
description : 'Apply machine learning and statistical techniques to analyze large datasets and extract valuable insights for our clients.' ,
applied : false ,
tags : [ 'Python' , 'Machine Learning' , 'Data Analysis' , 'SQL' ]
} ,
{
id : 8 ,
title : 'Frontend Developer (Contract)' ,
company : 'WebSolutions Ltd.' ,
location : 'Remote' ,
salary : '$90,000 - $120,000' ,
employmentType : 'Contract' ,
experience : '2+ years' ,
description : 'Short-term contract role for a Vue.js developer to help us complete a client project over the next 6 months.' ,
applied : false ,
tags : [ 'Vue.js' , 'JavaScript' , 'Contract' , 'Remote' ]
}
] ;
// Filtered job listings
const filteredJobListings = ref ( [ ... allJobListings ] ) ;
// Handle job application
const handleJobApplication = ( jobTitle ) => {
console . log ( ` Applied for: ${ jobTitle } ` ) ;
} ;
// View job details
const viewJobDetails = ( jobId ) => {
selectedJobId . value = jobId ;
showJobDetail . value = true ;
} ;
// Handle filter changes
const handleFilterChange = ( filteredJobs ) => {
filteredJobListings . value = filteredJobs ;
} ;
// Close job details
const closeJobDetails = ( ) => {
showJobDetail . value = false ;
} ;
< / script >
< template >
< div class = "app-container" >
< SideNav @navigate ="handleNavigation" / >
< div class = "content-wrapper" >
< header >
< h1 > { { activeSection === 'dashboard' ? 'Dashboard' : activeSection === 'jobs' ? 'Job Board' : activeSection . charAt ( 0 ) . toUpperCase ( ) + activeSection . slice ( 1 ) } } < / h1 >
< / header >
< main >
< section v-if ="activeSection === 'jobs'" class="job-listings" >
< div v-if ="!showJobDetail" class="jobs-container" >
< h2 class = "section-heading" > Available Positions < / h2 >
<!-- Job Filters Component -- >
< JobFilters
: jobs = "allJobListings"
: initially - expanded = "false"
@ filter - change = "filteredJobListings = $event"
/ >
< div class = "filter-results" >
< p class = "results-count" > { { filteredJobListings . length } } job { { filteredJobListings . length !== 1 ? 's' : '' } } found < / p >
< / div >
< div class = "job-cards" v-if ="filteredJobListings.length > 0" >
< JobCard
v - for = "job in filteredJobListings"
: key = "job.id"
: title = "job.title"
: company = "job.company"
: location = "job.location"
: salary = "job.salary"
: description = "job.description"
: applied = "job.applied"
: tags = "job.tags"
@ apply = "handleJobApplication"
@ click = "viewJobDetails(job.id)"
/ >
< / div >
< div v -else class = "no-results" >
< div class = "no-results-icon" > 🔍 < / div >
< h3 > No jobs found < / h3 >
< p > Try adjusting your search filters to find more opportunities . < / p >
< / div >
< / div >
< JobDetail
v - if = "showJobDetail"
: jobId = "selectedJobId"
@ close = "closeJobDetails"
@ apply = "handleJobApplication"
/ >
< / section >
< section v -else -if = " activeSection = = = ' dashboard ' " class = "dashboard-section" >
< Dashboard / >
< / section >
< section v -else -if = " activeSection = = = ' applications ' " class = "applications-section" >
< Applications / >
< / section >
< section v -else -if = " activeSection = = = ' saved ' " class = "saved-section" >
< SavedJobs / >
< / section >
2025-04-02 04:50:03 +00:00
< section v -else -if = " activeSection = = = ' profile ' " class = "profile-section" >
< Profile / >
2025-03-30 11:52:59 +00:00
< / section >
< section v -else -if = " activeSection = = = ' settings ' " class = "settings" >
< h2 > Settings < / h2 >
< p > Adjust your account settings . < / p >
< / section >
< / main >
< footer >
< p > Job Board Application < / p >
< / footer >
< / div >
< / div >
< / template >
< style scoped lang = "scss" >
. app - container {
display : flex ;
min - height : 100 vh ;
}
. content - wrapper {
flex : 1 ;
margin - left : 240 px ;
transition : margin - left 0.3 s ease ;
display : flex ;
flex - direction : column ;
min - height : 100 vh ;
. side - nav . collapsed + & {
margin - left : 60 px ;
}
}
header {
padding : 1.5 rem 2 rem ;
margin - bottom : 1 rem ;
border - bottom : 1 px solid # eee ;
h1 {
margin : 0 ;
font - size : 1.8 rem ;
}
}
main {
flex : 1 ;
width : 100 % ;
max - width : 1100 px ;
margin : 0 auto ;
padding : 0 2 rem ;
section {
margin - bottom : 2 rem ;
h2 {
margin - bottom : 1.5 rem ;
font - size : 1.4 rem ;
color : var ( -- text - color ) ;
}
}
. jobs - container {
padding : 1.5 rem ;
background - color : var ( -- bg - color , # f8f9fa ) ;
border - radius : 16 px ;
. section - heading {
font - size : 1.8 rem ;
font - weight : 600 ;
margin - bottom : 2 rem ;
color : var ( -- text - color , # 333 ) ;
}
. filter - results {
margin : 1.5 rem 0 ;
. results - count {
font - size : 1 rem ;
color : var ( -- text - color - secondary , # 666 ) ;
font - weight : 500 ;
}
}
. no - results {
display : flex ;
flex - direction : column ;
align - items : center ;
justify - content : center ;
padding : 3 rem 1 rem ;
text - align : center ;
background - color : var ( -- card - bg , # fff ) ;
border - radius : 12 px ;
box - shadow : 0 4 px 12 px rgba ( 0 , 0 , 0 , 0.05 ) ;
. no - results - icon {
font - size : 3 rem ;
margin - bottom : 1 rem ;
opacity : 0.7 ;
}
h3 {
font - size : 1.4 rem ;
margin : 0 0 0.5 rem ;
color : var ( -- text - color , # 333 ) ;
}
p {
color : var ( -- text - color - secondary , # 666 ) ;
max - width : 400 px ;
margin : 0 ;
}
}
}
. job - cards {
display : flex ;
flex - direction : column ;
width : 100 % ;
max - width : 900 px ;
margin : 0 auto ;
gap : 1.5 rem ;
}
. dashboard - section {
width : 100 % ;
}
}
footer {
text - align : center ;
padding : 1 rem 0 ;
margin - top : 2 rem ;
border - top : 1 px solid # eee ;
font - size : 0.9 rem ;
color : # 888 ;
}
@ media ( prefers - color - scheme : dark ) {
header {
border - bottom - color : # 333 ;
}
main section h2 {
color : # eee ;
}
footer {
border - top - color : # 333 ;
}
}
@ media ( max - width : 768 px ) {
. content - wrapper {
margin - left : 60 px ;
}
header {
padding : 1 rem ;
}
main {
padding : 0 1 rem ;
}
}
< / style >