Skip to content

Commit

Permalink
convert authApi to separate API slice and implement update user info …
Browse files Browse the repository at this point in the history
…through RTK query mutation

add get rcrainfo profile to RTK query endpoint

move get rcrainfo profile to RTK query

add get user profile to rtk query
  • Loading branch information
dpgraham4401 committed Dec 19, 2023
1 parent b13f059 commit 986e904
Show file tree
Hide file tree
Showing 15 changed files with 216 additions and 186 deletions.
2 changes: 1 addition & 1 deletion client/src/components/Auth/LoginForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import { FloatingLabel, Form } from 'react-bootstrap';
import { useForm } from 'react-hook-form';
import { useNavigate } from 'react-router-dom';
import { setCredentials, useAppDispatch, useAppSelector, useLoginMutation } from 'store';
import { selectAuthenticated } from 'store/userSlice/user.slice';
import { z } from 'zod';
import { selectAuthenticated } from 'store/authSlice/auth.slice';

const loginSchema = z.object({
username: z.string().min(1, 'Username Required').min(8),
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/Layout/PrivateRoute.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { ReactElement } from 'react';
import { Navigate } from 'react-router-dom';
import { useAppSelector } from 'store';
import { selectAuthenticated } from 'store/authSlice/auth.slice';
import { selectAuthenticated } from 'store/userSlice/user.slice';

interface Props {
children: any;
Expand Down
4 changes: 2 additions & 2 deletions client/src/components/Layout/TopNav/TopNav.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import logo from '/assets/img/haztrak-logos/haztrak-logo-zip-file/svg/logo-no-background.svg';
import { faArrowRightFromBracket, faBars, faGear, faUser } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import logo from '/assets/img/haztrak-logos/haztrak-logo-zip-file/svg/logo-no-background.svg';
import { NavContext, NavContextProps } from 'components/Layout/Root';
import React, { useContext } from 'react';
import { Button, Dropdown } from 'react-bootstrap';
import { useDispatch, useSelector } from 'react-redux';
import { Link, useNavigate } from 'react-router-dom';
import { logout, selectAuthenticated } from 'store/authSlice/auth.slice';
import { logout, selectAuthenticated } from 'store/userSlice/user.slice';

export function TopNav() {
const { showSidebar, setShowSidebar } = useContext<NavContextProps>(NavContext);
Expand Down
17 changes: 5 additions & 12 deletions client/src/components/User/UserInfoForm.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
import { faUser } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { zodResolver } from '@hookform/resolvers/zod';
import { AxiosError } from 'axios';
import { HtForm, HtSpinner } from 'components/UI';
import React, { createRef, useState } from 'react';
import { Button, Col, Container, Form, Row } from 'react-bootstrap';
import { Button, Col, Form, Row } from 'react-bootstrap';
import { useForm } from 'react-hook-form';
import { toast } from 'react-toastify';
import { UserApi } from 'services';
import { HaztrakUser, ProfileSlice, updateUserProfile, useAppDispatch } from 'store';
import { HaztrakUser, ProfileSlice, useUpdateUserMutation } from 'store';
import { z } from 'zod';

interface UserProfileProps {
user: HaztrakUser;
profile: ProfileSlice;
profile?: ProfileSlice;
}

const haztrakUserForm = z.object({
Expand All @@ -26,8 +23,8 @@ type HaztrakUserForm = z.infer<typeof haztrakUserForm>;

export function UserInfoForm({ user, profile }: UserProfileProps) {
const [editable, setEditable] = useState(false);
const [updateUser] = useUpdateUserMutation();
const fileRef = createRef<HTMLInputElement>();
const dispatch = useAppDispatch();

const {
register,
Expand All @@ -38,11 +35,7 @@ export function UserInfoForm({ user, profile }: UserProfileProps) {

const onSubmit = (data: HaztrakUserForm) => {
setEditable(!editable);
UserApi.updateUser(data)
.then((response) => {
dispatch(updateUserProfile(response.data));
})
.catch((error: AxiosError) => toast.error(error.message));
updateUser({ ...user, ...data });
};

if (user?.isLoading || profile?.loading) return <HtSpinner center />;
Expand Down
2 changes: 1 addition & 1 deletion client/src/features/Dashboard/Dashboard.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { afterAll, afterEach, beforeAll, describe, expect, test, vi } from 'vite
const USERNAME = 'testuser1';

const myAPIHandlers = [
http.get(`${API_BASE_URL}/api/rcra/profile/${USERNAME}`, (info) => {
http.get(`${API_BASE_URL}/api/user/rcrainfo-profile/${USERNAME}`, (info) => {
return HttpResponse.json(
{
user: USERNAME,
Expand Down
14 changes: 7 additions & 7 deletions client/src/features/Profile/Profile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,22 @@ import { UserInfoForm } from 'components/User';
import { useTitle } from 'hooks';
import React, { ReactElement } from 'react';
import { Col, Container, Row } from 'react-bootstrap';
import { selectHaztrakProfile, useAppSelector, useGetUserQuery } from 'store';
import { useGetProfileQuery, useGetRcrainfoProfileQuery, useGetUserQuery } from 'store';

/**
* Display user profile, including their Haztrak information, their organization,
* and their RCRAInfo profile.
* @constructor
*/
export function Profile(): ReactElement {
const profile = useAppSelector(selectHaztrakProfile);
const { data: user, isLoading } = useGetUserQuery();
const { data: profile, isLoading: profileLoading } = useGetProfileQuery();
const { data: user, isLoading: userLoading } = useGetUserQuery();
const { data: rcrainfoProfile } = useGetRcrainfoProfileQuery('testuser1');
const isLoading = profileLoading || userLoading;
useTitle('Profile');

if (isLoading) {
if (isLoading ?? !user ?? !profile) {
return <HtSpinner center />;
} else if (!user) {
return <div>Unable to load user profile.</div>;
}

return (
Expand All @@ -47,7 +47,7 @@ export function Profile(): ReactElement {
<Col>
<HtCard title="RCRAInfo Profile">
<HtCard.Body>
{profile.rcrainfoProfile && <RcraProfile profile={profile.rcrainfoProfile} />}
{rcrainfoProfile && <RcraProfile profile={rcrainfoProfile} />}
</HtCard.Body>
</HtCard>
</Col>
Expand Down
8 changes: 4 additions & 4 deletions client/src/services/APIs/UserApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ interface RcrainfoProfileResponse extends RcrainfoProfile<Array<RcrainfoProfileS
export const UserApi = {
/** Fetch the user's Haztrak profile from the Haztrak API*/
getUserProfile: async (): Promise<AxiosResponse<HaztrakProfileResponse>> => {
return await htApi.get('/profile');
return await htApi.get('/user/profile');
},

/** Fetch Haztrak user from server*/
Expand All @@ -38,7 +38,7 @@ export const UserApi = {

/** Fetch the user's RCRAInfo profile from the Haztrak API*/
getRcrainfoProfile: async (username: string): Promise<AxiosResponse<RcrainfoProfileResponse>> => {
return await htApi.get(`/rcra/profile/${username}`);
return await htApi.get(`/user/rcrainfo-profile/${username}`);
},

/** Update user's RCRAInfo Profile information such username, api ID & key*/
Expand All @@ -49,11 +49,11 @@ export const UserApi = {
username: string;
data: any;
}): Promise<AxiosResponse<any>> => {
return await htApi.put(`/rcra/profile/${username}`, data);
return await htApi.put(`/user/rcrainfo-profile/${username}`, data);
},

/** Launch task to pull user's site/module permissions (RCRAInfo profile) from RCRAInfo*/
syncRcrainfoProfile: async (): Promise<AxiosResponse<{ taskId: string }>> => {
return await htApi.get(`rcra/profile/sync`);
return await htApi.get(`user/rcrainfo-profile/sync`);
},
};
97 changes: 0 additions & 97 deletions client/src/store/authSlice/auth.slice.ts

This file was deleted.

3 changes: 2 additions & 1 deletion client/src/store/haztrakApiSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import { BaseQueryFn, createApi } from '@reduxjs/toolkit/query/react';
import { AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios';
import { HaztrakSite } from 'components/HaztrakSite';
import { Manifest } from 'components/Manifest';
import { QuickerSignature } from 'components/Manifest/QuickerSign';
import { Code } from 'components/Manifest/WasteLine/wasteLineSchema';
import { MtnDetails } from 'components/Mtn';
import { RcraSite } from 'components/RcraSite';
import { htApi } from 'services';
import { QuickerSignature } from 'components/Manifest/QuickerSign';

export interface TaskResponse {
taskId: string;
Expand Down Expand Up @@ -76,6 +76,7 @@ interface RcrainfoSiteSearch {
}

export const haztrakApi = createApi({
tagTypes: ['user'],
reducerPath: 'haztrakApi',
baseQuery: htApiBaseQuery({
baseUrl: `${import.meta.env.VITE_HT_API_URL}/api/`,
Expand Down
17 changes: 11 additions & 6 deletions client/src/store/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { AppDispatch, AppStore, RootState } from './rootStore';
import { authApi } from 'store/userSlice/user.slice';
// Haztrak API - RTK Query
import { haztrakApi } from './haztrakApiSlice';
import { authApi } from 'store/authSlice/auth.slice';
import type { AppDispatch, AppStore, RootState } from './rootStore';

// Root Store
export { rootStore, setupStore, useAppDispatch, useAppSelector } from './rootStore';
Expand All @@ -25,19 +25,24 @@ export const {
useUpdateManifestMutation,
} = haztrakApi;

export const { useLoginMutation, useGetUserQuery } = authApi;
export const {
useLoginMutation,
useGetUserQuery,
useGetProfileQuery,
useGetRcrainfoProfileQuery,
useUpdateUserMutation,
} = authApi;

// Authentication Slice
export {
selectUser,
selectUserName,
updateUserProfile,
setCredentials,
} from './authSlice/auth.slice';
} from 'store/userSlice/user.slice';

// Profile Slice
export {
getHaztrakProfile,
getRcraProfile,
selectRcrainfoSites,
selectRcraProfile,
Expand Down Expand Up @@ -65,7 +70,7 @@ export {
export { addError, selectAllErrors } from './errorSlice/error.slice';

// Types
export type { HaztrakUser } from './authSlice/auth.slice';
export type { HaztrakUser } from 'store/userSlice/user.slice';
export type { HaztrakError } from './errorSlice/error.slice';
export type { TaskStatus } from './haztrakApiSlice';
export type { LongRunningTask, HaztrakAlert } from './notificationSlice/notification.slice';
Expand Down
39 changes: 0 additions & 39 deletions client/src/store/profileSlice/profile.slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,25 +73,6 @@ const initialState: ProfileSlice = {
error: undefined,
};

/**Retrieves a user's profile from the server.*/
export const getHaztrakProfile = createAsyncThunk('profile/getHaztrakProfile', async () => {
const { data } = await UserApi.getUserProfile();
const sites = data.sites.reduce((obj, site) => {
return {
...obj,
[site.site.handler.epaSiteId]: {
...site.site,
permissions: { eManifest: site.eManifest },
},
};
}, {});
return {
user: data.user,
org: data.org,
sites: sites,
} as ProfileSlice;
});

/**Retrieves a user's RcrainfoProfile, if it exists, from the server.*/
export const getRcraProfile = createAsyncThunk<ProfileSlice>(
'profile/getRcrainfoProfile',
Expand Down Expand Up @@ -130,26 +111,6 @@ const profileSlice = createSlice({
},
extraReducers: (builder) => {
builder
.addCase(getHaztrakProfile.pending, (state) => {
return {
...state,
loading: true,
error: undefined,
};
})
.addCase(getHaztrakProfile.fulfilled, (state, action) => {
return {
...state,
...action.payload,
loading: false,
error: undefined,
};
})
.addCase(getHaztrakProfile.rejected, (state) => {
state.loading = false;
state.error = 'error';
return state;
})
.addCase(getRcraProfile.pending, (state) => {
return {
...state,
Expand Down
Loading

0 comments on commit 986e904

Please sign in to comment.