diff --git a/src/assets/empty-monitoring.svg b/src/assets/empty-monitoring.svg new file mode 100644 index 000000000..59c31e23a --- /dev/null +++ b/src/assets/empty-monitoring.svg @@ -0,0 +1,278 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/icons/chevron-up-stroke.svg b/src/assets/icons/chevron-up-stroke.svg new file mode 100644 index 000000000..72d9bbd24 --- /dev/null +++ b/src/assets/icons/chevron-up-stroke.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/common/schema.ts b/src/common/schema.ts index 2797f8d5e..3fb0f70db 100644 --- a/src/common/schema.ts +++ b/src/common/schema.ts @@ -481,6 +481,14 @@ export interface paths { get: operations["get-users-me-watched-plans"]; parameters: {}; }; + "/users/me/watched/campaigns": { + /** + * Get all users watched campaigns. + * Each returned item has isLast=1 when the user is the last watcher of that specific item. + */ + get: operations["get-users-me-watched-campaigns"]; + parameters: {}; + }; "/users/roles": { get: operations["get-users-roles"]; parameters: {}; @@ -639,6 +647,16 @@ export interface paths { }; }; }; + "/campaigns/{cid}/watchers": { + /** Returns all the watcher added to a campaign. It always returns at least one item. */ + get: operations["get-campaigns-cid-watchers"]; + post: operations["post-campaigns-cid-watchers"]; + parameters: { + path: { + cid: string; + }; + }; + }; "/workspaces/{wid}/templates": { get: operations["get-workspaces-templates"]; post: operations["post-workspaces-wid-templates"]; @@ -682,6 +700,15 @@ export interface paths { }; }; }; + "/campaigns/{cid}/watchers/{profile_id}": { + delete: operations["delete-campaigns-cid-watchers-profile_id"]; + parameters: { + path: { + profile_id: string; + cid: string; + }; + }; + }; } export interface components { @@ -3921,6 +3948,35 @@ export interface operations { 500: components["responses"]["Error"]; }; }; + /** + * Get all users watched campaigns. + * Each returned item has isLast=1 when the user is the last watcher of that specific item. + */ + "get-users-me-watched-campaigns": { + parameters: {}; + responses: { + 200: { + content: { + "application/json": { + items: { + id?: number; + name?: string; + project?: { + name?: string; + id?: number; + }; + isLast?: boolean; + }[]; + allItems: number; + }; + }; + }; + 400: components["responses"]["Error"]; + 403: components["responses"]["Error"]; + 404: components["responses"]["Error"]; + 500: components["responses"]["Error"]; + }; + }; "get-users-roles": { parameters: {}; responses: { @@ -4525,6 +4581,57 @@ export interface operations { }; }; }; + /** Returns all the watcher added to a campaign. It always returns at least one item. */ + "get-campaigns-cid-watchers": { + parameters: { + path: { + cid: string; + }; + }; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + items: { + id: number; + name: string; + surname: string; + email: string; + image?: string; + isInternal: boolean; + }[]; + }; + }; + }; + 403: components["responses"]["Error"]; + 404: components["responses"]["Error"]; + 500: components["responses"]["Error"]; + }; + }; + "post-campaigns-cid-watchers": { + parameters: { + path: { + cid: string; + }; + }; + responses: { + /** OK */ + 200: unknown; + 403: components["responses"]["Error"]; + 404: components["responses"]["Error"]; + 500: components["responses"]["Error"]; + }; + requestBody: { + content: { + "application/json": { + users: { + id: number; + }[]; + }; + }; + }; + }; "get-workspaces-templates": { parameters: { path: { @@ -4747,6 +4854,27 @@ export interface operations { 403: components["responses"]["Error"]; }; }; + "delete-campaigns-cid-watchers-profile_id": { + parameters: { + path: { + profile_id: string; + cid: string; + }; + }; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + success?: boolean; + }; + }; + }; + 400: components["responses"]["Error"]; + 403: components["responses"]["Error"]; + 500: components["responses"]["Error"]; + }; + }; } export interface external {} diff --git a/src/features/api/index.ts b/src/features/api/index.ts index 900ba5a87..4f9305905 100644 --- a/src/features/api/index.ts +++ b/src/features/api/index.ts @@ -617,6 +617,12 @@ const injectedRtkApi = api.injectEndpoints({ >({ query: () => ({ url: `/users/me/watched/plans` }), }), + getUsersMeWatchedCampaigns: build.query< + GetUsersMeWatchedCampaignsApiResponse, + GetUsersMeWatchedCampaignsApiArg + >({ + query: () => ({ url: `/users/me/watched/campaigns` }), + }), getUsersRoles: build.query({ query: () => ({ url: `/users/roles` }), }), @@ -818,6 +824,22 @@ const injectedRtkApi = api.injectEndpoints({ body: queryArg.body, }), }), + getCampaignsByCidWatchers: build.query< + GetCampaignsByCidWatchersApiResponse, + GetCampaignsByCidWatchersApiArg + >({ + query: (queryArg) => ({ url: `/campaigns/${queryArg.cid}/watchers` }), + }), + postCampaignsByCidWatchers: build.mutation< + PostCampaignsByCidWatchersApiResponse, + PostCampaignsByCidWatchersApiArg + >({ + query: (queryArg) => ({ + url: `/campaigns/${queryArg.cid}/watchers`, + method: 'POST', + body: queryArg.body, + }), + }), getWorkspacesByWidTemplates: build.query< GetWorkspacesByWidTemplatesApiResponse, GetWorkspacesByWidTemplatesApiArg @@ -903,6 +925,15 @@ const injectedRtkApi = api.injectEndpoints({ method: 'DELETE', }), }), + deleteCampaignsByCidWatchersAndProfileId: build.mutation< + DeleteCampaignsByCidWatchersAndProfileIdApiResponse, + DeleteCampaignsByCidWatchersAndProfileIdApiArg + >({ + query: (queryArg) => ({ + url: `/campaigns/${queryArg.cid}/watchers/${queryArg.profileId}`, + method: 'DELETE', + }), + }), }), overrideExisting: false, }); @@ -1835,6 +1866,19 @@ export type GetUsersMeWatchedPlansApiResponse = /** status 200 */ { allItems: number; }; export type GetUsersMeWatchedPlansApiArg = void; +export type GetUsersMeWatchedCampaignsApiResponse = /** status 200 */ { + items: { + id?: number; + name?: string; + project?: { + name?: string; + id?: number; + }; + isLast?: boolean; + }[]; + allItems: number; +}; +export type GetUsersMeWatchedCampaignsApiArg = void; export type GetUsersRolesApiResponse = /** status 200 OK */ { id: number; name: string; @@ -2093,6 +2137,28 @@ export type PutPlansByPidWatchersApiArg = { }[]; }; }; +export type GetCampaignsByCidWatchersApiResponse = /** status 200 OK */ { + items: { + id: number; + name: string; + surname: string; + email: string; + image?: string; + isInternal: boolean; + }[]; +}; +export type GetCampaignsByCidWatchersApiArg = { + cid: string; +}; +export type PostCampaignsByCidWatchersApiResponse = /** status 200 OK */ void; +export type PostCampaignsByCidWatchersApiArg = { + cid: string; + body: { + users: { + id: number; + }[]; + }; +}; export type GetWorkspacesByWidTemplatesApiResponse = /** status 200 OK */ { items: CpReqTemplate[]; } & PaginationData; @@ -2200,6 +2266,14 @@ export type DeletePlansByPidWatchersAndProfileIdApiArg = { pid: string; profileId: string; }; +export type DeleteCampaignsByCidWatchersAndProfileIdApiResponse = + /** status 200 OK */ { + success?: boolean; + }; +export type DeleteCampaignsByCidWatchersAndProfileIdApiArg = { + profileId: string; + cid: string; +}; export type Error = { code: number; error: boolean; @@ -3128,6 +3202,7 @@ export const { useGetUsersMePreferencesQuery, usePutUsersMePreferencesBySlugMutation, useGetUsersMeWatchedPlansQuery, + useGetUsersMeWatchedCampaignsQuery, useGetUsersRolesQuery, useGetVideosByVidQuery, useGetVideosByVidObservationsQuery, @@ -3150,6 +3225,8 @@ export const { useGetPlansByPidWatchersQuery, usePostPlansByPidWatchersMutation, usePutPlansByPidWatchersMutation, + useGetCampaignsByCidWatchersQuery, + usePostCampaignsByCidWatchersMutation, useGetWorkspacesByWidTemplatesQuery, usePostWorkspacesByWidTemplatesMutation, useDeleteWorkspacesByWidTemplatesAndTidMutation, @@ -3158,4 +3235,5 @@ export const { useGetWorkspacesByWidUsersQuery, usePostWorkspacesByWidUsersMutation, useDeletePlansByPidWatchersAndProfileIdMutation, + useDeleteCampaignsByCidWatchersAndProfileIdMutation, } = injectedRtkApi; diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 6d7df625d..ed326ed49 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -1233,15 +1233,6 @@ "__PROFILE_MODAL_GO_TO_PROFILE": "Edit profile", "__PROFILE_MODAL_LANGUAGES_TITLE": "Change Language", "__PROFILE_MODAL_LOGOUT_TITLE": "Log Out", - "__PROFILE_MODAL_NOTIFICATIONS_INTRO": "Manage the notifications we send you by email.", - "__PROFILE_MODAL_NOTIFICATIONS_OUTRO_P_1": " ", - "__PROFILE_MODAL_NOTIFICATIONS_OUTRO_P_2": "Enable to receive all updates: comments, mentions, quotes on the platform, confirmations, activity timelines, and invitations.", - "__PROFILE_MODAL_NOTIFICATIONS_OUTRO_P_3": "Disable to receive only essentials: mentions, quotes on the platform, activity confirmations, and invitations.", - "__PROFILE_MODAL_NOTIFICATIONS_TITLE": "Notifications settings", - "__PROFILE_MODAL_NOTIFICATIONS_TOGGLE_OFF": "No", - "__PROFILE_MODAL_NOTIFICATIONS_TOGGLE_ON": "Yes", - "__PROFILE_MODAL_NOTIFICATIONS_TOGGLE_TITLE": "Allow notifications", - "__PROFILE_MODAL_NOTIFICATIONS_UPDATED": "Changes saved", "__PROFILE_MODAL_PRIVACY_ITEM_LABEL": "Privacy settings", "__PROFILE_PAGE_COMPANY_SIZE_REQUIRED_ERROR": "Company size is required", "__PROFILE_PAGE_CONFIRM_PASSWORD_MUST_MATCH_NEW_PASSWORD": "The confirmation password must match the new password", @@ -1255,9 +1246,8 @@ "__PROFILE_PAGE_NOTIFICATIONS_CARD_ACTIVITY_PROGRESS_ALERT_ITEM_2": "When a payment is confirmed", "__PROFILE_PAGE_NOTIFICATIONS_CARD_ACTIVITY_PROGRESS_ALERT_ITEM_3": "When an activity is scheduled", "__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", @@ -1265,11 +1255,20 @@ "__PROFILE_PAGE_NOTIFICATIONS_CARD_ACTIVITY_PROGRESS_UPDATES_TAG": "Recommended to keep enabled", "__PROFILE_PAGE_NOTIFICATIONS_CARD_ACTIVITY_SETUP_CHECKBOX_HINT": "From configuration through planning", "__PROFILE_PAGE_NOTIFICATIONS_CARD_ACTIVITY_SETUP_CHECKBOX_LABEL": "Activity setup", + "__PROFILE_PAGE_NOTIFICATIONS_CARD_COMMENTS_PROGRESS_UPDATES_ALERT_TITLE": "You’ll always receive:", + "__PROFILE_PAGE_NOTIFICATIONS_CARD_COMMENTS_PROGRESS_UPDATES_HINT": "Choose which notifications about comments and conversations you’d like to receive by email.", + "__PROFILE_PAGE_NOTIFICATIONS_CARD_COMMENTS_PROGRESS_UPDATES_ITEM_1": "When you’re mentioned in a comment", + "__PROFILE_PAGE_NOTIFICATIONS_CARD_COMMENTS_PROGRESS_UPDATES_ITEM_2": "When a teammate adds you as a follower in an activity", + "__PROFILE_PAGE_NOTIFICATIONS_CARD_COMMENTS_PROGRESS_UPDATES_LABEL": "Communication updates", + "__PROFILE_PAGE_NOTIFICATIONS_CARD_COMMENTS_PROGRESS_UPDATESCHECKBOX_LABEL": "Conversations you’ve participated in", "__PROFILE_PAGE_NOTIFICATIONS_CARD_DESCRIPTION": "Manage which email updates you want to receive", "__PROFILE_PAGE_NOTIFICATIONS_CARD_FOLLOW_ACTIVITIES_BUTTON_TEXT": "Unfollow", + "__PROFILE_PAGE_NOTIFICATIONS_CARD_FOLLOW_ACTIVITIES_EMPTY_STATE_HINT": "Follow an activity to stay updated on its setup and progress", + "__PROFILE_PAGE_NOTIFICATIONS_CARD_FOLLOW_ACTIVITIES_EMPTY_STATE_LABEL": "You’re not following any activities", "__PROFILE_PAGE_NOTIFICATIONS_CARD_FOLLOW_ACTIVITIES_HINT": "You’ll receive updates for activities only for these activities", "__PROFILE_PAGE_NOTIFICATIONS_CARD_FOLLOW_ACTIVITIES_HINT_TEXT": "Your changes are saved automatically", "__PROFILE_PAGE_NOTIFICATIONS_CARD_FOLLOW_ACTIVITIES_LABEL": "Activities you’re following", + "__PROFILE_PAGE_NOTIFICATIONS_CARD_FOLLOW_ACTIVITIES_PROGRESS_DESCRIPTION": "Activity progress ", "__PROFILE_PAGE_NOTIFICATIONS_CARD_FOLLOW_ACTIVITIES_SETUP_DESCRIPTION": "Activity setup ", "__PROFILE_PAGE_NOTIFICATIONS_CARD_FOLLOW_ACTIVITIES_TAG": "tot.", "__PROFILE_PAGE_NOTIFICATIONS_CARD_LABEL": "Notification settings", @@ -1567,5 +1566,7 @@ "UX_SHORTCUT_MODAL_TITLE": "Keyboard Shortcuts", "UX_SHORTCUT_MUTE": "Mute", "UX_SHORTCUT_PLAY_PAUSE": "Play/Pause", - "UX_SHORTCUT_REWIND": "Rewind" + "UX_SHORTCUT_REWIND": "Rewind", + "View Less": "", + "View More": "" } diff --git a/src/locales/it/translation.json b/src/locales/it/translation.json index f0b6ae5dc..059821144 100644 --- a/src/locales/it/translation.json +++ b/src/locales/it/translation.json @@ -1267,15 +1267,6 @@ "__PROFILE_MODAL_GO_TO_PROFILE": "", "__PROFILE_MODAL_LANGUAGES_TITLE": "Cambia Lingua", "__PROFILE_MODAL_LOGOUT_TITLE": "Esci", - "__PROFILE_MODAL_NOTIFICATIONS_INTRO": "Gestisci le notifiche che ti mandiamo per email.", - "__PROFILE_MODAL_NOTIFICATIONS_OUTRO_P_1": "", - "__PROFILE_MODAL_NOTIFICATIONS_OUTRO_P_2": "", - "__PROFILE_MODAL_NOTIFICATIONS_OUTRO_P_3": "", - "__PROFILE_MODAL_NOTIFICATIONS_TITLE": "Gestisci notifiche", - "__PROFILE_MODAL_NOTIFICATIONS_TOGGLE_OFF": "No", - "__PROFILE_MODAL_NOTIFICATIONS_TOGGLE_ON": "Si", - "__PROFILE_MODAL_NOTIFICATIONS_TOGGLE_TITLE": "Vuoi ricevere le notifiche?", - "__PROFILE_MODAL_NOTIFICATIONS_UPDATED": "Modifiche salvate", "__PROFILE_MODAL_PRIVACY_ITEM_LABEL": "Opzioni Privacy", "__PROFILE_PAGE_COMPANY_SIZE_REQUIRED_ERROR": "", "__PROFILE_PAGE_CONFIRM_PASSWORD_MUST_MATCH_NEW_PASSWORD": "", @@ -1289,7 +1280,6 @@ "__PROFILE_PAGE_NOTIFICATIONS_CARD_ACTIVITY_PROGRESS_ALERT_ITEM_2": "", "__PROFILE_PAGE_NOTIFICATIONS_CARD_ACTIVITY_PROGRESS_ALERT_ITEM_3": "", "__PROFILE_PAGE_NOTIFICATIONS_CARD_ACTIVITY_PROGRESS_ALERT_ITEM_4": "", - "__PROFILE_PAGE_NOTIFICATIONS_CARD_ACTIVITY_PROGRESS_ALERT_ITEM_5": "", "__PROFILE_PAGE_NOTIFICATIONS_CARD_ACTIVITY_PROGRESS_ALERT_TITLE": "", "__PROFILE_PAGE_NOTIFICATIONS_CARD_ACTIVITY_PROGRESS_CHECKBOX_HINT": "", "__PROFILE_PAGE_NOTIFICATIONS_CARD_ACTIVITY_PROGRESS_CHECKBOX_LABEL": "", @@ -1299,11 +1289,20 @@ "__PROFILE_PAGE_NOTIFICATIONS_CARD_ACTIVITY_PROGRESS_UPDATES_TAG": "", "__PROFILE_PAGE_NOTIFICATIONS_CARD_ACTIVITY_SETUP_CHECKBOX_HINT": "", "__PROFILE_PAGE_NOTIFICATIONS_CARD_ACTIVITY_SETUP_CHECKBOX_LABEL": "", + "__PROFILE_PAGE_NOTIFICATIONS_CARD_COMMENTS_PROGRESS_UPDATES_ALERT_TITLE": "", + "__PROFILE_PAGE_NOTIFICATIONS_CARD_COMMENTS_PROGRESS_UPDATES_HINT": "", + "__PROFILE_PAGE_NOTIFICATIONS_CARD_COMMENTS_PROGRESS_UPDATES_ITEM_1": "", + "__PROFILE_PAGE_NOTIFICATIONS_CARD_COMMENTS_PROGRESS_UPDATES_ITEM_2": "", + "__PROFILE_PAGE_NOTIFICATIONS_CARD_COMMENTS_PROGRESS_UPDATES_LABEL": "", + "__PROFILE_PAGE_NOTIFICATIONS_CARD_COMMENTS_PROGRESS_UPDATESCHECKBOX_LABEL": "", "__PROFILE_PAGE_NOTIFICATIONS_CARD_DESCRIPTION": "", "__PROFILE_PAGE_NOTIFICATIONS_CARD_FOLLOW_ACTIVITIES_BUTTON_TEXT": "", + "__PROFILE_PAGE_NOTIFICATIONS_CARD_FOLLOW_ACTIVITIES_EMPTY_STATE_HINT": "", + "__PROFILE_PAGE_NOTIFICATIONS_CARD_FOLLOW_ACTIVITIES_EMPTY_STATE_LABEL": "", "__PROFILE_PAGE_NOTIFICATIONS_CARD_FOLLOW_ACTIVITIES_HINT": "", "__PROFILE_PAGE_NOTIFICATIONS_CARD_FOLLOW_ACTIVITIES_HINT_TEXT": "", "__PROFILE_PAGE_NOTIFICATIONS_CARD_FOLLOW_ACTIVITIES_LABEL": "", + "__PROFILE_PAGE_NOTIFICATIONS_CARD_FOLLOW_ACTIVITIES_PROGRESS_DESCRIPTION": "", "__PROFILE_PAGE_NOTIFICATIONS_CARD_FOLLOW_ACTIVITIES_SETUP_DESCRIPTION": "", "__PROFILE_PAGE_NOTIFICATIONS_CARD_FOLLOW_ACTIVITIES_TAG": "", "__PROFILE_PAGE_NOTIFICATIONS_CARD_LABEL": "", @@ -1612,5 +1611,7 @@ "UX_SHORTCUT_MODAL_TITLE": "", "UX_SHORTCUT_MUTE": "", "UX_SHORTCUT_PLAY_PAUSE": "", - "UX_SHORTCUT_REWIND": "" + "UX_SHORTCUT_REWIND": "", + "View Less": "", + "View More": "" } diff --git a/src/pages/Profile/FormNotificationSettings.tsx b/src/pages/Profile/FormNotificationSettings.tsx index 878585c32..f780db313 100644 --- a/src/pages/Profile/FormNotificationSettings.tsx +++ b/src/pages/Profile/FormNotificationSettings.tsx @@ -18,12 +18,15 @@ export const FormNotificationSettings = () => { const activitySetup = data?.items?.find((pref) => pref.name === 'plan_notifications_enabled') ?.value ?? '1'; - const activityProgress = + data?.items?.find((pref) => pref.name === 'campaign_notifications_enabled') + ?.value ?? '1'; + const commentsActivity = data?.items?.find((pref) => pref.name === 'notifications_enabled')?.value ?? '1'; const initialValues: NotificationSettingsFormValues = { + commentsActivity: commentsActivity === '1', activitySetupUpdates: activitySetup === '1', activityProgress: activityProgress === '1', }; @@ -47,9 +50,17 @@ export const FormNotificationSettings = () => { }, }).unwrap(); } - if (values.activityProgress !== initialValues.activityProgress) { + if (values.commentsActivity !== initialValues.commentsActivity) { await updatePreferences({ slug: 'notifications_enabled', + body: { + value: values.commentsActivity ? '1' : '0', + }, + }).unwrap(); + } + if (values.activityProgress !== initialValues.activityProgress) { + await updatePreferences({ + slug: 'campaign_notifications_enabled', body: { value: values.activityProgress ? '1' : '0', }, diff --git a/src/pages/Profile/parts/CommentNotificationsAccordion/CommentsUpdatesPanel.tsx b/src/pages/Profile/parts/CommentNotificationsAccordion/CommentsUpdatesPanel.tsx new file mode 100644 index 000000000..48dc0aeaa --- /dev/null +++ b/src/pages/Profile/parts/CommentNotificationsAccordion/CommentsUpdatesPanel.tsx @@ -0,0 +1,64 @@ +import { + Alert, + Checkbox, + FormField, + Label, + UnorderedList, +} from '@appquality/unguess-design-system'; +import { Field, FieldProps, useFormikContext } from 'formik'; +import { useTranslation } from 'react-i18next'; +import { appTheme } from 'src/app/theme'; +import styled from 'styled-components'; +import { NotificationSettingsFormValues } from '../../valuesType'; + +const StyledPanelContainer = styled.div` + display: flex; + flex-direction: column; + gap: ${({ theme }) => theme.space.lg}; +`; + +export const CommentsUpdatesPanel = () => { + const { t } = useTranslation(); + const { setFieldValue } = useFormikContext(); + return ( + + + {({ field }: FieldProps) => ( + + setFieldValue('commentsActivity', !field.value)} + > + + + + )} + + + + {t( + '__PROFILE_PAGE_NOTIFICATIONS_CARD_COMMENTS_PROGRESS_UPDATES_ALERT_TITLE' + )} + + + + {t( + '__PROFILE_PAGE_NOTIFICATIONS_CARD_COMMENTS_PROGRESS_UPDATES_ITEM_1' + )} + + + {t( + '__PROFILE_PAGE_NOTIFICATIONS_CARD_COMMENTS_PROGRESS_UPDATES_ITEM_2' + )} + + + + + ); +}; diff --git a/src/pages/Profile/parts/CommentNotificationsAccordion/index.tsx b/src/pages/Profile/parts/CommentNotificationsAccordion/index.tsx new file mode 100644 index 000000000..e7a0c935b --- /dev/null +++ b/src/pages/Profile/parts/CommentNotificationsAccordion/index.tsx @@ -0,0 +1,32 @@ +import { AccordionNew } from '@appquality/unguess-design-system'; +import { useTranslation } from 'react-i18next'; +import { CommentsUpdatesPanel } from './CommentsUpdatesPanel'; + +export const CommentsUpdatesAccordion = () => { + const { t } = useTranslation(); + + return ( + + + + + + + + + + + ); +}; diff --git a/src/pages/Profile/parts/FollowActivitiesAccordion.tsx/FollowActivitiesPanel.tsx b/src/pages/Profile/parts/FollowActivitiesAccordion.tsx/FollowActivitiesPanel.tsx index 316372200..a65409cd0 100644 --- a/src/pages/Profile/parts/FollowActivitiesAccordion.tsx/FollowActivitiesPanel.tsx +++ b/src/pages/Profile/parts/FollowActivitiesAccordion.tsx/FollowActivitiesPanel.tsx @@ -4,38 +4,21 @@ import { SM, useToast, Notification, + Button, } from '@appquality/unguess-design-system'; +import { useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { ReactComponent as InfoIcon } from 'src/assets/icons/info-icon.svg'; +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 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, StyledPanelSectionContainer } from './components'; export const FollowActivitiesPanel = ({ followedActivities, @@ -46,6 +29,13 @@ export const FollowActivitiesPanel = ({ const { addToast } = useToast(); const { data: userData } = useGetUsersMeQuery(); const [unfollowPlan] = useDeletePlansByPidWatchersAndProfileIdMutation(); + const [isExpanded, setIsExpanded] = useState(false); + + const displayedActivities = isExpanded + ? followedActivities + : followedActivities.slice(0, 3); + const hasMore = followedActivities.length > 3; + const remainingCount = followedActivities.length - 3; const truncateName = ( name: string | undefined, @@ -56,6 +46,7 @@ export const FollowActivitiesPanel = ({ ? `${name.substring(0, maxLength)}...` : name; }; + const handleUnfollow = async (planId: number) => { try { await unfollowPlan({ @@ -98,8 +89,8 @@ export const FollowActivitiesPanel = ({ )} {`(${followedActivities.length})`} - {followedActivities.map((activity) => ( - + {displayedActivities.map((activity) => ( +
{truncateName(activity?.name)} @@ -113,13 +104,33 @@ export const FollowActivitiesPanel = ({ /> ))} + {hasMore && ( + + )} - - - - {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/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 = ({