Project_Kulture_Tech_ํšŒ๊ณ ๐ŸŽต

Yeonnยท2023๋…„ 7์›” 16์ผ
0

Project_Kulture

๋ชฉ๋ก ๋ณด๊ธฐ
2/2
post-thumbnail

ํ”„๋กœ์ ํŠธ ์˜์ƒ๋งํฌ ๐ŸŒผ
https://www.youtube.com/watch?v=v78D9IcYdU8

1. Styled Component ํ™œ์šฉ

์ด์ „ ํ”„๋กœ์ ํŠธ์™€ ๊ฐ€์žฅ ํฐ ์ฐจ์ด์ ์€ Styled Component๋ฅผ ํ™œ์šฉํ•ด ๋ณด์•˜๋‹ค๋Š” ์ ์ด๋‹ค.
Styled Component๋ฅผ ํ™œ์šฉํ•˜๋ฉด ์ฝ”๋“œ๊ฐ€ ๊น”๋”ํ•˜๊ฒŒ ์ •๋ฆฌ๋˜๊ณ  ์ฝ”๋“œ ์Šคํฌ๋กค์ด ์ค„์–ด๋“ ๋‹ค.
html/css๊ฐ€ ์ฝ”๋“œ์™€ ๋ถ„๋ฆฌ๋˜์–ด jsxํŒŒ์ผ์—๋Š” ์™„์ „ํžˆ ๊ธฐ๋Šฅ์„ ์œ„ํ•œ ์ฝ”๋“œ๋งŒ์ด ๋ถ„๋ฆฌ๋˜์–ด ๊ด€๋ฆฌ๋˜๋ฏ€๋กœ
ํ™•์ธ์ด ํŽธ๋ฆฌํ•˜๊ณ  ๊ตฌ์กฐ ํ™•์ธ์— ์šฉ์ดํ•˜๋‹ค. ๋˜ํ•œ ํด๋ž˜์Šค ๋ช…์— ๋Œ€ํ•œ ๊ณ ๋ฏผ์„ ์ค„์ผ ์ˆ˜ ์žˆ์—ˆ๊ณ ,
์‹ค์ˆ˜๋กœ ์ค‘๋ณต๋œ ํด๋ž˜์Šค๋ช…์„ ๊ฐ–๊ฒŒ ๋˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์—†์–ด ์ž˜๋ชป๋œ css๊ฐ€ ์ ์šฉ๋˜์–ด ์˜ค์—ผ๋˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์—†์—ˆ๋‹ค.



2. EventCard Component

1. type

{type !== 'wishlist' ? (
          ''
        ) : (
          <S.Check
            src={
              checkList.includes(event_id)
                ? '/images/common/check-true.png'
                : '/images/common/check-false.png'
            }
            onClick={() => handleChecked(event_id)}
          />
        )}

EventCard ์ปดํฌ๋„ŒํŠธ๋Š” ํ•˜๋‚˜์˜ ์ปดํฌ๋„ŒํŠธ ์ด์ง€๋งŒ, wishlist์™€ ๊ทธ ์™ธ ํŽ˜์ด์ง€์—์„œ ํ™œ์šฉ๋„๊ฐ€ ๋‹ค๋ฅด๋‹ค.
์˜ˆ๋ฅผ ๋“ค์–ด checklist๊ธฐ๋Šฅ์€ wishlist์—๋งŒ ์žˆ๋‹ค. ์ด๋Ÿฌํ•œ ๊ธฐ๋Šฅ๋“ค์˜ ์ฐจ์ด๋ฅผ ๋”ฐ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก
๊ฐ ํŽ˜์ด์ง€์—์„œ EventCard ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ๋•Œ type์„ ๋ถ€์—ฌํ•œ๋‹ค.

์ด type์ด wishlist ์ธ์ง€, ๊ทธ ์™ธ์ธ์ง€๋ฅผ ๊ตฌ๋ถ„ํ•˜์—ฌ ๊ฐ๊ฐ ๋‹ค๋ฅด๊ฒŒ ๋ Œ๋”๋งํ•  ์ˆ˜ ์žˆ๋„๋ก ์ž‘์—…ํ•˜์˜€๋‹ค.
์œ„์˜ ์„ ํƒ์‚ญ์ œ๋ฅผ ์œ„ํ•œ ์ฒดํฌ๋ฆฌ์ŠคํŠธ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ UX์ ์ธ ๊ด€์ ์—์„œ๋„,
๋‹ค๋ฅธ ํŽ˜์ด์ง€์—์„œ๋Š” ์ด๋ฒคํŠธ ์ž์ฒด์˜ ์ •๋ณด๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๋ฐ ์ฃผ๋ ฅํ•˜๊ณ 
wishlist ํŽ˜์ด์ง€์—์„œ๋Š” ์ด๋ฏธ user๊ฐ€ ์ด๋ฒคํŠธ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๊ฐ–๊ณ  ํฅ๋ฏธ๋ฅผ ๊ฐ€์ง„ ์ƒํƒœ์ด๋ฏ€๋กœ
'์ž…์ฐฐ ๋งˆ๊ฐ ๋‚จ์€ ์‹œ๊ฐ„'๊ณผ '๋‚จ์€ ํ‹ฐ์ผ“ ์ˆ˜'๋ฅผ ํ‘œ๊ธฐํ•˜๋„๋ก ํ•˜์—ฌ ๊ตฌ๋งค ์š•๊ตฌ๋ฅผ ์ฆ๋Œ€ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๊ณ ์•ˆํ•˜์˜€๋‹ค.

2. fetchLiked

๋ชจ๋“  ํŽ˜์ด์ง€์—์„œ ๋ Œ๋”๋ง ๋  eventCard์˜ wishlist ํฌํ•จ ์—ฌ๋ถ€์˜ ์ƒํƒœ๋ฅผ ํ•œ๋ฒˆ์— ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก
๊ธฐ๋Šฅ์„ ๋”ฐ๋กœ fetchLiked ํ•จ์ˆ˜๋กœ ๋งŒ๋“ค์–ด ๊ด€๋ฆฌํ•˜์˜€๋‹ค.

์ด ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค ๋•Œ recoil ์‚ฌ์šฉ๊ณผ ๊ณ ๋ฏผ์„ ํ•ด๋ณด๊ฒŒ ๋˜์—ˆ๋‹ค.
ํ•˜์ง€๋งŒ ๋‹จ์ˆœํžˆ ํ”„๋ก ํŠธ ๋‹จ์—์„œ ์ €์žฅ๊ณผ์ • ์—†์ด ์‚ฌ์šฉํ•  ๋ฐ์ดํ„ฐ๊ฐ€ ์•„๋‹ˆ๊ณ ,
์ƒˆ๋กœ๊ณ ์นจ์ด๋‚˜ ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ํŽ˜์ด์ง€์˜ ๋‹ซํž˜ ๋“ฑ์ด ์ƒ๊ฒผ์„ ๋•Œ์—๋„ ์œ ์ง€๊ฐ€ ๋˜์–ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์—
๋ฐฑ ๋‹จ๊ณผ ๋ฐ”๋กœ ๋ฐ”๋กœ ํ†ต์‹ ํ•˜๋ฉด์„œ user data ์•ˆ์—์„œ ๊ด€๋ฆฌ๋˜์–ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์˜€๋‹ค.

๊ทธ๋ž˜์„œ user๊ฐ€ liked(heart)๋ฅผ ๋ˆ„๋ฅผ ๋•Œ ๋งˆ๋‹ค ํ†ต์‹ ์ด ์ผ์–ด๋‚  ์ˆ˜ ์žˆ์–ด์•ผ ํ•˜๊ณ 
๋กœ๊ทธ์ธ ๋œ user๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ, ์ฆ‰ TOKEN์„ ๋ถ€์—ฌ ๋ฐ›์€ ๊ฒฝ์šฐ์—๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“ค์—ˆ๋‹ค.

TOKEN, url, wishlist(data), event_id๋ฅผ ์ฃผ์š”๋กœ ์ „๋‹ฌ๋ฐ›๋„๋ก ํ•˜๊ณ 

const isExistData =
    wishlist &&
    wishlist.filter(el => el.event_id === Number(event_id)).length > 0;

wishlist data์— ๋“ค์–ด์žˆ๋Š” event_id์™€ data์—์„œ ๋ฐ›์€ event_id๋ฅผ filter๋กœ ๋น„๊ตํ•˜์—ฌ 1๊ฐœ๋ผ๋„ wishlist์— data๊ฐ€ ์กด์žฌํ•˜๋ฉด DELETEํ†ต์‹ ์„ ์ง„ํ–‰ํ•˜๊ณ  ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด event_id๋ฅผ ๊ธฐ์ค€์œผ๋กœ POST ํ†ต์‹ ์„ ์ง„ํ–‰ํ•œ๋‹ค.

์ด ํ†ต์‹ ๊ณผ ํ•จ๊ป˜ eventCard Component ๋‚ด๋ถ€์—์„œ๋Š” wishlist ID ์—ฌ๋ถ€๋ฅผ includes๋กœ ์ฒดํฌํ•˜์—ฌ ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์˜ heart๋ฅผ ์ƒํƒœ ๋ณ€ํ™˜ํ•œ๋‹ค.

3. fetchLiked ํ™œ์šฉ

๋ชจ๋“  ํŽ˜์ด์ง€์—์„œ fetchLiked๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ EventCard ๊ฐ€ ๋ Œ๋”๋ง ๋  ๋•Œ ํ•ด๋‹น ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•œ๋‹ค.

const setId = (data, event_id) => {
	fetchLiked(TOKEN, APIS.wishlist, data, event_id, setWishlist, getWishList);
		  };

์—ฌ๊ธฐ์„œ getWishlist๋Š” wishlist๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ํ†ต์‹ ์œผ๋กœ ๋”ฐ๋กœ ์„ ์–ธ๋œ ๋ณ€์ˆ˜์— ๋‹ด์•„๋‘๊ณ  ์‹คํ–‰ํ•˜๋„๋ก ํ•œ๋‹ค.



3. Wishlist

ย ๐Ÿ“ wishlist ํ†ต์‹ ์€ ํ•ญ์ƒ TOKEN ๊ฐ’์„ ๊ธฐ๋ณธ์œผ๋กœ ๊ฐ–๋„๋ก ํ•˜์—ฌ ํšŒ์› ๊ฐ๊ฐ์˜ wishlist ๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.

1. emptyBox

UX์ ์ธ ๊ด€์ ์—์„œ wishlist๊ฐ€ ๋น„์–ด์žˆ๋‹ค๊ณ  ์•„๋ฌด๊ฒƒ๋„ ๋…ธ์ถœ๋˜์ง€ ์•Š์œผ๋ฉด ์‚ฌ์šฉ์ž๋Š” ์•„์ง ๋ Œ๋”๋ง์ด ์ง„ํ–‰ ์ค‘์ธ์ง€, wishlist๊ฐ€ ๋น„์–ด์žˆ๋Š”์ง€ ํŒŒ์•…ํ•˜๊ธฐ๊ฐ€ ์–ด๋ ต๋‹ค. ๊ทธ๋ž˜์„œ ํ•œ ๋ˆˆ์— ์•Œ ์ˆ˜ ์žˆ๋„๋ก wishlist.length๋ฅผ ํ™œ์šฉํ•˜์—ฌ 0์ด๋ผ๋ฉด ๋ฏธ๋ฆฌ ์ง€์ •ํ•ด๋‘” ๋ฌธ๊ตฌ (์ด๋ฒคํŠธ ์นด๋“œ๋ฅผ ๋‹ด์•„์ฃผ์„ธ์š”!) ๋ฅผ ๋ Œ๋”๋ง ํ•  ์ˆ˜ ์žˆ๋„๋ก ์กฐ๊ฑด๋ถ€ ๋ Œ๋”๋ง์„ ์‚ฌ์šฉํ•˜์˜€๋‹ค.

2. handleChecked

const handleChecked = event_id => {
    if (checkList.includes(event_id)) {
      setCheckList(checkList.filter(el => el !== event_id));
    } else {
      setCheckList([...checkList, event_id]);
    }
  };

wishlist์—์„œ๋งŒ ๋ Œ๋”๋ง ๋˜๋Š” check icon์„ ํด๋ฆดํ•  ๋•Œ๋งˆ๋‹ค handleChecked๊ฐ€ ์‹คํ–‰๋œ๋‹ค.
checklist ๊ฐ€ ์ด๋ฏธ ํ•ด๋‹น event_id๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ์„ ๊ฒฝ์šฐ ๋ฐฐ์—ด ๋‚ด์—์„œ ์‚ญ์ œํ•˜๊ณ , ํฌํ•จ๋˜์ง€ ์•Š์•˜์„ ๊ฒฝ์šฐ ์ถ”๊ฐ€ํ•œ๋‹ค.

3. handleDeleteChecked

const handleDeleteChecked = id => {
    if (checkList !== []) {
      let copy = [...wishlist];
      setWishlist(copy.filter(el => !checkList.includes(el.id)));
      setType('checked');
    }
    
    const url = `${APIS.wishlist}`;
    const deleteCards = checkList.join(',');

    fetch(`${url}/${deleteCards}`, {
      method: 'DELETE',
      headers: {
        'Content-Type': 'application/json;charset=urf-8',
        Authorization: TOKEN,
      },
    }).then(response => {
      if (response.ok) {
        getWishList();
      }
    });
  };

์œ„์˜ handleChecked๋กœ ๋งŒ๋“  checklist ๋ฐฐ์—ด์ด ๋นˆ๋ฐฐ์—ด์ด ์•„๋‹ ๊ฒฝ์šฐ setWishlist๋ฅผ ํ™œ์šฉํ•˜์—ฌ wishlist์—์„œ checklist( ์‚ญ์ œ๋ฅผ ์œ„ํ•ด ์„ ํƒ๋œ ์ด๋ฒคํŠธ ๋“ค์˜ id๊ฐ€ ํฌํ•จ๋œ ๋ฐฐ์—ด ) ์— ํฌํ•จ๋œ id ๋ฐฐ์—ด์„ joinํ•˜์—ฌ endpoint์— ๋‹ด์•„ ๋ณด๋ƒ„์œผ๋กœ์จ ์„ ํƒ๋œ event๋ฅผ wishlist์—์„œ ์‚ญ์ œํ•œ๋‹ค.

์ด ๋•Œ type์„ checked๋กœ ์ง€์ •ํ•จ์œผ๋กœ์จ ์‚ญ์ œ ๋ชจ๋‹ฌ์ด ๋–ด์„ ๋•Œ ์„ ํƒ ์‚ญ์ œ๋ฅผ ์ง„ํ–‰ํ•  ์ง€ ์ „์ฒด ์‚ญ์ œ๋ฅผ ์ง„ํ–‰ํ•  ์ง€ ์ „๋‹ฌํ•œ๋‹ค.

4. handleDeleteAll

wishlist ๋ฐฐ์—ด ๋‚ด ๋ชจ๋“  ๊ฐœ์ฒด๋ฅผ joinํ•ด์„œ endpoint์— ๋‹ด์•„ ๋ณด๋ƒ„์œผ๋กœ์จ ๋ชจ๋“  wishlist๋ฅผ ์‚ญ์ œํ•œ๋‹ค.

5. ๋ฌดํ•œ๋ Œ๋”๋ง (๋”๋ณด๊ธฐ)

let limit = searchParams.get('limit');

const handleMoreEvent = () => {
	searchParams.set('limit', Number(limit) + 6);
    setSearchParams(searchParams);
  };

limit์„ ๋ฐฑ์—”๋“œ์—์„œ ๊ธฐ๋ณธ๊ฐ’ 6์œผ๋กœ ์ „๋‹ฌ๋ฐ›๊ณ  ์žˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋จผ์ € limit ์„ searchParams.get()์œผ๋กœ ๋ฐ›์•„์˜ค๋„๋ก ํ•œ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ํ™”๋ฉด ํ•˜๋‹จ์— ๋”๋ณด๊ธฐ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•  ๋•Œ ๋งˆ๋‹ค limit์— 6์„ ๊ณ„์†ํ•ด์„œ ๋”ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ž‘์—…ํ•˜์˜€๋‹ค.



4. EventList

1. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ™œ์šฉ ( calendar/range filter )

1. calendar

๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ™œ์šฉํ•œ ๊ฒƒ์€ ์ฒ˜์Œ์ด๋ผ ์ฒ˜์Œ ์ž‘์—…ํ•  ๋•Œ๋Š” ๋งค์šฐ ์ž‘์€ ๊ฑฐ ๋ถ€ํ„ฐ ๋งŽ์ด ํ—ค๋งธ๋‹ค. ์ƒˆ๋กœ์šด ํŒŒ์ผ์„ ์ถ”๊ฐ€ํ•ด์„œ CSS๋ฅผ ์ ์šฉํ•ด ์ปค์Šคํ„ฐ๋งˆ์ด์ง•์„ ํ•œ ํ›„์— ๊ธฐ๋Šฅ ์ž‘์—…์— ๋“ค์–ด๊ฐ”๋Š”๋ฐ, ์ฒ˜์Œ์— onClick ์ž์ฒด๊ฐ€ ๋™์ž‘์„ ํ•˜์ง€ ์•Š์•„ ๋„ˆ๋ฌด ๋‹นํ™ฉ์Šค๋Ÿฌ์› ๋‹ค. ๊ทธ๋ž˜์„œ ๊ทธ ๋‹ค์Œ์—” onChange๋ฅผ ์ ์šฉํ•ด ๋ณด๋‹ˆ ์ž‘๋™์€ ์ œ๋Œ€๋กœ ํ•˜์ง€๋งŒ, ํ•œ ํ…œํฌ ๋А๋ฆฌ๊ฒŒ ์ž‘๋™ํ•˜๋Š” ๊ฒƒ์ด ๋งˆ์Œ์— ๋“ค์ง€ ์•Š์•˜๋‹ค.

๋‹ค์‹œ ๊ณต์‹ ๋ฌธ์„œ๋ฅผ ๊ผผ๊ผผํžˆ ์‚ดํŽด๋ณด๋‹ˆ onClickDay๋ผ๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ๋”ฐ๋กœ ์ •๋ฆฌ ๋˜์–ด ์žˆ์—ˆ๋‹ค. ์ด๊ฑธ ํ™œ์šฉํ•˜๋‹ˆ ์ •์ƒ์ ์œผ๋กœ ์›ํ•˜๋˜ ๋Œ€๋กœ ์ž‘๋™ํ–ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ์ถœ๋ ฅํ•œ userDate๋ฅผ

const dateFormat = userDate => {
    const year = userDate.getFullYear();

    const month = String(userDate.getMonth() + 1).padStart(2, '0');
    const date = String(userDate.getDate()).padStart(2, '0');

    return `${year}-${month}-${date}`;
  };

๋ฐฑ์—”๋“œ์™€์˜ ํ†ต์‹ ์— ์•Œ๋งž๋Š” ํ˜•ํƒœ๋กœ ๋งŒ๋“ค๋„๋ก ํ–ˆ๋‹ค. ์ฒ˜์Œ์— ํ•œ ์ž๋ฆฌ ์ˆ˜๋งŒ ์•ž์— 0์„ ๋”ํ•ด์ฃผ๋Š” ๊ฒƒ์— ๋Œ€ํ•ด ์กฐ๊ธˆ ํ—ค๋งธ๋Š”๋ฐ padStart๋ฅผ ํ™œ์šฉํ•ด์„œ ํ•ด๊ฒฐํ–ˆ๋‹ค.

padStart(size, '๋นˆ์ž๋ฆฌ๋ฅผ ์ฑ„์šธ string')

๊ทธ๋ฆฌ๊ณ  ๋‹ค์‹œ ์ด fomattedDate๋ฅผ searchParams์— ํ™œ์šฉํ•˜์—ฌ ํ•ด๋‹น ๋‚ ์งœ์— ํ•ด๋‹นํ•˜๋Š” ์ด๋ฒคํŠธ๋งŒ ์ถœ๋ ฅํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜์˜€๋‹ค.

2. Range Filter

min๊ฐ’๊ณผ max๊ฐ’์„ value๋กœ ์ „๋‹ฌ๋ฐ›์•„ query์— ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜์˜€๊ณ ,
๊ณต์‹ ๋ฌธ์„œ๋ฅผ ํ†ตํ•ด step์„ ์ด์šฉํ•ด ํ•„์š”ํ•œ ๊ฐ„๊ฒฉ(10๋‹จ์œ„)์œผ๋กœ๋งŒ ์ด๋™ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ง€์ •ํ•˜์˜€๋‹ค.
์–ด๋–ค ํŠน์ • ๊ฐ’์ด ์ถ”๊ฐ€๋˜์–ด ํ•„ํ„ฐ๋ง ๋˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ํŠน์ • ๊ฐ’ ๋‚ด์˜ ๋ฒ”์œ„๊ฐ€ ๊ณ„์† ๋…ธ์ถœ๋  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์—
min๊ฐ’๊ณผ max๊ฐ’์€ url์— minPrice, maxPrice๋กœ ๊ธฐ๋ณธ์œผ๋กœ ์ „๋‹ฌ๋˜๋„๋ก ํ–ˆ๋‹ค.

2. Category Component

  • data ๊ตฌ์กฐ
{
    "id": 1,
    "mainCategory": "์นดํ…Œ๊ณ ๋ฆฌ",
    "subCategory": ["ํŽ˜์Šคํ‹ฐ๋ฒŒ", "์ฝ˜์„œํŠธ", "ํผํฌ๋จผ์Šค", "ํด๋ž˜์‹"],
    "key": "categoryId"
  },
  {
    "id": 2,
    "mainCategory": "๋‚˜์ด",
    "subCategory": ["์ „์ฒด", "์„ฑ์ธ"],
    "key": "ageRange"
  },
  {
    "id": 3,
    "mainCategory": "๊ตญ๊ฐ€",
    "subCategory": ["๊ตญ๋‚ด", "๋ฏธ๊ตญ", "ํ˜ธ์ฃผ", "์ผ๋ณธ"],
    "key": "countryId"
  },
  {
    "id": 4,
    "mainCategory": "์ž…์ฐฐ๊ฐ€",
    "subCategory": ""
  }

๋ฉ”์ธ ์นดํ…Œ๊ณ ๋ฆฌ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์„ธ๋ถ€ ์นดํ…Œ๊ณ ๋ฆฌ๊ฐ€ ๋‚˜๋‰˜์–ด ์ง€๋Š” ํ˜•ํƒœ์˜€๋Š”๋ฐ, ์ „์ฒด ์นดํ…Œ๊ณ ๋ฆฌ ๋ฐ์ดํ„ฐ๋ฅผ ํ•˜๋‚˜์˜ ํŒŒ์ผ๋กœ ๋งŒ๋“œ๋Š” ๊ฒŒ ์ข‹์ง€ ์•Š์„๊นŒ? ๋ผ๊ณ  ์ƒ๊ฐํ•ด์„œ data ๊ตฌ์กฐ๋ฅผ ์œ„์™€ ๊ฐ™์ด ๋งŒ๋“ค์—ˆ๋‹ค. ์—ฌ๊ธฐ์„œ key๋Š” query๋ฅผ ๋„ฃ์–ด์ฃผ์—ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  mainCategory๋ฅผ ๊ธฐ์ค€์œผ๋กœ componentํ™” ํ•ด์„œ map() ๋ฉ”์„œ๋“œ๋ฅผ ํ™œ์šฉํ•ด์„œ ๊ตฌํ˜„ํ•˜์˜€๋‹ค.

๋จผ์ € subCategory๊ฐ€ array๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ๋ฅผ ๋นผ๊ธฐ ์œ„ํ•ด Array.isArray(subCategory)๋ฅผ ํ™œ์šฉํ•˜์˜€๋‹ค.

* Array.isArray(subCategory )
    - subCategory๊ฐ€ array ์ธ์ง€ ํ™•์ธ ํ›„ ์•„๋‹ˆ๋ฉด subCategory๋ฅผ ๊ทธ๋Œ€๋กœ ์ถœ๋ ฅ
    - Array ์ผ ๊ฒฝ์šฐ
		: key ๊ฐ’์œผ๋กœ subcategory ๋ถ€์—ฌ 
		  (subcategory = ์ธ์ž === subCategory ๋ฐฐ์—ด ๋‚ด ๋ฌธ์ž ๊ทธ์ž์ฒด) -> query๋ฅผ ์œ„ํ•จ
<S.SubCategories
	key={subcategory}
	onClick={() => {
		handleCheckedCategory(String(idx + 1));
		handleCategoryState(subcategory, data.key);
		}}

์—ฌ๊ธฐ์„œ idx์— +1 ์„ ํ•˜๋Š” ์ด์œ ๋Š” ๋ฐฐ์—ด์€ idx๊ฐ€ 0 ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๊ณ ,
์ด idx๋ฅผ ์ดํ›„ data์˜ id ๊ฐ’๊ณผ ๋น„๊ตํ•  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค !

3. DropBox Component

  • data ๊ตฌ์กฐ
export const DROP_MENU = [
	{ id: 0, name: '๋‚ ์งœ์ˆœ', key: 'dateAsc' },
	{ id: 1, name: '๊ฐ€๊ฒฉ ๋‚ฎ์€ ์ˆœ', key: 'priceAsc' },
	{ id: 2, name: '๊ฐ€๊ฒฉ ๋†’์€ ์ˆœ', key: 'priceDesc' },
	];

์œ„์˜ ์นดํ…Œ๊ณ ๋ฆฌ data ๊ตฌ์กฐ์™€ ๋™์ผํ•˜๊ฒŒ id๋ฅผ index๋กœ ํ™œ์šฉํ•˜์—ฌ key๊ฐ’์„ searchParams๋ฅผ ํ™œ์šฉํ•ด orderBy์— ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋„๋ก ํ–ˆ๋‹ค.

4. handleCategoryState

const handleCategoryState = (category, key, categoryData) => {
const categoryIndex = categoryData.subCategory.indexOf(category) + 1;
const categoryIdArr = searchParams.getAll(key);

if (categoryIdArr.includes(String(categoryIndex))) {
	const newArr = categoryIdArr.filter(el => el != categoryIndex);
	searchParams.delete(key);
	newArr.forEach(el => {
	searchParams.append(key, el);
    });
    } else {
      searchParams.append(key, categoryIndex);
    }

    setSearchParams(searchParams);
  };

๋ฐฐ์—ด์€ index๊ฐ€ 0๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๋ฏ€๋กœ id ์™€ ๋งž์ถ”๊ธฐ ์œ„ํ•ด +1์„ ํ•ด์ค€๋‹ค.
categoryIdArr ๋Š” searchParams.getAll(key)๋ฅผ ํ†ตํ•ด key์™€ ์ผ์น˜ํ•˜๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ array๋กœ ๊ฐ€์ ธ์˜จ๋‹ค. ๊ทธ ๋’ค includes๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ categoryIdArr์— categoryIndex๊ฐ€ ์ด๋ฏธ ํฌํ•จ๋˜์–ด ์žˆ๋Š” ์ง€ ํ™•์ธํ•˜๊ณ  ์žˆ๋‹ค๋ฉด ํ•ด๋‹น ์นดํ…Œ๊ณ ๋ฆฌ ์ธ๋ฑ์Šค๋ฅผ ์ œ์™ธํ•œ ์ƒˆ๋กœ์šด ๋ฐฐ์—ด (newArr)๋ฅผ ๋งŒ๋“ค๊ณ  ๊ธฐ์กด ์ฟผ๋ฆฌ๋ฅผ ์ง€์šฐ๊ณ  ๋‹ค์‹œ appendํ•˜์—ฌ ์ค‘๋ณต๋œ ์นดํ…Œ๊ณ ๋ฆฌ๋ฅผ ์‚ญ์ œํ•œ๋‹ค.

๋งŒ์•ฝ ์ค‘๋ณต๋œ ์ธ๋ฑ์Šค๊ฐ€ ์—†๋‹ค๋ฉด append ํ•œ๋‹ค.

๋˜ ๋งˆ์ง€๋ง‰ ์ค„์˜ setSearchParams(searchParams)๋ฅผ ํ†ตํ•ด ์ƒˆ๋กœ๊ณ ์นจ ์‹œ์—๋„ ์ฟผ๋ฆฌ๊ฐ€ ์œ ์ง€๋  ์ˆ˜ ์žˆ๋„๋ก ๊ตฌํ˜„ํ•˜์˜€๋‹ค.

* value(min/max), limit, location.search, checkLiked ์˜์กด์„ฑ ๋ฐฐ์—ด
        

5. API fetch

useEffect(() => {
    const url = `${APIS.events}${location.search}&minPrice=${value[0]}&maxPrice=${value[1]}`;

    fetch(url)
      .then(response => response.json())
      .then(result => {
        setCardData(result.data);
      });
  }, [value, limit, location.search, checkLiked]);

fetch์˜ ์˜์กด์„ฑ ๋ฐฐ์—ด์—๋Š” value(mixPrice / maxPrice), location.search(์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ), checkLiked(๊ฐœ๋ณ„ ์ข‹์•„์š” ํ†ต์‹ ) ๋ฅผ ๊ฐ–๋Š”๋‹ค.

5. goToTop Component

์ƒ๋‹จ ์ด๋™ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ค ๋•Œ์—๋Š” UX/UI ๋ถ€๋ถ„์—์„œ ๊ณ ๋ฏผ์„ ์ข€ ํ•ด๋ณด์•˜๋‹ค.
ํ™”๋ฉด์˜ ํ˜•ํƒœ๊ฐ€ ์ขŒ/์šฐ๋กœ ๋ช…ํ™•ํ•˜๊ฒŒ ๋‚˜๋ˆ„์–ด์ ธ ์žˆ๊ณ , ์ขŒ์ธก ์นดํ…Œ๊ณ ๋ฆฌ ์ฒดํฌํ•˜๋Š” ๋ถ€๋ถ„์— ๋งˆ์šฐ์Šค๊ฐ€ ์ž์ฃผ ์ด๋™ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์„
๊ฐ์•ˆํ•˜์—ฌ ๋‹ค๋ฅธ ํŽ˜์ด์ง€๋Š” ์šฐ์ธก ํ•˜๋‹จ์—๋งŒ ์žˆ๋Š” ์ƒ๋‹จ ์ด๋™ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ขŒ์ธก ํ•˜๋‹จ์—๋„ ํ•ด๋‹น ๋ถ€๋ถ„์— ๋งž๊ฒŒ ๋””์ž์ธ์„ ์ˆ˜์ •ํ•˜์—ฌ ๊ตฌํ˜„ํ–ˆ๋‹ค. ์ด ๊ฒƒ๋„ ์œ„์˜ Eventcard component๊ฐ€ wishlist์—์„œ๋งŒ ๋‹ค๋ฅด๊ฒŒ ๋‚˜ํƒ€๋‚  ์ˆ˜ ์žˆ๋„๋ก ์กฐ๊ฑด๋ถ€ ๋ Œ๋”๋ง์„ ํ–ˆ๋˜ ๊ฒƒ ์ฒ˜๋Ÿผ type์„ ๋ถ€์—ฌํ•ด์„œ ํŽ˜์ด์ง€๋ฅผ ๊ตฌ๋ถ„ํ•˜์—ฌ ํŽ˜์ด์ง€์— ๋งž๋Š” ๋‹ค๋ฅธ ๋””์ž์ธ์ด ๋‚˜์˜ฌ ์ˆ˜ ์žˆ๋„๋ก ๊ตฌํ˜„ํ•˜์˜€๋‹ค.

0๊ฐœ์˜ ๋Œ“๊ธ€