Skip to content

Commit

Permalink
Merge pull request #234 from 3I-shikosai32/feat/231-add_signout_page
Browse files Browse the repository at this point in the history
サインアウトページ`/auth/sign-out`を作成した。他、修正
  • Loading branch information
dino3616 authored Oct 18, 2022
2 parents 08296cc + 0c89d63 commit e5d38fb
Show file tree
Hide file tree
Showing 6 changed files with 172 additions and 13 deletions.
11 changes: 11 additions & 0 deletions src/pages/auth/sign-out.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type { FC } from 'react';
import { Layout } from '@/presentation/layout/layout.container';
import { SignOutPage } from '@/presentation/relevant/auth/sign-out.page';

const IndexPage: FC = () => (
<Layout title="サインアウト | OZ">
<SignOutPage />
</Layout>
);

export default IndexPage;
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const useUserNavigationMenu = (): UserNavigationMenuStateProps => {

return {
userIconUrl: user?.characterStatus.iconUrl,
isLoggedIn: !!user,
isLoggedIn: currentUser !== null,
showAdminLink: user?.role === UserRole.Admin,
};
};
95 changes: 83 additions & 12 deletions src/presentation/relevant/auth/auth.page.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,56 @@
import Router from 'next/router';
import { FC, useState } from 'react';
import { FC, useState, useMemo, useEffect } from 'react';
import { FaTwitter } from 'react-icons/fa';
import { FcGoogle } from 'react-icons/fc';
import { RiUser3Fill } from 'react-icons/ri';
import { Button, ButtonIcon } from '../../primitive/component/button/button.presenter';
import { Card } from '../../primitive/component/card/card.presenter';
import { Link, LinkIcon } from '../../primitive/component/link/link.presenter';
import { loginWithGoogle } from '@/infra/firebase/auth';
import { Modal, ModalTitle, ModalDescription, ModalOverlay, ModalContent } from '@/presentation/primitive/component/modal/modal.presenter';
import { useCheckUserExistanceUseCase } from '@/use-case/user/use-check-user-existance.use-case';
import { useCurrentUserIdUseCase } from '@/use-case/user/use-current-user-id.use-case';

export const Auth: FC = () => {
const [isLoading, setIsLoading] = useState(false);

const [isAuthenticating, setIsAuthenticating] = useState(false);
const [shouldShowErrorModal, setShouldShowErrorModal] = useState(false);
const currentUser = useCurrentUserIdUseCase(); // Firebase Authの認証情報由来のid
const hasUserAuthenticated = useMemo(() => !!currentUser, [currentUser]); // ユーザーがFirebase Authでログイン済みかどうか
// ユーザーが各種情報を登録済みかどうか
const hasUserRegisteredInfo = useCheckUserExistanceUseCase({
id: currentUser?.id,
});
useEffect(() => {
if (hasUserAuthenticated) {
if (hasUserRegisteredInfo) {
Router.push('/');
} else {
Router.push('/auth/new-user');
}
}
}, [hasUserAuthenticated, hasUserRegisteredInfo]);
return (
<Card className="my-24 py-5 px-10">
<h1 className="text-center">
<span className="text-2xl font-semibold">sign in / sign up</span>
<span className="inline-flex items-center justify-center gap-2 text-2xl font-semibold">
<RiUser3Fill />
登録・ログイン
</span>
</h1>
<div className="my-5">
<Button
disabled={isLoading}
disabled={isAuthenticating}
className="bg-secondary-300"
onClick={async () => {
setIsLoading(true);
await loginWithGoogle().catch(() => {
setIsLoading(false);
});
if (isLoading) {
Router.push('/auth/is-new-user');
setIsAuthenticating(true);
try {
await loginWithGoogle();
} catch (e) {
// ログイン処理が失敗したときに、ダイアログを表示する
setShouldShowErrorModal(true);
} finally {
setIsAuthenticating(false);
}
setIsLoading(false);
}}
>
<ButtonIcon>
Expand All @@ -34,6 +59,52 @@ export const Auth: FC = () => {
Googleでログインする
</Button>
</div>
<Modal
trigger={
<Button aria-hidden className="hidden">
エラー文を表示する
</Button>
}
open={shouldShowErrorModal}
onOpenChange={(isOpen) => {
setShouldShowErrorModal(isOpen);
}}
>
<ModalOverlay>
<ModalContent className="flex items-stretch text-center">
<ModalTitle>ログインに失敗しました</ModalTitle>
<ModalDescription className="flex flex-col gap-2">
<span>
ログインメニューが途中で閉じられたか、
<br />
内部でエラーが発生した可能性があります。
<br />
</span>
<span className="text-xs text-neutral-500">
再度試してみても同様のエラーが発生する場合は、
<br />
お近くのスタッフもしくは下記のSNSアカウントに問い合わせてください。
<br />
</span>
</ModalDescription>
<div className="flex items-center justify-center">
<Link href="https://twitter.com/3i_shikosai32" className="inline-flex gap-2 font-normal text-neutral-400 drop-shadow-none">
<LinkIcon className="text-neutral-200">
<FaTwitter />
</LinkIcon>
@3i_shikosai32
</Link>
</div>
<Button
onClick={() => {
setShouldShowErrorModal(false);
}}
>
閉じる
</Button>
</ModalContent>
</ModalOverlay>
</Modal>
</Card>
);
};
16 changes: 16 additions & 0 deletions src/presentation/relevant/auth/sign-out.page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import Router from 'next/router';
import { useEffect } from 'react';
import type { FC } from 'react';
import { SignOut } from './sign-out.presenter';
import { logout } from '@/infra/firebase/auth';

export const SignOutPage: FC = () => {
useEffect(() => {
logout();
const timer = setTimeout(() => {
Router.push('/');
}, 10000);
return () => clearTimeout(timer);
}, []);
return <SignOut />;
};
44 changes: 44 additions & 0 deletions src/presentation/relevant/auth/sign-out.presenter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import Image from 'next/image';
import type { FC } from 'react';
import { Button } from '@/presentation/primitive/component/button/button.presenter';
import { Link } from '@/presentation/primitive/component/link/link.presenter';
import { Separator } from '@/presentation/primitive/component/sepatator/separator.presenter';

//
// TODO: http-errorとほぼ共通のUIを持つので、`priimtive/component`に共通部分を移動する
//

export const SignOut: FC = () => (
<div className="flex flex-col items-center justify-start gap-6 p-4 pt-0 lg:flex-row lg:justify-center lg:gap-12">
{/* グラデーションをよりきれいなものにするために、`primary-100`とほぼ同等だけれど、より若干明るく鮮やかな色を指定する! */}
<div className="fixed top-0 -z-10 flex h-80 w-full origin-top flex-col items-center justify-center bg-gradient-to-b from-[#FEECFE] to-secondary-100/0" />
<figure className="grid max-w-md flex-none select-none grid-cols-1 grid-rows-1">
<div className="relative col-span-full row-span-full">
<Image src="/heroes/concept.png" className="select-none" width={1176} height={1342} alt="OZ at 3Iのロゴ画像" />
</div>
<div className="col-span-full row-span-full flex items-center justify-center">
<div className="relative z-10 bg-gradient-to-br from-primary-400/75 to-secondary-400/75 p-6 text-center font-pixel-latin text-white backdrop-blur-md">
May We
<br />
Meet Again!
</div>
</div>
</figure>
<div className="hidden h-60 items-center justify-center lg:flex">
<Separator orientation="vertical" />
</div>
<div className="flex flex-col items-center justify-start gap-6 p-0">
<div className="text-center font-pixel-latin shadow-neutral-900 drop-shadow-lg ">
<div className="bg-gradient-to-br bg-clip-text p-0 text-5xl text-transparent gradient-primary">
<h1>SIGNOUT</h1>
</div>
<p>THANK YOU FOR PLAYING!</p>
</div>
<span>OZで遊んでくれてありがとう!またお会いしましょう。</span>
<span className="text-xs text-neutral-500">数秒後に自動でトップページにリダイレクトされます</span>
<Link href="/" className="drop-shadow-none hover:no-underline">
<Button outlined>トップページへ戻る</Button>
</Link>
</div>
</div>
);
17 changes: 17 additions & 0 deletions src/presentation/relevant/auth/sign-out.story.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// eslint-disable-next-line import/no-extraneous-dependencies
import type { ComponentStoryObj, ComponentMeta } from '@storybook/react';

import { SignOut } from './sign-out.presenter';

type Story = ComponentStoryObj<typeof SignOut>;

const meta: ComponentMeta<typeof SignOut> = {
component: SignOut,
parameters: {
layout: 'fullscreen',
},
};

export default meta;

export const Default: Story = {};

1 comment on commit e5d38fb

@vercel
Copy link

@vercel vercel bot commented on e5d38fb Oct 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.