synapsecns/sanguine

View on GitHub
packages/explorer-ui/components/pages/Home/UniversalSearch/index.tsx

Summary

Maintainability
F
5 days
Test Coverage
import { useState } from 'react'
import { CHAINS } from '@synapsecns/synapse-constants'
import TextField from '@mui/material/TextField'
import {
  inputStyle,
  dateInputStyle,
  comboSelectStyle,
  comboSelectStyleSmall,
  inputStyleRounded,
} from '@utils/styles/muiStyles'
import { validateAndParseAddress } from '@utils/validateAndParseAddress'
import { validateAndParseHash } from '@utils/validateAndParseHash'
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'
import { DatePicker } from '@mui/x-date-pickers/DatePicker'
import MenuItem from '@mui/material/MenuItem'
import { TRANSACTIONS_PATH } from '@urls'

const ChainId = CHAINS.ChainId
const CHAIN_ENUM_BY_ID = CHAINS.CHAIN_ENUM_BY_ID

export const UniversalSearch = ({
  setPending,
  pending,
  loading,
  setWallet,
  wallet,
  setMinSize,
  minSize,
  setMaxSize,
  maxSize,
  setStartDate,
  startDate,
  setEndDate,
  endDate,
  setToTx,
  setFromTx,
  setKappa,
  kappa,
  executeSearch,
  chains,
  setChains,
  chainsLocale,
  setChainsLocale,
  walletLocale,
  setWalletLocale,
}) => {
  const [searchField] = useState('')
  const [showText, setShowText] = useState(false)
  // const [startDate, setStartDate] = useState("s");
  const handleChains = (event) => {
    const {
      target: { value },
    } = event
    setChains(
      // On autofill we get a stringified value.
      typeof value === 'string' ? value.split(',') : value
    )
  }

  const unSelectStyle =
    'transition ease-out border-l-0 border-gray-700 border-opacity-30 text-gray-500 bg-gray-700 bg-opacity-30 hover:bg-opacity-20 hover:text-white'
  const selectStyle = 'text-white border-[#BE78FF] bg-synapse-radial'
  const resetFields = () => {
    setWallet('')
    setMinSize({ type: 'USD', value: '' })
    setMaxSize({ type: 'USD', value: '' })
    setStartDate(null)
    setEndDate(null)
    setToTx(true)
    setFromTx(true)
    setChains([])
    setKappa('')
  }
  // let isValid
  // let error
  // let inputType
  // let searchLink
  if (!searchField || searchField === '') {
    // error = 'Field cannot be empty.'
  } else if (validateAndParseAddress(searchField)) {
    // isValid = true
    // inputType = 'ADDRESS'
    // searchLink = '/txs?account=' + searchField
  } else if (validateAndParseHash(searchField)) {
    // isValid = true
    // inputType = 'TRANSACTION'
    // searchLink = '/tx/' + searchField
    // @ts-ignore
  } else if (Object.values(ChainId).includes(searchField as ChainId)) {
    // isValid = true
    // inputType = 'CHAIN'
    // searchLink = '/txs?chainId=' + searchField
  } else {
    // error = 'Not a valid address or transaction hash'
  }

  return (
    <>
      <div className="border-white border-y border-opacity-10 ">
        <div className="flex flex-col items-center justify-center p-2 py-6 space-y-2 sm:flex-row gap-x-4 sm:space-y-0">
          <h3
            className="flex items-center hidden mr-4 text-white sm:flex"
            onClick={() => setShowText(!showText)}
          >
            {!showText ? (
              <svg
                xmlns="http://www.w3.org/2000/svg"
                viewBox="0 0 24 24"
                fill="currentColor"
                className="w-4 h-4 mr-2"
              >
                <path
                  fillRule="evenodd"
                  d="M4.72 3.97a.75.75 0 011.06 0l7.5 7.5a.75.75 0 010 1.06l-7.5 7.5a.75.75 0 01-1.06-1.06L11.69 12 4.72 5.03a.75.75 0 010-1.06zm6 0a.75.75 0 011.06 0l7.5 7.5a.75.75 0 010 1.06l-7.5 7.5a.75.75 0 11-1.06-1.06L17.69 12l-6.97-6.97a.75.75 0 010-1.06z"
                  clipRule="evenodd"
                />
              </svg>
            ) : (
              <svg
                xmlns="http://www.w3.org/2000/svg"
                viewBox="0 0 24 24"
                fill="currentColor"
                className="w-4 h-4 mr-2"
              >
                <path
                  fillRule="evenodd"
                  d="M20.03 4.72a.75.75 0 010 1.06l-7.5 7.5a.75.75 0 01-1.06 0l-7.5-7.5a.75.75 0 011.06-1.06L12 11.69l6.97-6.97a.75.75 0 011.06 0zm0 6a.75.75 0 010 1.06l-7.5 7.5a.75.75 0 01-1.06 0l-7.5-7.5a.75.75 0 111.06-1.06L12 17.69l6.97-6.97a.75.75 0 011.06 0z"
                  clipRule="evenodd"
                />
              </svg>
            )}
            Filters
          </h3>
          <div className="flex flex-col gap-2 sm:flex-row grow">
            <TextField
              size="small"
              value={kappa}
              onChange={(e) => {
                setKappa(e.target.value)
              }}
              onKeyDown={(e) => {
                if (e.key === 'Enter') {
                  window.location.href =
                    TRANSACTIONS_PATH + (kappa ? '?hash=' + kappa : '')
                }
              }}
              id="outlined-basic"
              label="Search by TXID / TXHash"
              variant="outlined"
              sx={inputStyle}
              className="grow sm:flex-1"
            />
            <button
              onClick={() => executeSearch()}
              className={
                'type-"button" font-medium rounded-md border border-l-0 border-gray-700 text-white bg-gray-700 px-4 py-1 hover:bg-opacity-70 ease-in-out duration-200 ' +
                (loading ? ' pointer-events-none opacity-[0.4]' : '') +
                ' sm:flex-none sm:w-auto'
              }
            >
              Search
            </button>
          </div>
          {/* <button onClick={() => executeSearch()} className="px-4 py-2 font-medium text-white duration-200 ease-in-out bg-gray-700 border border-l-0 border-gray-700 rounded-md hover:bg-opacity-70">
            <a href={searchLink}>Search</a>
          </button> */}
          <div className="sm:w-auto sm:mx-auto sm:items-center sm:py-2">
            <button
              disabled={loading}
              onClick={() => setPending(false)}
              className={
                'font-medium rounded-l-md px-4 py-2 border ' +
                (pending ? unSelectStyle : selectStyle) +
                (loading ? ' pointer-events-none' : '')
              }
            >
              Confirmed
            </button>
            <button
              disabled={loading}
              onClick={() => setPending(true)}
              className={
                'font-medium rounded-r-md px-4 py-2 border ' +
                (pending ? selectStyle : unSelectStyle) +
                (loading ? ' pointer-events-none' : '')
              }
            >
              Pending
            </button>
          </div>
          {/* {!isValid && error ? (
          <div
          className="absolute p-4 mt-1 mb-4 text-sm font-medium text-red-700 bg-red-100 rounded-lg dark:bg-red-200 dark:text-red-800"
            role="alert"
          >
            {error}
          </div>
        ) : (
          ""
        )} */}
        </div>
        {showText ? (
          <div>
            {/* THIS IS WALLET ADDRESS */}
            <div className="flex items-center justify-center p-2 py-4 gap-x-4">
              <h3
                className="flex items-center mr-10 text-white"
                onClick={() => setShowText(!showText)}
              >
                Wallet
              </h3>
              <div className="grow">
                <TextField
                  size="small"
                  value={wallet}
                  onChange={(e) => {
                    setWallet(e.target.value)
                  }}
                  id="outlined-basic"
                  label="Wallet Address"
                  variant="outlined"
                  sx={inputStyle}
                />
              </div>
              <div className="flex justify-center rounded-md border-l-0 border-gray-700 border-opacity-70 bg-[#333333]  bg-opacity-30  py-[9px] px-3">
                <div
                  className="mx-1 form-check form-check-inline"
                  onClick={() => setWalletLocale(!walletLocale)}
                >
                  <input
                    checked={walletLocale}
                    className="float-left w-4 h-4 mt-1 mr-2 align-top transition duration-200 bg-white bg-center bg-no-repeat bg-contain border border-gray-300 rounded-sm appearance-none cursor-pointer form-check-input checked:bg-purple-300 checked:bg-opacity-90 checked:border-purple-600 focus:outline-none"
                    type="checkbox"
                    id="walletFrom"
                    value="option1"
                  />
                  <label
                    className="inline-block text-gray-500 form-check-label "
                    htmlFor="walletFrom"
                  >
                    From
                  </label>
                </div>
                <div
                  className="mx-1 form-check form-check-inline"
                  onClick={() => setWalletLocale(!walletLocale)}
                >
                  <input
                    checked={!walletLocale}
                    className="float-left w-4 h-4 mt-1 mr-2 align-top transition duration-200 bg-white bg-center bg-no-repeat bg-contain border border-gray-300 rounded-sm appearance-none cursor-pointer form-check-input checked:bg-purple-300 checked:bg-opacity-90 checked:border-purple-600 focus:outline-none"
                    type="checkbox"
                    id="walletTo"
                    value="option2"
                  />
                  <label
                    className="inline-block text-gray-500 form-check-label "
                    htmlFor="walletTo"
                  >
                    To
                  </label>
                </div>
              </div>

              {/* <input
                type="checkbox"
                className="w-4 h-4 text-indigo-600 border-gray-300 rounded focus:ring-indigo-500"
                checked={toTx}
                onClick={() => { setToTx(!toTx) }}

              />
              <h3 className="font-semibold text-white">To</h3>
              <input
                type="checkbox"
                className="w-4 h-4 text-indigo-600 border-gray-300 rounded focus:ring-indigo-500"
                checked={fromTx}
                onClick={() => { setFromTx(!fromTx) }}
              />
              <h3 className="font-semibold text-white">From</h3> */}
            </div>

            {/* THIS IS MIN/MAX SIZE */}
            <div className="flex items-center justify-center p-2 py-4 gap-x-14">
              <h3
                className="flex items-center mr-1 text-white"
                onClick={() => setShowText(!showText)}
              >
                Chain
              </h3>
              <div className="grow">
                <div className="flex flex-row items-center ">
                  <TextField
                    select
                    id="Chains"
                    name="Chains"
                    variant="outlined"
                    label="Chains"
                    size="small"
                    value={chains}
                    sx={comboSelectStyle}
                    SelectProps={{
                      multiple: true,
                      onChange: (e) => handleChains(e),
                    }}
                  >
                    {Object.values(CHAIN_ENUM_BY_ID).map((chain: string) => (
                      <MenuItem key={chain} value={chain}>
                        {chain.charAt(0).toUpperCase() + chain.slice(1)}
                      </MenuItem>
                    ))}
                  </TextField>

                  <div className="ml-4 w-fit flex justify-center rounded-md border-l-0 border-gray-700 border-opacity-70 bg-[#333333]  bg-opacity-30 py-[9px] px-3">
                    <div
                      className="mx-2 form-check form-check-inline"
                      onClick={() => setChainsLocale(!chainsLocale)}
                    >
                      <input
                        checked={chainsLocale}
                        className="float-left w-4 h-4 mt-1 mr-2 align-top transition duration-200 bg-white bg-center bg-no-repeat bg-contain border border-gray-300 rounded-sm appearance-none cursor-pointer form-check-input checked:bg-purple-300 checked:bg-opacity-90 checked:border-purple-600 focus:outline-none"
                        type="checkbox"
                        id="walletFrom"
                        value="option1"
                      />
                      <label
                        className="inline-block text-gray-500 form-check-label "
                        htmlFor="walletFrom"
                      >
                        From
                      </label>
                    </div>
                    <div
                      className="mx-2 form-check form-check-inline"
                      onClick={() => setChainsLocale(!chainsLocale)}
                    >
                      <input
                        checked={!chainsLocale}
                        className="float-left w-4 h-4 mt-1 mr-2 align-top transition duration-200 bg-white bg-center bg-no-repeat bg-contain border border-gray-300 rounded-sm appearance-none cursor-pointer form-check-input checked:bg-purple-300 checked:bg-opacity-90 checked:border-purple-600 focus:outline-none"
                        type="checkbox"
                        id="walletTo"
                        value="option2"
                      />
                      <label
                        className="inline-block text-gray-500 form-check-label "
                        htmlFor="walletTo"
                      >
                        To
                      </label>
                    </div>
                  </div>
                </div>
              </div>
            </div>

            {/* THIS IS MIN/MAX SIZE */}
            <div className="flex items-center justify-center p-2 py-4 gap-x-6">
              <h3
                className="flex items-center mr-6 text-white"
                onClick={() => setShowText(!showText)}
              >
                Volume
              </h3>
              <div className="flex flex-row justify-between w-full">
                <div className="w-[49%] flex flex-row ">
                  <div className="w-[80%]">
                    <TextField
                      type="number"
                      size="small"
                      value={minSize.value}
                      onChange={(e) => {
                        setMinSize({ ...minSize, value: e.target.value })
                      }}
                      id="outlined-basic"
                      label="Min Size"
                      variant="outlined"
                      sx={inputStyleRounded}
                    />
                  </div>
                  <div className="w-[20%]">
                    <TextField
                      select
                      id="UnitsMin"
                      name="UnitsMin"
                      variant="outlined"
                      label="Units"
                      size="small"
                      sx={comboSelectStyleSmall}
                      SelectProps={{
                        value: minSize.type,
                        onChange: (e) =>
                          setMinSize({ ...minSize, type: e.target.value }),
                      }}
                    >
                      <MenuItem key="USD" value="USD" selected>
                        USD
                      </MenuItem>
                      {/* <MenuItem
                        key="Amount"
                        value="Amount"
                      >
                        Amount
                      </MenuItem> */}
                    </TextField>
                  </div>
                </div>
                <div className="w-[49%] flex flex-row">
                  <div className="w-[80%]">
                    <TextField
                      size="small"
                      type="number"
                      onChange={(e) => {
                        setMaxSize({ ...maxSize, value: e.target.value })
                      }}
                      value={maxSize.value}
                      id="outlined-basic"
                      label="Max Size"
                      variant="outlined"
                      sx={inputStyleRounded}
                    />
                  </div>
                  <div className="w-[20%]">
                    <TextField
                      select
                      id="UnitsMax"
                      name="UnitsMax"
                      variant="outlined"
                      label="Units"
                      size="small"
                      sx={comboSelectStyleSmall}
                      SelectProps={{
                        value: maxSize.type,
                        onChange: (e) =>
                          setMaxSize({ ...maxSize, type: e.target.value }),
                      }}
                    >
                      <MenuItem key="USD" value="USD">
                        USD
                      </MenuItem>
                      {/* <MenuItem
                        key="Amount"
                        value="Amount"
                      >
                        Amount
                      </MenuItem> */}
                    </TextField>
                  </div>
                </div>
              </div>
            </div>
            {/* THIS IS START/DATE */}
            <div className="flex items-center justify-center p-2 py-4 gap-x-14">
              <h3
                className="flex items-center mr-2 text-white"
                onClick={() => setShowText(!showText)}
              >
                Time
              </h3>
              <div className="flex flex-row justify-between w-full">
                <div className="w-[49%]">
                  <LocalizationProvider dateAdapter={AdapterDayjs}>
                    <DatePicker
                      label="Start Date"
                      value={startDate}
                      onChange={(newValue) => {
                        setStartDate(newValue)
                      }}
                      renderInput={(params) => (
                        <TextField
                          size="small"
                          sx={dateInputStyle}
                          {...params}
                        />
                      )}
                    />
                  </LocalizationProvider>
                </div>
                <div className="w-[49%]">
                  <LocalizationProvider
                    sx={{ width: '100%' }}
                    dateAdapter={AdapterDayjs}
                  >
                    <DatePicker
                      label="End Date"
                      value={endDate}
                      onChange={(newValue) => {
                        setEndDate(newValue)
                      }}
                      renderInput={(params) => (
                        <TextField
                          size="small"
                          sx={dateInputStyle}
                          {...params}
                        />
                      )}
                    />
                  </LocalizationProvider>
                </div>
              </div>{' '}
            </div>
            {/* THIS IS BUTTONS */}
            <div className="flex items-center p-2 mb-3 gap-x-4">
              <button
                className="px-4 py-2 font-medium text-white duration-200 ease-in-out bg-gray-700 border border-l-0 border-gray-700 rounded-md hover:bg-opacity-70"
                onClick={() => resetFields()}
              >
                Reset
              </button>
            </div>
          </div>
        ) : null}
      </div>
    </>
  )
}