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

New: 글로벌 로딩 팝업 추가 #33

Merged
merged 1 commit into from
Nov 12, 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
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",
jobkaeHenry marked this conversation as resolved.
Show resolved Hide resolved
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>
jobkaeHenry marked this conversation as resolved.
Show resolved Hide resolved
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)",
jobkaeHenry marked this conversation as resolved.
Show resolved Hide resolved
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;
jobkaeHenry marked this conversation as resolved.
Show resolved Hide resolved
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
Loading