음성 재생과 운영 배포 정리
This commit is contained in:
parent
8ed185ce6c
commit
ac7db95542
1020 changed files with 46863 additions and 2175 deletions
176
apps/web/src/pages/PendingApproval.tsx
Normal file
176
apps/web/src/pages/PendingApproval.tsx
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
import { useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { Button, Icon } from "../components/ui";
|
||||
import { roleHomePath, useAuth } from "../lib/auth";
|
||||
|
||||
export default function PendingApproval() {
|
||||
const navigate = useNavigate();
|
||||
const { user, logout, refresh } = useAuth();
|
||||
const [checking, setChecking] = useState(false);
|
||||
|
||||
const checkAgain = async () => {
|
||||
if (checking) return;
|
||||
setChecking(true);
|
||||
try {
|
||||
const nextUser = await refresh();
|
||||
if (nextUser?.accountStatus === "approved") {
|
||||
navigate(
|
||||
nextUser.onboardingCompletedAt == null ? "/onboarding" : roleHomePath(nextUser.role),
|
||||
{ replace: true },
|
||||
);
|
||||
}
|
||||
} finally {
|
||||
setChecking(false);
|
||||
}
|
||||
};
|
||||
|
||||
const signOut = async () => {
|
||||
await logout();
|
||||
navigate("/login", { replace: true });
|
||||
};
|
||||
|
||||
const statusText = user?.accountStatus === "suspended" ? "접속 보류" : "승인 대기";
|
||||
|
||||
return (
|
||||
<>
|
||||
<style>{PENDING_APPROVAL_CSS}</style>
|
||||
<main className="pa-page" aria-label="계정 승인 대기">
|
||||
<section className="pa-panel">
|
||||
<div className="pa-mark" aria-hidden="true">
|
||||
<Icon name="shield" size={30} strokeWidth={1.9} />
|
||||
</div>
|
||||
<p className="pa-kicker">{statusText}</p>
|
||||
<h1>계정 확인이 끝나면 바로 이용할 수 있습니다.</h1>
|
||||
<p className="pa-copy">
|
||||
{user?.email ? <b>{user.email}</b> : "현재 계정"}으로 가입 요청이 접수되었습니다.
|
||||
운영자가 수업 또는 연구 참여 범위를 확인하는 동안 Vignette 화면은 열리지 않습니다.
|
||||
</p>
|
||||
<div className="pa-status" role="status">
|
||||
<span aria-hidden="true" />
|
||||
<div>
|
||||
<b>접속 권한 확인 중</b>
|
||||
<small>승인되면 새로고침 후 온보딩 또는 역할 홈으로 이동합니다.</small>
|
||||
</div>
|
||||
</div>
|
||||
<div className="pa-actions">
|
||||
<Button
|
||||
type="button"
|
||||
size="lg"
|
||||
leading={<Icon name="settings" size={16} />}
|
||||
onClick={() => void checkAgain()}
|
||||
disabled={checking}
|
||||
>
|
||||
{checking ? "확인 중" : "승인 상태 새로고침"}
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
size="lg"
|
||||
variant="secondary"
|
||||
leading={<Icon name="logout" size={16} />}
|
||||
onClick={() => void signOut()}
|
||||
>
|
||||
다른 계정으로 로그인
|
||||
</Button>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
const PENDING_APPROVAL_CSS = `
|
||||
.pa-page{
|
||||
min-height:100dvh;
|
||||
display:grid;
|
||||
place-items:center;
|
||||
padding:clamp(18px,5vw,56px);
|
||||
background:var(--bg-app);
|
||||
color:var(--text-body);
|
||||
}
|
||||
.pa-panel{
|
||||
width:min(100%,620px);
|
||||
display:grid;
|
||||
gap:var(--sp-4);
|
||||
padding:clamp(24px,5vw,44px);
|
||||
border:1px solid var(--border-subtle);
|
||||
border-radius:var(--radius);
|
||||
background:color-mix(in srgb,var(--bg-surface) 92%,white 8%);
|
||||
box-shadow:0 18px 50px rgba(28,43,40,.10);
|
||||
}
|
||||
.pa-mark{
|
||||
width:62px;
|
||||
height:62px;
|
||||
display:grid;
|
||||
place-items:center;
|
||||
border-radius:var(--radius);
|
||||
background:var(--accent-tint);
|
||||
color:var(--accent-deep);
|
||||
border:1px solid color-mix(in srgb,var(--accent) 20%,transparent);
|
||||
}
|
||||
.pa-kicker{
|
||||
margin:0;
|
||||
color:var(--accent-deep);
|
||||
font-size:12px;
|
||||
font-weight:820;
|
||||
}
|
||||
.pa-panel h1{
|
||||
margin:0;
|
||||
color:var(--text-strong);
|
||||
font-size:clamp(30px,5vw,46px);
|
||||
line-height:1.17;
|
||||
letter-spacing:0;
|
||||
}
|
||||
.pa-copy{
|
||||
margin:0;
|
||||
color:var(--text-muted);
|
||||
font-size:15px;
|
||||
line-height:1.7;
|
||||
}
|
||||
.pa-copy b{
|
||||
color:var(--text-strong);
|
||||
font-weight:760;
|
||||
}
|
||||
.pa-status{
|
||||
min-width:0;
|
||||
display:grid;
|
||||
grid-template-columns:auto minmax(0,1fr);
|
||||
gap:12px;
|
||||
align-items:center;
|
||||
padding:14px;
|
||||
border:1px solid var(--border-subtle);
|
||||
border-radius:var(--radius);
|
||||
background:var(--bg-surface-2);
|
||||
}
|
||||
.pa-status > span{
|
||||
width:10px;
|
||||
height:10px;
|
||||
border-radius:50%;
|
||||
background:#d89a2b;
|
||||
box-shadow:0 0 0 5px rgba(216,154,43,.14);
|
||||
}
|
||||
.pa-status b{
|
||||
display:block;
|
||||
color:var(--text-strong);
|
||||
font-size:14px;
|
||||
}
|
||||
.pa-status small{
|
||||
display:block;
|
||||
margin-top:3px;
|
||||
color:var(--text-muted);
|
||||
font-size:12.5px;
|
||||
line-height:1.45;
|
||||
}
|
||||
.pa-actions{
|
||||
display:flex;
|
||||
flex-wrap:wrap;
|
||||
gap:10px;
|
||||
}
|
||||
@media (max-width:560px){
|
||||
.pa-panel{
|
||||
border-radius:var(--radius);
|
||||
}
|
||||
.pa-actions .vg-btn{
|
||||
width:100%;
|
||||
}
|
||||
}
|
||||
`;
|
||||
Loading…
Add table
Add a link
Reference in a new issue