Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
feat(store): add implementation of user interface and authService
  • Loading branch information
Vikort committed Dec 2, 2021
commit f1b9703fcb836b7859e706cd3539cf0bc0c9c9ef
5 changes: 5 additions & 0 deletions web/frontend/src/store/actions/baseAction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface Action<T> {
type: string;
payload: T;
error?: boolean;
}
16 changes: 16 additions & 0 deletions web/frontend/src/store/actions/errorsActions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import {Action} from "./baseAction";

export namespace Type {
export const ChangeErFirstNameMsg = 'ERRORS_CHANGE_FIRST_NAME';
export const ChangeErLastNameMsg = 'ERRORS_CHANGE_LAST_NAME';
export const ChangeErLoginMsg = 'ERRORS_CHANGE_LOGIN';
export const ChangeErPasswordMsg = 'ERRORS_CHANGE_PASSWORD';
export const UpdateErrors = 'ERRORS_UPDATE'
}

export function UpdateErrors(errors: object): Action<object> {
return {
type: Type.UpdateErrors,
payload: errors,
};
}
3 changes: 3 additions & 0 deletions web/frontend/src/store/actions/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * as user from './userActions';
export * as services from './serviceActions';
export * as errors from './errorsActions';
13 changes: 13 additions & 0 deletions web/frontend/src/store/actions/serviceActions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Action } from './baseAction';
import * as services from '../interfaces/services';

export namespace Type {
export const Init = 'SERVICES_INIT';
}

export function Init(services: services.Services): Action<services.Services> {
return {
type: Type.Init,
payload: services,
};
}
12 changes: 12 additions & 0 deletions web/frontend/src/store/actions/userActions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import {Action} from "./baseAction";

export namespace Type {
export const UpdateUser = 'USER_UPDATE';
}

export function UpdateUser(user: object): Action<object> {
return {
type: Type.UpdateUser,
payload: user,
};
}
6 changes: 2 additions & 4 deletions web/frontend/src/store/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@ import { composeWithDevTools } from 'redux-devtools-extension';
import { rootReducer } from './reducers/root';
import { storeInitialState, Store } from './store';

const composeEnhancers = composeWithDevTools({

});
const composeEnhancers = composeWithDevTools();

export function configureStore(): redux.Store<Store> {
return redux.createStore(rootReducer, storeInitialState, composeEnhancers()) as redux.Store<Store>;
return redux.createStore(rootReducer, storeInitialState, composeEnhancers) as redux.Store<Store>;
}
7 changes: 6 additions & 1 deletion web/frontend/src/store/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
export { configureStore } from './config';
export { Store } from './store';
export { Store } from './store';
export * from './interfaces';

import * as actions from './actions';

export { actions };
13 changes: 13 additions & 0 deletions web/frontend/src/store/interfaces/errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export interface Errors{
erLoginMsg: string,
erPasswordMsg: string,
erFirstNameMsg: string,
erLastNameMsg: string
}

export const _initErrors: Errors = {
erLoginMsg: "",
erPasswordMsg: "",
erFirstNameMsg: "",
erLastNameMsg: ""
};
3 changes: 3 additions & 0 deletions web/frontend/src/store/interfaces/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * as services from './services';
export * as user from './user';
export * as errors from './errors';
9 changes: 9 additions & 0 deletions web/frontend/src/store/interfaces/services.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import {AuthService} from '../../utils/authService'

export interface Services {
authService: AuthService,
}

export const _initServices: Services = {
authService: null
};
18 changes: 14 additions & 4 deletions web/frontend/src/store/interfaces/user.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
export interface User {
name: string,
icon: string,
id: string,
firstName: string,
lastName: string,
login: string,
password: string,
online: boolean,
access_token: string,
}

export const _initUser: User = {
name: null,
icon: null
id: '',
firstName: '',
lastName: '',
login: '',
password: '',
online: false,
access_token: null,
}
12 changes: 12 additions & 0 deletions web/frontend/src/store/reducers/errorsReducer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import {Action} from '../actions/baseAction';
import * as errors from '../interfaces/errors'
import * as errorsAction from '../actions/errorsActions'

export function reducer(state: errors.Errors = errors._initErrors, action: Action<any>): any {
switch (action.type) {
case errorsAction.Type.UpdateErrors:
return { ...state, ...action.payload };
default:
return state;
}
}
6 changes: 6 additions & 0 deletions web/frontend/src/store/reducers/root.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { combineReducers } from 'redux';
import * as user from './userReducer'
import * as services from './serviceReducer'
import * as errors from './errorsReducer'

export const rootReducer = combineReducers({
user: user.reducer,
services: services.reducer,
errors: errors.reducer
});
13 changes: 13 additions & 0 deletions web/frontend/src/store/reducers/serviceReducer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import * as services from '../interfaces/services';
import { Action } from '../actions/baseAction';
import * as serviceAction from '../actions/serviceActions';

export function reducer(state: services.Services = services._initServices, action: Action<any>): any {
switch (action.type) {
case serviceAction.Type.Init:
return action.payload;

default:
return state;
}
}
13 changes: 13 additions & 0 deletions web/frontend/src/store/reducers/userReducer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import {Action} from '../actions/baseAction';
import * as user from '../interfaces/user'
import * as userAction from '../actions/userActions'

export function reducer(state: user.User = user._initUser, action: Action<any>): any {
switch (action.type) {
case userAction.Type.UpdateUser:
return { ...state, ...action.payload };

default:
return state;
}
}
10 changes: 7 additions & 3 deletions web/frontend/src/store/store.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import { User, _initUser } from './interfaces/user';
import { services, user , errors} from './interfaces';

export interface Store {
user: User,
user: user.User,
services: services.Services,
errors: errors.Errors
}

export const storeInitialState: Store = {
user: _initUser,
user: user._initUser,
services: services._initServices,
errors: errors._initErrors
}
89 changes: 89 additions & 0 deletions web/frontend/src/utils/authService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import * as redux from 'redux'
import * as store from '../store'


export class AuthService {
private _store: redux.Store<store.Store> = null;

constructor(st: redux.Store<store.Store>) {
this._store = st;
this._store.dispatch(
store.actions.services.Init({
authService: this,
}),
);
}

public updateUser(user: object): void {
this._store.dispatch(store.actions.user.UpdateUser(user))
}

public validateLogin(login: string): void {
if (!login) {
this.updateErrors({
erLoginMsg: "Login is required"
})
} else if (!/^[a-z0-9_-]+$/i.test(login)) {
this.updateErrors({
erLoginMsg: "Login must contain only letters, numbers, -, _"
})
} else {
this.updateErrors({
erLoginMsg: ""
})
}
}

public validatePassword(password: string): void {
if (!password) {
this.updateErrors({
erPasswordMsg: "Password is required"
})
} else if (!/^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{7,}$/i.test(password)) {
this.updateErrors({
erPasswordMsg: "Password must contain one letter and one number and must be longer than 8 characters"
}
)
} else {
this.updateErrors({
erPasswordMsg: ""
})
}
}

public validateFirstName(first_name: string): void {
if (!first_name) {
this.updateErrors({
erFirstNameMsg: "First name is required"
})
} else if (!/^[a-zA-Z ]+$/i.test(first_name)) {
this.updateErrors({
erFirstNameMsg: "First name must contain letters"
})
} else {
this.updateErrors({
erFirstNameMsg: ""
})
}
}

public validateLastName(second_name: string): void {
if (!second_name) {
this.updateErrors({
erLastNameMsg: "Last name is required"
})
} else if (!/^[a-zA-Z ]+$/i.test(second_name)) {
this.updateErrors({
erLastNameMsg: "Last name must contain letters"
})
} else {
this.updateErrors({
erLastNameMsg: ""
})
}
}

public updateErrors(errors: object): void {
this._store.dispatch(store.actions.errors.UpdateErrors(errors))
}
}