Update the type of data in project

This commit is contained in:
2023-09-27 17:08:54 +07:00
parent b48089ffe4
commit 50c19ff6c4
11 changed files with 227 additions and 5610 deletions
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
+1 -1
View File
@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
@@ -26,6 +26,6 @@ export const UPDATE_TRANSACTION_SUCCESS = 'Update success!';
export const REGISTER_SUCCESS = 'Register Success';
export const REQUIRED_MESSAGE = (field) => `The ${field} is required!`;
export const REQUIRED_MESSAGE = (field: string) => `The ${field} is required!`;
export const INVALID_EMAIL_FORMAT = `The email is not correct!`;
+22 -6
View File
@@ -1,6 +1,7 @@
import * as MESSAGE from '../constants/message';
import { TIME_OUT_SEC, REGEX } from '../constants/config';
import FirebaseService from '../services/firebaseService';
import { dataObj } from './interface';
/**
* Validate password
@@ -45,10 +46,10 @@ export const createIdUser = (): number => {
* @param {Function} action The action need to be perform.
* @returns { Object || Error } Return the any object from Firebase or Error
*/
export const timeOutConnect = async (
action: Promise<object>,
): Promise<string | object> => {
const result: object | string = await Promise.race([
export const timeOutConnect = async <T>(
action: Promise<T>,
): Promise<string | T> => {
const result: T | string = await Promise.race([
action,
timeout(TIME_OUT_SEC),
]);
@@ -56,7 +57,7 @@ export const timeOutConnect = async (
return result;
};
export const renderRequiredText = (field: string, element: Element) => {
export const renderRequiredText = (field: string, element: Element): void => {
const markup: string = `
<p class="error-text">${MESSAGE.REQUIRED_MESSAGE(field)}</p>
`;
@@ -64,6 +65,21 @@ export const renderRequiredText = (field: string, element: Element) => {
element.insertAdjacentHTML('afterend', markup);
};
export const redirectToLoginPage = () => {
export const redirectToLoginPage = (): void => {
window.location.replace('/login');
};
export const convertDataObjectToModel = (dataObj: {
id: string;
data: object;
}): dataObj => {
const { id } = dataObj;
return { id, ...dataObj.data } as dataObj;
};
export const convertModelToDataObject = <T extends dataObj>(model: T): T => {
const { id, ...data } = model;
return { id, data } as T;
};
@@ -0,0 +1,4 @@
export interface dataObj {
id: string;
data: object;
}
+18
View File
@@ -0,0 +1,18 @@
import { createIdUser } from '../helpers/helpers';
export default class User {
private id: number;
private email: string;
private password: string;
private accessToken: string;
constructor(email: string, password: string, accessToken: string) {
this.id = createIdUser();
this.email = email;
this.password = password;
this.accessToken = accessToken;
}
}
@@ -1,43 +1,30 @@
import {
timeOutConnect,
convertDataObjectToModel,
convertModelToDataObject,
timeOutConnect,
} from '../helpers/helpers';
import { dataObj } from '../helpers/interface';
import FirebaseService from './firebaseService';
export default class CommonService {
constructor() {
this.defaultPath = '/';
this.firebaseService = FirebaseService;
}
export default class CommonService<T extends dataObj> {
private defaultPath: string = '/';
private firebaseService = FirebaseService;
/**
* Connect to Firebase Databse
* Connect to Firebase Database
*/
connectToDb() {
this.firebaseService.reconnect();
}
async getDataFromProp(property, value, path = this.defaultPath) {
this.connectToDb();
const data = this.firebaseService.getDataFromProp(path, property, value);
const result = await timeOutConnect(data);
if (result.id && result.data) {
return convertDataObjectToModel(result);
}
return null;
}
/**
* Save data on database
* @param {*} data The data wants to save on database
* @param {string} path The path of database
*/
async save(model) {
async save(model: T): Promise<void> {
this.connectToDb();
const results = convertModelToDataObject(model);
const results: T = convertModelToDataObject(model);
const saveData = this.firebaseService.save(
results.data,
@@ -53,52 +40,70 @@ export default class CommonService {
* @param {string} path The path of database
* @returns {Object || null} Return the object if has, otherwise return null
*/
async getDataFromId(id, path = this.defaultPath) {
async getDataFromId(
id: string,
path: string = this.defaultPath,
): Promise<object | null> {
this.connectToDb();
const result = await this.firebaseService.getDataFromId(id, path);
const data = await timeOutConnect(result);
if (data) return data;
const data = await timeOutConnect(
this.firebaseService.getDataFromId(id, path),
);
if (typeof data !== 'string') return data;
return null;
}
async getAllDataFromPath(path = this.defaultPath) {
async getAllDataFromPath(path = this.defaultPath): Promise<object[] | null> {
this.connectToDb();
const results = await timeOutConnect(
this.firebaseService.getAllDataFromPath(path),
);
if (results) {
if (typeof results !== 'string') {
// Convert format object
return results.map((data) => {
return convertDataObjectToModel(data);
const tempData: dataObj = data as dataObj;
return convertDataObjectToModel(tempData);
});
}
return null;
}
async getListDataFromProp(property, value, path = this.defaultPath) {
async getListDataFromProp(
property: string,
value: object,
path: string = this.defaultPath,
): Promise<object[] | null> {
this.connectToDb();
const results = await timeOutConnect(
this.firebaseService.getListDataFromProp(path, property, value),
);
if (results) {
if (results && typeof results !== 'string') {
// Convert format object
return results.map((data) => {
return convertDataObjectToModel(data);
const tempData: dataObj = data as dataObj;
return convertDataObjectToModel(tempData);
});
}
return null;
}
async deleteData(id, path = this.defaultPath) {
async deleteData(
id: string,
path = this.defaultPath,
): Promise<string | void> {
this.connectToDb();
await timeOutConnect(this.firebaseService.delete(id, path));
}
}
@@ -29,25 +29,25 @@ class FirebaseService {
* @param {string} path The path of database need to be save
* @returns {Promise} Return the resolves when write to database completed
*/
save(data: object, path: string): Promise<any> {
save(data: object, path: string): Promise<void> {
return set(ref(this.db, path), data);
}
delete(id: string, path: string) {
delete(id: string, path: string): Promise<void> {
return remove(ref(this.db, path + id));
}
/**
* Disconnect to database
*/
disconnect() {
disconnect(): void {
goOffline(this.db);
}
/**
* Reconnect to database
*/
reconnect() {
reconnect(): void {
goOnline(this.db);
}
@@ -58,13 +58,18 @@ class FirebaseService {
* @param {value} value The value to compare in database
* @returns {Promise} Return the resolve when find completed
*/
getDataFromProp(path: string, property: string, value: object): Promise<any> {
getDataFromProp(
path: string,
property: string,
value: object,
): Promise<object | null> {
return new Promise((resolve) => {
onValue(
ref(this.db, path),
(snapshot) => {
let id: string | null = null;
let data: object | null = null;
let result: object | null = null;
// snapshot is a type of data by Firebase define
snapshot.forEach((childSnapshot) => {
@@ -75,7 +80,12 @@ class FirebaseService {
data = dataTemp;
}
});
resolve({ id, data });
if (id && data) {
result = { id, data };
}
resolve(result);
},
{
onlyOnce: true,
@@ -90,7 +100,7 @@ class FirebaseService {
* @param {string} path The path of data save in database
* @returns {Promise} Return new Promise
*/
getDataFromId(id: string, path: string): Promise<any> {
getDataFromId(id: string, path: string): Promise<object> {
return new Promise((resolve) => {
onValue(
ref(this.db, path + id),
@@ -104,12 +114,12 @@ class FirebaseService {
});
}
getAllDataFromPath(path) {
getAllDataFromPath(path: string): Promise<object[]> {
return new Promise((resolve) => {
onValue(
ref(this.db, path),
(snapshot) => {
const listData: object[] = [];
let listData: object[] = [];
// snapshot is a type of data by Firebase define
snapshot.forEach((childSnapshot) => {
@@ -121,6 +131,7 @@ class FirebaseService {
listData.push({ id, data });
});
resolve(listData);
},
{
@@ -130,7 +141,11 @@ class FirebaseService {
});
}
getListDataFromProp(path: string, property: string, value: object) {
getListDataFromProp(
path: string,
property: string,
value: object,
): Promise<object[]> {
return new Promise((resolve) => {
onValue(
ref(this.db, path),
@@ -5,19 +5,19 @@ class LocalStorageService {
this.localStorage = localStorage;
}
add(key: string, value: string) {
add(key: string, value: string): void {
this.localStorage.setItem(key, value);
}
get(key: string) {
get(key: string): string | null {
return this.localStorage.getItem(key);
}
remove(key: string) {
remove(key: string): void {
this.localStorage.removeItem(key);
}
clear() {
clear(): void {
this.localStorage.clear();
}
}
+114
View File
@@ -0,0 +1,114 @@
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig to read more about this file */
/* Projects */
// "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
// "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
/* Language and Environment */
"target": "es2016" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
"lib": [
"dom",
"ES2017",
"dom.iterable",
"scripthost"
] /* Specify a set of bundled library declaration files that describe the target runtime environment. */,
// "jsx": "preserve", /* Specify what JSX code is generated. */
"experimentalDecorators": true /* Enable experimental support for legacy experimental decorators. */,
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
// "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
/* Modules */
"module": "commonjs" /* Specify what module code is generated. */,
"rootDir": "./src" /* Specify the root folder within your source files. */,
// "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
// "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
// "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
// "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */
// "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */
// "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
// "resolveJsonModule": true, /* Enable importing .json files. */
// "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */
// "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
/* JavaScript Support */
// "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
/* Emit */
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
"sourceMap": true /* Create source map files for emitted JavaScript files. */,
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
"outDir": "./dist" /* Specify an output folder for all emitted files. */,
"removeComments": true /* Disable emitting comments. */,
// "noEmit": true, /* Disable emitting files from a compilation. */
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
// "newLine": "crlf", /* Set the newline character for emitting files. */
// "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
// "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
"noEmitOnError": true /* Disable emitting files if any type checking errors are reported. */,
// "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
/* Interop Constraints */
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
// "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */,
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
/* Type Checking */
"strict": true /* Enable all strict type-checking options. */,
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
// "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
// "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
// "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
"noUnusedLocals": true /* Enable error reporting when local variables aren't read. */,
"noUnusedParameters": true /* Raise an error when a function parameter isn't read. */,
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
"noImplicitReturns": true /* Enable error reporting for codepaths that do not explicitly return in a function. */,
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
// "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
/* Completeness */
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
}
}