Skip to content

Commit

Permalink
Add skill, category, package page
Browse files Browse the repository at this point in the history
  • Loading branch information
HoaAyWK committed Nov 15, 2022
1 parent 8e704a0 commit a3ec29f
Show file tree
Hide file tree
Showing 20 changed files with 697 additions and 238 deletions.
20 changes: 20 additions & 0 deletions src/app/api.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import axios from 'axios';

const instance = axios.create({
baseURL: 'http://localhost:5001/api/v1',
});


instance.interceptors.request.use((config) => {
const token = JSON.parse(localStorage.getItem('token'));

if (token) {
config.headers['Authorization'] = 'Bearer ' + token;
}

return config;
}, (error) => {
return Promise.reject(error);
});

export default instance;
6 changes: 5 additions & 1 deletion src/app/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ export const MESSAGE_VARIANT = {
ERROR: 'error'
};

export const MESSAGE_ERRORS = {
UNAUTHORIZE: "You don't have permission to acess this resource"
};

export const ROLES = {
ADMIN: 'admin'
ADMIN: 'Admin'
};
69 changes: 36 additions & 33 deletions src/app/slices/authSlice.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import axios from 'axios';
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";

import { BASE_API_URL, action_status, ROLES, MESSAGE_VARIANT } from '../constants';
import { BASE_API_URL, action_status, ROLES, MESSAGE_VARIANT, MESSAGE_ERRORS } from '../constants';
import { setMessage } from './messageSlice';
import api from '../api';

const initialState = {
user: null,
status: action_status.IDLE,
loginStatus: action_status.IDLE,
getUserStatus: action_status.IDLE,
error: null,
isAuthenticated: false,
updated: false,
updateStatus: action_status.IDLE,
changedPassword: false,
Expand All @@ -19,15 +20,9 @@ export const login = createAsyncThunk(
'auth/login',
async ({ email, password }, thunkApi) => {
try {
const response = await axios.post(`${BASE_API_URL}/login`, { email, password }, { withCredentials: true });
const { user } = response.data;

if (!user.roles.includes(ROLES.ADMIN)) {
throw new Error('You do not have permission to access this page');
}

console.log(response.data);
return response.data.user;
const { data } = await api.post('/account/login', { email, password });

return data.accessToken;
} catch (error) {
const message = (error.response && error.response.data && error.response.data.message)
|| error.message || error.toString();
Expand All @@ -41,9 +36,17 @@ export const login = createAsyncThunk(

export const getCurrentUser = createAsyncThunk(
'auth/getCurrentUser',
async () => {
const { data } = await axios.get(`${BASE_API_URL}/profile`, { withCredentials: true });
return data;
async (_, thunkApi) => {
try {
const { data } = await api.get(`/users/profile`);

return data;
} catch (error) {
const message = (error.response && error.response.data && error.response.data.message)
|| error.message || error.toString();

thunkApi.dispatch(setMessage({ message, variant: MESSAGE_VARIANT.ERROR }));
}
}
);

Expand Down Expand Up @@ -105,46 +108,47 @@ const authSlice = createSlice({
state.changedPasswordStatus = action_status.IDLE;
},
logout: (state, action) => {
state.user = null;
state.isAuthenticated = false;
state.changedPasswordStatus = action_status.IDLE;
state.updateStatus = action_status.IDLE;
state.error = null;
state.status = action_status.IDLE;
state.loginStatus = action_status.IDLE;
state.getUserStatus = action_status.IDLE;
state.changedPassword = false;
state.updated = false;
localStorage.setItem('user', null);
state.user = null;
localStorage.setItem('token', null);
}
},
extraReducers: (builder) => {
builder
.addCase(login.pending, (state, action) => {
state.status = action_status.LOADING;
state.loginStatus = action_status.LOADING;
})
.addCase(login.fulfilled, (state, action) => {
state.status = action_status.SUCCEEDED;
state.user = action.payload;
localStorage.setItem('user', JSON.stringify(action.payload));
state.isAuthenticated = true;
state.loginStatus = action_status.SUCCEEDED;
localStorage.setItem('token', JSON.stringify(action.payload));
})
.addCase(login.rejected, (state, action) => {
state.status = action_status.FAILED;
state.error = action;
state.loginStatus = action_status.FAILED;
})
.addCase(getCurrentUser.pending, (state, action) => {
state.getUserStatus = action_status.LOADING;
})
.addCase(getCurrentUser.fulfilled, (state, action) => {
state.loginStatus = false;
state.getUserStatus = action_status.SUCCEEDED;
state.user = action.payload.user;
state.isAuthenticated = true;
localStorage.setItem('user', JSON.stringify(action.payload.user));
})
.addCase(getCurrentUser.rejected, (state, action) => {
state.getUserStatus = action_status.FAILED;
})
.addCase(updateAccount.pending, (state, action) => {
state.updated = false;
state.updateStatus = action_status.LOADING;
})
.addCase(updateAccount.fulfilled, (state, action) => {
state.user = action.payload.user;
state.updated = true;
state.updateStatus = action_status.SUCCEEDED;
localStorage.setItem('user', JSON.stringify(action.payload.user));
})
.addCase(updateAccount.rejected, (state, action) => {
state.updateStatus = action_status.FAILED;
Expand All @@ -156,10 +160,9 @@ const authSlice = createSlice({
.addCase(changePassword.fulfilled, (state, action) => {
state.changedPassword = true;
state.user = null;
state.isAuthenticated = false;
state.status = action_status.IDLE;
state.changedPasswordStatus = action_status.SUCCEEDED;
localStorage.setItem('user', null);
localStorage.setItem('token', null);
})
.addCase(changePassword.rejected, (state, action) => {
state.changedPasswordStatus = action_status.FAILED;
Expand All @@ -168,5 +171,5 @@ const authSlice = createSlice({
});

const { actions, reducer } = authSlice;
export const { refresh, logout } = actions;
export const { refresh, logout } = actions;
export default reducer;
58 changes: 15 additions & 43 deletions src/app/slices/categorySlice.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import { createSlice, createAsyncThunk, createEntityAdapter, createSelector } from '@reduxjs/toolkit';
import axios from 'axios';

import { action_status, BASE_API_URL, MESSAGE_VARIANT } from '../constants';
import { setMessage } from './messageSlice';
import api from '../api';

const categoriesAdapter = createEntityAdapter();

const initialState = categoriesAdapter.getInitialState({
status: action_status.IDLE,
error: null,
updated: false,
added: false,
deleted: false
isUpdated: false,
isAdded: false,
isDeleted: false
});

export const getCategories = createAsyncThunk(
'categories/getCategories',
async () => {
const { data } = await axios.get(`${BASE_API_URL}/admin/categories`, { withCredentials: true });
const { data } = await api.get('/categories');
return data;
}
);
Expand All @@ -26,13 +26,7 @@ export const createCategory = createAsyncThunk(
'categories/create',
async (category, thunkApi) => {
try {
if (!category.parent) {
category.parent = null;
}
const { data } = await axios.post(
`${BASE_API_URL}/admin/categories/create`,
category,
{ withCredentials: true });
const { data } = await api.post('/categories/admin/create', category);

return data;
} catch (error) {
Expand All @@ -50,13 +44,7 @@ export const updateCategory = createAsyncThunk(
'categories/update',
async (category, thunkApi) => {
try {
if (!category.parent) {
category.parent = null;
}
const { data } = await axios.put(
`${BASE_API_URL}/admin/categories/${category.id}`,
category,
{ withCredentials: true });
const { data } = await api.put(`/categories/admin/${category.id}`, category);

return data;
} catch (error) {
Expand All @@ -74,10 +62,7 @@ export const deleteCategory = createAsyncThunk(
'categories/delete',
async (categoryId, thunkApi) => {
try {
const { data } = await axios.delete(
`${BASE_API_URL}/admin/categories/${categoryId}`,
{ withCredentials: true }
);
const { data } = await api.delete(`/categories/admin/${categoryId}`);

data.categoryId = categoryId;
return data;
Expand All @@ -97,9 +82,9 @@ const categorySlice = createSlice({
initialState,
reducers: {
refresh: (state, action) => {
state.updated = false;
state.added = false;
state.deleted = false;
state.isUpdated = false;
state.isAdded = false;
state.isDeleted = false;
}
},
extraReducers: (builder) => {
Expand All @@ -117,30 +102,22 @@ const categorySlice = createSlice({
})
.addCase(createCategory.fulfilled, (state, action) => {
categoriesAdapter.addOne(state, action.payload.category);
state.added = true;
state.isAdded = true;
})
.addCase(createCategory.rejected, (state, action) => {
state.error = action.error;
})
.addCase(updateCategory.fulfilled, (state, action) => {
const { category } = action.payload;
let existingCategory = state.entities[category.id];

console.log(existingCategory);
if (existingCategory) {
existingCategory = category;
}

state.updated = true;
state.isUpdated = true;
})
.addCase(updateCategory.rejected, (state, action) => {
state.error = action.error;
})
.addCase(deleteCategory.pending, (state, action) => {
state.deleted = false;
state.isDeleted = false;
})
.addCase(deleteCategory.fulfilled, (state, action) => {
state.deleted = true;
state.isDeleted = true;
categoriesAdapter.removeOne(state, action.payload.categoryId);
})
}
Expand All @@ -155,9 +132,4 @@ export const {
const { reducer, actions } = categorySlice;
export const { refresh } = actions;

export const selectRootCategories = createSelector(
[selectAllCategories],
(categories) => categories.filter(category => !category.parent)
);

export default reducer;
Loading

0 comments on commit a3ec29f

Please sign in to comment.