diff --git a/webui/src/pages/Setup.jsx b/webui/src/pages/Setup.jsx index 1ec3cb1..fd21c42 100644 --- a/webui/src/pages/Setup.jsx +++ b/webui/src/pages/Setup.jsx @@ -281,14 +281,20 @@ function Step2Domain({ const [picAvail, setPicAvail] = useState(null); // null|checking|available|taken|unknown const [cfStatus, setCfStatus] = useState(null); const [dnsStatus, setDnsStatus] = useState(null); + const [nextLoading, setNextLoading] = useState(false); const checkPicAvail = async name => { - if (!CELL_NAME_RE.test(name)) return; + if (!CELL_NAME_RE.test(name)) return null; setPicAvail('checking'); try { const res = await setupAPI.validate('pic_ngo_available', { cell_name: name }); - setPicAvail(res.data?.available ? 'available' : 'taken'); - } catch { setPicAvail('unknown'); } + const result = res.data?.available ? 'available' : 'taken'; + setPicAvail(result); + return result; + } catch { + setPicAvail('unknown'); + return 'unknown'; + } }; const verifyCf = async () => { @@ -307,11 +313,19 @@ function Step2Domain({ } catch { setDnsStatus('invalid'); } }; - const handleNext = () => { + const handleNext = async () => { const e = {}; if (domainType === 'pic_ngo') { - if (!picName) e.name = 'Subdomain is required.'; - else if (!CELL_NAME_RE.test(picName)) e.name = 'Lowercase letters, digits, hyphens. 2–31 chars, must start with a letter.'; + if (!picName) { + e.name = 'Subdomain is required.'; + } else if (!CELL_NAME_RE.test(picName)) { + e.name = 'Lowercase letters, digits, hyphens. 2–31 chars, must start with a letter.'; + } else if (picAvail !== 'available') { + setNextLoading(true); + const result = await checkPicAvail(picName); + setNextLoading(false); + if (result === 'taken') e.name = 'This subdomain is already taken. Choose another.'; + } } else if (domainType === 'cloudflare') { if (!customDomain || !DOMAIN_RE.test(customDomain)) e.domain = 'Enter a valid domain (e.g. home.example.com).'; if (!cloudflareToken.trim()) e.token = 'Cloudflare API token is required.'; @@ -441,7 +455,7 @@ function Step2Domain({ )} - + ); }