Files
clean-architecture-frontend…/src/presentation/examples/auth-example-page.jsx
T

81 lines
2.6 KiB
React

import { useState } from "react";
import { useLocation } from "react-router-dom";
import { PageHeader } from "../components/page-header.jsx";
import { useSession } from "../providers/session-provider.jsx";
export default function AuthExamplePage() {
const location = useLocation();
const { sessionState, beginSignIn, signOut, recover } = useSession();
const [pending, setPending] = useState(false);
const [failed, setFailed] = useState(false);
/** @param {() => Promise<unknown>} action */
async function execute(action) {
setPending(true);
setFailed(false);
try {
await action();
} catch {
setFailed(true);
} finally {
setPending(false);
}
}
return (
<section className="ui-page">
<PageHeader
eyebrow="예제"
title="인증 연동"
description="스켈레톤은 자격 증명을 소유하지 않고 외부 인증 구현이 연결될 포트와 화면 상태만 제공합니다."
/>
<section className="ui-panel auth-example" aria-labelledby="auth-state-title">
<div>
<h2 id="auth-state-title">현재 세션 상태</h2>
<output className="session-status" data-state={sessionState}>
{sessionState}
</output>
</div>
<div className="button-row">
<button
className="ui-button"
type="button"
disabled={pending || sessionState === "integration-failed"}
onClick={() =>
void execute(() =>
beginSignIn(`${location.pathname}${location.search}`),
)
}
>
로그인 시작
</button>
<button
className="ui-button ui-button--secondary"
type="button"
disabled={pending || sessionState !== "authenticated"}
onClick={() => void execute(signOut)}
>
로그아웃
</button>
<button
className="ui-button ui-button--secondary"
type="button"
disabled={pending || sessionState !== "recovery-pending"}
onClick={() => void execute(recover)}
>
세션 복구
</button>
</div>
{sessionState === "integration-failed" ? (
<p role="status">
외부 인증 소유자가 연결되지 않았습니다. 런타임 호스트의 인증
계약을 연결하세요.
</p>
) : null}
{failed ? <p role="alert">인증 작업을 완료하지 못했습니다.</p> : null}
</section>
</section>
);
}