📒 3탄 이전 벨로그

...

또 해야하는건 ✖ 누르면 지우는건데
Learning 해당되는 이걸 0번 인덱스를 지워야하고

그리고 하나 더 생각해야될게 만들어져있는 걸로 보면
이 Note 2에 exsercise 라는 태그가 할당이 되어있음

여기서 Exercise를 지우면

태그도 없어짐
Add로 태그 추가하면 tags 안에 추가한 quotes가 생김
근데 Edit Tags 에서 추가한 Quotes 삭제하면 tags 에서 사라지게 해야함

🔖태그를 지울 때 두가지 일을 해줘야됨🙆‍♀️

TagsList 에서 지워줘야함

notesList 안에 있는 mainNotes 해당 리스트도 지워줘야함

▫ src>components>Modal>TagsModal>TagsModal.jsx

✖를 클릭하는 거니까 DeleteBox 에서 onClick handleDeleteClick 만들어줌

🤷‍♀️Delete 할 때나 Edit 할 때나 이 함수에다 뭐를 전달해야할까❓

Edit 기능 만들땐 여러개 중에서 하나를 Edit 하는 거고
Delete 또한 여러개 중에서 하나를 Delete 하는 거니까

✅ 여러 개 중에서 어떤 걸 Edit / Delete 할 건지를 넣어줘야함

⭐무조건 ( ) => 해줘야함

tag( 타입은 string 태그의 이름이니까 ), id( 이것도 string 유니크한 값 ) 넣어주기

여기 같은 경우는 이미 tagsSlice 에서 deleteTags 만들어줬었음❗
이 로직을 이용해서 하면 됨✔

💡

1️⃣ filter 역할 : payload와 같은 id를 가진 태그를 삭제❌
( state.tagsList 에서 idpayload와 같지 않은( !== ) 태그만 남김 )

2️⃣ id !== payloadidpayload와 다르면( true ) 유지, 같으면( false ) 제거

3️⃣ { payload } 구조분해할당 하는 이유
👉 action.payload 에서 payload만 꺼내서 사용하기 위해
👉 deleteTags: (state, action) => { action.payload } 대신
{ payload }로 바로 사용 가능하기 때문

만들어놓은 deleteTagsdispatch 해주고
deleteTags 에서 지금 받아오는 payloadid
그래서 id를 넣어주기만 하면 됨⭕

🔥dispatch(deleteTags(id))➡하는 일 : tagsList를 지우는 것

mainNotes 에서 tags 에 있는 게 있으면 지우는 것

🧐이부분은 어떻게 만들어줘야할까❓

▫ src>store>notesList>notesListSlice.js

여기서 처리해줘야함🔨

mainNotes 안에 있는 데이터 중에서 수정을 지워줘야하는 것✔

remoeveTags 라는 이름으로 해줄거임
state 그리고 { payload } 바로 가져오고

여기있는 데이터 변경해줘야함🔄

태그 두개 추가했음

근데 여기서 New 라는 태그를 없앨거임

New 라는 태그에 ADD Tags 모달에도 있을 수 있음

같은 거 다 없애줘야함

🤪로직을 그럼 어떻게 해주면 될까❓

🗺 배열이니까 항상 map 한 담에 하나의 note 데이터

mainNotes 안에 있는 거 나열해주려면 스프레드 오퍼레이터 ...note 한 담에
어떤 것만 바꿀거냐면 tags만 바꿔줄거임

tags 2개 중에서 new 라는 애만 지워줄거임

Edit + Delete 둘 다 있는거임⭕

여기까진 원래 쓰던 Edit을 위한 로직을 쓴거고

✅ 여기선 Delete을 위한 로직을 써야함

원래 있던 tags의 데이터를 가져와야함❗

note.tags 로 가져오고 배열에서 지울 땐 항상 filter 메소드 사용
tag 데이터엔 태그 이름이랑 아이디 있음 ( 여기서 태그 이름만 가져올 것 )

여기 두개에서 note 한번씩 순회하면서 coding 이라는 태그를 지울건데

그럴려면 이걸 다 ( 얘네들은 변경 안할거니까 ) 전체를 다 ...note 나열하고

여기서 tags만 지울것
tags: 이렇게 한 담에 coding 이라는 애가 있으면 지울거니까

coding 이라는 애를 찾아서 찾았으면
filter 로직을 사용해서 지운 담에 새로운 태그를 넣어주면 됨

만든 removeTags를 이용할거니까 바깥으로 내보내주자🥏

▫ src>components>Modal>TagsModal>TagsModal.jsx

removeTagsTagsModal로 가져온 담에 { tag } 해주면 됨🙆‍♀️

🍞Edit Tags 모달 리스트 ✖ 누르면
태그가 삭제되었습니다. toast 뜨게 해주기

📥이부분을 위해서 토스트라는 거를 이미 모듈을 설치해놨음✔

toastify 이용해서 구현해보자❗

이걸 이용하려면 우선 App.jsx로 이동🌫🐱‍🏍

▫ src>App.jsx

ToastCotainer 라는 걸 여기다가 사용해줘야하고

Toast 사용할 때 몇 개의 옵션을 줄 수 있음

👉 autoClose : 얼마만에 클로즈 될 것인지

1.5초 만에 클로즈 되게 설정할 것
👉 pauseOnHover : 호버 할 땐 1.5초 만에 되는게 딱 스탑될 수 있게
👉 theme : 테마 어떤 색상으로 줄건지 설정
👉 position : 토스트가 오른쪽 밑에 나왔었는데 위치 설정할 수 있음

🗣 : 혼자 프로젝트 할 땐 스스로 만들어봐도 도움 되지만
실제로 운영 환경이나 이런데서 사용할 땐
라이브러리 사용해서 만드는 게 더 소스 코드 깔끔해짐✨

💪toast 사용할 준비 완, 이제 사용을 해보자❗

태그를 추가할 때나 삭제할 때나 이부분은 tagsSlice로 이동하기🌫🐱‍🏍

▫ src>store>tags>tagsSlice.js

태그를 첨에 추가할 때 이미 같은 태그의 이름( tag )이 있는지 확인 하는 부분🔍

tagsList 에서 find 메소드 이용해서 하나의 객체 안에 있는
tag 태그의 이름이랑 payload.tag 넣어준 태그 이름이랑
같은지를 확인해서 if 면 같은게 있는거니까

⚠️ toast.warning( "이미 존재하는 태그 입니다." ); ⚠️

Work 태그 이름이 이미 있는 상태에서 work 라고 쳤더니

이런식으로 나오는 걸 볼 수 있음( 스타일링 안 해줘서 그럼 )👀

👩‍🎨스타일링 해주기

node_modules 안에 react-toastify 이부분이 있음
여기에 들어있는 것 중에 ReactToastify.css 파일이 있음🔥

App.jsximport 해주기

이렇게 스타일까지 적용돼서 잘 나오는 것을 볼 수 있음👀

새로운 태그 이름이 추가되면 새로운 태그가 등록되었습니다. 뜨게 해주기

✖눌러서 삭제했으면 태그가 삭제되었습니다. 뜨게 해주기

둘 다 성공적으로 된 부분이니까 info로 해주기 ( 🟦파랑색 )


🎈메인페이지 만들기

▫ src>pages>AllNotes>AllNotes.jsx

전역 스타일 해놓은 styles.jsx 에서 Container를 가져올거임

Containerexport로 내보내줬으니까 바로 import 해서 가져올 수 있음😎

노트가 있으면 이렇게

없으면 이렇게 노트가 없습니다. 해줘야함

✅ 노트가 우선 있는지 없는지 부터 가져와야함

mainNotesLength0 이면 노트가 없는 상태인거고 아니면 있는 상태인거임❗

가져오기 위해서 useSelector 해주고 state.notesList 이렇게 한 담에
notesList 안에 있는 것 중에서 mainNotes를 가져올거니까➡{ mainNotes } 하면 됨⭕

전역 스타일 styles.jsx 에서 만들어놓은 EmptyMsgBox 가져와서

mainNotes.length0 이면 노트가 없습니다. 띄워줄 것

노트가 없으니까 노트가 없습니다. 라고 잘 나오는 걸 볼 수 있음👀

👩‍🎨EmptyMsgBox & Container 스타일링 해주기➡전역 스타일 : styles.jsx

// 노트가 없습니다. 이부분
export const EmptyMsgBox = styled.div`
	text-align: center;
	font-size: 1.4rem;
	font-weight: 500;
`;

// 메인을 감싸는 부분
export const Container = styled.div`
	padding: 25px 0px 25px 25px;

	// 너비가 650px 이하로 화면이 줄어들 때 적용됨
	@media (max-width: 650px) {
		padding: 20px;
	}	
`;

이렇게 해주고 다시 AllNotes로 돌아가기🌫🐱‍🏍

📒이젠 노트가 있을 때 부분을 해줘야함

이렇게 구성되어있음
👉 input / button / 핀 있는 노트들 / 핀 없는 All Notes

TopBox 스타일 컴포넌트 만들어줌

TopBox 안에 input & button이 들어갈 것👌

핀 노트랑 All Notes 이부분을 위해 Box 스타일 컴포넌트 만들어줌
TopBox 컴포넌트 바로 밑에 Box 컴포넌트 넣어주기🆗

⌨ 먼저 input을 위한 InputBox 컴포넌트 만들어주기

타이핑 한 값을 이 컴포넌트에서 기억하길 원하니까

🧠 useStatestate 만들기 💡

searchInputvalue로 넣어주고, 이걸 변경시키기 위해
onChange 써서 setSearchInpute.target.value 해주면 됨✔

전역 스타일 styles.jsx 에 작성해둔 ButtonOutline 가져오기

정렬 버튼 누르면 정렬 모달창을 보여주는 부분임🤓

modal에 있는 viewFilterModal 이걸 바꿔주기 위해서

이미 modalSlice 에서 만들어놨었음👍 toggleFiltersModal을 이용하면 됨🙆‍♀️

🖱정렬 버튼 클릭했을 때 나오는 모달창이니까
onClick 해서 modalSlicetoggleFiltersModaldispatch 해주면 됨🔥

📢 toggleFiltersModal 호출할 때 항상 action.payload 넣어줘야함 ⭕
👉 payload는 당연히 viewFiltersModaltrue 아니면 false가 돼야하니까

payload 에도 true 아니면 false 넣어줘야함⚡

더미데이터 이용해서 새로고침해도 노트들이 나올 수 있게 해줄것❗

여기 보면 notesList에 이미 두개가 있음 ( 이게 첨부터 있는 더미데이터 )

🚀메인페이지 2개의 노트 더미데이터 만들기

▫ src>notesData.js

더미데이터 만들어주기 위해 src 폴더 안에 notesData.js 파일 만들어주기

createTime: new Date("Sat Dec 10 2022 14:55:22").getTime( ),

tags는 여러 개 올 수 있으니까 배열에 하나의 태그가 하나의 객체 { } 이렇게 해주기
태그의 이름하고 유니크한 아이디가 필요했었음✔

🌈color : 노트의 색상, 🥇priority : 우선순위,
📌isPinned : 핀 고정이 되어있는지 아닌지,
📖isRead : 노트를 읽고 있는지 아닌지,
editedTime : 수정한 시간을 첨에 추정이 안 되니까 null,
#️⃣id : uuid 라이브러리를 통해 유니크한 아이디 주기위해 v4( )

notes 이걸

첨에 mainNotes에 들어있게 해야하는데

🤷‍♀️어떻게 해야 더미데이터들이 mainNotes 안에 들어올까❓

notesListSlice로 가보면 initialState에 다 빈 배열로 되어있음

만들고 있는 거에서 이거랑 위에랑 똑같은 것

두 개의 더미데이터 넣어주려면 mainNotes 여기에 넣어주면 됨✔

만들어놓은 더미데이터 파일인 notesDatadefault로 내보내주기🥏

배열 안에 객체들만 넣어주면 됨➡...notes 🔥

리덕스에 가보면 이렇게 mainNotes 에도 데이터가 잘 들어온 걸 볼 수 있음

👩‍🎨메인페이지 input & 정렬 버튼 UI 스타일링 해주기

👇

const TopBox = styled.div`
	margin-right: 25px;

	.notes__filter-btn {
		display: flex;
		justify-content: flex-end;
	}
`;

justify-content: flex-end 하면 위에 처럼 됨❗ ( 가장 끝으로 버튼을 밀어버리는 거임 )

// input을 감싸고있는 div
const InputBox = styled.div`
	flex: 1;
	height: 33px;
	display: flex;
	align-items: center;
	box-shadow: 0px 1px 2px 1px rgba(0, 0, 0, 0.25);
	border-radius: 5px;
	transition: 300ms box-shadow ease-in;
	margin-bottom: 16px;

	&:hover {
		box-shadow: 0px 2px 3px 1px rgba(0, 0, 0, 0.4); 
	}

	// input 스타일 
	input {
		// 너비 높이 꽉채우기
		width: 100%; height: 100%;
		padding: 0px 10px;
		border: none;
		border-radius: 5px;
		
		// 노트의 제목을 입력해주세요.
		&::placeholder {
			color: rgba(0, 0, 0, 0.3);  // 흐리게
		}	
	}
`;

flex: 1➡채울 수 있는 만큼 꽉 채우는 거

box-shadow 까지 하면 이렇게 됨👌

이제 정렬 버튼 할건데 ButtonOutline 있는 곳인 styles.jsx로 이동하기🌫🐱‍🏍

▫ src>styles>styles.jsx

export const ButtonOutline = styled.button`
	padding: 6px 20px;
	border-radius: 5px;
	cursor: pointer;
	background-color: rgba(0, 0, 0, 0.05);
	box-shadow: 0px 2px 1px 1px rgba(0, 0, 0, 0.2);
	transition: 250ms background-color ease-in-out;
	// 줄 바꿈 없이 한 줄로 표시
	white-space: nowrap;

	span {
		font-weight: 500;
		font-size: 1rem;
		margin-left: 5px;
	}

	border:none;
	
	&:hover {
		background-color: rgba(0, 0, 0, 0.1);
	}

	@media (max-width: 600px) {
		padding: 6px 12px;
	}
`;

호버 했을 때 버튼 배경색 달라짐

📦메인페이지 Box 영역 하기

▫ src>pages>AllNotes>AllNotes.jsx

TopBoxinput & 정렬 Btn 부분이고, Box 영역이 이부분임

원래 나열하려면 mainNotes 가지고 map 메소드 한 담에 이렇게 할텐데

조건 로직이 들어가야됨
핀 된거랑 안 된거가 나뉘어져야하고

이렇게 정렬 기능의 로직도 들어가야함🤓

Box 안에 로직들이 복잡해지니까 따로 빼둘거임😎

▫ src>utils>getAllNotes.jsx

☝ 첫번째로 받아올건 mainNotes의 데이터를 다 받아올 것

✌ 두번째로 받아올건 필터링을 지금 어떤 걸 하고 있는지
👉 Low to High, High to Low로 하고 있는지
Sort by /Latest/Created/Edited로 하고 있는지

AllNotes.jsx로 와서 이렇게 넣어주기

여기에 있는 UI 부분이 이런식으로 나오게 해야함✔

이렇게 해주고

전역 스타일 styles.jsx 에서 만들어놓은 NotesContainer 가져오기

🗺 mainNotes 배열이니까 map 메소드 이용해서 하나의 note 객체

위에 NoteCard 컴포넌트 가져오고
당연히 여러 개 나열하는거니까 key 값 필요🔑⭕

note 객체 데이터도 내려주고, 이거의 타입은 notes

지금 현재 이렇게 나옴

NoteCard 두 개로 나오는 이유 : 더미데이터에서 두 개 만들어놨기 때문❗

▫ src>components>NoteCard>NoteCard.jsx

이걸 바꿔줘야 NoteCard가 바뀌는 것

getAllNotes 에서 note 객체 데이터랑 typeprops로 내려가고 있으니까

이렇게 받아와야함

note 안에 있는 걸 다 구조분해할당으로 해줌🔥

그리고 여기 UI는 이거 하나가 될 수 있게 여기다 만들어줘야함 🆗

FooterBox는 10/12/22 2:55 PM 이부분 있어서 { date } 넣어주면 됨

이렇게 date가 나오는 걸 볼 수 있음👀

TagsBox는 만약에 태그가 지금은 coding 하나인데 Edit 아이콘 누른담에

Add Tag 버튼 누르고 Exercise & Quotes 태그 추가하고 저장하면

두 개가 추가돼서 총 3개의 태그가 됨
🤷‍♀️ 이렇게 보이게 하려면 어떻게 할까 ❓❓

tags 얘를 보여줘야하는데 배열이니까 당연히 map으로 순회해야함

<TagsBox>
  {
    tags?.map(({ tag, id }) => (
      <span key={id}>{tag}></span>
    ))
  }
</TagsBox>

🗺 TagsBox 에서 tags가 있으면 map 메소드 이용해서
tagstag, id 있으니까 { tag, id } 해주고 바로 span 태그 써서
이 안에 { tag } 하고 key 값으로 id를 주면 됨🙆‍♀️

exercisecoding 태그가 나온 걸 볼 수 있음👀

마지막으로 TopBox 부분은 이렇게 해줘야함

div 태그 써서 className을 'noteCard_title'로 해주고
✅ Note 1 tit...
➡10글자 넘으면 ...으로 보이게 할 것

titlelength10이 넘을 땐 title.slice(0, 10) 한담에
그 이후엔 " ..." 으로 해줌, 아닐 땐 title을 보여주면 됨🙋‍♀️

이렇게 잘 나오는 걸 볼 수 있음👀

priorityHIGH 이부분임

Coding 에도 있는데 얘를 만약에 Archive로 보낸다고 하면

Archive 에선 핀이 없음, 얘를 삭제 아이콘을 클릭하면

Trash로 이동하는데 여기에도 핀이 없음

getAllNotes 에서 NoteCardtype"notes" 라고 해줬었는데
Archive 에서 보여주는 노트면 "archive" 이걸 사용해야하고
Trash 에서 보여주는 노트면 "trash" 얘를 type에다 넣어줘야함✔

👉 "notes" 아니면 "archive" 아니면 "trash"

얘네들을 이용해서 NoteCard.jsx 여기서 조건처리 해주면 됨⭕

이부분은 다시 이렇게 돌려놓고

getAllNotes 에서 받아온 type으로 조건처리 해줄 것⚡

type"archive"가 아니고 그리고
type"trash"가 아닐 때만 이부분을 렌더링 해줄거임💻

전역 스타일인 styles.jsx 안에 만들어놓은 NotesIconBox를 가져옴

핀 아이콘이 나오는 걸 볼 수 있음👀

👩‍🎨메인페이지 Notes 부분 스타일링 해주기

Card

const Card = styled.div`
	width: clamp(250px, 100%, 265px);
	height: 220px;
	border-radius: 8px;
	box-shadow: 0px 1.5px 3px 0px rgba(0, 0, 0, 0.5);
	padding: 20px;
	margin: 0 35px 35px 0;
	background-color: white;
	transition: 250ms box-shadow ease-in-out, 300ms transform ease-out;
	
	&:hover {
		transform: scale(1.05);  // 아주 조금만 크게 해주기
		box-shadow: 0px 4px 6px 0px rgba(0, 0, 0, 0.6);
	}

	@media (max-width: 600px) {
		margin-right: 0px;
	}
`;

height 주면 이렇게 됨

모서리 둥글게( border-radius ), box-shadow로 이렇게 그림자 생기고
padding으로 안쪽 여백주고, margin으로 바깥 노트 사이 여백 주면 이렇게 됨

호버 했을 땐 이런식으로 됨

ContentBox

const ContentBox = styled.div`
	width: 100%; height: 65px;
	margin: 15px 0 10px;
	font-size: 14px;
	cursor: pointer;
	overflow-y: hidden;

	// 이미지도 올 수 있으니까
	img {
		width: 80px; height: 65px;
		border-radius: 5px;
	}
`;

혹시나 content 내용이 많을 수도 있으니까 어느정도 간담에 hidden 시킬 것
🐱‍👤 overflow-y: hidden;

TagsBox

const TagsBox = styled.div`
	height: 25px;
	margin-bottom: 15px;
	overflow: scroll;
	
	span {
		display: inline;
		background-color: rgba(0, 0, 0, 0.07);
		color: rgba(0, 0, 0, 0.7);
		padding: 2px 5px;
		border-radius: 5px;
		font-size: 11px;
		font-weight: 500;
		margin-right: 8px;
	}

	&::-webkit-scrollbar {
		display: none;
	}
`;

overflow: scroll➡지금은 태그가 한개 뿐이어서 없어도 무관하겠지만
여러 태그가 있을 땐 이동할 수 있게 해줘야하기 때문 ❗❗

스크롤 할 수 있게 만들지만 스크롤 모습 보여주기 싫을 땐 이렇게 해주면 됨😎

margin-right 줘야 태그가 여러 개 있을 때 뛰엄뛰엄 나올 수 있음✔

TopBox

const TopBox = styled.div`
	display: flex;
	justify-content: space-between;
	
	// Note 1 tit ... 부분
	.noteCard__title {
		font-weight: 600;
		font-size: 1.15rem;
		cursor: pointer;
	}

	// high랑 핀 부분
	.noteCard__top-opitons {
		white-space: nowrap;
		margin-left: 8px;
		
	}

	// high 부분
	.noteCard__priority {
		text-transform: uppercase;  // 대문자로
		font-size: 12px;
		font-weight: 600;
		margin-right: 10px;
	}

	// 핀 부분
	.noteCard__pin {
		svg {
			font-size: 15px;
		}
	}
`;

flex 주면 한줄로 정렬 되고, space-between 하면
Note 1 tit ...high 핀아이콘 간격이 벌어짐
flex-start 하면 위로 다 붙이는 것

FooterBox

const FooterBox = styled.div`
	display: flex;
	justify-content: space-between;
	align-items: center;

	.noteCard__date {
		font-size: 12px;
		font-weight: 500;
		color: rgba(0, 0, 0, 0.6);
	}
`;

...

📒 5탄 다음 벨로그

profile
안녕하세요! 퍼블리싱 & 프론트엔드 개발 공부 블로그 입니다!

0개의 댓글