app_employees_ShowEmployeesMain.jsx

'use client'

import { Modal } from 'modal-nextjs'
import { useEffect, useState } from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { setEmployeeList } from '../../redux/reducers'
import EmployeeCard from '../../components/employeeCard'
import EmployeesTable from '../../components/employeesTable'
import EmployeesCards from '../../components/employeesCards'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import {
  faSearch,
  faTable,
  faTableList,
} from '@fortawesome/free-solid-svg-icons'

/**
 * Main component to display the list of employees.
 * @namespace
 * @param {Object} props - Component properties.
 * @param {Array} props.data - Array of employee data.
 * @returns {ReactElement} Rendered component.
 */
function ShowEmployeesMain({ data }) {
  
  const dispatch = useDispatch()
  const { data: dataState } = useSelector((state) => state.employeeList)
  const [isList, setIsList] = useState(true)
  const [searchTerm, setSearchTerm] = useState('')
  const [numberOfLines, setNumberOfLines] = useState(30)
  const [filteredData, setFilteredData] = useState(data|[])
  const [modalIsOpen, setModalIsOpen] = useState(false)
  const [userToOpen, setUserToOpen] = useState({})
 
  useEffect(() => {
    // if (!Array.isArray(dataState)) {
    //   dispatch(setEmployeeList([]))
    // } else {
      dataState.length === 0 && data && dispatch(setEmployeeList({data}))
    // }
  }, [data])

  useEffect(() => {
    const filteredEmployees =
      Array.isArray(dataState) &&
      dataState.filter((employee) => {
        return (
          employee.firstName
            ?.toLowerCase()
            .includes(searchTerm.toLowerCase()) ||
          employee.lastName?.toLowerCase().includes(searchTerm.toLowerCase()) ||
          employee.startDate
            ?.toLowerCase()
            .includes(searchTerm.toLowerCase()) ||
          employee.department
            ?.toLowerCase()
            .includes(searchTerm.toLowerCase()) ||
          employee.street?.toLowerCase().includes(searchTerm.toLowerCase()) ||
          employee.city?.toLowerCase().includes(searchTerm.toLowerCase()) ||
          employee.state?.toLowerCase().includes(searchTerm.toLowerCase()) ||
          employee.zipCode?.toLowerCase().includes(searchTerm.toLowerCase()) ||
          employee.dateOfBirth?.toLowerCase().includes(searchTerm.toLowerCase())
        )
      })
    setFilteredData(filteredEmployees)
  }, [searchTerm, dataState])

  const handleToggleList = () => {
    setIsList(!isList)
  }

  const handleSearchChange = (e) => {
    setSearchTerm(e.target.value)
  }

  const handleChangeNbOfLines = (e) => {
    document.getElementById('searchfield').value = ''
    setFilteredData(dataState)
    e.target.value === 'all'
      ? setNumberOfLines(dataState.length)
      : setNumberOfLines(e.target.value)
  }

  return (
    <>
      <section className='w-full h-full'>
        {showTitle(
          isList,
          handleToggleList,
          handleSearchChange,
          filteredData,
          handleChangeNbOfLines,
        )}
        {showDataZone(
          isList,
          filteredData,
          numberOfLines,
          setModalIsOpen,
          setUserToOpen,
        )}
      </section>
      {modalIsOpen && (
        <Modal
          setModalIsOpen={setModalIsOpen}
          content={<EmployeeCard item={userToOpen} />}
        />
      )}
</>
  )
}

/**
 * Function to display the data zone.
 * 
 * @param {boolean} isList - Boolean to determine if the view mode is list.
 * @param {Array} dataState - Data to be displayed.
 * @param {number} numberOfLines - Number of lines to display.
 * @param {Function} setModalIsOpen - Setter for modal open state.
 * @param {Function} setUserToOpen - Setter for the user to open in modal.
 * @returns {ReactElement} Rendered component.
 */
function showDataZone(
  isList,
  dataState,
  numberOfLines,
  setModalIsOpen,
  setUserToOpen,
) {
  return (
    <div className='flex flex-col justify-between text-left overflow-hidden mb-2 '>
      {isList ? (
        <EmployeesTable
          dataState={Array.isArray(dataState) ? dataState : []}
          numberOfLines={numberOfLines}
          setModalIsOpen={setModalIsOpen}
          setUserToOpen={setUserToOpen}
        />
      ) : (
        <EmployeesCards dataState={dataState} />
      )}
    </div>
  )
}

/**
 * Function to display the title.
 * 
 * @param {boolean} isList - Boolean to determine if the view mode is list.
 * @param {Function} handleToggleList - Handler for toggling list view.
 * @param {Function} handleSearchChange - Handler for search change.
 * @param {Array} filteredData - Filtered data.
 * @param {Function} handleChangeNbOfLines - Handler to change number of lines.
 * @returns {ReactElement} Rendered component.
 */
function showTitle(
  isList,
  handleToggleList,
  handleSearchChange,
  filteredData,
  handleChangeNbOfLines,
) {
  return (
    <>
      <div className='flex flex-wrap'>
        <h1 className='grow text-lg xl:text-2xl my-1 text-secondary-color '>
          Employees list{' '}
          <span className='xl:text-lg text-base'>
            ({filteredData.length} result
            {filteredData.length > 1 ? 's' : ''})
          </span>
        </h1>
        {isList ? (
          <div className='flex'>
            <label
              htmlFor='pageSelector'
              className='xl:text-lg text-xs mr-2 my-auto'
            >
              Lines displayed
            </label>
            <select
              id='pageSelector'
              className='xl:text-lg text-xs mr-3 focus:outline-none'
              defaultValue='30'
              onChange={handleChangeNbOfLines}
            >
              <option>15</option>
              <option>30</option>
              <option>50</option>
              <option>100</option>
              <option>all</option>
            </select>
            <input
              type='text'
              placeholder='Instant search'
              className='text-sm xl:text-base pl-1 focus:outline-none'
              onChange={handleSearchChange}
              id='searchfield'
            ></input>
            <div className='p-2 text-secondary-color bg-white'>
              <span title={'Search'}>
                <FontAwesomeIcon
                  className='text-sm xl:text-xl'
                  icon={faSearch}
                  aria-label={'Search'}
                />
              </span>
            </div>
          </div>
        ) : (
          ''
        )}
        <div className='flex p-2 text-secondary-color'>
          <span title={'Toggle to ' + (isList ? 'cards' : 'table')}>
            {/* Need to wrap FontAwesome into a span to add title : bug with next.js */}
            <FontAwesomeIcon
              className=' text-sm xl:text-xl cursor-pointer hover:text-bg-color-light'
              icon={isList ? faTable : faTableList}
              onClick={handleToggleList}
              aria-label={'Toggle to ' + (isList ? 'cards' : 'table')}
            />
          </span>
        </div>
      </div>
    </>
  )
}

export default ShowEmployeesMain