/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* OpenCRVS is also distributed under the terms of the Civil Registration
* & Healthcare Disclaimer located at http://opencrvs.org/license.
*
* Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS.
*/
import React, { useState, useEffect } from 'react'
import { ClearText } from '../icons'
import { Button } from '../Button'
import { Icon } from '../Icon'
import styled from 'styled-components'
type SearchCriterias =
| 'TRACKING_ID'
| 'REGISTRATION_NUMBER'
| 'NATIONAL_ID'
| 'NAME'
| 'PHONE_NUMBER'
| 'EMAIL'
const SearchBox = styled.div`
background: ${({ theme }) => theme.colors.grey100};
box-sizing: border-box;
width: 664px;
height: 40px;
border-radius: 40px;
&:hover {
outline: 1px solid ${({ theme }) => theme.colors.grey400};
background: ${({ theme }) => theme.colors.grey100};
}
&:focus-within {
outline: 2px solid ${({ theme }) => theme.colors.grey600};
background: ${({ theme }) => theme.colors.white};
}
&:active {
outline: 2px solid ${({ theme }) => theme.colors.grey600};
}
&:focus-within input {
background: ${({ theme }) => theme.colors.white};
}
@media (max-width: ${({ theme }) => theme.grid.breakpoints.xl}px) {
width: 100%;
}
@media (max-width: ${({ theme }) => theme.grid.breakpoints.lg}px) {
width: 100%;
margin: auto;
}
`
const Wrapper = styled.form`
align-items: center;
border-radius: 2px;
display: flex;
${({ theme }) => theme.fonts.bold14};
color: ${({ theme }) => theme.colors.primary};
padding: 0px 8px 0px 4px;
position: relative;
`
const SearchInput = styled.input`
border: none;
margin: 0px 4px;
${({ theme }) => theme.fonts.reg16};
background-color: transparent;
flex-grow: 1;
&:focus {
outline: none;
background-color: ${({ theme }) => theme.colors.white};
}
@media (max-width: ${({ theme }) => theme.grid.breakpoints.md}px) {
margin: 0px 4px;
width: 40%;
}
`
export const LabelButton = styled(Button)`
width: auto;
height: auto;
border-radius: 2px;
color: ${({ theme }) => theme.colors.primary};
${({ theme }) => theme.fonts.bold14};
`
const DropDownWrapper = styled.ul`
background: ${({ theme }) => theme.colors.white};
border-radius: 4px;
border: 1px solid ${({ theme }) => theme.colors.grey300};
${({ theme }) => theme.shadows.light};
position: absolute;
padding: 6px 0;
min-width: 200px;
z-index: 9999;
list-style: none;
top: 100%;
right: 0px;
margin: 4px 0px;
cursor: pointer;
`
const DropDownItem = styled.li`
${({ theme }) => theme.fonts.bold14};
color: ${({ theme }) => theme.colors.grey500};
display: flex;
align-items: center;
gap: 8px;
cursor: pointer;
margin: 0 6px;
border-radius: 4px;
padding: 8px 12px;
&:hover {
color: ${({ theme }) => theme.colors.grey600};
background: ${({ theme }) => theme.colors.grey100};
}
&:active {
color: ${({ theme }) => theme.colors.grey600};
background: ${({ theme }) => theme.colors.grey200};
}
&:focus-visible {
background-color: ${({ theme }) => theme.colors.yellow};
}
`
const AdvancedSearchWrapper = styled.div`
display: flex;
justify-content: flex-start;
flex-flow: column nowrap;
align-items: stretch;
margin-top: 6px;
border-top: 1px solid ${({ theme }) => theme.colors.grey300};
padding: 6px;
padding-bottom: 0;
`
const SelectedSearchCriteria = styled.span`
display: flex;
margin-right: 16px;
&:hover:enabled {
background: none;
}
& .selected-icon {
display: none;
margin-right: 8px;
}
@media (max-width: ${({ theme }) => theme.grid.breakpoints.lg}px) {
margin-right: 0;
& .selected-icon {
display: flex;
}
& .selected-label {
display: none;
}
}
`
const DropDown = styled.div`
align-items: center;
cursor: pointer;
display: flex;
@media (max-width: ${({ theme }) => theme.grid.breakpoints.md}px) {
margin-left: auto;
}
`
const ClearTextIcon = styled((props) => )`
margin: 0 12px;
`
export interface ISearchType {
name: SearchCriterias // name is used to check default search field
label: string
icon: React.ReactNode
placeHolderText: string
}
export interface INavigationType {
label: string
id: string
icon?: React.ReactNode
onClick: () => void
}
export interface ISearchToolProps {
searchTypeList: ISearchType[]
navigationList?: INavigationType[]
searchText?: string
selectedSearchType?: string
language: string
searchHandler: (searchText: string, searchType: string) => void
onClearText?: () => void
className?: string
}
export const SearchTool = ({
searchTypeList,
navigationList,
searchText = '',
selectedSearchType: initialSelectedSearchType,
language,
searchHandler,
onClearText,
className
}: ISearchToolProps) => {
const getDefaultSearchType = (): ISearchType => {
if (initialSelectedSearchType) {
return (
searchTypeList.find(
(item: ISearchType) => item.name === initialSelectedSearchType
) || searchTypeList[0]
)
}
return searchTypeList[0]
}
const [dropDownIsVisible, setDropDownIsVisible] = useState(false)
const [searchParam, setSearchParam] = useState(searchText)
const [currentLanguage, setCurrentLanguage] = useState(language)
const [selectedSearchType, setSelectedSearchType] = useState(() =>
getDefaultSearchType()
)
useEffect(() => {
if (language !== currentLanguage) {
const newSelectedSearchType = searchTypeList.find(
(item) => item.name === selectedSearchType.name
)
setSelectedSearchType(newSelectedSearchType || searchTypeList[0])
setCurrentLanguage(language)
}
}, [language, searchTypeList, selectedSearchType.name, currentLanguage])
const search = (e: React.FormEvent) => {
e.preventDefault()
return searchParam && searchHandler(searchParam, selectedSearchType.name)
}
const dropdown = () => {
return (
dropDownIsVisible && (
{searchTypeList.map((item) => {
return (
dropDownItemSelect(item)}
>
{item.icon}
{item.label}
)
})}
{navigationList?.map((item) => {
return (
)
})}
)
)
}
const dropDownItemSelect = (item: ISearchType) => {
setSelectedSearchType(item)
setDropDownIsVisible(false)
}
const toggleDropdownDisplay = () => {
const handler = () => {
setDropDownIsVisible(false)
document.removeEventListener('click', handler)
}
if (!dropDownIsVisible) {
//https://github.com/facebook/react/issues/24657#issuecomment-1150119055
setTimeout(() => document.addEventListener('click', handler), 0)
}
setDropDownIsVisible(!dropDownIsVisible)
}
const onChangeHandler = (event: React.ChangeEvent) => {
setSearchParam(event.target.value)
setDropDownIsVisible(false)
}
const onClearTextHandler = () => {
setSearchParam('')
if (onClearText) {
onClearText()
}
}
const { placeHolderText, name } = selectedSearchType
return (
{searchParam && }
{selectedSearchType.icon}
{selectedSearchType.label}
{dropdown()}
)
}