Files
twenty/packages/twenty-front/src/pages/settings/workspace/SettingsCustomDomain.tsx
Antoine Moreaux 8a2a004fb5 feat(settings): add domain validation effect and delete functionality (#11643)
Introduced a new effect component to validate custom domain DNS records
on mount, centralizing logic. Added a button to reset the custom domain
field, improving user control and form handling. Refactored related code
for maintainability and enhanced UI structure.

Fix https://github.com/twentyhq/core-team-issues/issues/853
2025-04-18 08:18:36 +00:00

112 lines
3.5 KiB
TypeScript

/* @license Enterprise */
import { TextInputV2 } from '@/ui/input/components/TextInputV2';
import styled from '@emotion/styled';
import { useLingui } from '@lingui/react/macro';
import { Controller, useFormContext } from 'react-hook-form';
import { SettingsCustomDomainRecords } from '~/pages/settings/workspace/SettingsCustomDomainRecords';
import { SettingsCustomDomainRecordsStatus } from '~/pages/settings/workspace/SettingsCustomDomainRecordsStatus';
import { customDomainRecordsState } from '~/pages/settings/workspace/states/customDomainRecordsState';
import { useRecoilValue } from 'recoil';
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { useCheckCustomDomainValidRecords } from '~/pages/settings/workspace/hooks/useCheckCustomDomainValidRecords';
import { Button, ButtonGroup } from 'twenty-ui/input';
import { H2Title, IconReload, IconTrash } from 'twenty-ui/display';
import { Section } from 'twenty-ui/layout';
import { CheckCustomDomainValidRecordsEffect } from '~/pages/settings/workspace/CheckCustomDomainValidRecordsEffect';
const StyledDomainFormWrapper = styled.div`
display: flex;
gap: ${({ theme }) => theme.spacing(2)};
`;
const StyledButtonGroup = styled(ButtonGroup)`
& > :not(:first-of-type) > button {
border-left: none;
}
`;
const StyledButton = styled(Button)`
align-self: flex-start;
`;
const StyledRecordsWrapper = styled.div`
margin-top: ${({ theme }) => theme.spacing(2)};
& > :not(:first-of-type) {
margin-top: ${({ theme }) => theme.spacing(4)};
}
`;
export const SettingsCustomDomain = () => {
const { customDomainRecords, isLoading } = useRecoilValue(
customDomainRecordsState,
);
const { checkCustomDomainRecords } = useCheckCustomDomainValidRecords();
const currentWorkspace = useRecoilValue(currentWorkspaceState);
const { t } = useLingui();
const { control, setValue, trigger } = useFormContext<{
customDomain: string;
}>();
const deleteCustomDomain = () => {
setValue('customDomain', '');
trigger();
};
return (
<Section>
<H2Title
title={t`Custom Domain`}
description={t`Set the name of your custom domain and configure your DNS records.`}
/>
<CheckCustomDomainValidRecordsEffect />
<StyledDomainFormWrapper>
<Controller
name="customDomain"
control={control}
render={({ field: { onChange, value }, fieldState: { error } }) => (
<TextInputV2
value={value}
type="text"
onChange={onChange}
placeholder="crm.yourdomain.com"
error={error?.message}
fullWidth
/>
)}
/>
<StyledButtonGroup>
<StyledButton
isLoading={isLoading}
Icon={IconReload}
title={t`Reload`}
variant="primary"
onClick={checkCustomDomainRecords}
type="button"
/>
<StyledButton
Icon={IconTrash}
variant="primary"
onClick={deleteCustomDomain}
type="button"
/>
</StyledButtonGroup>
</StyledDomainFormWrapper>
{currentWorkspace?.customDomain && (
<StyledRecordsWrapper>
<SettingsCustomDomainRecordsStatus />
{customDomainRecords && (
<SettingsCustomDomainRecords
records={customDomainRecords.records}
/>
)}
</StyledRecordsWrapper>
)}
</Section>
);
};