Client:PortalSettings:OAuth2: show error on input blur

This commit is contained in:
Timofey Boyko 2023-12-05 17:41:30 +03:00
parent 20073c7158
commit 8b9c3af330
6 changed files with 67 additions and 114 deletions

View File

@ -26,6 +26,7 @@ interface BasicBlockProps {
isEdit: boolean;
errorFields: string[];
onBlur: (name: string) => void;
}
function getImageDimensions(
@ -74,6 +75,7 @@ const BasicBlock = ({
isEdit,
errorFields,
onBlur,
}: BasicBlockProps) => {
const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const target = e.target;
@ -144,6 +146,7 @@ const BasicBlock = ({
onChange={onChange}
isRequired
isError={errorFields.includes("name")}
onBlur={onBlur}
/>
<InputGroup
label={t("WebsiteUrl")}
@ -155,6 +158,7 @@ const BasicBlock = ({
disabled={isEdit}
isRequired
isError={errorFields.includes("website_url")}
onBlur={onBlur}
/>
<SelectGroup
label={t("AppIcon")}

View File

@ -35,6 +35,8 @@ interface InputGroupProps {
isRequired?: boolean;
isError?: boolean;
children?: React.ReactNode;
onBlur?: (name: string) => void;
}
const InputGroup = ({
@ -47,6 +49,7 @@ const InputGroup = ({
error,
onChange,
onBlur,
helpButtonText,
@ -110,6 +113,7 @@ const InputGroup = ({
iconName={withCopy ? CopyReactSvgUrl : null}
onIconClick={withCopy && onCopyClick}
type={isPassword ? "password" : "text"}
onBlur={() => onBlur?.(name)}
/>
)}
{buttonLabel && (

View File

@ -44,7 +44,7 @@ const MultiInputGroup = ({
isDisabled,
}: MultiInputGroupProps) => {
const [value, setValue] = React.useState("");
const timer = React.useRef<null | ReturnType<typeof setTimeout>>(null);
const [isError, setIsError] = React.useState(false);
const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
@ -53,23 +53,17 @@ const MultiInputGroup = ({
setValue(value);
};
React.useEffect(() => {
if (timer.current) {
clearTimeout(timer.current);
}
const onBlur = () => {
if (value) {
if (isValidUrl(value)) {
setIsError(false);
} else {
timer.current = setTimeout(() => {
setIsError(true);
}, 300);
setIsError(true);
}
} else {
setIsError(false);
}
}, [value]);
};
return (
<StyledInputGroup>
@ -94,6 +88,7 @@ const MultiInputGroup = ({
tabIndex={0}
maxLength={255}
isDisabled={isDisabled}
onBlur={onBlur}
/>
<SelectorAddButton
onClick={() => {

View File

@ -135,26 +135,29 @@ const ScopesBlock = ({
{t(`Common:${scope.read?.tKey}`)}
</Text>
)}
{/* @ts-ignore */}
<Text
className={"scope-desc"}
fontSize={"12px"}
fontWeight={400}
lineHeight={"16px"}
>
{/* @ts-ignore */}
<Text
className={"scope-desc"}
as={"span"}
fontSize={"12px"}
fontWeight={600}
lineHeight={"16px"}
>
{scope.write?.name}
</Text>{" "}
{t(`Common:${scope.write?.tKey}`)}
</Text>
{scope.write?.name && (
<>
{/* @ts-ignore */}
<Text
className={"scope-desc"}
fontSize={"12px"}
fontWeight={400}
lineHeight={"16px"}
>
{/* @ts-ignore */}
<Text
className={"scope-desc"}
as={"span"}
fontSize={"12px"}
fontWeight={600}
lineHeight={"16px"}
>
{scope.write?.name}
</Text>{" "}
{t(`Common:${scope.write?.tKey}`)}
</Text>
</>
)}
</StyledScopesName>
<StyledScopesCheckbox>
<Checkbox

View File

@ -14,6 +14,7 @@ interface SupportBlockProps {
isEdit: boolean;
errorFields: string[];
onBlur?: (name: string) => void;
}
const SupportBlock = ({
@ -25,6 +26,7 @@ const SupportBlock = ({
isEdit,
errorFields,
onBlur,
}: SupportBlockProps) => {
const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const target = e.target;
@ -47,6 +49,7 @@ const SupportBlock = ({
disabled={isEdit}
isRequired
isError={errorFields.includes("policy_url")}
onBlur={onBlur}
/>
<InputGroup
label={t("TermsOfServiceURL")}
@ -59,6 +62,7 @@ const SupportBlock = ({
disabled={isEdit}
isRequired
isError={errorFields.includes("terms_url")}
onBlur={onBlur}
/>
</StyledInputBlock>
</StyledBlock>

View File

@ -74,11 +74,6 @@ const ClientForm = ({
scopes: [],
});
const nameTimer = React.useRef<null | ReturnType<typeof setTimeout>>(null);
const websiteTimer = React.useRef<null | ReturnType<typeof setTimeout>>(null);
const policyTimer = React.useRef<null | ReturnType<typeof setTimeout>>(null);
const termsTimer = React.useRef<null | ReturnType<typeof setTimeout>>(null);
const [errorFields, setErrorFields] = React.useState<string[]>([]);
const { t } = useTranslation(["OAuth", "Common"]);
@ -193,8 +188,6 @@ const ClientForm = ({
} catch (e) {
setIsLoading(false);
console.log("11");
console.log(e);
}
}, [id, fetchScopes]);
@ -204,6 +197,28 @@ const ClientForm = ({
getClientData();
}, [getClientData, fetchScopes]);
const onBlur = (key: string) => {
if (
key === "name" &&
form[key] &&
!errorFields.includes(key) &&
(form[key].length < 3 || form[key].length > 256)
) {
setErrorFields((value) => {
return [...value, key];
});
} else if (
(key === "website_url" || key === "terms_url" || key === "policy_url") &&
form[key] &&
!errorFields.includes(key) &&
!isValidUrl(form[key])
) {
setErrorFields((value) => {
return [...value, key];
});
}
};
const compareAndValidate = () => {
let isValid = true;
@ -220,11 +235,9 @@ const ClientForm = ({
) {
isValid = false;
return (nameTimer.current = setTimeout(() => {
setErrorFields((value) => {
return [...value, key];
});
}, 300));
return setErrorFields((value) => {
return [...value, key];
});
}
if (
@ -234,8 +247,6 @@ const ClientForm = ({
setErrorFields((value) => {
return value.filter((n) => n !== key);
});
if (nameTimer.current) clearTimeout(nameTimer.current);
nameTimer.current = null;
return;
}
@ -265,20 +276,6 @@ const ClientForm = ({
case "name":
isValid = isValid && !!form[key];
if (
form[key] &&
!errorFields.includes(key) &&
(form[key].length < 3 || form[key].length > 256)
) {
isValid = false;
nameTimer.current = setTimeout(() => {
setErrorFields((value) => {
return [...value, key];
});
}, 300);
}
if (
errorFields.includes(key) &&
(!form[key] || (form[key].length > 2 && form[key].length < 256))
@ -286,8 +283,6 @@ const ClientForm = ({
setErrorFields((value) => {
return value.filter((n) => n !== key);
});
if (nameTimer.current) clearTimeout(nameTimer.current);
nameTimer.current = null;
}
isValid = isValid && !errorFields.includes(key);
@ -304,22 +299,6 @@ const ClientForm = ({
case "website_url":
isValid = isValid && !!form[key];
if (
form[key] &&
!errorFields.includes(key) &&
!isValidUrl(form[key])
) {
isValid = false;
websiteTimer.current = setTimeout(
() =>
setErrorFields((value) => {
return [...value, key];
}),
300
);
}
if (
errorFields.includes(key) &&
(!form[key] || isValidUrl(form[key]))
@ -327,8 +306,6 @@ const ClientForm = ({
setErrorFields((value) => {
return value.filter((n) => n !== key);
});
if (websiteTimer.current) clearTimeout(websiteTimer.current);
websiteTimer.current = null;
}
break;
@ -347,22 +324,6 @@ const ClientForm = ({
case "terms_url":
isValid = isValid && !!form[key];
if (
form[key] &&
!errorFields.includes(key) &&
!isValidUrl(form[key])
) {
isValid = false;
termsTimer.current = setTimeout(
() =>
setErrorFields((value) => {
return [...value, key];
}),
300
);
}
if (
errorFields.includes(key) &&
(!form[key] || isValidUrl(form[key]))
@ -370,30 +331,12 @@ const ClientForm = ({
setErrorFields((value) => {
return value.filter((n) => n !== key);
});
if (termsTimer.current) clearTimeout(termsTimer.current);
termsTimer.current = null;
}
break;
case "policy_url":
isValid = isValid && !!form[key];
if (
form[key] &&
!errorFields.includes(key) &&
!isValidUrl(form[key])
) {
isValid = false;
policyTimer.current = setTimeout(
() =>
setErrorFields((value) => {
return [...value, key];
}),
300
);
}
if (
errorFields.includes(key) &&
(!form[key] || isValidUrl(form[key]))
@ -401,8 +344,6 @@ const ClientForm = ({
setErrorFields((value) => {
return value.filter((n) => n !== key);
});
if (policyTimer.current) clearTimeout(policyTimer.current);
policyTimer.current = null;
}
break;
@ -439,6 +380,7 @@ const ClientForm = ({
changeValue={onChangeForm}
isEdit={isEdit}
errorFields={errorFields}
onBlur={onBlur}
/>
{isEdit && (
<ClientBlock
@ -469,6 +411,7 @@ const ClientForm = ({
changeValue={onChangeForm}
isEdit={isEdit}
errorFields={errorFields}
onBlur={onBlur}
/>
<ButtonsBlock
saveLabel={t("Common:SaveButton")}