-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #6 from caceresjuancruz/staging
Staging
- Loading branch information
Showing
13 changed files
with
566 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import LocalSearchbar from "@/components/shared/search/LocalSearchbar"; | ||
import { Skeleton } from "@/components/ui/skeleton"; | ||
|
||
const Loading = () => { | ||
return ( | ||
<section> | ||
<h1 className="h1-bold text-dark100_light900">Jobs</h1> | ||
|
||
<div className="mb-12 mt-11 flex flex-wrap gap-5"> | ||
<LocalSearchbar | ||
placeholder="Job Title, Company, or Keywords" | ||
iconPosition="left" | ||
iconSrc="/assets/icons/search.svg" | ||
route="/jobs" | ||
otherClasses="flex-1" | ||
/> | ||
<Skeleton className="h-14 w-28" /> | ||
</div> | ||
|
||
<div className="flex flex-col gap-6"> | ||
{[1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((item) => ( | ||
<Skeleton key={item} className="h-48 w-full rounded-xl" /> | ||
))} | ||
</div> | ||
</section> | ||
); | ||
}; | ||
|
||
export default Loading; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import UserCard from "@/components/cards/UserCard"; | ||
import Filter from "@/components/shared/Filter"; | ||
import NoResults from "@/components/shared/NoResults"; | ||
import Pagination from "@/components/shared/Pagination"; | ||
import LocalSearchbar from "@/components/shared/search/LocalSearchbar"; | ||
import { UserFilters } from "@/constants/filters"; | ||
import { getAllUsers } from "@/lib/actions/user.action"; | ||
import { SearchParamsProps } from "@/types"; | ||
import { Metadata } from "next"; | ||
|
||
import { | ||
fetchCountries, | ||
fetchJobs, | ||
fetchLocation, | ||
} from "@/lib/actions/job.action"; | ||
|
||
import { Job } from "@/types"; | ||
import JobsFilter from "@/components/jobs/JobsFilter"; | ||
import JobCard from "@/components/cards/JobCard"; | ||
|
||
interface JobsPageProps { | ||
searchParams: { | ||
q: string; | ||
location: string; | ||
page: string; | ||
}; | ||
} | ||
|
||
export const metadata: Metadata = { | ||
title: "Jobs | Dev Overflow", | ||
}; | ||
|
||
export default async function JobsPage({ searchParams }: JobsPageProps) { | ||
const userLocation = await fetchLocation(); | ||
|
||
const jobs = await fetchJobs({ | ||
query: | ||
`${searchParams.q},${searchParams.location}` ?? | ||
`Software Engineer in ${userLocation}`, | ||
page: searchParams.page ?? 1, | ||
}); | ||
|
||
const countries = await fetchCountries(); | ||
const page = parseInt(searchParams.page ?? 1); | ||
|
||
return ( | ||
<> | ||
<h1 className="h1-bold text-dark100_light900">Jobs</h1> | ||
|
||
<div className="flex"> | ||
<JobsFilter countriesList={countries} /> | ||
</div> | ||
|
||
<section className="mt-12 flex flex-wrap gap-4"> | ||
{jobs && jobs.length > 0 ? ( | ||
jobs.map((job: Job, index: number) => ( | ||
<JobCard key={index} job={job} /> | ||
)) | ||
) : ( | ||
<NoResults | ||
title="No jobs available" | ||
description="There are no jobs available at the moment. Please check back later." | ||
link="/" | ||
linkTitle="Go home" | ||
/> | ||
)} | ||
</section> | ||
<div className="mt-10"> | ||
<Pagination pageNumber={page} isNext={jobs?.length === 10 || false} /> | ||
</div> | ||
</> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
import RenderTag from "../shared/RenderTag"; | ||
import { | ||
formatAndDivideNumber, | ||
getTimestamp, | ||
processJobTitle, | ||
} from "@/lib/utils"; | ||
import Link from "next/link"; | ||
import Metric from "../shared/Metric"; | ||
import { toast } from "../ui/use-toast"; | ||
import { title } from "process"; | ||
import QuestionCard from "./QuestionCard"; | ||
import { Job } from "@/types"; | ||
import Image from "next/image"; | ||
import JobLocation from "../jobs/JobLocation"; | ||
|
||
interface JobCardProps { | ||
job: Job; | ||
} | ||
|
||
const JobCard = ({ job }: JobCardProps) => { | ||
const { | ||
employer_logo, | ||
employer_website, | ||
job_employment_type, | ||
job_title, | ||
job_description, | ||
job_apply_link, | ||
job_city, | ||
job_state, | ||
job_country, | ||
} = job; | ||
|
||
return ( | ||
<div className="background-light900_dark200 light-border shadow-light100_darknone flex flex-col items-start gap-6 rounded-lg border p-6 sm:flex-row sm:p-8"> | ||
<div className="flex w-full justify-end sm:hidden"> | ||
<JobLocation | ||
job_country={job_country} | ||
job_state={job_state} | ||
job_city={job_city} | ||
/> | ||
</div> | ||
|
||
<div className="flex items-center gap-6"> | ||
{employer_logo ? ( | ||
<Link | ||
href={employer_website ?? "/jobs"} | ||
target="_blank" | ||
className="background-light800_dark400 relative h-16 w-16 rounded-xl" | ||
> | ||
<Image | ||
src={employer_logo} | ||
alt="Company logo" | ||
fill | ||
className="h-full w-full object-contain p-2" | ||
unoptimized | ||
/> | ||
</Link> | ||
) : ( | ||
<Image | ||
src="/assets/images/site-logo.svg" | ||
alt="Default site logo" | ||
width={64} | ||
height={64} | ||
className="rounded-[10px]" | ||
/> | ||
)} | ||
</div> | ||
|
||
<div className="w-full"> | ||
<div className="flex-between flex-wrap gap-2"> | ||
<p className="base-semibold text-dark200_light900"> | ||
{processJobTitle(job_title)} | ||
</p> | ||
|
||
<div className="hidden sm:flex"> | ||
<JobLocation | ||
job_country={job_country} | ||
job_state={job_state} | ||
job_city={job_city} | ||
/> | ||
</div> | ||
</div> | ||
|
||
<p className="body-regular text-dark500_light700 mt-2 line-clamp-2"> | ||
{job_description?.slice(0, 200)} | ||
</p> | ||
|
||
<div className="flex-between mt-8 flex-wrap gap-6"> | ||
<div className="flex flex-wrap items-center gap-6"> | ||
<div className="flex items-center gap-2"> | ||
<Image | ||
src="/assets/icons/clock.svg" | ||
alt="clock" | ||
width={20} | ||
height={20} | ||
unoptimized | ||
/> | ||
<p className="body-medium text-light-500"> | ||
{job_employment_type} | ||
</p> | ||
</div> | ||
|
||
<div className="flex items-center gap-2"> | ||
<Image | ||
src="/assets/icons/currency-dollar-circle.svg" | ||
alt="dollar symbol" | ||
width={20} | ||
height={20} | ||
unoptimized | ||
/> | ||
<p className="body-medium text-light-500">Not disclosed</p> | ||
</div> | ||
</div> | ||
|
||
<Link | ||
href={job_apply_link ?? "/jobs"} | ||
className="flex items-center gap-2" | ||
target="_blank" | ||
> | ||
<p className="body-semibold primary-text-gradient">View job</p> | ||
|
||
<Image | ||
src="/assets/icons/arrow-up-right.svg" | ||
alt="arrow up right" | ||
width={20} | ||
height={20} | ||
unoptimized | ||
/> | ||
</Link> | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default JobCard; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import Image from "next/image"; | ||
import React from "react"; | ||
|
||
interface JobLocationProps { | ||
job_country?: string; | ||
job_city?: string; | ||
job_state?: string; | ||
} | ||
|
||
const JobLocation = ({ | ||
job_country, | ||
job_city, | ||
job_state, | ||
}: JobLocationProps) => { | ||
return ( | ||
<div className="background-light800_dark400 flex items-center justify-end gap-2 rounded-2xl px-3 py-1.5"> | ||
<Image | ||
src={`https://flagsapi.com/${job_country}/flat/64.png`} | ||
alt="Country flag" | ||
width={16} | ||
height={16} | ||
unoptimized | ||
className="rounded-full" | ||
/> | ||
|
||
<p className="body-medium text-dark400_light700"> | ||
{job_city && `${job_city}, `} | ||
{job_state && `${job_state}, `} | ||
{job_country && `${job_country}`} | ||
</p> | ||
</div> | ||
); | ||
}; | ||
|
||
export default JobLocation; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
"use client"; | ||
|
||
import { formUrlQuery } from "@/lib/utils"; | ||
import { Country } from "@/types"; | ||
import { usePathname, useRouter, useSearchParams } from "next/navigation"; | ||
import React from "react"; | ||
import LocalSearchbar from "../shared/search/LocalSearchbar"; | ||
import { | ||
Select, | ||
SelectContent, | ||
SelectGroup, | ||
SelectItem, | ||
SelectTrigger, | ||
SelectValue, | ||
} from "../ui/select"; | ||
import Image from "next/image"; | ||
|
||
interface JobsFilterProps { | ||
countriesList: Country[]; | ||
} | ||
|
||
const JobsFilter = ({ countriesList }: JobsFilterProps) => { | ||
const router = useRouter(); | ||
const path = usePathname(); | ||
const searchParams = useSearchParams(); | ||
|
||
const handleUpdateParams = (value: string) => { | ||
const newUrl = formUrlQuery({ | ||
params: searchParams.toString(), | ||
key: "location", | ||
value, | ||
}); | ||
|
||
router.push(newUrl, { scroll: false }); | ||
}; | ||
|
||
return ( | ||
<div className="relative mt-11 flex w-full justify-between gap-5 max-sm:flex-col sm:items-center"> | ||
<LocalSearchbar | ||
route={path} | ||
iconPosition="left" | ||
iconSrc="/assets/icons/search.svg" | ||
placeholder="Job Title, Company, or Keywords" | ||
otherClasses="flex-1 max-sm:w-full" | ||
/> | ||
|
||
<Select onValueChange={(value) => handleUpdateParams(value)}> | ||
<SelectTrigger className="body-regular light-border-2 background-light800_dark300 text-dark500_light700 line-clamp-1 flex min-h-[56px] items-center gap-3 border p-4 focus:ring-0 focus:ring-offset-0 sm:max-w-[210px]"> | ||
<Image | ||
src="/assets/icons/carbon-location.svg" | ||
alt="location" | ||
width={18} | ||
height={18} | ||
unoptimized | ||
/> | ||
<div className="line-clamp-1 flex-1 text-left"> | ||
<SelectValue placeholder="Select Location" /> | ||
</div> | ||
</SelectTrigger> | ||
|
||
<SelectContent className="body-semibold text-dark500_light700 light-border-2 max-h-[350px] max-w-[250px] border bg-light-900 dark:bg-dark-300"> | ||
<SelectGroup> | ||
{countriesList && countriesList.length > 0 ? ( | ||
countriesList.map((country: Country) => ( | ||
<SelectItem | ||
key={country.name.common} | ||
value={country.name.common} | ||
className="cursor-pointer px-4 py-3 hover:bg-light-800 dark:hover:bg-dark-400" | ||
> | ||
{country.name.common} | ||
</SelectItem> | ||
)) | ||
) : ( | ||
<SelectItem value="No results found">No results found</SelectItem> | ||
)} | ||
</SelectGroup> | ||
</SelectContent> | ||
</Select> | ||
</div> | ||
); | ||
}; | ||
|
||
export default JobsFilter; |
Oops, something went wrong.