diff --git a/frontend/src/component/user/Profile/ProfileTab/ProductivityEmailSubscription.tsx b/frontend/src/component/user/Profile/ProfileTab/ProductivityEmailSubscription.tsx new file mode 100644 index 000000000000..7545d5f64949 --- /dev/null +++ b/frontend/src/component/user/Profile/ProfileTab/ProductivityEmailSubscription.tsx @@ -0,0 +1,63 @@ +import { Box, Switch } from '@mui/material'; +import { formatUnknownError } from 'utils/formatUnknownError'; +import { useState } from 'react'; +import { useEmailSubscriptionApi } from 'hooks/api/actions/useEmailSubscriptionApi/useEmailSubscriptionApi'; +import useToast from 'hooks/useToast'; +import { usePlausibleTracker } from 'hooks/usePlausibleTracker'; + +export const ProductivityEmailSubscription = () => { + // TODO: read data from user profile when available + const [receiveProductivityReportEmail, setReceiveProductivityReportEmail] = + useState(false); + const { + subscribe, + unsubscribe, + loading: changingSubscriptionStatus, + } = useEmailSubscriptionApi(); + const { setToastData, setToastApiError } = useToast(); + const { trackEvent } = usePlausibleTracker(); + + return ( + + Productivity Email Subscription + { + try { + if (receiveProductivityReportEmail) { + await unsubscribe('productivity-report'); + setToastData({ + title: 'Unsubscribed from productivity report', + type: 'success', + }); + trackEvent('productivity-report', { + props: { + eventType: 'subscribe', + }, + }); + } else { + await subscribe('productivity-report'); + setToastData({ + title: 'Subscribed to productivity report', + type: 'success', + }); + trackEvent('productivity-report', { + props: { + eventType: 'unsubscribe', + }, + }); + } + } catch (error) { + setToastApiError(formatUnknownError(error)); + } + + setReceiveProductivityReportEmail( + !receiveProductivityReportEmail, + ); + }} + name='productivity-email' + checked={receiveProductivityReportEmail} + disabled={changingSubscriptionStatus} + /> + + ); +}; diff --git a/frontend/src/component/user/Profile/ProfileTab/ProfileTab.tsx b/frontend/src/component/user/Profile/ProfileTab/ProfileTab.tsx index f1a1ff564108..5c06f175f13f 100644 --- a/frontend/src/component/user/Profile/ProfileTab/ProfileTab.tsx +++ b/frontend/src/component/user/Profile/ProfileTab/ProfileTab.tsx @@ -19,6 +19,8 @@ import { useNavigate } from 'react-router-dom'; import { PageContent } from 'component/common/PageContent/PageContent'; import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; import { RoleBadge } from 'component/common/RoleBadge/RoleBadge'; +import { useUiFlag } from 'hooks/useUiFlag'; +import { ProductivityEmailSubscription } from './ProductivityEmailSubscription'; const StyledHeader = styled('div')(({ theme }) => ({ display: 'flex', @@ -121,6 +123,8 @@ export const ProfileTab = ({ user }: IProfileTabProps) => { setLocationSettings({ locale }); }; + const productivityReportEmailEnabled = useUiFlag('productivityReportEmail'); + return ( <> @@ -187,7 +191,7 @@ export const ProfileTab = ({ user }: IProfileTabProps) => { - Settings + Date/Time Settings This is the format used across the system for time and date @@ -215,6 +219,13 @@ export const ProfileTab = ({ user }: IProfileTabProps) => { })} + {productivityReportEmailEnabled ? ( + <> + + Email Settings + + + ) : null} ); diff --git a/frontend/src/hooks/api/actions/useEmailSubscriptionApi/useEmailSubscriptionApi.ts b/frontend/src/hooks/api/actions/useEmailSubscriptionApi/useEmailSubscriptionApi.ts new file mode 100644 index 000000000000..aed98ec9e6e8 --- /dev/null +++ b/frontend/src/hooks/api/actions/useEmailSubscriptionApi/useEmailSubscriptionApi.ts @@ -0,0 +1,32 @@ +import useAPI from '../useApi/useApi'; + +export const useEmailSubscriptionApi = () => { + const { makeRequest, createRequest, errors, loading } = useAPI({ + propagateErrors: true, + }); + + const subscribe = async (subscriptionName: string) => { + const path = `api/admin/email-subscription/${subscriptionName}`; + const req = createRequest(path, { + method: 'PUT', + }); + + await makeRequest(req.caller, req.id); + }; + + const unsubscribe = async (subscriptionName: string) => { + const path = `api/admin/email-subscription/${subscriptionName}`; + const req = createRequest(path, { + method: 'DELETE', + }); + + await makeRequest(req.caller, req.id); + }; + + return { + subscribe, + unsubscribe, + errors, + loading, + }; +}; diff --git a/frontend/src/hooks/usePlausibleTracker.ts b/frontend/src/hooks/usePlausibleTracker.ts index 2840ff9473c6..9f3ec64be6db 100644 --- a/frontend/src/hooks/usePlausibleTracker.ts +++ b/frontend/src/hooks/usePlausibleTracker.ts @@ -72,7 +72,8 @@ export type CustomEvents = | 'personal-dashboard' | 'order-environments' | 'unleash-ai-chat' - | 'project-navigation'; + | 'project-navigation' + | 'productivity-report'; export const usePlausibleTracker = () => { const plausible = useContext(PlausibleContext); diff --git a/frontend/src/interfaces/uiConfig.ts b/frontend/src/interfaces/uiConfig.ts index 5c622eae4f90..b2d59607c7e4 100644 --- a/frontend/src/interfaces/uiConfig.ts +++ b/frontend/src/interfaces/uiConfig.ts @@ -94,6 +94,7 @@ export type UiFlags = { releasePlans?: boolean; 'enterprise-payg'?: boolean; simplifyProjectOverview?: boolean; + productivityReportEmail?: boolean; }; export interface IVersionInfo {