From d54d2a65560cb32ee317154d1751209f687d062d Mon Sep 17 00:00:00 2001 From: barshathakuri Date: Thu, 14 Nov 2024 16:29:41 +0545 Subject: [PATCH] Add subscription alert detail page --- src/App/routes/index.tsx | 17 ++- src/components/Badge/index.tsx | 21 +++ src/components/Badge/styles.module.css | 6 + .../ActiveTableActions/index.tsx | 10 +- .../ArchiveTableActions/index.tsx | 8 +- .../AlertInfoItem/i18n.json | 6 + .../AlertInfoItem/index.tsx | 43 ++++++ .../AlertInfoItem/styles.module.css | 4 + .../SubscriptionDetail/i18n.json | 9 ++ .../SubscriptionDetail/index.tsx | 140 ++++++++++++++++++ .../SubscriptionDetail/styles.module.css | 19 +++ .../SubscriptionTableItem/i18n.json | 6 + .../SubscriptionTableItem/index.tsx | 30 +++- .../SubscriptionTableItem/styles.module.css | 6 + src/views/MySubscription/common.tsx | 18 +++ src/views/MySubscription/i18n.json | 5 +- src/views/MySubscription/index.tsx | 4 +- src/views/NewSubscriptionModal/index.tsx | 3 +- src/views/Resources/i18n.json | 3 +- src/views/Resources/index.tsx | 1 + 20 files changed, 345 insertions(+), 14 deletions(-) create mode 100644 src/components/Badge/index.tsx create mode 100644 src/components/Badge/styles.module.css create mode 100644 src/views/MySubscription/SubscriptionDetail/AlertInfoItem/i18n.json create mode 100644 src/views/MySubscription/SubscriptionDetail/AlertInfoItem/index.tsx create mode 100644 src/views/MySubscription/SubscriptionDetail/AlertInfoItem/styles.module.css create mode 100644 src/views/MySubscription/SubscriptionDetail/i18n.json create mode 100644 src/views/MySubscription/SubscriptionDetail/index.tsx create mode 100644 src/views/MySubscription/SubscriptionDetail/styles.module.css create mode 100644 src/views/MySubscription/SubscriptionTableItem/i18n.json diff --git a/src/App/routes/index.tsx b/src/App/routes/index.tsx index e194c24..f0f856f 100644 --- a/src/App/routes/index.tsx +++ b/src/App/routes/index.tsx @@ -54,8 +54,20 @@ const mySubscription = customWrapRoute({ wrapperComponent: Auth, context: { title: 'My Subscriptions', - // TODO: Change visibility after login feature - visibility: 'anything', + visibility: 'is-authenticated', + }, +}); + +const subscriptionDetail = customWrapRoute({ + parent: rootLayout, + path: 'subscriptions/:subscriptionId', + component: { + render: () => import('#views/MySubscription/SubscriptionDetail'), + props: {}, + }, + context: { + title: 'Subscription Detail', + visibility: 'is-authenticated', }, }); @@ -277,6 +289,7 @@ const wrappedRoutes = { mySubscription, cookiePolicy, historicalAlerts, + subscriptionDetail, }; export const unwrappedRoutes = unwrapRoute(Object.values(wrappedRoutes)); diff --git a/src/components/Badge/index.tsx b/src/components/Badge/index.tsx new file mode 100644 index 0000000..52ec6a8 --- /dev/null +++ b/src/components/Badge/index.tsx @@ -0,0 +1,21 @@ +import { Container } from '@ifrc-go/ui'; + +import styles from './styles.module.css'; + +interface Props { + title: string; +} + +function Badge(props: Props) { + const { + title, + } = props; + + return ( + + {title} + + ); +} + +export default Badge; diff --git a/src/components/Badge/styles.module.css b/src/components/Badge/styles.module.css new file mode 100644 index 0000000..43bfb74 --- /dev/null +++ b/src/components/Badge/styles.module.css @@ -0,0 +1,6 @@ +.badge { + display: flex; + border-radius: 1em; + background-color: var(--go-ui-color-gray-20); + padding: var(--go-ui-spacing-2xs) var(--go-ui-spacing-sm); +} diff --git a/src/views/MySubscription/ActiveTableActions/index.tsx b/src/views/MySubscription/ActiveTableActions/index.tsx index 8073ab6..48feb20 100644 --- a/src/views/MySubscription/ActiveTableActions/index.tsx +++ b/src/views/MySubscription/ActiveTableActions/index.tsx @@ -1,4 +1,9 @@ -import { MoreOptionsIcon } from '@ifrc-go/icons'; +import { + DeleteBinSixLineIcon, + EditTwoLineIcon, + LayoutBottomLineIcon, + MoreOptionsIcon, +} from '@ifrc-go/icons'; import { DropdownMenu } from '@ifrc-go/ui'; import { useTranslation } from '@ifrc-go/ui/hooks'; @@ -19,12 +24,14 @@ function ActiveTableActions() { type="button" name="archive" onClick={undefined} + icons={} > {strings.archiveSubscriptionActions} } > {strings.editSubscriptionActions} @@ -32,6 +39,7 @@ function ActiveTableActions() { type="button" name="delete" onClick={undefined} + icons={} > {strings.deleteSubscriptionActions} diff --git a/src/views/MySubscription/ArchiveTableActions/index.tsx b/src/views/MySubscription/ArchiveTableActions/index.tsx index aec03ac..667f7dd 100644 --- a/src/views/MySubscription/ArchiveTableActions/index.tsx +++ b/src/views/MySubscription/ArchiveTableActions/index.tsx @@ -1,4 +1,8 @@ -import { MoreOptionsIcon } from '@ifrc-go/icons'; +import { + DeleteBinSixLineIcon, + LayoutBottomLineIcon, + MoreOptionsIcon, +} from '@ifrc-go/icons'; import { DropdownMenu } from '@ifrc-go/ui'; import { useTranslation } from '@ifrc-go/ui/hooks'; @@ -18,6 +22,7 @@ function ArchiveTableActions() { } > {strings.unarchiveSubscriptionActions} @@ -25,6 +30,7 @@ function ArchiveTableActions() { type="button" name="delete" onClick={undefined} + icons={} > {strings.deleteSubscriptionActions} diff --git a/src/views/MySubscription/SubscriptionDetail/AlertInfoItem/i18n.json b/src/views/MySubscription/SubscriptionDetail/AlertInfoItem/i18n.json new file mode 100644 index 0000000..cb92f61 --- /dev/null +++ b/src/views/MySubscription/SubscriptionDetail/AlertInfoItem/i18n.json @@ -0,0 +1,6 @@ +{ + "namespace": "alertInfo", + "strings": { + "alertInfoView": "View" + } +} \ No newline at end of file diff --git a/src/views/MySubscription/SubscriptionDetail/AlertInfoItem/index.tsx b/src/views/MySubscription/SubscriptionDetail/AlertInfoItem/index.tsx new file mode 100644 index 0000000..495a396 --- /dev/null +++ b/src/views/MySubscription/SubscriptionDetail/AlertInfoItem/index.tsx @@ -0,0 +1,43 @@ +import { Container } from '@ifrc-go/ui'; +import { useTranslation } from '@ifrc-go/ui/hooks'; + +import Link from '#components/Link'; + +import i18n from './i18n.json'; +import styles from './styles.module.css'; + +interface Props { + alertId: string; + alertTitle: string; + alertDescription?: string; +} + +function AlertInfoItem(props: Props) { + const strings = useTranslation(i18n); + + const { + alertId, + alertTitle, + alertDescription, + } = props; + + return ( + + {strings.alertInfoView} + + )} + footerContent={alertDescription} + /> + ); +} + +export default AlertInfoItem; diff --git a/src/views/MySubscription/SubscriptionDetail/AlertInfoItem/styles.module.css b/src/views/MySubscription/SubscriptionDetail/AlertInfoItem/styles.module.css new file mode 100644 index 0000000..d335e76 --- /dev/null +++ b/src/views/MySubscription/SubscriptionDetail/AlertInfoItem/styles.module.css @@ -0,0 +1,4 @@ +.alert-detail { + background-color: var(--go-ui-color-gray-20); + padding: var(--go-ui-spacing-md); +} diff --git a/src/views/MySubscription/SubscriptionDetail/i18n.json b/src/views/MySubscription/SubscriptionDetail/i18n.json new file mode 100644 index 0000000..6d6bc4e --- /dev/null +++ b/src/views/MySubscription/SubscriptionDetail/i18n.json @@ -0,0 +1,9 @@ +{ + "namespace": "subscriptionDetail", + "strings": { + "subscriptionDetailTitle": "Subscription Detail", + "subscriptionHeading": "Subscription", + "filterStartDateFrom": "Start date from", + "filterStartDateTo": "Start date To" + } +} \ No newline at end of file diff --git a/src/views/MySubscription/SubscriptionDetail/index.tsx b/src/views/MySubscription/SubscriptionDetail/index.tsx new file mode 100644 index 0000000..ec7feea --- /dev/null +++ b/src/views/MySubscription/SubscriptionDetail/index.tsx @@ -0,0 +1,140 @@ +import { useCallback } from 'react'; +import { + Container, + DateInput, + List, + Pager, +} from '@ifrc-go/ui'; +import { useTranslation } from '@ifrc-go/ui/hooks'; + +import Badge from '#components/Badge'; +import Page from '#components/Page'; +import { AlertFilter } from '#generated/types/graphql'; +import useFilterState from '#hooks/useFilterState'; +import { stringIdSelector } from '#utils/selectors'; + +import { + AlertInfo, + SubscriptionAndAlertDetail, +} from '../common'; +import AlertInfoItem from './AlertInfoItem'; + +import i18n from './i18n.json'; +import styles from './styles.module.css'; + +const PAGE_SIZE = 20; + +// eslint-disable-next-line import/prefer-default-export +export function Component() { + const strings = useTranslation(i18n); + + const subscriptionAndAlertsDetail: SubscriptionAndAlertDetail = { + id: '1', + alertFilters: ['Future', 'Severe', 'Nepal', 'Bagmati'], + alertInfo: [ + { + id: '1', + alertId: '101', + alertTitle: 'Flood Alert', + alertDescription: 'Severe flooding expected in the coastal region.', + }, + { + id: '2', + alertId: '102', + alertTitle: 'Heatwave Warning', + alertDescription: 'Extreme heatwave affecting northern regions.', + }, + { + id: '3', + alertId: '103', + alertTitle: 'Earthquake Advisory', + alertDescription: 'Possible aftershocks in the affected areas.', + }, + ], + }; + + const { + // limit, + page, + setPage, + // filter, + // setFilter, + // offset, + } = useFilterState({ + pageSize: PAGE_SIZE, + filter: {}, + }); + + const subscriptionKeySelector = (filter: string) => filter; + + const subscriptionRendererParams = useCallback((_: string, value: string) => ({ + title: value, + }), []); + + const rendererParams = useCallback((_: string, value: AlertInfo) => ({ + alertId: value.alertId, + alertTitle: value.alertTitle, + alertDescription: value?.alertDescription, + }), []); + + return ( + + + { }} + /> + { }} + /> + + )} + footerActions={( + + )} + > + + + + + ); +} + +Component.displayName = 'SubscriptionDetail'; diff --git a/src/views/MySubscription/SubscriptionDetail/styles.module.css b/src/views/MySubscription/SubscriptionDetail/styles.module.css new file mode 100644 index 0000000..0e8a811 --- /dev/null +++ b/src/views/MySubscription/SubscriptionDetail/styles.module.css @@ -0,0 +1,19 @@ +.subscription-detail { + .alert-filters { + display: flex; + flex-direction: column; + gap: var(--go-ui-spacing-md); + + .badge-container { + display: flex; + gap: var(--go-ui-spacing-md); + min-height: 0%; + } + + .alert-item { + display: flex; + flex-direction: column; + gap: var(--go-ui-spacing-md); + } + } +} \ No newline at end of file diff --git a/src/views/MySubscription/SubscriptionTableItem/i18n.json b/src/views/MySubscription/SubscriptionTableItem/i18n.json new file mode 100644 index 0000000..1b8a7d4 --- /dev/null +++ b/src/views/MySubscription/SubscriptionTableItem/i18n.json @@ -0,0 +1,6 @@ +{ + "namespace": "subscriptionItem", + "strings": { + "subscriptionItemView": "View" + } +} \ No newline at end of file diff --git a/src/views/MySubscription/SubscriptionTableItem/index.tsx b/src/views/MySubscription/SubscriptionTableItem/index.tsx index ee7bf39..f6dd756 100644 --- a/src/views/MySubscription/SubscriptionTableItem/index.tsx +++ b/src/views/MySubscription/SubscriptionTableItem/index.tsx @@ -1,14 +1,18 @@ import { Container } from '@ifrc-go/ui'; +import { useTranslation } from '@ifrc-go/ui/hooks'; +import Link from '#components/Link'; import { AlertInfoCertaintyEnum, AlertInfoSeverityEnum, AlertInfoUrgencyEnum, } from '#generated/types/graphql'; +import i18n from './i18n.json'; import styles from './styles.module.css'; interface Props { + id: string; country: string | undefined; admin1: string | undefined; urgency?: AlertInfoUrgencyEnum[] | undefined; @@ -21,6 +25,7 @@ interface Props { function SubscriptionTableItem(props: Props) { const { + id, country, admin1, urgency, @@ -31,8 +36,11 @@ function SubscriptionTableItem(props: Props) { actions, } = props; + const strings = useTranslation(i18n); + return ( )} + footerContentClassName={styles.alertDetail} footerContent={( <> - {country} - {admin1} - {urgency} - {certainty} - {severity} +
{country}
+
{admin1}
+
{urgency}
+
{certainty}
+
{severity}
)} + footerActions={( + + {strings.subscriptionItemView} + + )} /> ); } diff --git a/src/views/MySubscription/SubscriptionTableItem/styles.module.css b/src/views/MySubscription/SubscriptionTableItem/styles.module.css index a50abf2..69194df 100644 --- a/src/views/MySubscription/SubscriptionTableItem/styles.module.css +++ b/src/views/MySubscription/SubscriptionTableItem/styles.module.css @@ -1,4 +1,10 @@ .subscription-detail { background-color: var(--go-ui-color-gray-20); padding: var(--go-ui-spacing-md); + + .alertDetail { + display: flex; + flex-wrap: wrap; + gap: var(--go-ui-spacing-sm); + } } diff --git a/src/views/MySubscription/common.tsx b/src/views/MySubscription/common.tsx index 41a6cd2..72e1e6f 100644 --- a/src/views/MySubscription/common.tsx +++ b/src/views/MySubscription/common.tsx @@ -9,6 +9,24 @@ export interface FrequencyOption { key: 'daily' | 'weekly'; } +export interface AlertFilters { + id: string; + filters: string[]; +} + +export interface AlertInfo { + id: string; + alertId: string; + alertTitle: string; + alertDescription?: string; +} + +export interface SubscriptionAndAlertDetail { + id: string; + alertFilters: string[]; + alertInfo?: AlertInfo[] | undefined; +} + // TODO: Add subscription interface from generated export interface SubscriptionDetail { id: string; diff --git a/src/views/MySubscription/i18n.json b/src/views/MySubscription/i18n.json index dd16309..ea33e4a 100644 --- a/src/views/MySubscription/i18n.json +++ b/src/views/MySubscription/i18n.json @@ -6,6 +6,7 @@ "createNewSubscription": "Create", "sendViaEmailLabel": "Send via email", "activeSubscriptionsTab": "Active Subscriptions", - "archivedSubscriptionTab": "Archive Subscriptions" + "archivedSubscriptionTab": "Archive Subscriptions", + "subscriptionDescription": "Customize your alerts with tailored filters, manage your subscriptions, and stay informed with relevant alerts delivered directly to your inbox." } -} \ No newline at end of file +} diff --git a/src/views/MySubscription/index.tsx b/src/views/MySubscription/index.tsx index 1bab16b..07c0376 100644 --- a/src/views/MySubscription/index.tsx +++ b/src/views/MySubscription/index.tsx @@ -66,6 +66,7 @@ export function Component() { }] = useBooleanState(false); const activeRendererParams = useCallback((_: string, value: SubscriptionDetail) => ({ + id: value.id, title: value.title, totalCount: value.totalCount ?? 0, country: value?.country, @@ -77,6 +78,7 @@ export function Component() { }), []); const archiveRendererParams = useCallback((_: string, value: SubscriptionDetail) => ({ + id: value.id, title: value.title, totalCount: value.totalCount ?? 0, country: value?.country, @@ -92,7 +94,7 @@ export function Component() { title={strings.mySubscription} className={styles.mySubscription} heading={strings.mySubscription} - // TODO: Add subscription description + description={strings.subscriptionDescription} mainSectionClassName={styles.content} > ({ title: subscription?.title, urgency: subscription?.urgency, @@ -192,7 +194,6 @@ function NewSubscriptionModal(props: Props) { const fieldError = getErrorObject(formError); - const strings = useTranslation(i18n); const { data: alertEnumsResponse, } = useQuery( diff --git a/src/views/Resources/i18n.json b/src/views/Resources/i18n.json index ca58173..0046c11 100644 --- a/src/views/Resources/i18n.json +++ b/src/views/Resources/i18n.json @@ -23,6 +23,7 @@ "ifrcRelatedExternalLinksGo": "WMO register of alerting authorities", "ifrcRelatedExternalLinksCapImplementation": "CAP implementation workshop", "ifrcRelatedExternalLinksGooglePublicAlerts": "Google Public Alerts", - "ifrcRelatedExternalLinksEarlyWarningAllInitiative":"Early Warning For All Initiative" + "ifrcRelatedExternalLinksEarlyWarningAllInitiative":"Early Warning For All Initiative", + "ifrcSubscriptionDescription": "To subscribe to alerts on the IFRC AlertHub platform, log in to your account and navigate to the My Subscriptions section located in the top-left corner of the site. Choose the topics or categories that interest you, such as specific countries, hazards, or urgency levels. Click the Subscribe button, set your preferred alert frequency (e.g., daily or weekly), and save your preferences. Once subscribed, you’ll receive updates tailored to your selections. You can create multiple subscriptions to cover different interests. To modify or cancel your subscriptions, simply return to the My Subscriptions section." } } \ No newline at end of file diff --git a/src/views/Resources/index.tsx b/src/views/Resources/index.tsx index 84c44b8..b5966e0 100644 --- a/src/views/Resources/index.tsx +++ b/src/views/Resources/index.tsx @@ -136,6 +136,7 @@ export function Component() {