|  | 
|  | 1 | +import * as Shop from "@frontend/shop"; | 
|  | 2 | +import { AccountCircleOutlined, Google } from "@mui/icons-material"; | 
|  | 3 | +import { Backdrop, Button, ButtonProps, CircularProgress, Stack, styled, Typography } from "@mui/material"; | 
|  | 4 | +import { Suspense } from "@suspensive/react"; | 
|  | 5 | +import { enqueueSnackbar, OptionsObject } from "notistack"; | 
|  | 6 | +import * as React from "react"; | 
|  | 7 | +import { useNavigate } from "react-router-dom"; | 
|  | 8 | + | 
|  | 9 | +import { useAppContext } from "../../contexts/app_context"; | 
|  | 10 | + | 
|  | 11 | +const SignInPageContainer = styled(Stack)(({ theme }) => ({ | 
|  | 12 | +  height: "75%", | 
|  | 13 | +  width: "100%", | 
|  | 14 | +  maxWidth: "1200px", | 
|  | 15 | + | 
|  | 16 | +  justifyContent: "flex-start", | 
|  | 17 | +  alignItems: "center", | 
|  | 18 | + | 
|  | 19 | +  paddingTop: theme.spacing(8), | 
|  | 20 | +  paddingBottom: theme.spacing(8), | 
|  | 21 | + | 
|  | 22 | +  paddingRight: theme.spacing(16), | 
|  | 23 | +  paddingLeft: theme.spacing(16), | 
|  | 24 | + | 
|  | 25 | +  [theme.breakpoints.down("lg")]: { | 
|  | 26 | +    padding: theme.spacing(4), | 
|  | 27 | +  }, | 
|  | 28 | +  [theme.breakpoints.down("sm")]: { | 
|  | 29 | +    padding: theme.spacing(2), | 
|  | 30 | +  }, | 
|  | 31 | +})); | 
|  | 32 | + | 
|  | 33 | +type PageeStateType = { | 
|  | 34 | +  openBackdrop: boolean; | 
|  | 35 | +}; | 
|  | 36 | + | 
|  | 37 | +export const ShopSignInPage: React.FC = Suspense.with({ fallback: <CircularProgress /> }, () => { | 
|  | 38 | +  const { setAppContext, language } = useAppContext(); | 
|  | 39 | +  const [state, setState] = React.useState<PageeStateType>({ openBackdrop: false }); | 
|  | 40 | +  const navigate = useNavigate(); | 
|  | 41 | +  const shopAPIClient = Shop.Hooks.useShopClient(); | 
|  | 42 | +  const SignInMutation = Shop.Hooks.useSignInWithSNSMutation(shopAPIClient); | 
|  | 43 | +  const { data } = Shop.Hooks.useUserStatus(shopAPIClient); | 
|  | 44 | + | 
|  | 45 | +  const shouldOpenBackdrop = SignInMutation.isPending || state.openBackdrop; | 
|  | 46 | + | 
|  | 47 | +  const addSnackbar = (c: string | React.ReactNode, variant: OptionsObject["variant"]) => | 
|  | 48 | +    enqueueSnackbar(c, { variant, anchorOrigin: { vertical: "bottom", horizontal: "center" } }); | 
|  | 49 | + | 
|  | 50 | +  const triggerSignIn = (provider: "google" | "kakao" | "naver") => { | 
|  | 51 | +    setState((ps) => ({ ...ps, openBackdrop: true })); | 
|  | 52 | +    SignInMutation.mutate({ provider, callback_url: window.location.origin }); | 
|  | 53 | +  }; | 
|  | 54 | +  const signInWithGoogle = () => triggerSignIn("google"); | 
|  | 55 | +  const signInWithKakao = () => triggerSignIn("kakao"); | 
|  | 56 | +  const signInWithNaver = () => triggerSignIn("naver"); | 
|  | 57 | + | 
|  | 58 | +  const signInTitleStr = language === "ko" ? "로그인" : "Sign In"; | 
|  | 59 | +  const signInWithGoogleStr = language === "ko" ? "구글로 로그인" : "Sign In with Google"; | 
|  | 60 | +  const signInWithKakaoStr = language === "ko" ? "카카오로 로그인" : "Sign In with Kakao"; | 
|  | 61 | +  const signInWithNaverStr = language === "ko" ? "네이버로 로그인" : "Sign In with Naver"; | 
|  | 62 | + | 
|  | 63 | +  React.useEffect(() => { | 
|  | 64 | +    if (data && data.meta.is_authenticated) { | 
|  | 65 | +      addSnackbar( | 
|  | 66 | +        language === "ko" | 
|  | 67 | +          ? `이미 ${data.data.user.username}님으로 로그인되어 있습니다!` | 
|  | 68 | +          : `You are already signed in as ${data.data.user.username}!`, | 
|  | 69 | +        "success" | 
|  | 70 | +      ); | 
|  | 71 | +      navigate("/"); | 
|  | 72 | +      return; | 
|  | 73 | +    } | 
|  | 74 | + | 
|  | 75 | +    setAppContext((prev) => ({ | 
|  | 76 | +      ...prev, | 
|  | 77 | +      title: signInTitleStr, | 
|  | 78 | +      shouldShowTitleBanner: true, | 
|  | 79 | +      shouldShowSponsorBanner: false, | 
|  | 80 | +    })); | 
|  | 81 | +  }, [signInTitleStr]); | 
|  | 82 | + | 
|  | 83 | +  const commonBtnProps: ButtonProps = { | 
|  | 84 | +    variant: "contained", | 
|  | 85 | +    fullWidth: true, | 
|  | 86 | +    size: "large", | 
|  | 87 | +    disabled: SignInMutation.isPending, | 
|  | 88 | +  }; | 
|  | 89 | +  const commonBtnSxProps: ButtonProps["sx"] = { | 
|  | 90 | +    textTransform: "none", | 
|  | 91 | +  }; | 
|  | 92 | +  const btnProps: ButtonProps[] = [ | 
|  | 93 | +    { | 
|  | 94 | +      children: signInWithGoogleStr, | 
|  | 95 | +      onClick: signInWithGoogle, | 
|  | 96 | +      startIcon: <Google />, | 
|  | 97 | +      sx: { ...commonBtnSxProps, backgroundColor: "#4285F4", color: "#fff" }, | 
|  | 98 | +    }, | 
|  | 99 | +    { | 
|  | 100 | +      children: signInWithNaverStr, | 
|  | 101 | +      onClick: signInWithNaver, | 
|  | 102 | +      startIcon: <AccountCircleOutlined />, | 
|  | 103 | +      sx: { ...commonBtnSxProps, backgroundColor: "#03C75A", color: "#fff" }, | 
|  | 104 | +    }, | 
|  | 105 | +    { | 
|  | 106 | +      children: signInWithKakaoStr, | 
|  | 107 | +      onClick: signInWithKakao, | 
|  | 108 | +      startIcon: <AccountCircleOutlined />, | 
|  | 109 | +      sx: { ...commonBtnSxProps, backgroundColor: "#FEE500", color: "#000" }, | 
|  | 110 | +    }, | 
|  | 111 | +  ]; | 
|  | 112 | + | 
|  | 113 | +  return ( | 
|  | 114 | +    <> | 
|  | 115 | +      <SignInPageContainer spacing={6}> | 
|  | 116 | +        <Typography variant="h4" sx={{ textAlign: "center", fontWeight: "bolder" }} children={signInTitleStr} /> | 
|  | 117 | +        <Stack spacing={1} sx={{ width: "100%", maxWidth: "400px" }}> | 
|  | 118 | +          {btnProps.map((props, index) => ( | 
|  | 119 | +            <Button key={index} {...commonBtnProps} {...props} /> | 
|  | 120 | +          ))} | 
|  | 121 | +        </Stack> | 
|  | 122 | +      </SignInPageContainer> | 
|  | 123 | +      <Backdrop sx={({ zIndex }) => ({ zIndex: zIndex.drawer + 1 })} open={shouldOpenBackdrop} onClick={() => {}} /> | 
|  | 124 | +    </> | 
|  | 125 | +  ); | 
|  | 126 | +}); | 
0 commit comments