-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Minor : 파일 확장자 변경 * Refactor : 게시글 최대길이가 넘어갈 경우 입력되지 않도록함 * Minor : 파일 미리보기 AspectRatio 적용 * Refactor : IntialValue 를 받도록 변경 * New : 게시글 수정하기 기능 추가 * FIX : 테스트 엣지케이스 추가
- Loading branch information
1 parent
de5b272
commit 413e354
Showing
16 changed files
with
476 additions
and
120 deletions.
There are no files selected for viewing
24 changes: 24 additions & 0 deletions
24
client/src/app/(protectedRoute)/edit-post/[pid]/layout.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import CustomAppbar from "@/components/layout/CustomAppbar"; | ||
import { ReactNode, Suspense } from "react"; | ||
import CustomContainer from "@/components/layout/CustomContainer"; | ||
|
||
type Props = { | ||
children: ReactNode; | ||
}; | ||
|
||
const layout = ({ children }: Props) => { | ||
return ( | ||
<Suspense | ||
fallback={ | ||
<> | ||
<CustomAppbar /> | ||
<CustomContainer /> | ||
</> | ||
} | ||
> | ||
{children} | ||
</Suspense> | ||
); | ||
}; | ||
|
||
export default layout; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
"use client"; | ||
|
||
import { useRouter } from "next/navigation"; | ||
import { useState } from "react"; | ||
import HOME from "@/const/clientPath"; | ||
import { useGlobalLoadingStore } from "@/store/useGlobalLoadingStore"; | ||
import { useInvalidatePostList } from "@/queries/post/useGetPostListInfiniteQuery"; | ||
import { NewPostRequestInterface } from "@/types/newPost/NewPostInterface"; | ||
|
||
import CustomAppbar from "@/components/layout/CustomAppbar"; | ||
import CustomContainer from "@/components/layout/CustomContainer"; | ||
import useSubmitEditPostMutation from "@/queries/newPost/useSubmitEditPostMutation"; | ||
import PostEditor from "@/components/newpost/PostEditor"; | ||
import useGetPostDetailQuery, { useInvalidatePostDetail } from "@/queries/post/useGetPostDetailQuery"; | ||
|
||
export default function EditPostPage({ params }: { params: { pid: string } }) { | ||
const { setLoading } = useGlobalLoadingStore(); | ||
|
||
const router = useRouter(); | ||
const invalidatePreviousPost = useInvalidatePostList(); | ||
const invalidatePostDetail = useInvalidatePostDetail() | ||
|
||
const { data: initialData } = useGetPostDetailQuery(params.pid); | ||
const { alcoholName, alcoholNo, alcoholType, postContent, postAttachUrls,postNo } = | ||
initialData; | ||
|
||
const [formData, setFormData] = useState<NewPostRequestInterface>(); | ||
const [file, setFile] = useState<File>(); | ||
|
||
const { mutateAsync: submitHandler, isSuccess } = useSubmitEditPostMutation({ | ||
onMutate: () => setLoading(true), | ||
onSuccess: () => { | ||
invalidatePreviousPost(); | ||
invalidatePostDetail(String(postNo)) | ||
router.push(HOME); | ||
}, | ||
onSettled: () => setLoading(false), | ||
}); | ||
|
||
return ( | ||
<> | ||
{/* 최상단 앱바 */} | ||
<CustomAppbar | ||
title="포스팅" | ||
appendButton="공유" | ||
disableAppend={isSuccess} | ||
onClickAppend={() => | ||
formData && | ||
submitHandler({ | ||
postNo: String(initialData.postNo), | ||
formData, | ||
file, | ||
prevFileNo: initialData.postAttachUrls?.[0]?.attachNo, | ||
}) | ||
} | ||
/> | ||
<CustomContainer> | ||
<PostEditor | ||
onFormChange={(formData) => setFormData(formData)} | ||
onFileChange={(file) => setFile(file)} | ||
initialAlcohol={ | ||
alcoholName ? { alcoholName, alcoholNo, alcoholType } : undefined | ||
} | ||
initialContent={postContent} | ||
initialImage={(postAttachUrls ?? [])[0]?.attachUrl} | ||
/> | ||
</CustomContainer> | ||
</> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,128 +1,47 @@ | ||
"use client"; | ||
|
||
import { Box, Container, Paper, Tooltip } from "@mui/material"; | ||
|
||
import { useRouter } from "next/navigation"; | ||
import { useCallback, useState } from "react"; | ||
import { useState } from "react"; | ||
import HOME from "@/const/clientPath"; | ||
import PictureIcon from "@/assets/icons/PictureIcon.svg"; | ||
import PinIcon from "@/assets/icons/PinIcon.svg"; | ||
import { useGlobalLoadingStore } from "@/store/useGlobalLoadingStore"; | ||
import useNewPostMutation from "@/queries/newPost/useNewPostMutation"; | ||
import useNewAttachMutation from "@/queries/attach/useNewAttachMutation"; | ||
import { useInvalidatePostList } from "@/queries/post/useGetPostListInfiniteQuery"; | ||
import { useDeletePostMutation } from "@/queries/post/useDeletePostMutation"; | ||
import { | ||
NewPostRequestInterface, | ||
NewPostRequestAlCohol, | ||
} from "@/types/newPost/NewPostInterface"; | ||
import SearchAlcoholInput from "@/components/newpost/SearchAlcoholInput"; | ||
import { NewPostRequestInterface } from "@/types/newPost/NewPostInterface"; | ||
|
||
import CustomAppbar from "@/components/layout/CustomAppbar"; | ||
import SquareIconButton from "@/components/SquareIconButton"; | ||
import PreviewImageByURL from "@/components/PreviewImageByURL"; | ||
import NewPostTextEditor from "@/components/newpost/NewPostTextEditor"; | ||
import useRenderAsDataUrl from "@/hooks/useRenderAsDataUrl"; | ||
import SingleImageInput from "@/components/SingleImageInput"; | ||
import { POST_IMAGE_SIZE } from "@/const/imageSize"; | ||
import CustomContainer from "@/components/layout/CustomContainer"; | ||
import useSubmitPostMutation from "@/queries/newPost/useSubmitPostMutation"; | ||
import PostEditor from "@/components/newpost/PostEditor"; | ||
|
||
export default function NewpostPage() { | ||
const { setLoading } = useGlobalLoadingStore(); | ||
|
||
const router = useRouter(); | ||
const invalidatePreviousPost = useInvalidatePostList(); | ||
|
||
const [formValue, setFormValue] = useState<NewPostRequestInterface>({ | ||
postContent: "", | ||
postType: "BASIC", | ||
positionInfo: "", | ||
tagList: [] as string[], | ||
}); | ||
|
||
const [alcoholNo, setAlcoholNo] = | ||
useState<NewPostRequestAlCohol["alcoholNo"]>(); | ||
|
||
const [formValue, setFormValue] = useState<NewPostRequestInterface>(); | ||
const [file, setFile] = useState<File>(); | ||
const fileUrl = useRenderAsDataUrl(file); | ||
|
||
const [isSuccess, SetIsSuccess] = useState(false); | ||
|
||
const { mutateAsync: newPostHandler } = useNewPostMutation(); | ||
const { mutateAsync: attachFileHandler } = useNewAttachMutation(); | ||
const { mutateAsync: deletePostHandler } = useDeletePostMutation(); | ||
|
||
const submitHandler = useCallback( | ||
async (formValue: NewPostRequestInterface, file?: File) => { | ||
setLoading(true); | ||
let postNo; | ||
try { | ||
const { postNo: res } = await newPostHandler(formValue); | ||
postNo = res; | ||
if (file) { | ||
try { | ||
await attachFileHandler({ | ||
file, | ||
url: { pk: postNo, type: "POST" }, | ||
size: POST_IMAGE_SIZE, | ||
}); | ||
} catch { | ||
deletePostHandler(postNo); | ||
return; | ||
} | ||
} | ||
invalidatePreviousPost(); | ||
SetIsSuccess(true); | ||
router.push(HOME); | ||
} catch { | ||
return; | ||
} finally { | ||
setLoading(false); | ||
} | ||
const { mutateAsync: submitHandler, isSuccess } = useSubmitPostMutation({ | ||
onMutate: () => setLoading(true), | ||
onSuccess: () => { | ||
invalidatePreviousPost(); | ||
router.push(HOME); | ||
}, | ||
[router] | ||
); | ||
onSettled: () => setLoading(false), | ||
}); | ||
|
||
return ( | ||
<Paper> | ||
<> | ||
{/* 최상단 앱바 */} | ||
<CustomAppbar | ||
title="포스팅" | ||
appendButton="공유" | ||
disableAppend={isSuccess} | ||
onClickAppend={() => submitHandler({ ...formValue, alcoholNo }, file)} | ||
onClickAppend={() => formValue && submitHandler({ formValue, file })} | ||
/> | ||
|
||
<CustomContainer> | ||
{/* 검색창 */} | ||
<SearchAlcoholInput setAlcoholNo={setAlcoholNo} /> | ||
{/* 내용 */} | ||
<NewPostTextEditor | ||
onContentChange={({ content, tagList }) => | ||
setFormValue((prev) => ({ | ||
...prev, | ||
postContent: content, | ||
tagList, | ||
})) | ||
} | ||
/> | ||
{/* 파일 미리보기 */} | ||
{fileUrl && <PreviewImageByURL fileUrl={fileUrl} />} | ||
{/* 버튼 그룹 */} | ||
<Box sx={{ display: "flex", gap: 2 }}> | ||
{/* 사진 */} | ||
<Tooltip title="사진 첨부"> | ||
<SquareIconButton | ||
component={"label"} | ||
iconComponent={<PictureIcon />} | ||
> | ||
<SingleImageInput onChange={(file) => setFile(file)} /> | ||
</SquareIconButton> | ||
</Tooltip> | ||
{/* 위치 */} | ||
<Tooltip title="위치 추가"> | ||
<SquareIconButton iconComponent={<PinIcon />} /> | ||
</Tooltip> | ||
</Box> | ||
<PostEditor onFormChange={setFormValue} onFileChange={setFile} /> | ||
</CustomContainer> | ||
</Paper> | ||
</> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.