Skip to content

Commit

Permalink
New: 글로벌 로딩 팝업 추가 (#33)
Browse files Browse the repository at this point in the history
  • Loading branch information
jobkaeHenry authored Nov 12, 2023
1 parent 1ce00e6 commit 8c87ef8
Show file tree
Hide file tree
Showing 8 changed files with 164 additions and 74 deletions.
38 changes: 37 additions & 1 deletion client/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
"react": "^18",
"react-dom": "^18",
"react-intersection-observer": "^9.5.3",
"sharp": "^0.32.6"
"sharp": "^0.32.6",
"zustand": "^4.4.6"
},
"devDependencies": {
"@storybook/addon-essentials": "7.5.2",
Expand Down
128 changes: 66 additions & 62 deletions client/src/app/(protectedRoute)/new-post/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ import {
Button,
ButtonBase,
Container,
IconButton,
Paper,
TextField,
Toolbar,
Tooltip,
Typography,
} from "@mui/material";
import GoBackIcon from "@/assets/icons/GoBackIcon.svg";
Expand All @@ -21,6 +23,7 @@ import HOME from "@/const/clientPath";
import CameraIcon from "@/assets/icons/CameraIcon.svg";
import PinIcon from "@/assets/icons/PinIcon.svg";
import getTokenFromLocalStorage from "@/utils/getTokenFromLocalStorage";
import { useGlobalLoadingStore } from "@/store/useGlobalLoadingStore";

export default function NewpostPage() {
const [formValue, setFormValue] = useState({
Expand All @@ -35,14 +38,15 @@ export default function NewpostPage() {
}: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
setFormValue((prev) => ({ ...prev, [target.name]: target.value }));
};

const { setLoading } = useGlobalLoadingStore();
const token = getTokenFromLocalStorage();

const router = useRouter();

const submitHandler = () => {
let userId;
let pk;
setLoading(true);
axios
.get("/user/me", { headers: { Authorization: token } })
.then((res) => {
Expand All @@ -60,9 +64,7 @@ export default function NewpostPage() {
const formData = new FormData();
if (file) {
formData.append("image", file);
}
axios
.post(`/attach/resources/POST/${pk}`, formData, {
axios.post(`/attach/resources/POST/${pk}`, formData, {
headers: {
Authorization: token,
"Content-Type": "multipart/form-data",
Expand All @@ -72,10 +74,10 @@ export default function NewpostPage() {
return formData;
},
],
})
.then(() => {
router.push(HOME);
});
}
setLoading(false);
router.push(HOME);
});
});
};
Expand All @@ -94,44 +96,42 @@ export default function NewpostPage() {

return (
<Paper>
{/* 최상단 앱바 */}
<AppBar position={"static"}>
<Toolbar sx={{ display: "flex", justifyContent: "space-between" }}>
<ButtonBase onClick={() => router.back()}>
<IconButton onClick={() => router.back()}>
<GoBackIcon></GoBackIcon>
</ButtonBase>
</IconButton>
<Typography variant="subtitle2" fontWeight={"bold"}>
포스팅
</Typography>
<Typography
onClick={submitHandler}
variant="subtitle2"
color={"primary.main"}
>
<Button onClick={submitHandler} variant="text" sx={{ minWidth: 40 }}>
공유
</Typography>
</Button>
</Toolbar>
</AppBar>
<Container sx={{ px: { xs: 0, sm: 4 } }} maxWidth={"lg"}>

<Container sx={{ p: { xs: 0, sm: 4 } }} maxWidth={"lg"}>
<Paper
sx={{
minHeight: "calc(100vh - 112px)",
display: "flex",
flexDirection: "column",
gap: 2,
p: 2,
}}
>
{/* 검색창 */}
<TextField
placeholder="지금 어떤 술을 마시고 있나요?"
autoFocus
name="positionInfo"
size="small"
InputProps={{
startAdornment: (
<AlcholeSearchIcon style={{ marginRight: "8px" }} />
),
startAdornment: <AlcholeSearchIcon />,
endAdornment: <InputSearchIcon />,
}}
onChange={changeHadler}
sx={{ px: 0 }}
/>

<TextField
Expand Down Expand Up @@ -193,49 +193,53 @@ export default function NewpostPage() {
/>
)}
<Box sx={{ display: "flex", gap: 2 }}>
<Box
component={"label"}
sx={{
bgcolor: "#F5F5F5",
border: "1px solid",
borderColor: "#E6E6E6",
width: 72,
height: 72,
borderRadius: 1.5,
display: "flex",
justifyContent: "center",
alignItems: "center",
}}
>
<CameraIcon />
<input
name="image"
style={{ display: "none" }}
type="file"
accept="image/*"
onChange={(e) => {
if (e.target.files) {
setFile(e.target.files[0]);
}
<Tooltip title="사진 첨부">
<ButtonBase
component={"label"}
sx={{
bgcolor: "#F5F5F5",
border: "1px solid",
borderColor: "#E6E6E6",
width: 72,
height: 72,
borderRadius: 1.5,
display: "flex",
justifyContent: "center",
alignItems: "center",
}}
/>
</Box>
<Box
component={"label"}
sx={{
bgcolor: "#F5F5F5",
border: "1px solid",
borderColor: "#E6E6E6",
width: 72,
height: 72,
borderRadius: 1.5,
display: "flex",
justifyContent: "center",
alignItems: "center",
}}
>
<PinIcon />
</Box>
>
<CameraIcon />
<input
name="image"
style={{ display: "none" }}
type="file"
accept="image/*"
onChange={(e) => {
if (e.target.files) {
setFile(e.target.files[0]);
}
}}
/>
</ButtonBase>
</Tooltip>
<Tooltip title="위치 추가">
<ButtonBase
component={"label"}
sx={{
bgcolor: "#F5F5F5",
border: "1px solid",
borderColor: "#E6E6E6",
width: 72,
height: 72,
borderRadius: 1.5,
display: "flex",
justifyContent: "center",
alignItems: "center",
}}
>
<PinIcon />
</ButtonBase>
</Tooltip>
</Box>
</Paper>
</Container>
Expand Down
13 changes: 7 additions & 6 deletions client/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import NavigationBar from "~/components/NavigationBar";
import "./globals.css";
import CustomQueryClientProvider from "@/components/queryClient/CustomQueryClientProvider";
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
import GlobalLoadingPopup from "./../components/GlobalLoadingPopup";

export const metadata: Metadata = {
title: `${nameOfApp} | ${oneLineMessage}`,
Expand All @@ -21,20 +22,20 @@ export const viewport: Viewport = {
themeColor: "black",
};

export default function RootLayout({
children,
Modal,
}: {
interface RootLayoutInterface {
children: React.ReactNode;
Modal: React.ReactNode;
}) {
}

export default function RootLayout({ children, Modal }: RootLayoutInterface) {
return (
<html lang="kr" className={Pretendard.className}>
<body>
<CustomQueryClientProvider>
<ThemeRegistry options={{ key: "mui" }}>
{Modal}
<GlobalStyles styles={OverrideCSS} />
<GlobalLoadingPopup />
{Modal}
<Box
sx={{
maxHeight: "calc(100vh - 56px)",
Expand Down
24 changes: 24 additions & 0 deletions client/src/components/GlobalLoadingPopup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"use client";
import { useGlobalLoadingStore } from "@/store/useGlobalLoadingStore";
import { CircularProgress, Modal } from "@mui/material";

const GlobalLoadingPopup = () => {
const { isLoading } = useGlobalLoadingStore();
return (
<Modal
open={isLoading}
disablePortal
disableAutoFocus
sx={{
alignItems: "center",
justifyContent: "center",
zIndex: 9999,
display: "flex",
}}
>
<CircularProgress />
</Modal>
);
};

export default GlobalLoadingPopup;
8 changes: 8 additions & 0 deletions client/src/queries/auth/useLoginMutation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,21 @@ import { useRouter } from "next/navigation";
import HOME from "@/const/clientPath";
import errorHandler from "@/utils/errorHandler";
import { AxiosError } from "axios";
import { useGlobalLoadingStore } from "@/store/useGlobalLoadingStore";

const useLoginMutation = () => {
const { loginHandler } = useLogin();
const queryClient = useQueryClient();
const router = useRouter();
const { setLoading } = useGlobalLoadingStore();

return useMutation({
mutationKey: LoginMuataionKey.all,
mutationFn: async ({ id, password }: SigninRequirement) =>
await loginHandler({ id, password }),
onMutate: () => {
setLoading(true);
},
// 로그인에 성공한 경우, 토큰을 로컬스토리지에 저장, 이전 로그인 쿼리를 인벨리데이트
onSuccess: async ({ token }) => {
localStorage?.setItem("accessToken", token);
Expand All @@ -26,6 +31,9 @@ const useLoginMutation = () => {
},
onError: (error: AxiosError<{ detailMessage: string }>) =>
errorHandler(error.response?.data.detailMessage ?? "에러가 발생했니다"),
onSettled: () => {
setLoading(false);
},
});
};

Expand Down
Loading

0 comments on commit 8c87ef8

Please sign in to comment.