Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor : 파일 및 파일인풋 훅스 분리 #68

Merged
merged 3 commits into from
Dec 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 33 additions & 50 deletions client/src/app/(protectedRoute)/new-post/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { Box, Container, Paper, Tooltip } from "@mui/material";

import { useRouter } from "next/navigation";
import { useCallback, useEffect, useState } from "react";
import { useCallback, useState } from "react";
import HOME from "@/const/clientPath";
import PictureIcon from "@/assets/icons/PictureIcon.svg";
import PinIcon from "@/assets/icons/PinIcon.svg";
Expand All @@ -21,6 +21,8 @@ import CustomAppbar from "@/components/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";

export default function NewpostPage() {
const { setLoading } = useGlobalLoadingStore();
Expand All @@ -38,52 +40,43 @@ export default function NewpostPage() {
useState<NewPostRequestAlCohol["alcoholNo"]>();

const [file, setFile] = useState<File>();
const [fileUrl, setFileUrl] = useState<string | ArrayBuffer | null>();
const fileUrl = useRenderAsDataUrl(file);

const [isSuccess, SetIsSuccess] = useState(false);

useEffect(() => {
if (!file) {
return;
}
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onloadend = () => setFileUrl(reader.result);
}, [file]);

const { mutateAsync: newPostHandler } = useNewPostMutation();
const { mutateAsync: attachFileHandler } = useNewAttachMutation();
const { mutateAsync: deletePostHandler } = useDeletePostMutation();

const submitHandler = useCallback(async () => {
setLoading(true);
let postNo;
try {
const { postNo: res } = await newPostHandler({
...formValue,
alcoholNo,
});
postNo = res;
if (file) {
try {
await attachFileHandler({
file,
url: { pk: postNo, type: "POST" },
});
} catch {
deletePostHandler(postNo);
return;
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" },
});
} catch {
deletePostHandler(postNo);
return;
}
}
invalidatePreviousPost();
SetIsSuccess(true);
router.push(HOME);
} catch {
return;
} finally {
setLoading(false);
}
invalidatePreviousPost();
SetIsSuccess(true);
router.push(HOME);
} catch {
return;
} finally {
setLoading(false);
}
}, [formValue, alcoholNo, router, file]);
},
[router]
);

return (
<Paper>
Expand All @@ -92,7 +85,7 @@ export default function NewpostPage() {
title="포스팅"
appendButton="공유"
disableAppend={isSuccess}
onClickAppend={submitHandler}
onClickAppend={()=>submitHandler({...formValue,alcoholNo},file)}
/>

<Container sx={{ p: { xs: 0, sm: 4 } }} maxWidth={"lg"}>
Expand Down Expand Up @@ -127,17 +120,7 @@ export default function NewpostPage() {
component={"label"}
iconComponent={<PictureIcon />}
>
<input
name="image"
style={{ display: "none" }}
type="file"
accept="image/*"
onChange={(e) => {
if (e.target.files) {
setFile(e.target.files[0]);
}
}}
/>
<SingleImageInput onChange={(file) => setFile(file)} />
</SquareIconButton>
</Tooltip>
{/* 위치 */}
jobkaeHenry marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
32 changes: 32 additions & 0 deletions client/src/components/SingleImageInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React, { InputHTMLAttributes } from "react";

interface SingleImageInputInterface
extends Omit<
InputHTMLAttributes<HTMLInputElement>,
"onChange" | "type" | "capture" | "style" | "name"
> {
onChange: (file: File) => void;
}

const SingleImageInput = ({
onChange,
...others
}: SingleImageInputInterface) => {
return (
<input
name="image"
style={{ display: "none" }}
type="file"
accept="image/*"
capture="environment"
onChange={(e) => {
if (e.target.files) {
onChange(e.target.files[0]);
}
}}
{...others}
/>
);
};

export default SingleImageInput;
jobkaeHenry marked this conversation as resolved.
Show resolved Hide resolved
7 changes: 6 additions & 1 deletion client/src/components/post/PostCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,12 @@ const PostCard = ({
</Typography>
</Stack>

{isMyPost && <PostCardOptionDropdown postId={postNo} />}
{isMyPost && (
<PostCardOptionDropdown
postId={postNo}
filePk={postAttachUrls?.[0]?.attachNo}
/>
)}
</Stack>

{alcoholName && (
Expand Down
31 changes: 20 additions & 11 deletions client/src/components/post/PostCardOptionDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,36 @@ import React, { useState } from "react";
import { MoreVertOutlined } from "@mui/icons-material";
import { ButtonBase, Menu, MenuItem } from "@mui/material";
import { useDeletePostMutation } from "@/queries/post/useDeletePostMutation";
import useDeleteAttachMutation from "@/queries/attach/useDeleteAttachMutation";
import { useRouter } from "next/navigation";
import HOME from "@/const/clientPath";

type PostCardOptionDropdownProps = {
postId: number;
filePk?: string;
};

const PostCardOptionDropdown = ({ postId }: PostCardOptionDropdownProps) => {
const PostCardOptionDropdown = ({
postId,
filePk,
}: PostCardOptionDropdownProps) => {
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const open = Boolean(anchorEl);
const router = useRouter();

const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
setAnchorEl(event.currentTarget);
};
const { mutate: deletePost } = useDeletePostMutation();
const { mutateAsync: deletePost } = useDeletePostMutation();
const { mutateAsync: deleteFile } = useDeleteAttachMutation();

const deleteHandler = async () => {
if (confirm("정말 삭제하시겠습니까?")) {
await deletePost(postId);
filePk && (await deleteFile(filePk));
router.push(HOME);
}
};

const handleClose = () => {
setAnchorEl(null);
Expand All @@ -25,15 +42,7 @@ const PostCardOptionDropdown = ({ postId }: PostCardOptionDropdownProps) => {
<MoreVertOutlined />
</ButtonBase>
<Menu open={open} anchorEl={anchorEl} onClose={handleClose}>
<MenuItem
onClick={() => {
if (confirm("정말 삭제하시겠습니까?")) {
deletePost(postId);
}
}}
>
삭제
</MenuItem>
<MenuItem onClick={deleteHandler}>삭제</MenuItem>
<MenuItem>수정</MenuItem>
</Menu>
</>
jobkaeHenry marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
27 changes: 6 additions & 21 deletions client/src/components/user/info/drawer/UserInfoEditingForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ import {
Badge,
} from "@mui/material";
import CameraIcon from "@/assets/icons/badge/CameraIcon.svg";
import { useCallback, useContext, useEffect, useState } from "react";
import { useCallback, useContext, useState } from "react";
import useNewAttachMutation from "@/queries/attach/useNewAttachMutation";
import useDeleteAttachMutation from "@/queries/attach/useDeleteAttachMutation";
import UserPageContext from "@/store/user/UserPageContext";
import CustomAppbar from "@/components/CustomAppbar";
import { useGlobalLoadingStore } from "./../../../../store/useGlobalLoadingStore";
import usePatchUserInfoMutation from "@/queries/user/usePatchUserInfoMutation";
import useRenderAsDataUrl from "@/hooks/useRenderAsDataUrl";
import SingleImageInput from "@/components/SingleImageInput";

const UserInfoEditingForm = () => {
const { setIsEditing } = useContext(UserPageContext);
Expand All @@ -25,8 +27,9 @@ const UserInfoEditingForm = () => {
const { data } = useMyInfoQuery();

const [introduction, setIntroduction] = useState(data?.introduction);

const [file, setFile] = useState<File>();
const [fileUrl, setFileUrl] = useState<string | ArrayBuffer | null>(null);
const fileUrl = useRenderAsDataUrl(file);

const { mutateAsync: attachFile } = useNewAttachMutation();
const { mutateAsync: removeFile } = useDeleteAttachMutation();
Expand Down Expand Up @@ -58,15 +61,6 @@ const UserInfoEditingForm = () => {
setLoading(false);
};

useEffect(() => {
if (!file) {
return;
}
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onloadend = () => setFileUrl(reader.result);
}, [file]);

return (
<>
<CustomAppbar
Expand Down Expand Up @@ -98,16 +92,7 @@ const UserInfoEditingForm = () => {
sx={{ width: 80, height: 80, border: "1px solid #ccc" }}
/>
</Badge>
<input
type="file"
accept="image/*"
onChange={(e) => {
if (e.target.files) {
setFile(e.target.files[0]);
}
}}
style={{ display: "none" }}
/>
<SingleImageInput onChange={(file) => setFile(file)} />
</label>
<Stack gap={2} width="100%">
<Stack direction="row" width="100%">
jobkaeHenry marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
23 changes: 23 additions & 0 deletions client/src/hooks/useRenderAsDataUrl.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { useEffect, useState } from "react";

/**
* file 을 입력받아 dataUrl을 리턴하는 훅
* @param file
* @returns fileDataUrl
*/
const useRenderAsDataUrl = (file: File | undefined) => {
const [fileUrl, setFileUrl] = useState<string | ArrayBuffer | null>(null);

useEffect(() => {
if (!file) {
return;
}
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onloadend = () => setFileUrl(reader.result);
}, [file]);

return fileUrl;
};

export default useRenderAsDataUrl;
jobkaeHenry marked this conversation as resolved.
Show resolved Hide resolved