From 62fa55eae6f92661e9f3ef1a0912a30ce7871757 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tha=C3=AFs?= Date: Thu, 7 Dec 2023 12:43:38 +0100 Subject: [PATCH] feat: add Settings/Accounts Settings section (#2853) Closes #2818 --- .../SettingsAccountsSettingsSection.tsx | 43 ++++++++++ .../components/SettingsNavigationCard.tsx | 79 +++++++++++++++++++ .../SettingsObjectFieldTypeCard.tsx | 12 ++- .../components/SettingsObjectTypeCard.tsx | 6 +- .../components/SettingsObjectAboutSection.tsx | 6 +- front/src/modules/ui/display/icon/index.ts | 1 + .../ui/display/pill/components/SoonPill.tsx | 9 ++- .../ui/input/button/components/Button.tsx | 6 +- .../ui/layout/card/components/Card.tsx | 10 +++ .../components/__stories__/Card.stories.tsx | 13 +++ .../settings/accounts/SettingsAccounts.tsx | 2 + 11 files changed, 172 insertions(+), 15 deletions(-) create mode 100644 front/src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx create mode 100644 front/src/modules/settings/components/SettingsNavigationCard.tsx create mode 100644 front/src/modules/ui/layout/card/components/Card.tsx create mode 100644 front/src/modules/ui/layout/card/components/__stories__/Card.stories.tsx diff --git a/front/src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx b/front/src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx new file mode 100644 index 000000000..3c5337e65 --- /dev/null +++ b/front/src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx @@ -0,0 +1,43 @@ +import { useNavigate } from 'react-router-dom'; +import styled from '@emotion/styled'; + +import { SettingsNavigationCard } from '@/settings/components/SettingsNavigationCard'; +import { IconCalendarEvent, IconMailCog } from '@/ui/display/icon'; +import { H2Title } from '@/ui/display/typography/components/H2Title'; +import { Section } from '@/ui/layout/section/components/Section'; + +const StyledCardsContainer = styled.div` + display: flex; + gap: ${({ theme }) => theme.spacing(4)}; + margin-top: ${({ theme }) => theme.spacing(6)}; +`; + +export const SettingsAccountsSettingsSection = () => { + const navigate = useNavigate(); + + return ( +
+ + + navigate('/settings/accounts/emails')} + > + Set email visibility, manage your blocklist and more. + + + Configure and customize your calendar preferences. + + +
+ ); +}; diff --git a/front/src/modules/settings/components/SettingsNavigationCard.tsx b/front/src/modules/settings/components/SettingsNavigationCard.tsx new file mode 100644 index 000000000..0ec1dcf9b --- /dev/null +++ b/front/src/modules/settings/components/SettingsNavigationCard.tsx @@ -0,0 +1,79 @@ +import { ReactNode } from 'react'; +import { useTheme } from '@emotion/react'; +import styled from '@emotion/styled'; + +import { IconChevronRight } from '@/ui/display/icon'; +import { IconComponent } from '@/ui/display/icon/types/IconComponent'; +import { SoonPill } from '@/ui/display/pill/components/SoonPill'; +import { Card } from '@/ui/layout/card/components/Card'; + +type SettingsNavigationCardProps = { + children: ReactNode; + disabled?: boolean; + hasSoonPill?: boolean; + Icon: IconComponent; + onClick?: () => void; + title: string; +}; + +const StyledCard = styled(Card)<{ + disabled?: boolean; + onClick?: () => void; +}>` + color: ${({ theme }) => theme.font.color.tertiary}; + cursor: ${({ disabled, onClick }) => + disabled ? 'not-allowed' : onClick ? 'pointer' : 'default'}; + display: flex; + flex-direction: column; + gap: ${({ theme }) => theme.spacing(2)}; + padding-bottom: ${({ theme }) => theme.spacing(4)}; + padding-top: ${({ theme }) => theme.spacing(4)}; +`; + +const StyledHeader = styled.div` + align-items: center; + display: flex; + gap: ${({ theme }) => theme.spacing(3)}; +`; + +const StyledTitle = styled.div` + color: ${({ theme }) => theme.font.color.secondary}; + display: flex; + flex: 1 0 auto; + font-weight: ${({ theme }) => theme.font.weight.medium}; + gap: ${({ theme }) => theme.spacing(2)}; + justify-content: flex-start; +`; + +const StyledIconChevronRight = styled(IconChevronRight)` + color: ${({ theme }) => theme.font.color.light}; +`; + +const StyledDescription = styled.div` + padding-left: ${({ theme }) => theme.spacing(8)}; +`; + +export const SettingsNavigationCard = ({ + children, + disabled, + hasSoonPill, + Icon, + onClick, + title, +}: SettingsNavigationCardProps) => { + const theme = useTheme(); + + return ( + + + + + {title} + {hasSoonPill && } + + + + {children} + + ); +}; diff --git a/front/src/modules/settings/data-model/components/SettingsObjectFieldTypeCard.tsx b/front/src/modules/settings/data-model/components/SettingsObjectFieldTypeCard.tsx index c70d26b87..8bfeba2de 100644 --- a/front/src/modules/settings/data-model/components/SettingsObjectFieldTypeCard.tsx +++ b/front/src/modules/settings/data-model/components/SettingsObjectFieldTypeCard.tsx @@ -1,16 +1,16 @@ import { ReactNode } from 'react'; import styled from '@emotion/styled'; +import { Card } from '@/ui/layout/card/components/Card'; + type SettingsObjectFieldTypeCardProps = { className?: string; preview: ReactNode; form?: ReactNode; }; -const StyledPreviewContainer = styled.div` +const StyledPreviewContainer = styled(Card)` background-color: ${({ theme }) => theme.background.transparent.lighter}; - border: 1px solid ${({ theme }) => theme.border.color.medium}; - border-radius: ${({ theme }) => theme.border.radius.sm}; padding: ${({ theme }) => theme.spacing(4)}; &:not(:last-child) { @@ -32,14 +32,12 @@ const StyledPreviewContent = styled.div` gap: 6px; `; -const StyledFormContainer = styled.div` - background-color: ${({ theme }) => theme.background.secondary}; - border: 1px solid ${({ theme }) => theme.border.color.medium}; - border-radius: ${({ theme }) => theme.border.radius.sm}; +const StyledFormContainer = styled(Card)` border-top: 0; border-top-left-radius: 0; border-top-right-radius: 0; overflow: hidden; + padding: 0; `; export const SettingsObjectFieldTypeCard = ({ diff --git a/front/src/modules/settings/data-model/new-object/components/SettingsObjectTypeCard.tsx b/front/src/modules/settings/data-model/new-object/components/SettingsObjectTypeCard.tsx index c2ddf18c7..e31e8b48f 100644 --- a/front/src/modules/settings/data-model/new-object/components/SettingsObjectTypeCard.tsx +++ b/front/src/modules/settings/data-model/new-object/components/SettingsObjectTypeCard.tsx @@ -37,6 +37,10 @@ const StyledIconCheck = styled(IconCheck)` margin-left: auto; `; +const StyledSoonPill = styled(SoonPill)` + margin-left: auto; +`; + type SettingsObjectTypeCardProps = { prefixIcon?: React.ReactNode; title: string; @@ -68,7 +72,7 @@ export const SettingsObjectTypeCard = ({ > {prefixIcon} - {soon && } + {soon && } {!disabled && selected && } ); diff --git a/front/src/modules/settings/data-model/object-details/components/SettingsObjectAboutSection.tsx b/front/src/modules/settings/data-model/object-details/components/SettingsObjectAboutSection.tsx index 3e29adb18..6275782fb 100644 --- a/front/src/modules/settings/data-model/object-details/components/SettingsObjectAboutSection.tsx +++ b/front/src/modules/settings/data-model/object-details/components/SettingsObjectAboutSection.tsx @@ -6,6 +6,7 @@ import { Tag } from '@/ui/display/tag/components/Tag'; import { H2Title } from '@/ui/display/typography/components/H2Title'; import { LightIconButton } from '@/ui/input/button/components/LightIconButton'; import { useLazyLoadIcon } from '@/ui/input/hooks/useLazyLoadIcon'; +import { Card } from '@/ui/layout/card/components/Card'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; @@ -22,11 +23,8 @@ type SettingsAboutSectionProps = { onEdit: () => void; }; -const StyledCard = styled.div` +const StyledCard = styled(Card)` align-items: center; - background-color: ${({ theme }) => theme.background.secondary}; - border: ${({ theme }) => `1px solid ${theme.border.color.medium}`}; - border-radius: ${({ theme }) => theme.border.radius.sm}; display: flex; gap: ${({ theme }) => theme.spacing(2)}; padding: ${({ theme }) => theme.spacing(2)}; diff --git a/front/src/modules/ui/display/icon/index.ts b/front/src/modules/ui/display/icon/index.ts index 226df9746..09482ee94 100644 --- a/front/src/modules/ui/display/icon/index.ts +++ b/front/src/modules/ui/display/icon/index.ts @@ -60,6 +60,7 @@ export { IconList, IconLogout, IconMail, + IconMailCog, IconMap, IconMinus, IconMoneybag, diff --git a/front/src/modules/ui/display/pill/components/SoonPill.tsx b/front/src/modules/ui/display/pill/components/SoonPill.tsx index 2a6b43408..8e1393436 100644 --- a/front/src/modules/ui/display/pill/components/SoonPill.tsx +++ b/front/src/modules/ui/display/pill/components/SoonPill.tsx @@ -1,5 +1,9 @@ import styled from '@emotion/styled'; +type SoonPillProps = { + className?: string; +}; + const StyledSoonPill = styled.span` align-items: center; background: ${({ theme }) => theme.background.transparent.light}; @@ -13,8 +17,9 @@ const StyledSoonPill = styled.span` height: ${({ theme }) => theme.spacing(4)}; justify-content: flex-end; line-height: ${({ theme }) => theme.text.lineHeight.lg}; - margin-left: auto; padding: ${({ theme }) => `0 ${theme.spacing(2)}`}; `; -export const SoonPill = () => Soon; +export const SoonPill = ({ className }: SoonPillProps) => ( + Soon +); diff --git a/front/src/modules/ui/input/button/components/Button.tsx b/front/src/modules/ui/input/button/components/Button.tsx index 1eddaba13..b42157269 100644 --- a/front/src/modules/ui/input/button/components/Button.tsx +++ b/front/src/modules/ui/input/button/components/Button.tsx @@ -277,6 +277,10 @@ const StyledButton = styled.button< } `; +const StyledSoonPill = styled(SoonPill)` + margin-left: auto; +`; + export const Button = ({ className, Icon, @@ -307,7 +311,7 @@ export const Button = ({ > {Icon && } {title} - {soon && } + {soon && } ); }; diff --git a/front/src/modules/ui/layout/card/components/Card.tsx b/front/src/modules/ui/layout/card/components/Card.tsx new file mode 100644 index 000000000..745bdc678 --- /dev/null +++ b/front/src/modules/ui/layout/card/components/Card.tsx @@ -0,0 +1,10 @@ +import styled from '@emotion/styled'; + +const StyledCard = styled.div` + background-color: ${({ theme }) => theme.background.secondary}; + border: 1px solid ${({ theme }) => theme.border.color.medium}; + border-radius: ${({ theme }) => theme.border.radius.sm}; + padding: ${({ theme }) => theme.spacing(3)}; +`; + +export { StyledCard as Card }; diff --git a/front/src/modules/ui/layout/card/components/__stories__/Card.stories.tsx b/front/src/modules/ui/layout/card/components/__stories__/Card.stories.tsx new file mode 100644 index 000000000..ecff673a6 --- /dev/null +++ b/front/src/modules/ui/layout/card/components/__stories__/Card.stories.tsx @@ -0,0 +1,13 @@ +import { Meta, StoryObj } from '@storybook/react'; + +import { Card } from '../Card'; + +const meta: Meta = { + title: 'UI/Layout/Card/Card', + component: Card, +}; + +export default meta; +type Story = StoryObj; + +export const Default: Story = {}; diff --git a/front/src/pages/settings/accounts/SettingsAccounts.tsx b/front/src/pages/settings/accounts/SettingsAccounts.tsx index aca1c0706..101089050 100644 --- a/front/src/pages/settings/accounts/SettingsAccounts.tsx +++ b/front/src/pages/settings/accounts/SettingsAccounts.tsx @@ -1,3 +1,4 @@ +import { SettingsAccountsSettingsSection } from '@/settings/accounts/components/SettingsAccountsSettingsSection'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; import { IconSettings } from '@/ui/display/icon'; import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'; @@ -7,6 +8,7 @@ export const SettingsAccounts = () => ( + );