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 {