feat(web): show legal documents in registration dialogs
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useRef, useState } from 'react';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
|
||||
import { Link, Navigate, useNavigate } from 'react-router-dom';
|
||||
|
||||
@@ -33,9 +33,18 @@ export function RegisterPage() {
|
||||
const [agreed, setAgreed] = useState(false);
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
const [error, setError] = useState('');
|
||||
const [legalDocument, setLegalDocument] = useState<'terms' | 'privacy' | null>(null);
|
||||
const legalDialogRef = useRef<HTMLDialogElement>(null);
|
||||
const verifiedRef = useRef<{ key: string; response: string } | null>(null);
|
||||
const submitRef = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
const dialog = legalDialogRef.current;
|
||||
if (!dialog) return;
|
||||
if (legalDocument && !dialog.open) dialog.showModal();
|
||||
if (!legalDocument && dialog.open) dialog.close();
|
||||
}, [legalDocument]);
|
||||
|
||||
if (!tenant) return <Navigate to="/tenant" replace />;
|
||||
const minPasswordLength = tenant.passwordPolicy?.minLength ?? 8;
|
||||
// The deployed file endpoint is pinned to the IM API host; the web host serves
|
||||
@@ -146,7 +155,7 @@ export function RegisterPage() {
|
||||
autoComplete="new-password" maxLength={tenant.passwordPolicy?.maxLength} />
|
||||
<label className="flex items-start gap-2 text-sm text-text-secondary">
|
||||
<input type="checkbox" checked={agreed} onChange={(e) => setAgreed(e.target.checked)} className="mt-1" />
|
||||
<span>我已阅读并同意 <a href={`${legalOrigin}/legal/user-terms`} target="_blank" rel="noreferrer" className="text-accent">用户条款</a> 和 <a href={`${legalOrigin}/legal/privacy-policy`} target="_blank" rel="noreferrer" className="text-accent">隐私政策</a></span>
|
||||
<span>我已阅读并同意 <button type="button" onClick={() => setLegalDocument('terms')} className="cursor-pointer p-0 text-accent">用户条款</button> 和 <button type="button" onClick={() => setLegalDocument('privacy')} className="cursor-pointer p-0 text-accent">隐私政策</button></span>
|
||||
</label>
|
||||
<button type="submit" disabled={submitting || !agreed || (!username && !phone)}
|
||||
className="h-[50px] rounded-md bg-btn text-base font-medium text-white disabled:bg-btn-disabled">
|
||||
@@ -154,6 +163,29 @@ export function RegisterPage() {
|
||||
</button>
|
||||
</form>
|
||||
</main>
|
||||
<dialog
|
||||
ref={legalDialogRef}
|
||||
onClose={() => setLegalDocument(null)}
|
||||
className="m-auto h-[min(88dvh,800px)] w-[min(92vw,800px)] overflow-hidden rounded-md border border-border-panel bg-white p-0 shadow-xl backdrop:bg-black/50"
|
||||
aria-label={legalDocument === 'privacy' ? '隐私政策' : '用户条款'}
|
||||
>
|
||||
<div className="flex h-full min-h-0 flex-col">
|
||||
<div className="flex h-14 shrink-0 items-center justify-between border-b border-border-panel px-5">
|
||||
<h2 className="m-0 text-base font-semibold text-text-title">{legalDocument === 'privacy' ? '隐私政策' : '用户条款'}</h2>
|
||||
<button type="button" onClick={() => legalDialogRef.current?.close()} aria-label="关闭协议弹窗" title="关闭"
|
||||
className="grid h-9 w-9 place-items-center text-text-secondary hover:text-text-title">
|
||||
<Icon name="close" className="text-[20px]" />
|
||||
</button>
|
||||
</div>
|
||||
{legalDocument && <iframe
|
||||
key={legalDocument}
|
||||
title={legalDocument === 'privacy' ? '隐私政策正文' : '用户条款正文'}
|
||||
src={`${legalOrigin}/legal/${legalDocument === 'privacy' ? 'privacy-policy' : 'user-terms'}`}
|
||||
referrerPolicy="no-referrer"
|
||||
className="min-h-0 w-full flex-1 border-0 bg-white"
|
||||
/>}
|
||||
</div>
|
||||
</dialog>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user