Create a simple search bar with checkboxes
Tags: nextjs, typescript, tailwindcss, nextjs14
Published: 2024-04-10 13:29:28


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/scw0zpb780hjpmyayldf.png)

In this post, we'll create a job search application using React and Next.js. The application will consist of two main pages: a front page with a welcome message and a link to the search page, and a search page where users can filter job listings based on various criteria.

Prerequisites
Basic knowledge of React and Next.js
Node.js and npm installed on your machine
Step 1: Setting Up the Project
First, let's set up a new Next.js project. Open your terminal and run the following commands:

```
npx create-next-app job-search-app
cd job-search-app
```

Step 2: Creating the Front Page Component
Inside the pages directory, create a new file named page.tsx with the following content:

```
import React from 'react';
import Link from 'next/link';

export default function Home() {
  return (
    <main className="flex min-h-screen flex-col items-center justify-between p-24">
    <div>
      <h1>Welcome to My Search App</h1>
      <Link href="/search">
        Go to Search Page
      </Link>
    </div>
    </main>
  )
}
```

Step 3: Creating the Search Page Component
In the pages directory, create a folder (webpages) in side that folder add a folder search in that folder you create a new file named page.tsx with the following content:


```
"use client"
import React, { useState } from 'react';
import { jobListings } from "@/compoments/joblisting"

export default function Page() {
    const [searchQuery, setSearchQuery] = useState('');
    const [selectedEmployment, setSelectedEmployment] = useState<string[]>([]);
    const [selectedLocations, setSelectedLocations] = useState<string[]>([]);



    // Filter job listings based on search query, selected employment types, and selected locations
    const filteredJobListings = jobListings.filter(job =>
        job.title.toLowerCase().includes(searchQuery.toLowerCase()) &&
        (selectedEmployment.length === 0 || selectedEmployment.includes(job.employment)) &&
        (selectedLocations.length === 0 || selectedLocations.includes(job.location))
    );

    // Get unique employment types and locations
    const uniqueEmploymentTypes = Array.from(new Set(jobListings.map(job => job.employment)));
    const uniqueLocations = Array.from(new Set(jobListings.map(job => job.location)));


    return (
        <div className=' px-4 py-4'>
        <h1>Job Listings</h1>
        {/* Search bar */}
        <input
          type="text"
          placeholder="Search..."
          value={searchQuery}
          onChange={(e) => setSearchQuery(e.target.value)}
        />
        {/* Employment type checkboxes */}
        <div>
          <h3>Employment Type</h3>
          {uniqueEmploymentTypes.map(type => (
            <label key={type}>
              <input
                type="checkbox"
                value={type}
                checked={selectedEmployment.includes(type)}
                onChange={(e) => {
                  if (e.target.checked) {
                    setSelectedEmployment([...selectedEmployment, type]);
                  } else {
                    setSelectedEmployment(selectedEmployment.filter(item => item !== type));
                  }
                }}
              />
              {type}
            </label>
          ))}
        </div>
        {/* Location checkboxes */}
        <div>
          <h3>Location</h3>
          {uniqueLocations.map(location => (
            <label key={location}>
              <input
                type="checkbox"
                value={location}
                checked={selectedLocations.includes(location)}
                onChange={(e) => {
                  if (e.target.checked) {
                    setSelectedLocations([...selectedLocations, location]);
                  } else {
                    setSelectedLocations(selectedLocations.filter(item => item !== location));
                  }
                }}
              />
              {location}
            </label>
          ))}
        </div>
        {/* Display filtered job listings */}
        {filteredJobListings.map(job => (
          <div key={job.id}>
            <h2>{job.title}</h2>
            <p><strong>Company:</strong> {job.company}</p>
            <p><strong>Employment:</strong> {job.employment}</p>
            <p><strong>Location:</strong> {job.location}</p>
            <p><strong>Description:</strong> {job.description}</p>
            <p><strong>Salary:</strong> {job.salary}</p>
          </div>
        ))}
      </div>
    );
  }
```

step 4: On the last stage we need dummy data, create a map called compoments add a new file in this directory called joblisting.tsx


```
interface Job {
    id: number;
    title: string;
    company: string;
    employment: string;
    location: string;
    description: string;
    salary: string;
}

const jobListings: Job[]  = [
    {
      id: 1,
      title: "Software Engineer",
      company: "Tech Co.",
      employment: "Full-time",
      location: "New York, NY",
      description: "We are seeking a talented software engineer to join our team...",
      salary: "$80,000 - $100,000 per year"
    },
    {
      id: 2,
      title: "Data Analyst",
      company: "Data Corp.",
      employment: "Contract",
      location: "San Francisco, CA",
      description: "Data Corp. is looking for a skilled data analyst to analyze...",
      salary: "$70,000 - $90,000 per year"
    },
    {
      id: 3,
      title: "UX/UI Designer",
      company: "Design Studio",
      employment: "Part-time",
      location: "Los Angeles, CA",
      description: "Design Studio is seeking a creative UX/UI designer to help...",
      salary: "$60,000 - $80,000 per year"
    }
  ];
  
  // Extract unique locations
  const locations = Array.from(new Set(jobListings.map(job => job.location)));
  
  export { jobListings , locations };
```

Step 4: Running the Application
To run the application, go back to your terminal and run:

```
npm run dev

```