Files
twenty_crm/packages/twenty-front/src/pages/settings/workspace/SettingsCustomDomain.tsx
Antoine Moreaux 92462b3ae5 feat(settings): review custom domain (#10393)
Introduce improved validation logic for custom domains, including regex
validation with descriptive error messages. Implement asynchronous
domain update functionality with a loading indicator and polling to
check record statuses. Refactor components to streamline functionality
and align with updated state management.

Fix https://github.com/twentyhq/core-team-issues/issues/453
2025-02-24 11:31:45 +01:00

84 lines
2.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 { H2Title, Section } from 'twenty-ui';
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';
const StyledDomainFormWrapper = styled.div`
align-items: center;
display: flex;
`;
const StyledRecordsWrapper = styled.div`
margin-top: ${({ theme }) => theme.spacing(2)};
& > :not(:first-of-type) {
margin-top: ${({ theme }) => theme.spacing(4)};
}
`;
export const SettingsCustomDomain = ({
handleSave,
}: {
handleSave: () => void;
}) => {
const { customDomainRecords, loading } = useRecoilValue(
customDomainRecordsState,
);
const currentWorkspace = useRecoilValue(currentWorkspaceState);
const { t } = useLingui();
const { control, handleSubmit } = useFormContext<{
customDomain: string;
}>();
return (
<Section>
<H2Title
title={t`Custom Domain`}
description={t`Set the name of your custom domain and configure your DNS records.`}
/>
<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}
onKeyDown={(e) => {
if (e.key === 'Enter') {
handleSubmit(handleSave);
}
}}
loading={!!loading}
fullWidth
/>
)}
/>
</StyledDomainFormWrapper>
{currentWorkspace?.customDomain && (
<StyledRecordsWrapper>
<SettingsCustomDomainRecordsStatus />
{customDomainRecords && (
<SettingsCustomDomainRecords
records={customDomainRecords.records}
/>
)}
</StyledRecordsWrapper>
)}
</Section>
);
};