생각보다 구현하는데 오래 걸렸던 페이지입니다.
원래라면 저런식으로 제목란, 태그란, 내용란 전부를 textfield로 구현해야했지만 textfield 내부에는 사진을 첨부할 수 없었기 때문에 계속해서 오류가 났습니다. 저는 그 사실을 모르고 계속해서 구현을 해보려고 시도하다가 오래 걸렸습니다.

팀원중 한명이 toast Editor을 사용하는 방법을 알려줘서 내용란은 editor을 사용하기로 했습니다.
이곳을 참고해서 만들었습니다!

<Stack alignItems="center">
<TextField
label="제목"
placeholder="제목을 입력하세요."
variant="outlined"
style={{ width: "71%", backgroundColor: "#FFF" }}
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
</Stack>
const handleTagInputChange = (event) => {
setTagInput(event.target.value);
};
const handleTagInputKeyPress = (event) => {
if (event.key === "Enter" && tagInput.trim() !== "") {
const newTag = tagInput.trim();
setTags([...tags, newTag]);
setPostTags([...postTags, { value: newTag }]);
setTagInput("");
}
};
const handleTagClick = (tagToRemove) => {
const updatedTags = tags.filter((tag) => tag !== tagToRemove);
setTags(updatedTags);
const updatedPostTags = postTags.filter(
(tagObj) => tagObj.value !== tagToRemove
);
setPostTags(updatedPostTags);
};
<Stack alignItems="center">
<TextField
label="태그"
placeholder="태그를 입력하세요."
variant="outlined"
value={tagInput}
onChange={handleTagInputChange}
onKeyPress={handleTagInputKeyPress}
style={{ width: "71%", backgroundColor: "#FFF" }}
/>
<Stack
direction="row"
flexWrap="wrap"
justifyContent="flex-start"
alignItems="center"
style={{ width: "71%" }}
>
{tags.map((tag, index) => (
<Chip
key={index}
label={tag}
onClick={() => handleTagClick(tag)}
style={{
margin: "4px",
whiteSpace: "nowrap",
overflow: "hidden",
textOverflow: "ellipsis",
maxWidth: "100%",
color: "#FF8181",
backgroundColor: "#FAF3F0",
border: "1px solid #FF8181",
cursor: "pointer",
}}
/>
))}
</Stack>
</Stack>
<Editor
ref={editorRef}
initialValue="내용을 입력하세요."
value={editorContent}
previewStyle="vertical"
height="450px"
initialEditType="markdown"
useCommandShortcut={false}
hideModeSwitch={true}
onChange={(e) => setEditorContent(e)}
/>
글쓰기 클릭시 나오는 모달창입니다!
로그아웃 상태에 나오는 모달창과 구분해두었습니다.



<Stack alignItems="center">
<label htmlFor="thumbnailInput">
<img
src={writepoto}
alt="writeouto"
width="40px"
height="40px"
></img>
</label>
<input
id="thumbnailInput"
type="file"
accept="image/*"
style={{ display: "none" }}
onChange={handleThumbnailChange}
/>
</Stack>


<Stack
bgcolor="#D76464"
direction="row"
sx={{
color: "white",
borderRadius: "20px",
alignItems: "center",
width: "170px",
height: "30px",
"& .MuiIconButton-root": {
backgroundColor: "white",
},
}}
>
<Stack fontSize="15px" marginLeft="30%">
확인 했어요~!
</Stack>
<Checkbox
sx={{
color: "white",
"&.Mui-checked": {
color: "white",
},
}}
checked={isChecked}
onChange={handleCheckboxChange}
/>
</Stack>
<Stack
bgcolor="#7AAAA7"
sx={{
cursor: isChecked ? "pointer" : "default",
color: "white",
borderRadius: "20px",
alignItems: "center",
width: "170px",
height: "30px",
justifyContent: "center",
opacity: isChecked ? 1 : 0.5,
}}
onClick={handleWriteClick}
>
<Stack fontSize="15px">글쓰기</Stack>
</Stack>

관리자 권한을 가진 사용자가 고정글을 선택할 수 있도록 체크박스를 만들어주었습니다.
이 체크박스는 관리자 권한을 가진 사용자에게만 보이도록 설정해두었습니다.
관리자 권한이 있는지 없는지 판별하기 위해서 JWT decode을 해주었습니다.
useEffect(() => {
if (accessToken) {
const decoded = jwt_decode(accessToken);
setDecodedToken(decoded);
console.log(accessToken);
if (decoded && decoded.auth === "ROLE_ADMIN") {
setIsAdmin(true);
}
console.log(decoded);
}
}, [accessToken]);
{isAdmin && isLogin && (
<Stack justifyContent="flex-end" alignItems="center">
<Checkbox
checked={checked}
onChange={() => setChecked(!checked)}
/>
</Stack>
)}
마크다운 형식을 올바르게 출력하기 위한 기능을 구현해야 합니다.
현재 프로젝트에서 게시글이 보여지는 페이지에 다음과 같은 코드를 추가해주었습니다.
<Stack
width="75%"
minHeight="18.7vh"
height="fit-content"
margin="10% 0 10% 0"
justifyContent="center"
alignItems="center"
bgcolor="white"
>
{postData?.contents.map((content, i) => (
<ReactMarkdown key={i} children={content.value} />
))}
</Stack>
