diff --git a/src/backend/src/prisma/schema.prisma b/src/backend/src/prisma/schema.prisma index d693609748..8f4a185042 100644 --- a/src/backend/src/prisma/schema.prisma +++ b/src/backend/src/prisma/schema.prisma @@ -116,7 +116,7 @@ model User { googleAuthId String @unique email String @unique emailId String? @unique - completedOnboarding Boolean @default(true) + completedOnboarding Boolean @default(false) roles Role[] userSettings User_Settings? userSecureSettings User_Secure_Settings? diff --git a/src/backend/src/services/users.services.ts b/src/backend/src/services/users.services.ts index a03c231000..e69e88d10a 100644 --- a/src/backend/src/services/users.services.ts +++ b/src/backend/src/services/users.services.ts @@ -395,7 +395,7 @@ export default class UsersService { } /** - * Toggles the completed onboarding status of a user + * Toggles the completed onboarding status of a user and elevates role to member if user completed onboarding * @param user the user who's onboarding status is being toggled * @returns the updated user */ @@ -409,8 +409,24 @@ export default class UsersService { ...getUserQueryArgs(organization.organizationId) }); + if (updatedUser.completedOnboarding) { + const currentRole = updatedUser.roles.find((role) => role.organizationId === organization.organizationId); + + if (currentRole && currentRole.roleType !== RoleEnum.MEMBER) { + await prisma.role.update({ + where: { + uniqueRole: { userId, organizationId: organization.organizationId } + }, + data: { + roleType: RoleEnum.MEMBER + } + }); + } + } + return userTransformer(updatedUser); } + /** * Gets a user's secure settings * @param userId the id of user who's secure settings are being returned diff --git a/src/frontend/src/apis/users.api.ts b/src/frontend/src/apis/users.api.ts index 44d7a40d70..36770460fc 100644 --- a/src/frontend/src/apis/users.api.ts +++ b/src/frontend/src/apis/users.api.ts @@ -141,3 +141,7 @@ export const updateUserScheduleSettings = (settings: SetUserScheduleSettingsPayl export const updateUserRole = (id: string, role: string) => { return axios.post<{ message: string }>(apiUrls.userRoleByUserId(id), { role }); }; + +export const toggleCompletedOnboarding = (id: string) => { + return axios.post<{ message: string }>(apiUrls.toggleCompletedOnboarding(id)); +}; diff --git a/src/frontend/src/hooks/users.hooks.ts b/src/frontend/src/hooks/users.hooks.ts index b0c76b09b9..835141f47d 100644 --- a/src/frontend/src/hooks/users.hooks.ts +++ b/src/frontend/src/hooks/users.hooks.ts @@ -17,7 +17,8 @@ import { getCurrentUserSecureSettings, getUserSecureSettings, getUserScheduleSettings, - updateUserScheduleSettings + updateUserScheduleSettings, + toggleCompletedOnboarding } from '../apis/users.api'; import { User, @@ -28,7 +29,8 @@ import { UserSecureSettings, UserScheduleSettings, UserWithScheduleSettings, - SetUserScheduleSettingsPayload + SetUserScheduleSettingsPayload, + ToggleCompletedOnboardingPayload } from 'shared'; import { useAuth } from './auth.hooks'; import { useContext } from 'react'; @@ -233,3 +235,22 @@ export const useUpdateUserRole = () => { } ); }; + +/** + * Custom React Hook to update a user's role. + */ +export const useToggleCompletedOnboarding = () => { + const queryClient = useQueryClient(); + return useMutation<{ message: string }, Error, ToggleCompletedOnboardingPayload>( + ['users', 'toggle-onboarding'], + async (toggleCompletedOnboardingPayload: ToggleCompletedOnboardingPayload) => { + const { data } = await toggleCompletedOnboarding(toggleCompletedOnboardingPayload.userId); + return data; + }, + { + onSuccess: () => { + queryClient.invalidateQueries(['users']); + } + } + ); +}; diff --git a/src/frontend/src/pages/HomePage/OnboardingHomePage.tsx b/src/frontend/src/pages/HomePage/OnboardingHomePage.tsx index a9e8dd006d..fa2ceda074 100644 --- a/src/frontend/src/pages/HomePage/OnboardingHomePage.tsx +++ b/src/frontend/src/pages/HomePage/OnboardingHomePage.tsx @@ -1,19 +1,29 @@ -import React, { useEffect } from 'react'; -import { Box, Grid, Typography, useTheme } from '@mui/material'; +import { Box, Grid, Typography } from '@mui/material'; import PageLayout from '../../components/PageLayout'; import { useCurrentOrganization } from '../../hooks/organizations.hooks'; +import React, { useEffect, useState } from 'react'; import LoadingIndicator from '../../components/LoadingIndicator'; import ErrorPage from '../ErrorPage'; import { useHomePageContext } from '../../app/HomePageContext'; import ChecklistSection from './components/ChecklistSection'; import OnboardingInfoSection from './components/OnboardingInfoSection'; -import OnboardingProgressBar from '../../components/OnboardingProgressBar'; +import ConfirmOnboardingChecklistModal from './components/ConfirmOnboardingChecklistModal'; import { NERButton } from '../../components/NERButton'; +import { useCurrentUser, useToggleCompletedOnboarding } from '../../hooks/users.hooks'; +import { useToast } from '../../hooks/toasts.hooks'; const OnboardingHomePage = () => { const { data: organization, isError, error, isLoading } = useCurrentOrganization(); const { setCurrentHomePage } = useHomePageContext(); - const theme = useTheme(); + const [isModalOpen, setModalOpen] = useState(false); + + const user = useCurrentUser(); + + console.log(user); + + const toast = useToast(); + + const toggleCompletedOnboarding = useToggleCompletedOnboarding(); useEffect(() => { setCurrentHomePage('onboarding'); @@ -22,13 +32,31 @@ const OnboardingHomePage = () => { if (!organization || isLoading) return ; if (isError) return ; + const handleOpenModal = () => { + setModalOpen(true); + }; + + const handleCloseModal = () => { + setModalOpen(false); + }; + + const handleConfirmModal = async () => { + await toggleCompletedOnboarding.mutateAsync({ userId: user.userId }); + toast.success('Role updated successfully!'); + setModalOpen(false); + }; + return ( - + Welcome to the {organization.name} Team - Finished? + + + Finished? + + { flexDirection: 'column' }} > - - - - + + Progress Bar - + { + {isModalOpen && ( + + )} ); }; diff --git a/src/frontend/src/pages/HomePage/components/ConfirmOnboardingChecklistModal.tsx b/src/frontend/src/pages/HomePage/components/ConfirmOnboardingChecklistModal.tsx index dd2d2adcee..9394797ee3 100644 --- a/src/frontend/src/pages/HomePage/components/ConfirmOnboardingChecklistModal.tsx +++ b/src/frontend/src/pages/HomePage/components/ConfirmOnboardingChecklistModal.tsx @@ -1,34 +1,26 @@ import React from 'react'; import { Typography, Box } from '@mui/material'; import NERModal from '../../../components/NERModal'; -import { useCurrentUser } from '../../../hooks/users.hooks'; interface ConfirmOnboardingChecklistModalProps { open: boolean; onHide: () => void; + onConfirm: () => void; title?: string; + message?: string; } const ConfirmOnboardingChecklistModal: React.FC = ({ open, onHide, + onConfirm, title = 'Confirm Action' }) => { - const user = useCurrentUser(); - - const handleConfirm = () => { - if (user) { - user.role = 'MEMBER'; - } - onHide(); - }; - return ( - + `${users()}/secure-settings/current-user const userSecureSettingsSet = () => `${users()}/secure-settings/set`; const userRoleByUserId = (id: string) => `${usersById(id)}/change-role`; const userFavoriteProjects = (id: string) => `${usersById(id)}/favorite-projects`; -const userSecureSettings = (id: string) => `${usersById(id)}/secure-settings`; +const userSecureSettings = (id: string) => `${usersById(id)}/secure-psettings`; const userScheduleSettings = (id: string) => `${usersById(id)}/schedule-settings`; const userScheduleSettingsSet = () => `${users()}/schedule-settings/set`; +const toggleCompletedOnboarding = (id: string) => `${usersById(id)}/toggle-completed-onboarding`; /**************** Projects Endpoints ****************/ const projects = () => `${API_URL}/projects`; @@ -217,6 +218,7 @@ export const apiUrls = { userSecureSettings, userScheduleSettings, userScheduleSettingsSet, + toggleCompletedOnboarding, projects, allProjects, diff --git a/src/shared/src/types/user-types.ts b/src/shared/src/types/user-types.ts index 4cb0626f96..6ae35fb093 100644 --- a/src/shared/src/types/user-types.ts +++ b/src/shared/src/types/user-types.ts @@ -91,6 +91,10 @@ export interface UpdateUserRolePayload { role: string; } +export interface ToggleCompletedOnboardingPayload { + userId: string; +} + export interface UserScheduleSettings { drScheduleSettingsId: string; personalGmail: string;