TIL

2024.04.12 TIL #์ฑ„ํŒ…๋‚ด์šฉ_๊ฒ€์ƒ‰

inz1234 2024. 5. 7. 22:22

๐Ÿ“Œ Task TODOLIST

- [x] ๊ฒ€์ƒ‰์ฐฝ์„ ์—ด์ง€ ๋ง์ง€ ๊ฒฐ์ •ํ•˜๋Š” searchMode ์ƒํƒœ ์ƒ์„ฑ

- [x] ๊ฒ€์ƒ‰๊ธฐ๋Šฅ input์ฐฝ + ๊ฒ€์ƒ‰ ๋ฒ„ํŠผ + ์œ„/์•„๋ž˜ ๋ฒ„ํŠผ ์ƒ์„ฑ

- [x] ์Šคํฌ๋กค ์ค‘์ธ์ง€ ์—ฌ๋ถ€์— ๋”ฐ๋ผ์„œ absolute ๊ฐ’ ์ฃผ๊ธฐ

- [x] ํ˜„์žฌ ๋ณด์ด๋Š” ๋ฉ”์„ธ์ง€๋“ค ์ค‘ ์›ํ•˜๋Š” ๊ฒ€์ƒ‰์–ด ๊ฒ€์ƒ‰ ์‹œ ์ผ์น˜ํ•˜๋Š” ๊ฒฐ๊ณผ ๋ฐฐ์—ด ์ƒ์„ฑ

- [x] ์œ„/์•„๋ž˜ ๋ฒ„ํŠผ ๋ˆ„๋ฅผ ์‹œ ๊ฒ€์ƒ‰ํšŸ์ˆ˜ ๊ธฐ๋ฐ˜์œผ๋กœ up/down count state ์ƒ์„ฑ

- [x] ํ•ด๋‹น์š”์†Œ ์ฐพ์•„์„œ ์Šคํฌ๋กค

- [x] ์ƒ‰ ์น ํ•˜๊ธฐ(๊ฐ•์กฐ์ฒ˜๋ฆฌ)

- [x] ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ

- [x] ๊ฒ€์ƒ‰์ข…๋ฃŒ ์‹œ ์ด์ „๊นŒ์ง€ ๊ฒ€์ƒ‰ํ•˜๋˜ ๊ฑฐ ๋ชจ๋‘ clear


โœจ ๊ฐœ๋ฐœ ๋‚ด์šฉ

1. ๊ฒ€์ƒ‰์ฐฝ์„ ์—ด์ง€ ๋ง์ง€ ๊ฒฐ์ •ํ•˜๋Š” searchMode ์ƒํƒœ ์ƒ์„ฑ

2. ๊ฒ€์ƒ‰๊ธฐ๋Šฅ input์ฐฝ + ๊ฒ€์ƒ‰ ๋ฒ„ํŠผ + ์œ„/์•„๋ž˜ ๋ฒ„ํŠผ ์ƒ์„ฑ

3. ์Šคํฌ๋กค ์ค‘์ธ์ง€ ์—ฌ๋ถ€์— ๋”ฐ๋ผ์„œ absolute ๊ฐ’ ์ฃผ๊ธฐ

import { useMsgsQuery } from '@/hooks/useQueries/useChattingQuery';
import { chatStore } from '@/store/chatStore';
import { useEffect, useState } from 'react';
import { FaChevronDown, FaChevronUp } from 'react-icons/fa';
import { FaX } from 'react-icons/fa6';
import { IoIosSearch } from 'react-icons/io';

const ChatSearch = ({ isScrollTop }: { isScrollTop: boolean }) => {
  const { searchMode, chatRoomId, setSearchMode } = chatStore((state) => state);
  const [searchWord, setSearchWord] = useState('');

  return (
    <>
      {searchMode ? (
        <div className={`${isScrollTop ? 'w-full' : 'absolute z-50 w-[90%]'} flex items-center gap-2`}>
          <form
            onSubmit={(e) => {
              e.preventDefault();
              handleSearch();
            }}
            className="flex w-full gap-2 relative items-center"
          >
            <div className="absolute ml-[10px] flex items-center gap-[6px] text-[#A1A1AA]">
              {searchWord ? null : (
                <>
                  <IoIosSearch />
                </>
              )}
            </div>

            <input
              value={searchWord}
              onChange={(e) => setSearchWord(e.target.value)}
              className="h-[40px] w-full p-[8px] border-2 border-[#D4D4D8] rounded-md focus:outline-none"
              placeholder="     ์ฑ„ํŒ…๋‚ด์šฉ ๊ฒ€์ƒ‰ํ•˜๊ธฐ"
              autoFocus
            ></input>
            <div className="absolute right-3">{doneSearchDivs?.length ? `(${doneSearchDivs?.length})` : ''}</div>
          </form>

          <div className="flex gap-2">
            <div className="flex flex-col justify-center items-center">
              <button onClick={handleSearchUp}>
                <FaChevronUp />
              </button>
              <button onClick={handleSearchDown}>
                <FaChevronDown />
              </button>
            </div>
            <button onClick={stopSearch}>
              <FaX />
            </button>
          </div>
        </div>
      ) : null}
    </>
  );
};

export default ChatSearch;

 

4. ํ˜„์žฌ ๋ณด์ด๋Š” ๋ฉ”์„ธ์ง€๋“ค ์ค‘ ์›ํ•˜๋Š” ๊ฒ€์ƒ‰์–ด ๊ฒ€์ƒ‰ ์‹œ ์ผ์น˜ํ•˜๋Š” ๊ฒฐ๊ณผ ๋ฐฐ์—ด ์ƒ์„ฑ

5. ์œ„/์•„๋ž˜ ๋ฒ„ํŠผ ๋ˆ„๋ฅผ ์‹œ ๊ฒ€์ƒ‰ํšŸ์ˆ˜ ๊ธฐ๋ฐ˜์œผ๋กœ up/down count state ์ƒ์„ฑ

6. ํ•ด๋‹น์š”์†Œ ์ฐพ์•„์„œ ์Šคํฌ๋กค

7. ์ƒ‰ ์น ํ•˜๊ธฐ(๊ฐ•์กฐ์ฒ˜๋ฆฌ)

8. ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ

  const [doneSearchDivs, setDoneSearchdivs] = useState<(HTMLElement | null)[]>();
  const [searchCount, setSearchCount] = useState(0);
  const [upDownCount, setUpDownCount] = useState(0);
 
 const handleSearch = () => {
    if (searchWord) {
      const filteredIds =
        messages &&
        messages
          .filter((m) => m.message?.includes(searchWord))
          .map((messages) => messages.message_id)
          .reverse();
      const idsDivs = filteredIds?.map((id) => {
        return document.getElementById(`${messages?.find((m) => m.message_id === id)?.message_id}`);
      });
      setDoneSearchdivs(idsDivs);

      if (idsDivs && searchCount < idsDivs.length) {
        if (searchCount > 0) idsDivs[searchCount - 1]!.style.backgroundColor = '';
        const theDiv = idsDivs[searchCount];
        if (theDiv) {
          theDiv.style.backgroundColor! = '#E4D4F4';
          theDiv.style.borderRadius = '5px';
          theDiv.scrollIntoView({ block: 'center' });
          setSearchCount((prev) => prev + 1);
          setUpDownCount((prev) => prev + 1);
          // upDownCount๋Š” ์ง€๊ธˆ๊นŒ์ง€ searchํ•œ ๊ฒƒ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋˜์–ด์•ผ ํ•˜๋‹ˆ๊นŒ ์—ฌ๊ธฐ์— ์ข…์†๋˜์–ด์„œ +
        }
      } else {
        alert('๋” ์ด์ƒ ์ฐพ์„ ๋‚ด์šฉ์ด ์—†์Šต๋‹ˆ๋‹ค.');
      }
    } else {
      alert('๊ฒ€์ƒ‰์–ด๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”');
    }
  };

  const handleSearchUp = () => {
    if (doneSearchDivs && upDownCount < doneSearchDivs.length) {
      if (upDownCount > 0) doneSearchDivs[upDownCount - 1]!.style.backgroundColor = '';
      const theDiv = doneSearchDivs[upDownCount];
      if (theDiv) {
        theDiv.style.backgroundColor! = '#E4D4F4';
        theDiv.style.borderRadius = '5px';
        theDiv.scrollIntoView({ block: 'center' });
      }
      setUpDownCount((prev) => prev + 1);
    }
  };

  const handleSearchDown = () => {
    if (doneSearchDivs && 1 < upDownCount) {
      if (upDownCount <= doneSearchDivs.length) doneSearchDivs[upDownCount - 1]!.style.backgroundColor = '';
      const theDiv = doneSearchDivs[upDownCount - 2];
      if (theDiv) {
        theDiv.style.backgroundColor! = '#E4D4F4';
        theDiv.style.borderRadius = '5px';
        theDiv.scrollIntoView({ block: 'center' });
      }
      setUpDownCount((prev) => prev - 1);
    }
  };

  const clearColor = () => {
    doneSearchDivs?.forEach((div) => {
      if (div) div.style.backgroundColor = '';
    });
  };

 

9. ๊ฒ€์ƒ‰์ข…๋ฃŒ ์‹œ ์ด์ „๊นŒ์ง€ ๊ฒ€์ƒ‰ํ•˜๋˜ ๊ฑฐ ๋ชจ๋‘ clear

const stopSearch = () => {
    setSearchMode();
    setSearchCount(0);
    setSearchWord('');
    clearColor();
    setDoneSearchdivs([]);
    setUpDownCount(0);
  };

  useEffect(() => {
    if (!searchWord) {
      setSearchCount(0);
      setUpDownCount(0);
      clearColor();
      setDoneSearchdivs([]);
    }
  }, [searchWord]);

๐Ÿšจ  TroubleShotting 

1. ๋ถ„๋ช…ํžˆ ๊ฐ’์ด ์žˆ๋Š”์ง€ ํ™•์ธํ–ˆ์Œ์—๋„ null์ธ ๊ฒƒ ๊ฐ™๋‹ค๋Š” ์˜ค๋ฅ˜๊ฐ€ ๋‚˜์™”๋‹ค.

 

=> ๋ณ€์ˆ˜์— ํ• ๋‹นํ•ด์„œ ํ™•์ธํ•ด์คฌ๋”๋‹ˆ ํ•ด๊ฒฐ๋˜์—ˆ๋‹ค.

 

 

2. ์ฑ„ํŒ…๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๋ฅผ up & down ํ•  ๋•Œ, ๋‹ค์Œ ๊ฒฐ๊ณผ๋ฅผ focus ํ•˜๋ฉด ์ด์ „ ๊ฒฐ๊ณผ ๊ฐ•์กฐ์ฒ˜๋ฆฌ๊ฐ€ ๊ณ„์† ๋‚จ์•„์žˆ์—ˆ๋‹ค.

=> ๋‹ค์Œ ๊ฒฐ๊ณผ๋กœ focus ๋˜๋ฉด ์ด์ „ ๊ฒฐ๊ณผ์˜ backgroundColor ์Šคํƒ€์ผ์„ "" ๋นˆ ๊ฐ’์œผ๋กœ ๋ณ€๊ฒฝํ•ด์ฃผ์—ˆ๋‹ค.

 

3. upDownCount๊ฐ€ ๋๋„ ์—†์ด ์˜ฌ๋ผ๊ฐ€๊ณ , ๋‚ด๋ ค๊ฐ€๋Š” ์ด์Šˆ ๋ฐœ์ƒ

=> upDownCount๋Š” doneSearchDivs(= ๊ฒ€์ƒ‰๊ฒฐ๊ณผ)์˜ length์— ๋”ฐ๋ผ ์ ์„ ๋•Œ๋งŒ up, 1๋ณด๋‹ค ํด ๋•Œ๋งŒ downํ•  ์ˆ˜ ์žˆ๋„๋ก ์กฐ๊ฑด์„ ์ถ”๊ฐ€ํ•จ

 

 ๐Ÿ“ธ ์Šคํฌ๋ฆฐ์ƒท

๊ฒ€์ƒ‰ํ•˜๊ธฐ(๊ฐ€์žฅ ์ตœ์‹ ์˜ "3" ๊ฐ•์กฐ์ฒ˜๋ฆฌ) ์œ„๋กœ ์˜ฌ๋ฆฌ๋ฉด, ๊ทธ ์ „์˜ "3" ๊ฐ•์กฐ์ฒ˜๋ฆฌ

๐Ÿ“š ๋ ˆํผ๋Ÿฐ์Šค

scrollIntoView()
https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
https://mosei.tistory.com/entry/Javascript-div-%EC%9A%94%EC%86%8C%EC%9D%98-top%EC%8B%9C%EC%9E%91-%EC%9C%84%EC%B9%98-%EC%95%8C%EC%95%84%EB%82%B4%EA%B8%B0

 

[Javascript] div ์š”์†Œ์˜ top(์‹œ์ž‘) ์œ„์น˜ ์•Œ์•„๋‚ด๊ธฐ

ํ˜„์žฌ ๋ธŒ๋ผ์šฐ์ €์—์„œ ์–ผ๋งˆ๋‚˜ ์Šคํฌ๋กค ์ด๋™ ํ–ˆ๋Š”์ง€ ํ™•์ธ var winX = window.pageXOffset; var winY = window.pageYOffset; ํ˜„์žฌ ๋ณด๊ณ ์žˆ๋Š” ํ™”๋ฉด ๊ธฐ์ค€์œผ๋กœ ํŠน์ • ์š”์†Œ์˜ ์œ„์น˜ ์•Œ์•„๋‚ด๊ธฐ var div = document.getElementById("div_id"); va

mosei.tistory.com

https://github.com/Team-MeetGo/MeetGO/pull/105

 

ํ™ฉ์ธ์ • - [feat]: ์ฑ„ํŒ…๋ฐฉ ๋‚ด ๊ฒ€์ƒ‰๊ธฐ๋Šฅ by 2njeong · Pull Request #105 · Team-MeetGo/MeetGO

๐Ÿ“Œ ๊ด€๋ จ ์ด์Šˆ #103 Task TODOLIST ๊ฒ€์ƒ‰์ฐฝ์„ ์—ด์ง€ ๋ง์ง€ ๊ฒฐ์ •ํ•˜๋Š” searchMode ์ƒํƒœ ์ƒ์„ฑ ๊ฒ€์ƒ‰๊ธฐ๋Šฅ input์ฐฝ + ๊ฒ€์ƒ‰ ๋ฒ„ํŠผ + ์œ„/์•„๋ž˜ ๋ฒ„ํŠผ ์ƒ์„ฑ ์Šคํฌ๋กค ์ค‘์ธ์ง€ ์—ฌ๋ถ€์— ๋”ฐ๋ผ์„œ absolute ๊ฐ’ ์ฃผ๊ธฐ ํ˜„์žฌ ๋ณด์ด๋Š” ๋ฉ”์„ธ์ง€

github.com

https://github.com/Team-MeetGo/MeetGO/pull/205

 

ํ™ฉ์ธ์ • - [fix]: ์ฑ„ํŒ… ๊ฒ€์ƒ‰ ๊ธฐ๋Šฅ ์ˆ˜์ • + ๋กœ๋น„ ์ฐธ์—ฌ์ค‘ ๋ฐฉ ์Šคํƒ€์ผ ์ˆ˜์ • by 2njeong · Pull Request #205 · Team-M

๐Ÿ“Œ ๊ด€๋ จ ์ด์Šˆ #128 Task TODOLIST ์ฑ„ํŒ… ๊ฒ€์ƒ‰ ์‹œ ๋‹ค์Œ๊ฒฐ๊ณผ๋กœ up/down ๋  ๋•Œ ์ด์ „๊ฒฐ๊ณผ ๊ฐ•์กฐ๋˜๋Š” ๊ฒƒ ์ทจ์†Œํ•˜๋Š” ๋กœ์ง ์ถ”๊ฐ€ ๋กœ๋น„ ํŽ˜์ด์ง€ ์ฐธ์—ฌ์ค‘ ๋ฆฌ์ŠคํŠธ ์Šคํƒ€์ผ ์ „๋ฐ˜ ์ˆ˜์ • ์ƒˆ๋กœ์šด ๋ฉ”์„ธ์ง€ ์ˆ˜ ๋กœ์ง MeetingRoom.tsx๋กœ

github.com