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({
)}
-
+
);
}