diff --git a/packages/twenty-front/src/modules/accounts/types/Account.ts b/packages/twenty-front/src/modules/accounts/types/Account.ts index e432b12c36..d65ee24c18 100644 --- a/packages/twenty-front/src/modules/accounts/types/Account.ts +++ b/packages/twenty-front/src/modules/accounts/types/Account.ts @@ -1 +1,8 @@ -export type Account = { email: string; isSynced?: boolean; uuid: string }; +import { InboxSettingsVisibilityValue } from '@/settings/accounts/components/SettingsAccountsInboxSettingsVisibilitySection'; + +export type Account = { + email: string; + isSynced?: boolean; + uuid: string; + visibility: InboxSettingsVisibilityValue; +}; diff --git a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsInboxSettingsCardMedia.tsx b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsInboxSettingsCardMedia.tsx index 6d8987634a..cbf7f28d4f 100644 --- a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsInboxSettingsCardMedia.tsx +++ b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsInboxSettingsCardMedia.tsx @@ -3,10 +3,11 @@ import styled from '@emotion/styled'; const StyledCardMedia = styled.div` align-items: center; border: 2px solid ${({ theme }) => theme.border.color.medium}; - border-radius: ${({ theme }) => theme.border.radius.xs}; + border-radius: ${({ theme }) => theme.border.radius.sm}; color: ${({ theme }) => theme.font.color.light}; display: flex; flex-direction: column; + gap: ${({ theme }) => theme.spacing(0.5)}; height: ${({ theme }) => theme.spacing(8)}; justify-content: center; padding: ${({ theme }) => theme.spacing(0.5)}; diff --git a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsInboxSettingsVisibilitySection.tsx b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsInboxSettingsVisibilitySection.tsx new file mode 100644 index 0000000000..1a834edfc5 --- /dev/null +++ b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsInboxSettingsVisibilitySection.tsx @@ -0,0 +1,133 @@ +import styled from '@emotion/styled'; + +import { SettingsAccountsInboxSettingsCardMedia } from '@/settings/accounts/components/SettingsAccountsInboxSettingsCardMedia'; +import { H2Title } from '@/ui/display/typography/components/H2Title'; +import { Radio } from '@/ui/input/components/Radio'; +import { Card } from '@/ui/layout/card/components/Card'; +import { CardContent } from '@/ui/layout/card/components/CardContent'; +import { Section } from '@/ui/layout/section/components/Section'; + +export enum InboxSettingsVisibilityValue { + Everything = 'everything', + SubjectMetadata = 'subject-metadata', + Metadata = 'metadata', +} + +type SettingsAccountsInboxSettingsVisibilitySectionProps = { + onChange: (nextValue: InboxSettingsVisibilityValue) => void; + value?: InboxSettingsVisibilityValue; +}; + +const StyledCardContent = styled(CardContent)` + align-items: center; + display: flex; + gap: ${({ theme }) => theme.spacing(4)}; +`; + +const StyledCardMedia = styled(SettingsAccountsInboxSettingsCardMedia)` + align-items: stretch; +`; + +const StyledSubjectSkeleton = styled.div<{ isActive?: boolean }>` + background-color: ${({ isActive, theme }) => + isActive ? theme.accent.accent4060 : theme.background.quaternary}; + border-radius: 1px; + height: 3px; +`; + +const StyledMetadataSkeleton = styled(StyledSubjectSkeleton)` + margin-right: ${({ theme }) => theme.spacing(2)}; +`; + +const StyledBodySkeleton = styled(StyledSubjectSkeleton)` + border-radius: ${({ theme }) => theme.border.radius.xs}; + height: 22px; +`; + +const StyledTitle = styled.div` + color: ${({ theme }) => theme.font.color.primary}; + font-weight: ${({ theme }) => theme.font.weight.medium}; + margin-bottom: ${({ theme }) => theme.spacing(2)}; +`; + +const StyledDescription = styled.div` + color: ${({ theme }) => theme.font.color.tertiary}; + font-size: ${({ theme }) => theme.font.size.sm}; +`; + +const StyledRadio = styled(Radio)` + margin-left: auto; +`; + +const inboxSettingsVisibilityOptions = [ + { + title: 'Everything', + description: 'Subject, body and attachments will be shared with your team.', + value: InboxSettingsVisibilityValue.Everything, + visibleElements: { + metadata: true, + subject: true, + body: true, + }, + }, + { + title: 'Subject and metadata', + description: 'Subject and metadata will be shared with your team.', + value: InboxSettingsVisibilityValue.SubjectMetadata, + visibleElements: { + metadata: true, + subject: true, + body: false, + }, + }, + { + title: 'Metadata', + description: 'Timestamp and participants will be shared with your team.', + value: InboxSettingsVisibilityValue.Metadata, + visibleElements: { + metadata: true, + subject: false, + body: false, + }, + }, +]; + +export const SettingsAccountsInboxSettingsVisibilitySection = ({ + onChange, + value = InboxSettingsVisibilityValue.Everything, +}: SettingsAccountsInboxSettingsVisibilitySectionProps) => ( + + + + {inboxSettingsVisibilityOptions.map( + ( + { title, description, value: optionValue, visibleElements }, + index, + ) => ( + + + + + + + + {title} + {description} + + onChange(optionValue)} + checked={value === optionValue} + /> + + ), + )} + + +); diff --git a/packages/twenty-front/src/modules/ui/input/components/Radio.tsx b/packages/twenty-front/src/modules/ui/input/components/Radio.tsx index 9b577a6772..696759e3d7 100644 --- a/packages/twenty-front/src/modules/ui/input/components/Radio.tsx +++ b/packages/twenty-front/src/modules/ui/input/components/Radio.tsx @@ -38,7 +38,15 @@ const StyledRadioInput = styled(motion.input)` appearance: none; background-color: transparent; border: 1px solid ${({ theme }) => theme.font.color.secondary}; - border-radius: 50%; + border-radius: ${({ theme }) => theme.border.radius.rounded}; + height: ${({ 'radio-size': radioSize }) => + radioSize === RadioSize.Large ? '18px' : '16px'}; + margin: 0; + margin-left: 3px; + position: relative; + width: ${({ 'radio-size': radioSize }) => + radioSize === RadioSize.Large ? '18px' : '16px'}; + :hover { background-color: ${({ theme, checked }) => { if (!checked) { @@ -53,6 +61,7 @@ const StyledRadioInput = styled(motion.input)` return rgba(theme.color.blue, 0.12); }}; } + &:checked { background-color: ${({ theme }) => theme.color.blue}; border: none; @@ -70,15 +79,11 @@ const StyledRadioInput = styled(motion.input)` radioSize === RadioSize.Large ? '8px' : '6px'}; } } + &:disabled { cursor: not-allowed; opacity: 0.12; } - height: ${({ 'radio-size': radioSize }) => - radioSize === RadioSize.Large ? '18px' : '16px'}; - position: relative; - width: ${({ 'radio-size': radioSize }) => - radioSize === RadioSize.Large ? '18px' : '16px'}; `; type LabelProps = { @@ -99,26 +104,28 @@ const StyledLabel = styled.label` `; export type RadioProps = { - style?: React.CSSProperties; - className?: string; checked?: boolean; - value?: string; + className?: string; + disabled?: boolean; + label?: string; + labelPosition?: LabelPosition; onChange?: (event: React.ChangeEvent) => void; onCheckedChange?: (checked: boolean) => void; size?: RadioSize; - disabled?: boolean; - labelPosition?: LabelPosition; + style?: React.CSSProperties; + value?: string; }; export const Radio = ({ checked, - value, + className, + disabled = false, + label, + labelPosition = LabelPosition.Right, onChange, onCheckedChange, size = RadioSize.Small, - labelPosition = LabelPosition.Right, - disabled = false, - className, + value, }: RadioProps) => { const handleChange = (event: React.ChangeEvent) => { onChange?.(event); @@ -133,7 +140,7 @@ export const Radio = ({ name="input-radio" data-testid="input-radio" checked={checked} - value={value} + value={value || label} radio-size={size} disabled={disabled} onChange={handleChange} @@ -141,13 +148,13 @@ export const Radio = ({ animate={{ scale: checked ? 1.05 : 0.95 }} transition={{ type: 'spring', stiffness: 300, damping: 20 }} /> - {value && ( + {label && ( - {value} + {label} )} diff --git a/packages/twenty-front/src/modules/ui/input/components/__stories__/Radio.stories.tsx b/packages/twenty-front/src/modules/ui/input/components/__stories__/Radio.stories.tsx index d33ccdf4ef..3bf2f72ed4 100644 --- a/packages/twenty-front/src/modules/ui/input/components/__stories__/Radio.stories.tsx +++ b/packages/twenty-front/src/modules/ui/input/components/__stories__/Radio.stories.tsx @@ -16,7 +16,7 @@ type Story = StoryObj; export const Default: Story = { args: { - value: 'Radio', + label: 'Radio', checked: false, disabled: false, size: RadioSize.Small, @@ -26,10 +26,9 @@ export const Default: Story = { export const Catalog: CatalogStory = { args: { - value: 'Radio', + label: 'Radio', }, argTypes: { - value: { control: false }, size: { control: false }, }, parameters: { diff --git a/packages/twenty-front/src/pages/settings/accounts/SettingsAccountsEmailsInboxSettings.tsx b/packages/twenty-front/src/pages/settings/accounts/SettingsAccountsEmailsInboxSettings.tsx index 00ed41ac09..26fc458426 100644 --- a/packages/twenty-front/src/pages/settings/accounts/SettingsAccountsEmailsInboxSettings.tsx +++ b/packages/twenty-front/src/pages/settings/accounts/SettingsAccountsEmailsInboxSettings.tsx @@ -2,6 +2,10 @@ import { useEffect } from 'react'; import { useNavigate, useParams } from 'react-router-dom'; import { SettingsAccountsInboxSettingsSynchronizationSection } from '@/settings/accounts/components/SettingsAccountsInboxSettingsSynchronizationSection'; +import { + InboxSettingsVisibilityValue, + SettingsAccountsInboxSettingsVisibilitySection, +} from '@/settings/accounts/components/SettingsAccountsInboxSettingsVisibilitySection'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; import { AppPath } from '@/types/AppPath'; import { IconSettings } from '@/ui/display/icon'; @@ -20,9 +24,11 @@ export const SettingsAccountsEmailsInboxSettings = () => { if (!account) navigate(AppPath.NotFound); }, [account, navigate]); - const handleToggle = (_value: boolean) => {}; + if (!account) return null; - if (!account) return <>>; + const handleSynchronizationToggle = (_value: boolean) => {}; + + const handleVisibilityChange = (_value: InboxSettingsVisibilityValue) => {}; return ( @@ -36,7 +42,11 @@ export const SettingsAccountsEmailsInboxSettings = () => { /> + diff --git a/packages/twenty-front/src/testing/mock-data/accounts.ts b/packages/twenty-front/src/testing/mock-data/accounts.ts index 0e19d7ef10..aa6c7de18c 100644 --- a/packages/twenty-front/src/testing/mock-data/accounts.ts +++ b/packages/twenty-front/src/testing/mock-data/accounts.ts @@ -1,14 +1,17 @@ import { Account } from '@/accounts/types/Account'; +import { InboxSettingsVisibilityValue } from '@/settings/accounts/components/SettingsAccountsInboxSettingsVisibilitySection'; export const mockedAccounts: Account[] = [ { email: 'thomas@twenty.com', isSynced: true, uuid: '0794b782-f52e-48c3-977e-b0f57f90de24', + visibility: InboxSettingsVisibilityValue.Everything, }, { email: 'thomas@twenty.dev', isSynced: false, uuid: 'dc66a7ec-56b2-425b-a8e8-26ff0396c3aa', + visibility: InboxSettingsVisibilityValue.Metadata, }, ];