Improve domain input loading
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import {useEffect, useState} from 'react';
|
import {useMemo} from 'react';
|
||||||
import {
|
import {
|
||||||
Alert,
|
Alert,
|
||||||
AlertDescription,
|
AlertDescription,
|
||||||
@@ -28,69 +28,40 @@ export function EmailDomainInput({value, onChange, id, placeholder, required, la
|
|||||||
const {activeProject} = useActiveProject();
|
const {activeProject} = useActiveProject();
|
||||||
const {domains, isLoading} = useDomains(activeProject?.id);
|
const {domains, isLoading} = useDomains(activeProject?.id);
|
||||||
|
|
||||||
// Split the email into local part and domain
|
// Get verified domains only - memoized to avoid re-creating on every render
|
||||||
const [localPart, setLocalPart] = useState('');
|
const verifiedDomains = useMemo(() => domains?.filter(d => d.verified) || [], [domains]);
|
||||||
const [selectedDomain, setSelectedDomain] = useState('');
|
|
||||||
|
|
||||||
// Get verified domains only
|
// Derive local state directly from the value prop
|
||||||
const verifiedDomains = domains?.filter(d => d.verified) || [];
|
const parsedEmail = useMemo(() => {
|
||||||
|
|
||||||
// Initialize from value
|
|
||||||
useEffect(() => {
|
|
||||||
if (value && value.includes('@')) {
|
if (value && value.includes('@')) {
|
||||||
const [local, domain] = value.split('@');
|
const [local, domain] = value.split('@');
|
||||||
|
return {localPart: local ?? '', domain: domain ?? ''};
|
||||||
setLocalPart(local ?? '');
|
|
||||||
|
|
||||||
// Check if the domain is in our verified list
|
|
||||||
const domainPart = domain ?? '';
|
|
||||||
const matchingDomain = verifiedDomains.find(d => d.domain === domainPart);
|
|
||||||
if (matchingDomain) {
|
|
||||||
setSelectedDomain(domainPart);
|
|
||||||
} else {
|
|
||||||
// If domain not verified, keep it in the domain field
|
|
||||||
|
|
||||||
setSelectedDomain(domainPart);
|
|
||||||
}
|
|
||||||
} else if (value) {
|
} else if (value) {
|
||||||
// If no @ sign, treat entire value as local part
|
return {localPart: value, domain: ''};
|
||||||
|
|
||||||
setLocalPart(value);
|
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
return {localPart: '', domain: ''};
|
||||||
}, [value]);
|
}, [value]);
|
||||||
|
|
||||||
// Initialize selected domain with first verified domain if none selected
|
// Use derived state for display, with fallback to first domain if none specified
|
||||||
useEffect(() => {
|
const displayDomain = parsedEmail.domain || (verifiedDomains.length > 0 ? verifiedDomains[0]!.domain : '');
|
||||||
if (!selectedDomain && verifiedDomains.length > 0) {
|
const displayLocalPart = parsedEmail.localPart;
|
||||||
const firstDomain = verifiedDomains[0];
|
|
||||||
if (firstDomain) {
|
|
||||||
setSelectedDomain(firstDomain.domain);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, [selectedDomain]);
|
|
||||||
|
|
||||||
// Update parent component when local part or domain changes
|
|
||||||
const handleUpdate = (newLocal: string, newDomain: string) => {
|
|
||||||
if (newLocal && newDomain) {
|
|
||||||
onChange(`${newLocal}@${newDomain}`);
|
|
||||||
} else if (newLocal) {
|
|
||||||
onChange(newLocal);
|
|
||||||
} else {
|
|
||||||
onChange('');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleLocalPartChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleLocalPartChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
const newLocal = e.target.value;
|
const newLocal = e.target.value;
|
||||||
setLocalPart(newLocal);
|
if (newLocal && displayDomain) {
|
||||||
handleUpdate(newLocal, selectedDomain);
|
onChange(`${newLocal}@${displayDomain}`);
|
||||||
|
} else {
|
||||||
|
onChange(newLocal);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDomainChange = (newDomain: string) => {
|
const handleDomainChange = (newDomain: string) => {
|
||||||
setSelectedDomain(newDomain);
|
if (displayLocalPart && newDomain) {
|
||||||
handleUpdate(localPart, newDomain);
|
onChange(`${displayLocalPart}@${newDomain}`);
|
||||||
|
} else if (displayLocalPart) {
|
||||||
|
onChange(displayLocalPart);
|
||||||
|
}
|
||||||
|
// If no local part, don't call onChange - wait for user to type something
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
@@ -142,14 +113,14 @@ export function EmailDomainInput({value, onChange, id, placeholder, required, la
|
|||||||
<Input
|
<Input
|
||||||
id={id}
|
id={id}
|
||||||
type="text"
|
type="text"
|
||||||
value={localPart}
|
value={displayLocalPart}
|
||||||
onChange={handleLocalPartChange}
|
onChange={handleLocalPartChange}
|
||||||
placeholder={placeholder || 'hello'}
|
placeholder={placeholder || 'hello'}
|
||||||
required={required}
|
required={required}
|
||||||
className="flex-1"
|
className="flex-1"
|
||||||
/>
|
/>
|
||||||
<span className="text-neutral-500">@</span>
|
<span className="text-neutral-500">@</span>
|
||||||
<Select value={selectedDomain} onValueChange={handleDomainChange} required={required}>
|
<Select value={displayDomain} onValueChange={handleDomainChange} required={required}>
|
||||||
<SelectTrigger className="w-[200px] shrink-0">
|
<SelectTrigger className="w-[200px] shrink-0">
|
||||||
<SelectValue />
|
<SelectValue />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
|
|||||||
Reference in New Issue
Block a user