initial commit

This commit is contained in:
2026-07-21 15:36:49 +07:00
commit 77f66132bc
2640 changed files with 850901 additions and 0 deletions
@@ -0,0 +1,90 @@
const AxiosManager = (() => {
const axiosInstance = axios.create({
baseURL: '/api',
headers: {
'accept': 'application/json',
'Content-Type': 'application/json',
}
});
let isRefreshing = false;
let retryQueue = [];
axiosInstance.interceptors.request.use(
(config) => {
const token = StorageManager.getAccessToken();
if (token) {
config.headers['Authorization'] = `Bearer ${token}`;
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
axiosInstance.interceptors.response.use(
(response) => response,
async (error) => {
const originalRequest = error.config;
if (error.response && error.response.status === 498) {
if (!isRefreshing) {
isRefreshing = true;
try {
const refreshToken = StorageManager.getRefreshToken();
const response = await axiosInstance.post('/Security/RefreshToken', { refreshToken });
if (response?.data?.code === 200) {
StorageManager.saveLoginResult(response?.data);
isRefreshing = false;
retryQueue.forEach((cb) => cb());
retryQueue = [];
return axiosInstance(originalRequest);
} else {
throw new Error('Refresh token failed');
}
} catch (refreshError) {
retryQueue.forEach((cb) => cb());
retryQueue = [];
isRefreshing = false;
throw refreshError;
}
}
return new Promise((resolve, reject) => {
retryQueue.push(() => {
resolve(axiosInstance(originalRequest));
});
});
}
return Promise.reject(error);
}
);
const request = async (method, url, data = {}, customHeaders = {}, responseType = 'json') => {
try {
const response = await axiosInstance({
method,
url,
data,
headers: {
...customHeaders,
},
responseType,
});
return response;
} catch (error) {
throw error;
}
};
return {
request,
get: (url, config = {}) => request('get', url, {}, config.headers, config.responseType),
post: (url, data, config = {}) => request('post', url, data, config.headers, config.responseType),
put: (url, data, config = {}) => request('put', url, data, config.headers, config.responseType),
delete: (url, config = {}) => request('delete', url, {}, config.headers, config.responseType),
};
})();
@@ -0,0 +1,25 @@
const DateFormatManager = {
formatToLocale: (date) => {
const formatter = new Intl.DateTimeFormat('en-CA', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
});
const newDate = new Date(date)
return formatter.format(newDate);
},
preserveClientDate: (date) => {
if (!date) return null
const now = new Date()
const localDate = new Date(date.getFullYear(), date.getMonth(), date.getDate(), now.getHours(), now.getMinutes(), now.getSeconds())
return localDate.getFullYear() + '-' +
String(localDate.getMonth() + 1).padStart(2, '0') + '-' +
String(localDate.getDate()).padStart(2, '0') + 'T' +
String(localDate.getHours()).padStart(2, '0') + ':' +
String(localDate.getMinutes()).padStart(2, '0') + ':' +
String(localDate.getSeconds()).padStart(2, '0')
},
};
@@ -0,0 +1,33 @@
const NumberFormatManager = {
formatToLocale: (number) => {
const userLocale = navigator.language || 'en-US';
const formatter = new Intl.NumberFormat(userLocale, {
style: 'decimal',
minimumFractionDigits: 2,
maximumFractionDigits: 2,
});
if (typeof number !== 'number') {
console.warn("Input must be a number, default value returned: 0");
number = 0;
}
return formatter.format(number);
},
formatToLocaleNoDecimal: (number) => {
const userLocale = navigator.language || 'en-US';
const formatter = new Intl.NumberFormat(userLocale, {
style: 'decimal',
minimumFractionDigits: 0,
maximumFractionDigits: 0,
});
if (typeof number !== 'number') {
console.warn("Input must be a number, default value returned: 0");
number = 0;
}
return formatter.format(number);
},
};
@@ -0,0 +1,58 @@
const SecurityManager = {
authorizePage: async (requiredRoles) => {
const userRoles = StorageManager.getUserRoles();
const isAuthorized = userRoles?.some(role => requiredRoles.includes(role));
if (!isAuthorized) {
Swal.fire({
icon: 'error',
title: 'Unauthorized',
text: 'You are being redirected...',
timer: 2000,
showConfirmButton: false
});
setTimeout(() => {
window.location.href = '/Accounts/Login';
}, 2000);
}
},
validateToken: async () => {
try {
const response = await AxiosManager.post('/Security/ValidateToken',
{},
);
if (response?.data?.code === 200) {
return true;
} else {
Swal.fire({
icon: 'error',
title: 'Token not valid',
text: 'You are being redirected...',
timer: 2000,
showConfirmButton: false
});
setTimeout(() => {
window.location.href = '/Accounts/Login';
}, 2000);
return false;
}
} catch (error) {
Swal.fire({
icon: 'error',
title: error?.response?.data?.message || 'Error validating token',
text: 'You are being redirected...',
timer: 2000,
showConfirmButton: false
});
setTimeout(() => {
window.location.href = '/Accounts/Login';
}, 2000);
return false;
}
}
};
@@ -0,0 +1,106 @@
const STORAGE_KEYS = {
ACCESS_TOKEN: 'accessToken',
REFRESH_TOKEN: 'refreshToken',
IS_AUTHENTICATED: 'isAuthenticated',
FIRST_NAME: 'firstName',
LAST_NAME: 'lastName',
EMAIL: 'email',
USER_ID: 'userId',
USER_ROLES: 'userRoles',
MENU_NAVIGATION: 'menuNavigation',
AVATAR: 'avatar',
COMPANY: 'company'
};
const StorageManager = {
save: (key, value) => {
try {
localStorage.setItem(key, JSON.stringify(value));
} catch (error) {
console.error('Failed to save data to localStorage', error);
}
},
get: (key) => {
try {
const value = localStorage.getItem(key);
return value ? JSON.parse(value) : null;
} catch (error) {
console.error('Failed to retrieve data from localStorage', error);
return null;
}
},
remove: (key) => {
try {
localStorage.removeItem(key);
} catch (error) {
console.error('Failed to remove data from localStorage', error);
}
},
clearStorage: () => {
try {
localStorage.clear();
} catch (error) {
console.error('Failed to clear localStorage', error);
}
},
saveAccessToken: (token) => StorageManager.save(STORAGE_KEYS.ACCESS_TOKEN, token),
getAccessToken: () => StorageManager.get(STORAGE_KEYS.ACCESS_TOKEN),
removeAccessToken: () => StorageManager.remove(STORAGE_KEYS.ACCESS_TOKEN),
saveRefreshToken: (token) => StorageManager.save(STORAGE_KEYS.REFRESH_TOKEN, token),
getRefreshToken: () => StorageManager.get(STORAGE_KEYS.REFRESH_TOKEN),
removeRefreshToken: () => StorageManager.remove(STORAGE_KEYS.REFRESH_TOKEN),
saveIsAuthenticated: (status) => StorageManager.save(STORAGE_KEYS.IS_AUTHENTICATED, status),
getIsAuthenticated: () => StorageManager.get(STORAGE_KEYS.IS_AUTHENTICATED),
removeIsAuthenticated: () => StorageManager.remove(STORAGE_KEYS.IS_AUTHENTICATED),
saveFirstName: (firstName) => StorageManager.save(STORAGE_KEYS.FIRST_NAME, firstName),
getFirstName: () => StorageManager.get(STORAGE_KEYS.FIRST_NAME),
removeFirstName: () => StorageManager.remove(STORAGE_KEYS.FIRST_NAME),
saveLastName: (lastName) => StorageManager.save(STORAGE_KEYS.LAST_NAME, lastName),
getLastName: () => StorageManager.get(STORAGE_KEYS.LAST_NAME),
removeLastName: () => StorageManager.remove(STORAGE_KEYS.LAST_NAME),
saveEmail: (email) => StorageManager.save(STORAGE_KEYS.EMAIL, email),
getEmail: () => StorageManager.get(STORAGE_KEYS.EMAIL),
removeEmail: () => StorageManager.remove(STORAGE_KEYS.EMAIL),
saveUserId: (userId) => StorageManager.save(STORAGE_KEYS.USER_ID, userId),
getUserId: () => StorageManager.get(STORAGE_KEYS.USER_ID),
removeUserId: () => StorageManager.remove(STORAGE_KEYS.USER_ID),
saveUserRoles: (roles) => StorageManager.save(STORAGE_KEYS.USER_ROLES, roles),
getUserRoles: () => StorageManager.get(STORAGE_KEYS.USER_ROLES),
removeUserRoles: () => StorageManager.remove(STORAGE_KEYS.USER_ROLES),
saveMenuNavigation: (navigations) => StorageManager.save(STORAGE_KEYS.MENU_NAVIGATION, navigations),
getMenuNavigation: () => StorageManager.get(STORAGE_KEYS.MENU_NAVIGATION),
removeMenuNavigation: () => StorageManager.remove(STORAGE_KEYS.MENU_NAVIGATION),
saveAvatar: (avatar) => StorageManager.save(STORAGE_KEYS.AVATAR, avatar),
getAvatar: () => StorageManager.get(STORAGE_KEYS.AVATAR),
removeAvatar: () => StorageManager.remove(STORAGE_KEYS.AVATAR),
saveCompany: (company) => StorageManager.save(STORAGE_KEYS.COMPANY, company),
getCompany: () => StorageManager.get(STORAGE_KEYS.COMPANY),
removeCompany: () => StorageManager.remove(STORAGE_KEYS.COMPANY),
saveLoginResult: (data) => {
StorageManager.saveAccessToken(data?.content?.data?.accessToken);
StorageManager.saveRefreshToken(data?.content?.data?.refreshToken);
StorageManager.saveFirstName(data?.content?.data?.firstName);
StorageManager.saveLastName(data?.content?.data?.lastName);
StorageManager.saveEmail(data?.content?.data?.email);
StorageManager.saveUserId(data?.content?.data?.userId);
StorageManager.saveUserRoles(data?.content?.data?.roles);
StorageManager.saveMenuNavigation(data?.content?.data?.menuNavigation);
StorageManager.saveIsAuthenticated(StorageManager.getUserId() != null);
StorageManager.saveAvatar(data?.content?.data?.avatar);
}
};