From a71b50fa212722451ec4abb6b1dd83d3eed7db31 Mon Sep 17 00:00:00 2001 From: barshathakuri Date: Wed, 23 Oct 2024 16:23:25 +0545 Subject: [PATCH] Add my subscription page --- src/App/routes/index.tsx | 49 ++++++ src/components/Navbar/i18n.json | 4 +- src/components/Navbar/index.tsx | 6 + src/views/Home/AlertsMap/i18n.json | 3 +- src/views/Home/AlertsMap/index.tsx | 34 ++-- src/views/Home/AlertsMap/styles.module.css | 25 +-- src/views/Home/AlertsTable/i18n.json | 3 +- src/views/Home/AlertsTable/index.tsx | 34 ++-- .../SubscriptionActions/i18n.json | 8 + .../SubscriptionActions/index.tsx | 50 ++++++ .../SubscriptionDetail/index.tsx | 45 ++++++ .../SubscriptionDetail/styles.module.css | 19 +++ .../ActiveSubscription/index.tsx | 90 +++++++++++ .../ActiveSubscription/styles.module.css | 7 + .../SubscriptionActions/i18n.json | 7 + .../SubscriptionActions/index.tsx | 43 +++++ .../SubscriptionDetail/index.tsx | 38 +++++ .../SubscriptionDetail/styles.module.css | 10 ++ .../ArchiveSubscription/index.tsx | 75 +++++++++ .../ArchiveSubscription/styles.module.css | 7 + src/views/MySubscription/i18n.json | 11 ++ src/views/MySubscription/index.tsx | 150 ++++++++++++++++++ src/views/MySubscription/styles.module.css | 13 ++ 23 files changed, 698 insertions(+), 33 deletions(-) create mode 100644 src/views/MySubscription/ActiveSubscription/SubscriptionDetail/SubscriptionActions/i18n.json create mode 100644 src/views/MySubscription/ActiveSubscription/SubscriptionDetail/SubscriptionActions/index.tsx create mode 100644 src/views/MySubscription/ActiveSubscription/SubscriptionDetail/index.tsx create mode 100644 src/views/MySubscription/ActiveSubscription/SubscriptionDetail/styles.module.css create mode 100644 src/views/MySubscription/ActiveSubscription/index.tsx create mode 100644 src/views/MySubscription/ActiveSubscription/styles.module.css create mode 100644 src/views/MySubscription/ArchiveSubscription/SubscriptionDetail/SubscriptionActions/i18n.json create mode 100644 src/views/MySubscription/ArchiveSubscription/SubscriptionDetail/SubscriptionActions/index.tsx create mode 100644 src/views/MySubscription/ArchiveSubscription/SubscriptionDetail/index.tsx create mode 100644 src/views/MySubscription/ArchiveSubscription/SubscriptionDetail/styles.module.css create mode 100644 src/views/MySubscription/ArchiveSubscription/index.tsx create mode 100644 src/views/MySubscription/ArchiveSubscription/styles.module.css create mode 100644 src/views/MySubscription/i18n.json create mode 100644 src/views/MySubscription/index.tsx create mode 100644 src/views/MySubscription/styles.module.css diff --git a/src/App/routes/index.tsx b/src/App/routes/index.tsx index c6c6b483..a0039b37 100644 --- a/src/App/routes/index.tsx +++ b/src/App/routes/index.tsx @@ -57,6 +57,20 @@ const homeLayout = customWrapRoute({ }, }); +const mySubscription = customWrapRoute({ + parent: rootLayout, + path: 'subscription', + component: { + render: () => import('#views/MySubscription'), + props: {}, + }, + context: { + title: 'My Subscription', + // TODO: Change visibility after login feature + visibility: 'anything', + }, +}); + const homeIndex = customWrapRoute({ parent: homeLayout, index: true, @@ -74,6 +88,38 @@ const homeIndex = customWrapRoute({ }, }); +const historicalAlerts = customWrapRoute({ + parent: homeLayout, + path: 'map' satisfies DefaultHomeChild, + component: { + render: () => import('#views/Home'), + props: {}, + }, + context: { + title: 'Historical Alerts', + // TODO: Change visibility after login feature + visibility: 'anything', + }, +}); + +const myPastAlerts = customWrapRoute({ + parent: homeLayout, + index: true, + component: { + eagerLoad: true, + render: Navigate, + props: { + to: 'MySubscription', + replace: true, + }, + }, + context: { + title: 'My Past Alerts', + // TODO: Change visibility after login feature + visibility: 'anything', + }, +}); + const homeMap = customWrapRoute({ parent: homeLayout, path: 'map' satisfies DefaultHomeChild, @@ -190,6 +236,9 @@ const wrappedRoutes = { allSourcesFeeds, about, pageNotFound, + historicalAlerts, + mySubscription, + myPastAlerts, }; export const unwrappedRoutes = unwrapRoute(Object.values(wrappedRoutes)); diff --git a/src/components/Navbar/i18n.json b/src/components/Navbar/i18n.json index 78595b24..f16c6b95 100644 --- a/src/components/Navbar/i18n.json +++ b/src/components/Navbar/i18n.json @@ -6,6 +6,8 @@ "appAbout": "About", "appResources": "Resources", "headerMenuHome": "Home", - "headerMenuMySubscription": "My Subscription" + "headerMenuMySubscription": "My Subscription", + "headerMenuHistoricalAlerts": "Historical Alerts", + "headerMenuMyPastAlerts": "My Past Alerts" } } diff --git a/src/components/Navbar/index.tsx b/src/components/Navbar/index.tsx index e095a6af..53bec7a3 100644 --- a/src/components/Navbar/index.tsx +++ b/src/components/Navbar/index.tsx @@ -81,9 +81,15 @@ function Navbar(props: Props) { > {strings.headerMenuHome} + + {strings.headerMenuMySubscription} + ); } + export default Navbar; diff --git a/src/views/Home/AlertsMap/i18n.json b/src/views/Home/AlertsMap/i18n.json index 64c9deea..dcca6882 100644 --- a/src/views/Home/AlertsMap/i18n.json +++ b/src/views/Home/AlertsMap/i18n.json @@ -6,6 +6,7 @@ "ongoingAlertCountries": "Ongoing Alert Countries", "backToAlertsLabel": "Back to Alerts", "alertViewDetails": "View Details", - "alertInfo": "The IFRC AlertHub shows current warnings from official alerting agencies. These warnings have a start time (when the event might happen) and an end time (when it's expected to be over). The IFRC Alert Hub shows warnings that are happening right now (their start time has already passed) but aren't finished yet (their end time hasn't come yet)." + "alertInfo": "The IFRC AlertHub shows current warnings from official alerting agencies. These warnings have a start time (when the event might happen) and an end time (when it's expected to be over). The IFRC Alert Hub shows warnings that are happening right now (their start time has already passed) but aren't finished yet (their end time hasn't come yet).", + "alertNewSubscription": "New Subscription" } } diff --git a/src/views/Home/AlertsMap/index.tsx b/src/views/Home/AlertsMap/index.tsx index 0154322c..c335fb02 100644 --- a/src/views/Home/AlertsMap/index.tsx +++ b/src/views/Home/AlertsMap/index.tsx @@ -7,7 +7,10 @@ import { gql, useQuery, } from '@apollo/client'; -import { ChevronRightLineIcon } from '@ifrc-go/icons'; +import { + AddLineIcon, + ChevronRightLineIcon, +} from '@ifrc-go/icons'; import { Container, InfoPopup, @@ -185,15 +188,26 @@ export function Component() { withHeaderBorder childrenContainerClassName={styles.mainContent} actions={( - - )} - > - {strings.mapViewAllSources} - +
+ + )} + > + {strings.alertNewSubscription} + + + )} + > + {strings.mapViewAllSources} + +
)} overlayPending pending={countryListLoading} diff --git a/src/views/Home/AlertsMap/styles.module.css b/src/views/Home/AlertsMap/styles.module.css index d3a908c3..2676274d 100644 --- a/src/views/Home/AlertsMap/styles.module.css +++ b/src/views/Home/AlertsMap/styles.module.css @@ -36,16 +36,21 @@ } } - .sources { + .links { display: flex; - align-items: center; - text-decoration: none; - color: var(--go-ui-color-text); - font-weight: var(--go-ui-font-weight-medium); - } - - .sources:hover { - text-decoration: underline; - color: var(--go-ui-color-primary-red); + gap: var(--go-ui-spacing-lg); + + .sources { + display: flex; + align-items: center; + text-decoration: none; + color: var(--go-ui-color-text); + font-weight: var(--go-ui-font-weight-medium); + } + + .sources:hover { + text-decoration: underline; + color: var(--go-ui-color-primary-red); + } } } \ No newline at end of file diff --git a/src/views/Home/AlertsTable/i18n.json b/src/views/Home/AlertsTable/i18n.json index c578ebe0..67cf3300 100644 --- a/src/views/Home/AlertsTable/i18n.json +++ b/src/views/Home/AlertsTable/i18n.json @@ -10,6 +10,7 @@ "alertTableAdminsTitle":"Admin1s", "alertTableSentLabel":"Sent", "tableViewAllSources": "View All Sources", - "alertInfo": "The IFRC AlertHub shows current warnings from official alerting agencies. These warnings have a start time (when the event might happen) and an end time (when it's expected to be over). The IFRC Alert Hub shows warnings that are happening right now (their start time has already passed) but aren't finished yet (their end time hasn't come yet)." + "alertInfo": "The IFRC AlertHub shows current warnings from official alerting agencies. These warnings have a start time (when the event might happen) and an end time (when it's expected to be over). The IFRC Alert Hub shows warnings that are happening right now (their start time has already passed) but aren't finished yet (their end time hasn't come yet).", + "alertNewSubscription": "New Subscription" } } diff --git a/src/views/Home/AlertsTable/index.tsx b/src/views/Home/AlertsTable/index.tsx index e9b12766..05a5218f 100644 --- a/src/views/Home/AlertsTable/index.tsx +++ b/src/views/Home/AlertsTable/index.tsx @@ -9,7 +9,10 @@ import { gql, useQuery, } from '@apollo/client'; -import { ChevronRightLineIcon } from '@ifrc-go/icons'; +import { + AddLineIcon, + ChevronRightLineIcon, +} from '@ifrc-go/icons'; import { Container, DateOutput, @@ -286,15 +289,26 @@ export function Component() { withHeaderBorder withGridViewInFilter actions={( - - )} - > - {strings.tableViewAllSources} - +
+ + )} + > + {strings.alertNewSubscription} + + + )} + > + {strings.tableViewAllSources} + +
)} overlayPending pending={alertInfoLoading} diff --git a/src/views/MySubscription/ActiveSubscription/SubscriptionDetail/SubscriptionActions/i18n.json b/src/views/MySubscription/ActiveSubscription/SubscriptionDetail/SubscriptionActions/i18n.json new file mode 100644 index 00000000..b48fd972 --- /dev/null +++ b/src/views/MySubscription/ActiveSubscription/SubscriptionDetail/SubscriptionActions/i18n.json @@ -0,0 +1,8 @@ +{ + "namespace": "SubscriptionActions", + "strings": { + "archiveSubscriptionActions": "Archive", + "deleteSubscriptionActions": "Delete", + "editSubscriptionActions": "Edit" + } +} diff --git a/src/views/MySubscription/ActiveSubscription/SubscriptionDetail/SubscriptionActions/index.tsx b/src/views/MySubscription/ActiveSubscription/SubscriptionDetail/SubscriptionActions/index.tsx new file mode 100644 index 00000000..38e75bed --- /dev/null +++ b/src/views/MySubscription/ActiveSubscription/SubscriptionDetail/SubscriptionActions/index.tsx @@ -0,0 +1,50 @@ +import { MoreOptionsIcon } from '@ifrc-go/icons'; +import { DropdownMenu } from '@ifrc-go/ui'; +import { useTranslation } from '@ifrc-go/ui/hooks'; + +import DropdownMenuItem from '#components/DropdownMenuItem'; + +interface Props { + onSubscriptionDelete: () => void; + onSubscriptionArchive: () => void; +} + +function SubscriptionActions(props: Props) { + const { + onSubscriptionDelete, + onSubscriptionArchive, + } = props; + + const strings = useTranslation(i18n); + + return ( + } + variant="tertiary" + withoutDropdownIcon + > + + {strings.archiveSubscriptionActions} + + + {strings.editSubscriptionActions} + + + {strings.deleteSubscriptionActions} + + + ); +} + +export default SubscriptionActions; diff --git a/src/views/MySubscription/ActiveSubscription/SubscriptionDetail/index.tsx b/src/views/MySubscription/ActiveSubscription/SubscriptionDetail/index.tsx new file mode 100644 index 00000000..c17e49f2 --- /dev/null +++ b/src/views/MySubscription/ActiveSubscription/SubscriptionDetail/index.tsx @@ -0,0 +1,45 @@ +import { Container } from '@ifrc-go/ui'; + +import SubscriptionActions from './SubscriptionActions'; + +import styles from './styles.module.css'; + +interface Props { + data: any; + onDelete: () => void; + onArchive: () => void; +} + +function SubscriptionDetail(props: Props) { + const { + data, + onDelete, + onArchive, + } = props; + + return ( + +
+
+ {data.alertName} +
+
+ ( + {data.totalAlertCount} + ) + +
+
+
+ {data.filtersApplied} +
+
+ ); +} + +export default SubscriptionDetail; diff --git a/src/views/MySubscription/ActiveSubscription/SubscriptionDetail/styles.module.css b/src/views/MySubscription/ActiveSubscription/SubscriptionDetail/styles.module.css new file mode 100644 index 00000000..97694a0c --- /dev/null +++ b/src/views/MySubscription/ActiveSubscription/SubscriptionDetail/styles.module.css @@ -0,0 +1,19 @@ +.subscription-detail { + padding: var(--go-ui-spacing-lg); + background-color: var(--go-ui-color-gray-20); + + .subscription-filters { + display: flex; + gap: var(--go-ui-spacing-lg); + justify-content: space-between; + + .alert-name { + font-weight: bold; + } + } + + .filter-applied { + display: flex; + gap: var(--go-ui-spacing-lg); + } +} \ No newline at end of file diff --git a/src/views/MySubscription/ActiveSubscription/index.tsx b/src/views/MySubscription/ActiveSubscription/index.tsx new file mode 100644 index 00000000..0e546f2d --- /dev/null +++ b/src/views/MySubscription/ActiveSubscription/index.tsx @@ -0,0 +1,90 @@ +import { + useCallback, + useState, +} from 'react'; +import { + Container, + List, +} from '@ifrc-go/ui'; +import { isNotDefined } from '@togglecorp/fujs'; + +import SubscriptionDetail from './SubscriptionDetail'; + +import styles from './styles.module.css'; + +function ActiveTable() { + const [data, setData] = useState([ + { + id: 1, + alertName: 'Flood', + filtersApplied: [ + 'North America', + 'America', + 'Critical', + ], + totalAlertCount: 150, + }, + { + id: 2, + alertName: 'Landslide', + filtersApplied: [ + 'Europe', + 'France', + 'Warning', + ], + totalAlertCount: 80, + }, + { + id: 3, + alertName: 'High tides', + filtersApplied: [ + 'Asia-Pacific', + 'Nepal', + 'Critical', + ], + totalAlertCount: 200, + }, + ]); + + const handleDelete = useCallback((id: any) => { + setData((prevData) => prevData.filter((item) => item.id !== id)); + }, []); + + const handleArchive = useCallback((id: any) => { + setData((prevActiveData) => { + const itemToArchive = prevActiveData.find((item) => item.id === id); + if (isNotDefined(itemToArchive)) return prevActiveData; + setData((prevArchivedData) => [...prevArchivedData, itemToArchive]); + return prevActiveData.filter((item) => item.id !== id); + }); + }, []); + + const rendererParams = useCallback((_: string, value: any) => ({ + data: value, + onDelete: () => handleDelete(value.id), + onArchive: () => handleArchive(value.id), + }), [ + handleDelete, + handleArchive, + ]); + + return ( + + data.id} + filtered={false} + pending={false} + errored={false} + /> + + ); +} + +export default ActiveTable; diff --git a/src/views/MySubscription/ActiveSubscription/styles.module.css b/src/views/MySubscription/ActiveSubscription/styles.module.css new file mode 100644 index 00000000..8de430e2 --- /dev/null +++ b/src/views/MySubscription/ActiveSubscription/styles.module.css @@ -0,0 +1,7 @@ +.active-subscription { + .subscription { + display: flex; + flex-direction: column; + gap: var(--go-ui-spacing-lg); + } +} \ No newline at end of file diff --git a/src/views/MySubscription/ArchiveSubscription/SubscriptionDetail/SubscriptionActions/i18n.json b/src/views/MySubscription/ArchiveSubscription/SubscriptionDetail/SubscriptionActions/i18n.json new file mode 100644 index 00000000..cd2fa016 --- /dev/null +++ b/src/views/MySubscription/ArchiveSubscription/SubscriptionDetail/SubscriptionActions/i18n.json @@ -0,0 +1,7 @@ +{ + "namespace": "SubscriptionActions", + "strings": { + "unarchiveSubscriptionActions": "Unarchive", + "deleteSubscriptionActions": "Delete" + } +} diff --git a/src/views/MySubscription/ArchiveSubscription/SubscriptionDetail/SubscriptionActions/index.tsx b/src/views/MySubscription/ArchiveSubscription/SubscriptionDetail/SubscriptionActions/index.tsx new file mode 100644 index 00000000..aec8c70b --- /dev/null +++ b/src/views/MySubscription/ArchiveSubscription/SubscriptionDetail/SubscriptionActions/index.tsx @@ -0,0 +1,43 @@ +import { MoreOptionsIcon } from '@ifrc-go/icons'; +import { DropdownMenu } from '@ifrc-go/ui'; +import { useTranslation } from '@ifrc-go/ui/hooks'; + +import DropdownMenuItem from '#components/DropdownMenuItem'; + +import i18n from './i18n.json'; + +interface Props { + onSubscriptionDelete: () => void; +} + +function SubscriptionActions(props: Props) { + const { + onSubscriptionDelete, + } = props; + + const strings = useTranslation(i18n); + + return ( + } + variant="tertiary" + withoutDropdownIcon + > + + {strings.unarchiveSubscriptionActions} + + + {strings.deleteSubscriptionActions} + + + ); +} + +export default SubscriptionActions; diff --git a/src/views/MySubscription/ArchiveSubscription/SubscriptionDetail/index.tsx b/src/views/MySubscription/ArchiveSubscription/SubscriptionDetail/index.tsx new file mode 100644 index 00000000..a0371b1b --- /dev/null +++ b/src/views/MySubscription/ArchiveSubscription/SubscriptionDetail/index.tsx @@ -0,0 +1,38 @@ +import { Container } from '@ifrc-go/ui'; + +import SubscriptionActions from './SubscriptionActions'; + +import styles from './styles.module.css'; + +interface Props { + data: any; + onDelete: () => void; +} + +function SubscriptionDetail(props: Props) { + const { + data, + onDelete, + } = props; + + return ( + +
+ {data.alertName} +
+
+ ( + {data.totalAlertCount} + ) + +
+
+ ); +} + +export default SubscriptionDetail; diff --git a/src/views/MySubscription/ArchiveSubscription/SubscriptionDetail/styles.module.css b/src/views/MySubscription/ArchiveSubscription/SubscriptionDetail/styles.module.css new file mode 100644 index 00000000..7d547716 --- /dev/null +++ b/src/views/MySubscription/ArchiveSubscription/SubscriptionDetail/styles.module.css @@ -0,0 +1,10 @@ +.subscription-detail { + padding: var(--go-ui-spacing-lg); + background-color: var(--go-ui-color-gray-20); + + .subscription-filters { + display: flex; + gap: var(--go-ui-spacing-lg); + justify-content: space-between; + } +} \ No newline at end of file diff --git a/src/views/MySubscription/ArchiveSubscription/index.tsx b/src/views/MySubscription/ArchiveSubscription/index.tsx new file mode 100644 index 00000000..e4ebd07a --- /dev/null +++ b/src/views/MySubscription/ArchiveSubscription/index.tsx @@ -0,0 +1,75 @@ +import { + useCallback, + useState, +} from 'react'; +import { + Container, + List, +} from '@ifrc-go/ui'; + +import SubscriptionDetail from './SubscriptionDetail'; + +import styles from './styles.module.css'; + +function ArchiveTable() { + const [data, setData] = useState([ + { + id: 1, + alertName: 'Forest Fire', + filtersApplied: { + region: 'North America', + severity: 'Critical', + }, + totalAlertCount: 150, + }, + { + id: 2, + alertName: 'Earthquake', + filtersApplied: { + region: 'Europe', + severity: 'Warning', + }, + totalAlertCount: 80, + }, + { + id: 3, + alertName: 'High Wind', + filtersApplied: { + region: 'Asia-Pacific', + severity: 'Critical', + }, + totalAlertCount: 200, + }, + ]); + + const handleDelete = useCallback((id: any) => { + setData((prevData) => prevData.filter((item) => item.id !== id)); + }, []); + + const rendererParams = useCallback((_: string, value: any) => ({ + data: value, + onDelete: () => handleDelete(value.id), + }), [ + handleDelete, + ]); + + return ( + + data.id} + filtered={false} + pending={false} + errored={false} + /> + + ); +} + +export default ArchiveTable; diff --git a/src/views/MySubscription/ArchiveSubscription/styles.module.css b/src/views/MySubscription/ArchiveSubscription/styles.module.css new file mode 100644 index 00000000..f0d16cb3 --- /dev/null +++ b/src/views/MySubscription/ArchiveSubscription/styles.module.css @@ -0,0 +1,7 @@ +.archive-subscription { + .subscription { + display: flex; + flex-direction: column; + gap: var(--go-ui-spacing-lg); + } +} \ No newline at end of file diff --git a/src/views/MySubscription/i18n.json b/src/views/MySubscription/i18n.json new file mode 100644 index 00000000..dd163098 --- /dev/null +++ b/src/views/MySubscription/i18n.json @@ -0,0 +1,11 @@ +{ + "namespace": "mySubscription", + "strings": { + "mySubscription": "My Subscription", + "myNewSubscription": "New Subscription", + "createNewSubscription": "Create", + "sendViaEmailLabel": "Send via email", + "activeSubscriptionsTab": "Active Subscriptions", + "archivedSubscriptionTab": "Archive Subscriptions" + } +} \ No newline at end of file diff --git a/src/views/MySubscription/index.tsx b/src/views/MySubscription/index.tsx new file mode 100644 index 00000000..aeb1c759 --- /dev/null +++ b/src/views/MySubscription/index.tsx @@ -0,0 +1,150 @@ +import { useState } from 'react'; +import { AddLineIcon } from '@ifrc-go/icons'; +import { + Button, + Checkbox, + Container, + Modal, + RadioInput, + Tab, + TabList, + TabPanel, + Tabs, + TextInput, +} from '@ifrc-go/ui'; +import { useTranslation } from '@ifrc-go/ui/hooks'; + +import Link from '#components/Link'; +import Page from '#components/Page'; + +import ActiveSubscription from './ActiveSubscription'; +import ArchiveSubscription from './ArchiveSubscription'; + +import i18n from './i18n.json'; +import styles from './styles.module.css'; + +// eslint-disable-next-line import/prefer-default-export +export function Component() { + const strings = useTranslation(i18n); + + type TabKey = 'active' | 'archive'; + const [activeTab, setActiveTab] = useState('active'); + const [isModalOpen, setModalOpen] = useState(false); + const [isCheckboxChecked, setCheckboxChecked] = useState(false); + const [selectedValue, setSelectedValue] = useState('daily'); + const [alertTitle, setAlertTitle] = useState(''); + + const openModal = () => setModalOpen(true); + + const closeModal = () => setModalOpen(false); + + const handleCheckboxChange = (checked: any) => { + setCheckboxChecked(checked); + }; + + const handleRadioChange = (newValue: any) => { + setSelectedValue(newValue); + }; + + const handleInputChange = (event: any) => { + setAlertTitle(event.target.value); + }; + + return ( + + + )} + > + {strings.myNewSubscription} + + )} + > + {isModalOpen && ( + + {strings.createNewSubscription} + + )} + footerContentClassName={styles.createButton} + contentViewType="vertical" + spacing="comfortable" + onClose={closeModal} + > + + + option.value} + labelSelector={(option) => option.label} + value={selectedValue} + onChange={handleRadioChange} + disabled={!isCheckboxChecked} + /> + + )} + + + + {strings.activeSubscriptionsTab} + + + {strings.archivedSubscriptionTab} + + + + + + + + + + + + ); +} +Component.displayName = 'MySubscription'; diff --git a/src/views/MySubscription/styles.module.css b/src/views/MySubscription/styles.module.css new file mode 100644 index 00000000..036800bf --- /dev/null +++ b/src/views/MySubscription/styles.module.css @@ -0,0 +1,13 @@ +.mySubscription { + .content { + display: flex; + flex-direction: column; + gap: var(--go-ui-spacing-2xl); + + .create-button { + display: flex; + flex-direction: column; + align-items: flex-start; + } + } +}