All files / src/components/shared/search-bar index.tsx

20.77% Statements 16/77
100% Branches 0/0
0% Functions 0/1
20.77% Lines 16/77

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 781x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x                                                                                                                            
'use client';
 
import { ChangeEvent, InputHTMLAttributes, KeyboardEvent, useState } from 'react';
 
import { Icon } from '@/components/icon';
import { Input } from '@/components/ui';
import { cn } from '@/lib/utils';
 
interface SearchBarProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange'> {
  onSearch?: (value: string) => void;
  onChange?: (value: string) => void;
  value?: string;
  defaultValue?: string;
}
 
export const SearchBar = ({
  className,
  placeholder = '검색어를 입력하세요',
  onSearch,
  onChange,
  value,
  defaultValue = '',
  ...props
}: SearchBarProps) => {
  const isControlled = value !== undefined;

  const [innerValue, setInnerValue] = useState(defaultValue);

  const currentValue = isControlled ? value : innerValue;

  const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
    const newValue = event.target.value;

    if (!isControlled) {
      setInnerValue(newValue);
    }

    onChange?.(newValue);
  };

  const handleSearch = () => {
    onSearch?.(currentValue ?? '');

    // 추가 동작 추천?
    // 검색 실행 전 공백 제거 로직
  };

  const handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {
    if (event.key === 'Enter') {
      handleSearch();
    }
  };

  return (
    <Input
      className={cn(
        'focus:border-mint-500 rounded-3xl border border-transparent bg-gray-100',
        className,
      )}
      iconButton={
        <button
          className='absolute top-1/2 right-5 h-6 w-6 -translate-y-1/2'
          aria-label='검색 실행'
          type='button'
          onClick={handleSearch}
        >
          <Icon id='search' className='text-mint-600' />
        </button>
      }
      placeholder={placeholder}
      value={currentValue}
      onChange={handleChange}
      onKeyDown={handleKeyDown}
      {...props}
    />
  );
};