From 50235aa5fd81d38a4ac34f513aefa3a29a6d3b1e Mon Sep 17 00:00:00 2001 From: ZecD Date: Fri, 14 Nov 2025 09:43:52 +0100 Subject: [PATCH 1/2] refactor: streamline notification settings and improve styling components --- src/locales/en/translation.json | 2 +- .../FollowActivitiesPanel.tsx | 27 ++++--------------- .../UnfollowButton.tsx | 1 - .../components.tsx | 22 +++++++++++++++ .../FollowActivitiesAccordion.tsx/index.tsx | 1 - .../CommunicationUpdatesPanel.tsx | 5 ---- .../parts/NotificationsAccordion/index.tsx | 1 - 7 files changed, 28 insertions(+), 31 deletions(-) create mode 100644 src/pages/Profile/parts/FollowActivitiesAccordion.tsx/components.tsx diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 6d7df625d..60dbcddab 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -1257,7 +1257,7 @@ "__PROFILE_PAGE_NOTIFICATIONS_CARD_ACTIVITY_PROGRESS_ALERT_ITEM_4": "When an activity is completed", "__PROFILE_PAGE_NOTIFICATIONS_CARD_ACTIVITY_PROGRESS_ALERT_ITEM_5": "When you’re mentioned in a comment", "__PROFILE_PAGE_NOTIFICATIONS_CARD_ACTIVITY_PROGRESS_ALERT_TITLE": "You’ll always receive:", - "__PROFILE_PAGE_NOTIFICATIONS_CARD_ACTIVITY_PROGRESS_CHECKBOX_HINT": "From execution to completion, including comments in threads you participate in", + "__PROFILE_PAGE_NOTIFICATIONS_CARD_ACTIVITY_PROGRESS_CHECKBOX_HINT": "From execution to completion", "__PROFILE_PAGE_NOTIFICATIONS_CARD_ACTIVITY_PROGRESS_CHECKBOX_LABEL": "Activity progress", "__PROFILE_PAGE_NOTIFICATIONS_CARD_ACTIVITY_PROGRESS_UPDATES_FORM_LABEL": "Receive updates for:", "__PROFILE_PAGE_NOTIFICATIONS_CARD_ACTIVITY_PROGRESS_UPDATES_HINT": "Choose which progress notifications you’d like to receive by email for the activities you follow", diff --git a/src/pages/Profile/parts/FollowActivitiesAccordion.tsx/FollowActivitiesPanel.tsx b/src/pages/Profile/parts/FollowActivitiesAccordion.tsx/FollowActivitiesPanel.tsx index 316372200..ad11a65ed 100644 --- a/src/pages/Profile/parts/FollowActivitiesAccordion.tsx/FollowActivitiesPanel.tsx +++ b/src/pages/Profile/parts/FollowActivitiesAccordion.tsx/FollowActivitiesPanel.tsx @@ -8,34 +8,17 @@ import { import { useTranslation } from 'react-i18next'; import { ReactComponent as InfoIcon } from 'src/assets/icons/info-icon.svg'; -import styled from 'styled-components'; import { GetUsersMeWatchedPlansApiResponse, useDeletePlansByPidWatchersAndProfileIdMutation, useGetUsersMeQuery, } from 'src/features/api'; import { UnfollowButton } from './UnfollowButton'; - -const StyledPanelSectionContainer = styled.div` - display: flex; - flex-direction: column; - gap: ${({ theme }) => theme.space.xs}; - margin-bottom: ${({ theme }) => theme.space.xxl}; -`; - -const StyledHintContainer = styled.div` - display: flex; - align-items: center; - gap: ${({ theme }) => theme.space.xs}; -`; - -const StyledActivityItem = styled.div` - padding-top: ${({ theme }) => theme.space.sm}; - padding-bottom: ${({ theme }) => theme.space.sm}; - display: flex; - align-items: center; - justify-content: space-between; -`; +import { + StyledActivityItem, + StyledHintContainer, + StyledPanelSectionContainer, +} from './components'; export const FollowActivitiesPanel = ({ followedActivities, diff --git a/src/pages/Profile/parts/FollowActivitiesAccordion.tsx/UnfollowButton.tsx b/src/pages/Profile/parts/FollowActivitiesAccordion.tsx/UnfollowButton.tsx index 18386db1f..5e97b0555 100644 --- a/src/pages/Profile/parts/FollowActivitiesAccordion.tsx/UnfollowButton.tsx +++ b/src/pages/Profile/parts/FollowActivitiesAccordion.tsx/UnfollowButton.tsx @@ -16,7 +16,6 @@ const UnfollowButton = ({ + )} - - - - {t('__PROFILE_PAGE_NOTIFICATIONS_CARD_FOLLOW_ACTIVITIES_HINT_TEXT')} - - ); }; diff --git a/src/pages/Profile/parts/FollowActivitiesAccordion.tsx/FollowCampaignActivitiesPanel.tsx b/src/pages/Profile/parts/FollowActivitiesAccordion.tsx/FollowCampaignActivitiesPanel.tsx new file mode 100644 index 000000000..b5bcd6c3e --- /dev/null +++ b/src/pages/Profile/parts/FollowActivitiesAccordion.tsx/FollowCampaignActivitiesPanel.tsx @@ -0,0 +1,137 @@ +import { + Anchor, + Label, + SM, + useToast, + Notification, + Button, +} from '@appquality/unguess-design-system'; +import { useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { ReactComponent as ChevronDown } from 'src/assets/icons/chevron-down-stroke.svg'; +import { ReactComponent as ChevronUp } from 'src/assets/icons/chevron-up-stroke.svg'; +import { appTheme } from 'src/app/theme'; + +import { + GetUsersMeWatchedCampaignsApiResponse, + useDeletePlansByPidWatchersAndProfileIdMutation, + useGetUsersMeQuery, +} from 'src/features/api'; +import { UnfollowButton } from './UnfollowButton'; +import { StyledActivityItem, StyledPanelSectionContainer } from './components'; + +export const FollowCampaignActivitiesPanel = ({ + followedCampaigns, +}: { + followedCampaigns: GetUsersMeWatchedCampaignsApiResponse['items']; +}) => { + const { t } = useTranslation(); + const { addToast } = useToast(); + const { data: userData } = useGetUsersMeQuery(); + const [unfollowPlan] = useDeletePlansByPidWatchersAndProfileIdMutation(); + const [isExpanded, setIsExpanded] = useState(false); + + const displayedActivities = isExpanded + ? followedCampaigns + : followedCampaigns.slice(0, 3); + const hasMore = followedCampaigns.length > 3; + const remainingCount = followedCampaigns.length - 3; + + const truncateName = ( + name: string | undefined, + maxLength: number = 40 + ): string => { + if (!name) return ''; + return name.length > maxLength + ? `${name.substring(0, maxLength)}...` + : name; + }; + + const handleUnfollow = async (planId: number) => { + try { + await unfollowPlan({ + pid: planId.toString(), + profileId: userData?.profile_id.toString() ?? '', + }).unwrap(); + + addToast( + ({ close }) => ( + + ), + { placement: 'top' } + ); + } catch (error) { + addToast( + ({ close }) => ( + + ), + { placement: 'top' } + ); + } + }; + + return ( +
+ + + {displayedActivities.map((activity) => ( + +
+ + {truncateName(activity?.name)} + + {activity?.project?.name} +
+ +
+ ))} + {hasMore && ( + + )} +
+
+ ); +}; diff --git a/src/pages/Profile/parts/FollowActivitiesAccordion.tsx/NotificationSettingsEmptyState.tsx b/src/pages/Profile/parts/FollowActivitiesAccordion.tsx/NotificationSettingsEmptyState.tsx new file mode 100644 index 000000000..d01280e75 --- /dev/null +++ b/src/pages/Profile/parts/FollowActivitiesAccordion.tsx/NotificationSettingsEmptyState.tsx @@ -0,0 +1,32 @@ +import { Hint, Label, LG } from '@appquality/unguess-design-system'; +import { useTranslation } from 'react-i18next'; +import { appTheme } from 'src/app/theme'; +import { ReactComponent as EmptyState } from 'src/assets/empty-monitoring.svg'; + +export const NotificationSettingsEmptyState = () => { + const { t } = useTranslation(); + return ( +
+ + + + {t( + '__PROFILE_PAGE_NOTIFICATIONS_CARD_FOLLOW_ACTIVITIES_EMPTY_STATE_HINT' + )} + +
+ ); +}; diff --git a/src/pages/Profile/parts/FollowActivitiesAccordion.tsx/index.tsx b/src/pages/Profile/parts/FollowActivitiesAccordion.tsx/index.tsx index 9f3a721b1..f0cfcec11 100644 --- a/src/pages/Profile/parts/FollowActivitiesAccordion.tsx/index.tsx +++ b/src/pages/Profile/parts/FollowActivitiesAccordion.tsx/index.tsx @@ -2,9 +2,14 @@ import { AccordionNew, Tag } from '@appquality/unguess-design-system'; import { useTranslation } from 'react-i18next'; import { appTheme } from 'src/app/theme'; import { ReactComponent as EyeIcon } from 'src/assets/icons/eye-icon-fill.svg'; -import { useGetUsersMeWatchedPlansQuery } from 'src/features/api'; +import { + useGetUsersMeWatchedCampaignsQuery, + useGetUsersMeWatchedPlansQuery, +} from 'src/features/api'; import { FollowActivitiesPanel } from './FollowActivitiesPanel'; import { Loader } from '../cardLoader'; +import { FollowCampaignActivitiesPanel } from './FollowCampaignActivitiesPanel'; +import { NotificationSettingsEmptyState } from './NotificationSettingsEmptyState'; export const FollowActivitiesAccordion = () => { const { t } = useTranslation(); @@ -14,6 +19,14 @@ export const FollowActivitiesAccordion = () => { isError, } = useGetUsersMeWatchedPlansQuery(); + const { + data: followedCampaigns, + isLoading: isCampaignsLoading, + isError: isCampaignsError, + } = useGetUsersMeWatchedCampaignsQuery(); + const totalFollowed = + (followedActivities?.items.length || 0) + + (followedCampaigns?.items.length || 0); if (isLoading) return ; if (isError || !followedActivities) return null; return ( @@ -43,18 +56,35 @@ export const FollowActivitiesAccordion = () => { /> - {`${followedActivities.items.length}/${followedActivities.allItems} `} + {`${totalFollowed}/${ + followedActivities.allItems + (followedCampaigns?.allItems || 0) + } `} {t('__PROFILE_PAGE_NOTIFICATIONS_CARD_FOLLOW_ACTIVITIES_TAG')} - - {followedActivities.items.length > 0 && ( - - )} - + {totalFollowed > 0 ? ( + <> + + {followedActivities.items.length > 0 && ( + + )} + + {followedCampaigns && followedCampaigns.items.length > 0 && ( + + + + )} + + ) : ( + + + + )} ); diff --git a/src/pages/Profile/parts/NotificationSettingsCard.tsx b/src/pages/Profile/parts/NotificationSettingsCard.tsx index a403150c3..43157d86c 100644 --- a/src/pages/Profile/parts/NotificationSettingsCard.tsx +++ b/src/pages/Profile/parts/NotificationSettingsCard.tsx @@ -17,6 +17,7 @@ import { import { NotificationSettingsAccordion } from './NotificationsAccordion'; import { FollowActivitiesAccordion } from './FollowActivitiesAccordion.tsx'; import { NotificationSettingsFormValues } from '../valuesType'; +import { CommentsUpdatesAccordion } from './CommentNotificationsAccordion'; export const NotificationSettingsCard = () => { const { t } = useTranslation(); @@ -53,6 +54,7 @@ export const NotificationSettingsCard = () => { marginBottom: appTheme.space.sm, }} /> +