[FEAT]: add create user logic

This commit is contained in:
behnamrhp 2023-05-21 18:03:53 +03:00
parent 6ccf3ee25b
commit dbb9ed742c
13 changed files with 168 additions and 29 deletions

View File

@ -1,3 +1,3 @@
import createUserInfra from './infra/createUserInfra'; import CreateUserInfra from './infra/createUserInfra';
export default createUserInfra; export default CreateUserInfra;

View File

@ -4,7 +4,7 @@ import CreateProfileRepo from '../create-profile/data/repository/CreateRepositor
import { HttpHandler as HttpProfileHandler } from '../create-profile/data/repository/protocols'; import { HttpHandler as HttpProfileHandler } from '../create-profile/data/repository/protocols';
import CreateUserUsecase from '../usecase/createUserUsecase'; import CreateUserUsecase from '../usecase/createUserUsecase';
class createUserInfra { class CreateUserInfra {
private httpAccountHandler: HttpAccountHandler; private httpAccountHandler: HttpAccountHandler;
private httpProfileHandler: HttpProfileHandler; private httpProfileHandler: HttpProfileHandler;
@ -26,4 +26,4 @@ class createUserInfra {
} }
} }
export default createUserInfra; export default CreateUserInfra;

View File

@ -1,7 +1,10 @@
import { HttpHandler as HttpProfileHandler } from './create-profile/data/repository/protocols'; import { HttpHandler as HttpProfileHandler } from './create-profile/data/repository/protocols';
import { HttpHandler as HttpAccountHandler } from './create-account/data/repository/protocols'; import { HttpHandler as HttpAccountHandler } from './create-account/data/repository/protocols';
import CreateUserUsecase from './usecase/createUserUsecase';
export default interface createUserPort { export default interface createUserPort {
httpAccountHandler: HttpAccountHandler; httpAccountHandler: HttpAccountHandler;
httpProfileHandler: HttpProfileHandler; httpProfileHandler: HttpProfileHandler;
} }
export type createUserReturnType = CreateUserUsecase;

View File

@ -1,18 +1,41 @@
import React from 'react'; import React from 'react';
interface ISimpleInput { export type SetStateInputMethod<NameType> = (name: NameType, newValue: string) => void;
interface ISimpleInput<NameType> {
inputData: {
title: string; title: string;
name: string;
};
className?: string; className?: string;
stateHanlder: {
state: string;
setState: SetStateInputMethod<NameType>;
};
} }
export default function SimpleInput(props: ISimpleInput) { export default function SimpleInput<NameType>(props: ISimpleInput<NameType>) {
const { title, className } = props; const { className, inputData, stateHanlder } = props;
const { name, title } = inputData;
const { setState, state } = stateHanlder;
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { value, name: inputName } = e.target;
setState(inputName as NameType, value);
};
return ( return (
<div className={`flex flex-col ${className}`}> <div className={`flex flex-col ${className}`}>
<label className='mb-1 text-txt-second text-xs' htmlFor={title}> <label className='mb-1 text-txt-second text-xs' htmlFor={title}>
{title} {title}
</label> </label>
<input className='bg-bg-gray h-11 rounded-lg focus:outline-0 px-2 text-txt-medium' id={title} /> <input
value={state}
onChange={handleInputChange}
name={name}
className='bg-bg-gray h-11 rounded-lg focus:outline-0 px-2 text-txt-medium'
id={title}
/>
</div> </div>
); );
} }

View File

@ -5,7 +5,7 @@ export const staticMessages = {
}, },
users: 'Users', users: 'Users',
submit: 'Submit', submit: 'Submit',
fistname: 'Firstname', firstname: 'Firstname',
lastname: 'Lastname', lastname: 'Lastname',
place_id: 'Place id', place_id: 'Place id',
title: 'title', title: 'title',
@ -14,7 +14,7 @@ export const staticMessages = {
address: 'Address', address: 'Address',
qrCode: 'qrCode', qrCode: 'qrCode',
createUser: 'Create user', createUser: 'Create user',
phoneNumber: 'Phone Number', phonenumber: 'Phone Number',
}, },
service: { service: {
errors: { errors: {

View File

@ -1,8 +1,5 @@
import StateManagementService from '~/driven/boundaries/state-management'; import StateManagementService from '~/driven/boundaries/state-management';
import { import { errorHandlingStateTypes, UIErrorHandling } from './protocols/globalHelpersProtocols';
errorHandlingStateTypes,
UIErrorHandling,
} from './protocols/globalHelpersProtocols';
export const UIErrorHandlingFactory = <DATA_RESPONSE>({ export const UIErrorHandlingFactory = <DATA_RESPONSE>({
state, state,
@ -18,13 +15,14 @@ export const UIErrorHandlingFactory = <DATA_RESPONSE>({
state, state,
}); });
export const prepareStateManagementForVM = <ReturnType>( export const prepareStateManagementForVM = <ReturnType>(apiUrl: string, model: () => Promise<ReturnType>) => {
apiUrl: string,
model: () => Promise<ReturnType>
) => {
const stateManagement = StateManagementService.swr(); const stateManagement = StateManagementService.swr();
const useGetPlacesList = () => stateManagement.useGetQuery(apiUrl, model); const useGetPlacesList = () => stateManagement.useGetQuery(apiUrl, model);
return useGetPlacesList; return useGetPlacesList;
}; };
export const checkPhoneNumberInput = (newValue: string) => {
return (Number.isFinite(+newValue) || newValue === '+') && newValue.length <= 12;
};

View File

@ -1,6 +1,22 @@
import React from 'react'; import React from 'react';
import createAccountAdapter from '~/driven/adapters/create-account-adapter/createAccountAdapter';
import createProfileAdapter from '~/driven/adapters/create-profile-adapter/createProfileAdapter';
import CreateUserInfra from '~/business-logic/core/users/create-user';
import CreateUserView from '../view/CreateUserView'; import CreateUserView from '../view/CreateUserView';
import useCreateUserVM from '../viewmodel/CreateUserVM';
import createUserModel from '../model/createUserModel';
export default function CreateUser() { export default function CreateUser() {
return <CreateUserView />; // get adapters from driven layer
const createAccountDrivenAdapter = createAccountAdapter();
const createProfileDrivenAdapter = createProfileAdapter();
// pass to the logic and get the usecase
const createUserInfra = new CreateUserInfra(createAccountDrivenAdapter, createProfileDrivenAdapter);
const createUserLogic = createUserInfra.execute();
// pass the usecase to the model
const { handleSubmitForm } = createUserModel({ createUserLogic });
// pass the method to the viewmodel to call on submit
const { stateHandler, onSubmit, inputNames } = useCreateUserVM({ handleSubmitForm });
// get all of the needed information to the user to show
return <CreateUserView stateHandler={stateHandler} inputNames={inputNames} onSubmit={onSubmit} />;
} }

View File

@ -0,0 +1,21 @@
import CreateUserUsecase from '~/business-logic/core/users/create-user/usecase/createUserUsecase';
import { INewUserData } from '~/business-logic/core/users/create-user/create-account/data/dto/protocols';
import IUseCreateUserVm from '../viewmodel/protocols';
interface ICreateUserModel {
createUserLogic: CreateUserUsecase;
}
const createUserModel = (dependencies: ICreateUserModel): IUseCreateUserVm => {
const { createUserLogic } = dependencies;
const handleSubmitForm = async (newUserData: INewUserData) => {
await createUserLogic.execute(newUserData);
};
return {
handleSubmitForm,
};
};
export default createUserModel;

View File

@ -2,18 +2,35 @@ import React from 'react';
import PrimaryButton from '~/driven/utils/components/buttons/primary-button/PrimaryButton'; import PrimaryButton from '~/driven/utils/components/buttons/primary-button/PrimaryButton';
import SimpleInput from '~/driven/utils/components/inputs/simple-input/SimpleInput'; import SimpleInput from '~/driven/utils/components/inputs/simple-input/SimpleInput';
import { staticMessages } from '~/driven/utils/constants/staticMessages'; import { staticMessages } from '~/driven/utils/constants/staticMessages';
import ICreateUserViewProps from './protocols';
export default function CreateUserView() { export default function CreateUserView(props: ICreateUserViewProps) {
const { onSubmit, inputNames, stateHandler } = props;
const { inputStates, inputsSetStates } = stateHandler;
const inputs = inputNames.map((inputName) => {
const title = staticMessages.global[inputName] as string;
return ( return (
<div className='px-4 my-8'> <SimpleInput
<div className='flex flex-wrap w-full gap-4'> inputData={{
<SimpleInput title={staticMessages.global.fistname} className='mb-4 w-[48%]' /> title,
<SimpleInput title={staticMessages.global.lastname} className='mb-4 w-[48%]' /> name: inputName,
<SimpleInput title={staticMessages.global.phoneNumber} className='mb-4 w-[48%]' /> }}
</div> stateHanlder={{
setState: inputsSetStates,
state: inputStates[inputName],
}}
key={inputName}
className='mb-4 w-[48%]'
/>
);
});
return (
<form onSubmit={onSubmit} className='px-4 my-8'>
<div className='flex flex-wrap w-full gap-4'>{inputs}</div>
<div className='flex'> <div className='flex'>
<PrimaryButton onClick={() => null} title={staticMessages.global.submit} /> <PrimaryButton onClick={() => null} title={staticMessages.global.submit} />
</div> </div>
</div> </form>
); );
} }

View File

@ -0,0 +1,11 @@
import { INewUserData } from '~/business-logic/core/users/create-user/create-account/data/dto/protocols';
import { SetStateInputMethod } from '~/driven/utils/components/inputs/simple-input/SimpleInput';
export default interface ICreateUserViewProps {
onSubmit: (e: React.FormEvent) => void;
stateHandler: {
inputStates: INewUserData;
inputsSetStates: SetStateInputMethod<keyof INewUserData>;
};
inputNames: (keyof INewUserData)[];
}

View File

@ -0,0 +1,45 @@
import { useState } from 'react';
import { checkPhoneNumberInput } from '~/driven/utils/helpers/globalHelpers';
import { INewUserData } from '~/business-logic/core/users/create-user/create-account/data/dto/protocols';
import ICreateUserViewProps from '../view/protocols';
import IUseCreateUserVm from './protocols';
const inputStateInitialValue: INewUserData = {
firstname: '',
lastname: '',
phonenumber: '',
};
const inputNames: (keyof INewUserData)[] = ['firstname', 'lastname', 'phonenumber'];
const useCreateUserVM = (dependencies: IUseCreateUserVm): ICreateUserViewProps => {
const { handleSubmitForm } = dependencies;
const [inputsValue, setInputValues] = useState<INewUserData>(inputStateInitialValue);
const inputsSetStates = (name: keyof INewUserData, newValue: string) => {
if (name === 'phonenumber' && !checkPhoneNumberInput(newValue)) return;
setInputValues((prev) => ({
...prev,
[name]: newValue,
}));
};
const onSubmitCreateUserForm = (e: React.FormEvent) => {
e.preventDefault();
console.log('submit user', inputsValue);
handleSubmitForm(inputsValue);
};
const inputStates: INewUserData = { ...inputsValue };
return {
stateHandler: {
inputsSetStates,
inputStates,
},
onSubmit: onSubmitCreateUserForm,
inputNames,
};
};
export default useCreateUserVM;

View File

@ -0,0 +1,5 @@
import { INewUserData } from '~/business-logic/core/users/create-user/create-account/data/dto/protocols';
export default interface IUseCreateUserVm {
handleSubmitForm: (newUserData: INewUserData) => void;
}

View File

@ -27,7 +27,7 @@ export default function UsersListView(props: IUserListProps) {
}); });
}, [usersList]); }, [usersList]);
const tableTitles: Pick<Users, 'firstname' | 'lastname'> = { const tableTitles: Pick<Users, 'firstname' | 'lastname'> = {
firstname: staticMessages.global.fistname, firstname: staticMessages.global.firstname,
lastname: staticMessages.global.lastname, lastname: staticMessages.global.lastname,
}; };