-
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.
- Loading branch information
1 parent
9680cfa
commit 1006b77
Showing
11 changed files
with
431 additions
and
107 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
import { Box, Tooltip } from "@mui/material"; | ||
import SquareIconButton from "@/components/SquareIconButton"; | ||
import PreviewImageByURL from "@/components/PreviewImageByURL"; | ||
import NewPostTextEditor from "@/components/newpost/NewPostTextEditor"; | ||
import SearchAlcoholInput from "@/components/newpost/SearchAlcoholInput"; | ||
import PictureIcon from "@/assets/icons/PictureIcon.svg"; | ||
import PinIcon from "@/assets/icons/PinIcon.svg"; | ||
import SingleImageInput from "@/components/SingleImageInput"; | ||
import { useEffect, useState } from "react"; | ||
import useRenderAsDataUrl from "@/hooks/useRenderAsDataUrl"; | ||
import { NewPostRequestInterface } from "@/types/newPost/NewPostInterface"; | ||
import { AlcoholDetailInterface } from "@/types/alcohol/AlcoholInterface"; | ||
|
||
interface PostEditorProps { | ||
initialContent?: string; | ||
initialAlcohol?: Pick< | ||
AlcoholDetailInterface, | ||
"alcoholName" | "alcoholNo" | "alcoholType" | ||
>; | ||
initialImage?: string; | ||
/** | ||
* formvalue와 file 을 인자로 넘겨주는 커스텀이벤트핸들러 | ||
* @param props {formvalue,file} | ||
* @returns | ||
*/ | ||
onFormChange: (formValue: NewPostRequestInterface) => void; | ||
onFileChange: (file?: File) => void; | ||
} | ||
|
||
const PostEditor = ({ | ||
initialContent, | ||
initialAlcohol, | ||
initialImage, | ||
onFormChange, | ||
onFileChange, | ||
}: PostEditorProps) => { | ||
const [formValue, setFormValue] = useState<NewPostRequestInterface>({ | ||
postType: "BASIC", | ||
positionInfo: "", | ||
tagList: [] as string[], | ||
}); | ||
|
||
useEffect(() => { | ||
onFormChange(formValue); | ||
}, [formValue]); | ||
|
||
const [file, setFile] = useState<File>(); | ||
|
||
useEffect(() => { | ||
onFileChange(file); | ||
}, [file]); | ||
|
||
const fileUrl = useRenderAsDataUrl(file) ?? initialImage; | ||
|
||
return ( | ||
<> | ||
{/* 검색창 */} | ||
<SearchAlcoholInput | ||
initialValue={initialAlcohol} | ||
setAlcoholNo={(alcoholNo) => | ||
setFormValue((prev) => ({ ...prev, alcoholNo })) | ||
} | ||
/> | ||
{/* 내용 */} | ||
<NewPostTextEditor | ||
onContentChange={({ content, tagList }) => | ||
setFormValue((prev) => ({ | ||
...prev, | ||
postContent: content, | ||
tagList, | ||
})) | ||
} | ||
initialValue={initialContent} | ||
/> | ||
{/* 파일 미리보기 */} | ||
{(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> | ||
</> | ||
); | ||
}; | ||
|
||
export default PostEditor; |
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.