모달 창 추가
※모달 창 열기/닫기
※모달 창 외부 버튼 클릭 허용/방지
-stopPropagation(): 이벤트 버블링을 방지
-이벤트 버블링: 이벤트가 동작될 시 루트까지 해당되는 부모 요소의 이벤트도 동작
※모달 창 외부 클릭 시 모달 창 닫기
component
-Input.JSX
-Button.JSX
-Textarea.JSX
-DiaryWrite.JSX
-DiaryBlock.JSX
-Category.JSX
-CategoryButton.JSX
module
-Diary.JSX
css
-Diary.css
-Category.css
component - < DiaryBlock.JSX>
import React, {useState} from 'react'
import '../css/Diary.css'
import Button from './Button'
import Textarea from './Textarea'
function DiaryBlock({
title,
content,
id,
name,
date,
deleteDiary,
editDiary,
modalOutEventNone //모달 창 유무 확인
}) {
const [editBool, setEditBool] = useState(true)
const [editValue, setEditValue] = useState(content)
const changeEditValue = event => {
setEditValue(event.target.value)
}
const handleDelete = () => {
deleteDiary(id)
}
const handleEdit = () => {
if (editBool === true) {
setEditBool(false)
} else {
setEditBool(true)
editDiary(id, editValue)
}
}
return (
<div className="blockDiv" key={id} name={name}>
<div className="blockTitleDiv">
<h3 className="blockTitle">{title}</h3>
<Button
className={'deleteButton'}
onClick={modalOutEventNone ? handleDelete : null}
name={'삭제'}
/>
<Button
className={'editButton'}
onClick={modalOutEventNone ? handleEdit : null}
name={editBool ? '수정' : '적용'}
/>
</div>
<div className="blockDateDiv">
<p>{date}</p>
</div>
<p>
---------------------------------------------------------------------------------------------
</p>
{editBool ? (
<p>{content}</p>
) : (
<Textarea
className={'writeContentTextarea'}
value={editValue}
onChange={changeEditValue}
/>
)}
</div>
)
}
export default DiaryBlock
module - <Diary.JSX> : 모달 창 열기/닫기, 모달 창 외부 버튼 클릭 허용/방지(stopPropagation())
import React, {useEffect, useRef, useState} from 'react'
import '../css/Diary.css'
import DiaryWrite from '../component/DiaryWrite'
import DiaryBlock from '../component/DiaryBlock'
import CategoryButton from '../component/CatogoryButton'
import Button from '../component/Button'
function Diary() {
const [diary, setDiary] = useState(JSON.parse(localStorage.getItem('Diary')) || [])
const [categoryDiary, setCategoryDiary] = useState(diary)
const [categoryValue, setCategoryValue] = useState('none')
const [modalBool, setModalBool] = useState(false) //모달 창 오픈 유무
const [modalOutEventNone, setModalOutEventNone] = useState(true) //모달 창 외부 버튼 클릭 방지 유무
const diaryKey = useRef(parseInt(localStorage.getItem('DiaryKey')) || 0)
const changeCategoryValue = event => {
setCategoryValue(event.target.value)
}
const addDiary = (title, content) => {
if (categoryValue === 'none') {
alert('카테고리를 지정해주세요.')
} else {
const newDiary = {
title,
content,
name: categoryValue,
id: diaryKey.current,
date: new Date().toLocaleString()
}
diaryKey.current += 1
setDiary([newDiary, ...diary])
setCategoryValue('none')
setModalBool(false) //모달 창 닫기
setModalOutEventNone(true) //모달 창 외부 버튼 클릭 허용
}
}
const deleteDiary = id => {
const remainDiary = diary.filter(remove => remove.id !== id)
setDiary(remainDiary)
}
const editDiary = (id, content) => {
setDiary(diary.map(edit => (edit.id === id ? {...edit, content: content} : edit)))
}
const allDivDiaryBtn = () => {
setCategoryDiary(diary)
}
const routineDivDiaryBtn = () => {
const routineDiary = diary.filter(divide => divide.name === 'routine')
setCategoryDiary(routineDiary)
}
const studyDivDiaryBtn = () => {
const studyDiary = diary.filter(divide => divide.name === 'study')
setCategoryDiary(studyDiary)
}
const travelDivDiaryBtn = () => {
const travelDiary = diary.filter(divide => divide.name === 'travel')
setCategoryDiary(travelDiary)
}
const gameDivDiaryBtn = () => {
const gameDiary = diary.filter(divide => divide.name === 'game')
setCategoryDiary(gameDiary)
}
const openModal = event => {
setModalBool(true) //모달 창 열기
setModalOutEventNone(false) //모달 창 외부 버튼 클릭 방지
event.stopPropagation()
}
const closeModal = () => {
setModalBool(false) //모달 창 닫기
setModalOutEventNone(true) //모달 창 외부 버튼 클릭 허용
setCategoryValue('none')
}
const modalOutClick = () => { //모달 창 외부 클릭 시 모달창 닫기
setModalBool(false)
setModalOutEventNone(true)
setCategoryValue('none')
}
useEffect(() => {
localStorage.setItem('Diary', JSON.stringify(diary))
localStorage.setItem('DiaryKey', parseInt(diaryKey.current))
setCategoryDiary(diary)
}, [diary])
return (
<div className={modalBool ? 'diaryDiv' : null} onClick={modalOutClick}>
<div>
<Button
className="openModalButton"
name={'글쓰기'}
onClick={modalOutEventNone ? openModal : null}
/>
</div>
<div onClick={event => event.stopPropagation()}>
{modalBool ? (
<DiaryWrite
addDiary={addDiary}
closeModal={closeModal}
categoryValue={categoryValue}
changeCategory={changeCategoryValue}
/>
) : null}
</div>
<div>
<CategoryButton
allDivDiaryBtn={modalOutEventNone ? allDivDiaryBtn : null}
routineDivDiaryBtn={modalOutEventNone ? routineDivDiaryBtn : null}
studyDivDiaryBtn={modalOutEventNone ? studyDivDiaryBtn : null}
travelDivDiaryBtn={modalOutEventNone ? travelDivDiaryBtn : null}
gameDivDiaryBtn={modalOutEventNone ? gameDivDiaryBtn : null}
/>
{categoryDiary.map(diaryData => {
return (
<DiaryBlock
key={diaryData.id}
name={diaryData.name}
date={diaryData.date}
{...diaryData}
deleteDiary={deleteDiary}
editDiary={editDiary}
modalOutEventNone={modalOutEventNone}
/>
)
})}
</div>
</div>
)
}
export default Diary
Diary.css
.writeDiv {
border: 1px solid black;
display: inline-block;
padding: 20px;
position: absolute;
background-color: white;
left: 37%;
top: 10%;
box-shadow: rgba(0, 0, 0, 0.7) 0 0 0 9999px;
}
.writeMain {
text-align: center;
margin-left: 30px;
}
.writeTitleDiv {
margin-top: 20px;
}
.writeTitleInput {
width: 400px;
height: 30px;
font-size: 15px;
}
.writeContentDiv {
margin-top: 20px;
}
.writeContentTextarea {
width: 400px;
height: 100px;
resize: none;
font-size: 15px;
}
.blockDiv {
border: 1px solid rgb(211, 211, 211);
background-color: rgb(211, 211, 211);
width: 600px;
padding: 10px;
margin-top: 20px;
}
.blockTitleDiv {
display: flex;
justify-content: flex-start;
align-items: center;
}
.blockTitle {
margin-right: auto;
margin-top: 10px;
margin-bottom: 0;
}
.blockDateDiv {
font-size: 15px;
font-style: italic;
}
.diaryDiv {
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
background-color: rgba(0, 0, 0, 0.4);
}
.openModalButton {
margin-top: 10px;
margin-right: 20px;
padding: 7px 15px 7px 15px;
background-color: black;
color: white;
border: none;
}
.closeModalButton {
float: right;
background: none;
border: none;
font-size: 20px;
}
.submitButton {
margin-top: 20px;
width: 400px;
height: 40px;
font-size: 20px;
}
.deleteButton {
font-size: 15px;
padding: 3px 10px 3px 10px;
margin-right: 10px;
margin-top: 10px;
background-color: rgb(211, 211, 211);
}
.editButton {
font-size: 15px;
padding: 3px 10px 3px 10px;
margin-right: 30px;
margin-top: 10px;
background-color: rgb(211, 211, 211);
}
'개인 공부 > 게시판' 카테고리의 다른 글
8. 일기 수정 모달 창 (0) | 2024.02.15 |
---|---|
7. 페이지 구성 (0) | 2024.02.13 |
5. 카테고리, 작성 날짜 (0) | 2024.01.31 |
4. EditDiary (0) | 2024.01.29 |
3. DeleteDiary, diaryKey 값 유지 (0) | 2024.01.29 |