DEV Community

Cover image for Hire+Plus! For Employees Here's how I built it (Redux - Profile)
AjeaS
AjeaS

Posted on

Hire+Plus! For Employees Here's how I built it (Redux - Profile)

Purpose: The candidate will be able to view and edit their profile.

Types, Actions, and Reducers: Profile State

Types

inside app > features > profile > profileTypes.ts
Data types for a profile. UpdatedFields are the only fields I needed to update the profile page.

export type ProfileData = {
    id: string;
    email: string;
    createdAt: number;
    headline: string;
    isForHire: boolean;
    websiteURL: string;
    skills: string[];
    summary: string;
    projects: ProjectData[];
    experience: ExperienceData[];
};
export type ExperienceData = {
    date: string;
    position: string;
    positionSummary: string;
};
export type ProjectData = {
    date: string;
    title: string;
    summary: string;
    github: string;
    projectUrl: string;
};

export type UpdatedFields = {
    id: string;
    headline: string;
    summary: string;
    isForHire: boolean;
    websiteURL: string;
    skills: string[];
    experience: ExperienceData[];
    projects: ProjectData[];
};
Enter fullscreen mode Exit fullscreen mode

Actions

inside app > features > profile > profileSlice.ts
The initial state for profile reducer. getProfileById gets its profile by id and returns the stringified version. updateProfileById updates your profile.

import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
import { getProfile, updateUserProfileById } from '../../../utils/firebase/firebase.utils';
import { signoutUser } from '../auth/authSlice';
import { ProfileData, UpdatedFields } from './profileTypes';

interface userState {
    profile: ProfileData;
    isLoading: boolean;
    isEditting: boolean;
}
const initialState: userState = {
    profile: {
        id: '',
        email: '',
        createdAt: Date.now(),
        headline: '',
        isForHire: false,
        websiteURL: '',
        skills: [],
        summary: '',
        projects: [],
        experience: [],
    },
    isLoading: false,
    isEditting: false,
};

export const getProfileById = createAsyncThunk(
    'profile/getProfileById',
    async (id: string) => {
        const profile = await getProfile(id);
        const [profileObj] = profile;
        return JSON.stringify(profileObj);
    }
);
export const updateProfileById = createAsyncThunk(
    'profile/updateProfileById',
    async (data: UpdatedFields): Promise<void> => {
        await updateUserProfileById(data);
    }
);
Enter fullscreen mode Exit fullscreen mode

Reducers

setEditView - if editing is set to true, it'll show an editing page for the candidate to edit their profile.
setProjects - will set projects from the editing page
setExperiences - will set experiences from the editing page

extraReducers: I handled the response states and set the state accordingly.

const profileSlice = createSlice({
    name: 'profile',
    initialState,
    reducers: {
        setEditView(state, action) {
            state.isEditting = action.payload;
        },
        setProjects(state, action) {
            state.profile.projects = action.payload;
        },
        setExperiences(state, action) {
            state.profile.experience = action.payload;
        },
    },
    extraReducers: (builder) => {
        builder
            .addCase(getProfileById.pending, (state) => {
                state.isLoading = true;
            })
            .addCase(signoutUser.fulfilled, (state) => {
                state.profile = {
                    id: '',
                    email: '',
                    createdAt: Date.now(),
                    headline: '',
                    isForHire: false,
                    websiteURL: '',
                    skills: [],
                    summary: '',
                    projects: [],
                    experience: [],
                };
            })
            .addCase(getProfileById.fulfilled, (state, action) => {
                state.isLoading = false;
                state.profile = JSON.parse(action.payload);
            })
            .addCase(getProfileById.rejected, (state, action) => {
                state.isLoading = false;
                console.log('error with profile', action.error);
            });
    },
});

export const { setEditView, setProjects, setExperiences } =
    profileSlice.actions;

export default profileSlice.reducer;

Enter fullscreen mode Exit fullscreen mode

That's all for the profile/redux portion of the project, stay tuned!

Top comments (0)