feature/create-place #8
@ -0,0 +1,45 @@
|
|||||||
|
import AdminUserModel from '~/business-logic/generic/admin-user/common/data/model/adminUserModel';
|
||||||
|
import { HTTPPovider } from '~/driven/boundaries/http-boundary/httpBoundary';
|
||||||
|
import { HttpOptionsType } from '~/driven/boundaries/http-boundary/protocols';
|
||||||
|
import { apiUrls } from '~/driven/utils/configs/appConfig';
|
||||||
|
import {
|
||||||
|
ICreatePlaceLogicMaker,
|
||||||
|
createPlaceArguments,
|
||||||
|
} from '~/driving/application/core/places/create-place/model/submiCreatePlace';
|
||||||
|
|
||||||
|
const createPlacesDto = (newPlace: createPlaceArguments) => ({
|
||||||
|
place_type: newPlace.placeType,
|
||||||
|
parent_id: newPlace.parentId || null,
|
||||||
|
name: newPlace.placeName,
|
||||||
|
});
|
||||||
|
|
||||||
|
const createPlaceAdapter = (
|
||||||
|
userAdmin: AdminUserModel | null,
|
||||||
|
updateAccessToken: (newAccessToken: string) => void,
|
||||||
|
navigateToAuth: () => void,
|
||||||
|
): ICreatePlaceLogicMaker => {
|
||||||
|
const url = apiUrls.core.createPlace;
|
||||||
|
const httpHandler = async (newPlace: createPlaceArguments) => {
|
||||||
|
const httpProvider = new HTTPPovider(
|
||||||
|
{
|
||||||
|
accessToken: (userAdmin && userAdmin?.adminUserData.accessToken) || null,
|
||||||
|
refreshToken: (userAdmin && userAdmin?.adminUserData.refreshToken) || null,
|
||||||
|
},
|
||||||
|
updateAccessToken,
|
||||||
|
navigateToAuth,
|
||||||
|
);
|
||||||
|
const dto = createPlacesDto(newPlace);
|
||||||
|
const options: HttpOptionsType = {
|
||||||
|
url,
|
||||||
|
method: 'POST',
|
||||||
|
data: dto,
|
||||||
|
};
|
||||||
|
|
||||||
|
return await httpProvider.request<string>(options);
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
httpHandler,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createPlaceAdapter;
|
@ -46,7 +46,6 @@ export class HTTPPovider {
|
|||||||
async request<R>(customOptions: HttpOptionsType) {
|
async request<R>(customOptions: HttpOptionsType) {
|
||||||
const axiosInstance = this.handleRequestInterceptor();
|
const axiosInstance = this.handleRequestInterceptor();
|
||||||
this.responseIncepter(axiosInstance);
|
this.responseIncepter(axiosInstance);
|
||||||
|
|
||||||
const response = await axiosInstance<ApiGlobalResponseObject<R>>(customOptions);
|
const response = await axiosInstance<ApiGlobalResponseObject<R>>(customOptions);
|
||||||
if (!response) throw new Error(staticMessages.service.errors[500]);
|
if (!response) throw new Error(staticMessages.service.errors[500]);
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ export const apiUrls = {
|
|||||||
createUserAccount: `${baseApiUrl}${ENVs.apiCreateUserAccount}`,
|
createUserAccount: `${baseApiUrl}${ENVs.apiCreateUserAccount}`,
|
||||||
createUserProfile: `${baseApiUrl}${ENVs.apiCreateUserProfile}`,
|
createUserProfile: `${baseApiUrl}${ENVs.apiCreateUserProfile}`,
|
||||||
createMember: `${baseApiUrl}${ENVs.apiCreateMember}`,
|
createMember: `${baseApiUrl}${ENVs.apiCreateMember}`,
|
||||||
|
createPlace: `${baseApiUrl}${ENVs.apiCreatePlace}`,
|
||||||
},
|
},
|
||||||
generic: {
|
generic: {
|
||||||
authPhonenumber: `${ENVs.apiAuthOrigin}${ENVs.apiAuthPhonenumber}`,
|
authPhonenumber: `${ENVs.apiAuthOrigin}${ENVs.apiAuthPhonenumber}`,
|
||||||
|
@ -10,4 +10,5 @@ export const ENVs = {
|
|||||||
apiQr: process.env.VITE_API_QR,
|
apiQr: process.env.VITE_API_QR,
|
||||||
apiCreateUserProfile: process.env.VITE_API_USERS_PROFILE,
|
apiCreateUserProfile: process.env.VITE_API_USERS_PROFILE,
|
||||||
apiCreateMember: process.env.VITE_API_CREATE_MEMBER,
|
apiCreateMember: process.env.VITE_API_CREATE_MEMBER,
|
||||||
|
apiCreatePlace: process.env.VITE_API_PLACES,
|
||||||
};
|
};
|
||||||
|
@ -4,6 +4,7 @@ export const staticMessages = {
|
|||||||
input: 'please fill all inputs correctly',
|
input: 'please fill all inputs correctly',
|
||||||
phonenumber: 'please fill the valid number',
|
phonenumber: 'please fill the valid number',
|
||||||
otp: 'please fill the otp fields correctly',
|
otp: 'please fill the otp fields correctly',
|
||||||
|
inputPlace: 'place type and name of place is necessary',
|
||||||
},
|
},
|
||||||
users: 'Users',
|
users: 'Users',
|
||||||
submit: 'Submit',
|
submit: 'Submit',
|
||||||
@ -26,6 +27,7 @@ export const staticMessages = {
|
|||||||
success: {
|
success: {
|
||||||
createUser: 'user created successfully',
|
createUser: 'user created successfully',
|
||||||
createMember: 'member created successfully',
|
createMember: 'member created successfully',
|
||||||
|
createPlace: 'place created successfully',
|
||||||
},
|
},
|
||||||
and: 'and',
|
and: 'and',
|
||||||
canUseFor: 'can use for',
|
canUseFor: 'can use for',
|
||||||
@ -47,7 +49,7 @@ export const staticMessages = {
|
|||||||
},
|
},
|
||||||
service: {
|
service: {
|
||||||
errors: {
|
errors: {
|
||||||
500: 'server not respond please try again later!',
|
500: 'there is a problem with connecting to the server please try again later!',
|
||||||
401: 'Authentication error!',
|
401: 'Authentication error!',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1,15 +1,23 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import createPlaceAdapter from '~/driven/adapters/create-place-adapter/createPlaceAdapter';
|
||||||
|
import useGetNavigatorAndTokenUpdater from '~/driven/utils/helpers/hooks/getNavigatorAndAccessTokenUpdator';
|
||||||
import CreatePlaceView from '../view/CreatePlaceView';
|
import CreatePlaceView from '../view/CreatePlaceView';
|
||||||
import useCreatePlaceVm from '../viewmodel/createPlaceVM';
|
import useCreatePlaceVm from '../viewmodel/createPlaceVM';
|
||||||
import createPlaceModel from '../model/createPlaceModel';
|
import createPlaceModel from '../model/createPlaceModel';
|
||||||
|
|
||||||
export default function CreatePlace() {
|
export default function CreatePlace() {
|
||||||
const { inputOptions } = createPlaceModel();
|
const { accessTokenUpdateHandler, notLoginAuth, userData } = useGetNavigatorAndTokenUpdater();
|
||||||
const { formStateData, inputStateHandlers, selectBoxOptions } = useCreatePlaceVm({
|
const { user } = userData;
|
||||||
|
|
||||||
|
const createPlaceDrivenAdapter = createPlaceAdapter(user, accessTokenUpdateHandler, notLoginAuth);
|
||||||
|
const { inputOptions, createPlace } = createPlaceModel(createPlaceDrivenAdapter);
|
||||||
|
const { formStateData, inputStateHandlers, selectBoxOptions, handleSubmitCreatePlaceForm } = useCreatePlaceVm({
|
||||||
getInputOptions: inputOptions,
|
getInputOptions: inputOptions,
|
||||||
|
createPlaceModel: createPlace,
|
||||||
});
|
});
|
||||||
return (
|
return (
|
||||||
<CreatePlaceView
|
<CreatePlaceView
|
||||||
|
handleSubmitCreatePlaceForm={handleSubmitCreatePlaceForm}
|
||||||
inputOptions={{
|
inputOptions={{
|
||||||
parentId: selectBoxOptions.parentIdsOptions,
|
parentId: selectBoxOptions.parentIdsOptions,
|
||||||
placeType: selectBoxOptions.placeTypesOptions,
|
placeType: selectBoxOptions.placeTypesOptions,
|
||||||
|
@ -1,9 +1,15 @@
|
|||||||
import { CreatePlaceType } from './protocols';
|
import { CreatePlaceType } from './protocols';
|
||||||
import getValidOptionsOfSelectBox from './getValidOptionsOfSelectBox';
|
import getValidOptionsOfSelectBox from './getValidOptionsOfSelectBox';
|
||||||
|
import createPlaceLogicMaker, { ICreatePlaceLogicMaker } from './submiCreatePlace';
|
||||||
|
|
||||||
const createPlaceModel = (): CreatePlaceType => {
|
type ICreatePlaceModel = ICreatePlaceLogicMaker;
|
||||||
|
|
||||||
|
const createPlaceModel = (depenedencies: ICreatePlaceModel): CreatePlaceType => {
|
||||||
const { getPlacesTypeOptionsOfSelectBox, getValidParentIdsOptionsOfSelectBox } = getValidOptionsOfSelectBox;
|
const { getPlacesTypeOptionsOfSelectBox, getValidParentIdsOptionsOfSelectBox } = getValidOptionsOfSelectBox;
|
||||||
|
|
||||||
|
const { createPlace } = createPlaceLogicMaker(depenedencies);
|
||||||
return {
|
return {
|
||||||
|
createPlace,
|
||||||
inputOptions: {
|
inputOptions: {
|
||||||
getPlaceType: getPlacesTypeOptionsOfSelectBox,
|
getPlaceType: getPlacesTypeOptionsOfSelectBox,
|
||||||
getParentIds: getValidParentIdsOptionsOfSelectBox,
|
getParentIds: getValidParentIdsOptionsOfSelectBox,
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
import createPlaceModel from './createPlaceModel';
|
||||||
|
|
||||||
|
export default createPlaceModel;
|
@ -1,7 +1,9 @@
|
|||||||
import PlacesModel from '~/business-logic/core/places/common/model/placesModel';
|
import PlacesModel from '~/business-logic/core/places/common/model/placesModel';
|
||||||
import { placeTypes } from '../view/protocol';
|
import { placeTypes } from '../view/protocol';
|
||||||
|
import { createPlaceArguments } from './submiCreatePlace';
|
||||||
|
|
||||||
export type CreatePlaceType = {
|
export type CreatePlaceType = {
|
||||||
|
createPlace: (placeData: createPlaceArguments) => Promise<string>;
|
||||||
inputOptions: {
|
inputOptions: {
|
||||||
getPlaceType: () => {
|
getPlaceType: () => {
|
||||||
value: placeTypes;
|
value: placeTypes;
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
import { placeTypes } from '../view/protocol';
|
||||||
|
|
||||||
|
export type createPlaceArguments = {
|
||||||
|
placeType: `${placeTypes}`;
|
||||||
|
placeName: string;
|
||||||
|
parentId: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface ICreatePlaceLogicMaker {
|
||||||
|
httpHandler: (placeData: createPlaceArguments) => Promise<string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const createPlaceLogicMaker = (depenedencies: ICreatePlaceLogicMaker) => {
|
||||||
|
const { httpHandler } = depenedencies;
|
||||||
|
|
||||||
|
const createPlace = async (placeData: createPlaceArguments) => {
|
||||||
|
return await httpHandler(placeData);
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
createPlace,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createPlaceLogicMaker;
|
@ -3,14 +3,23 @@ import SimpleInput from '~/driven/utils/components/inputs/simple-input/SimpleInp
|
|||||||
import InputBox from '~/driven/utils/components/inputs/select-box/InputBox';
|
import InputBox from '~/driven/utils/components/inputs/select-box/InputBox';
|
||||||
import { staticMessages } from '~/driven/utils/constants/staticMessages';
|
import { staticMessages } from '~/driven/utils/constants/staticMessages';
|
||||||
import PrimaryButton from '~/driven/utils/components/buttons/primary-button/PrimaryButton';
|
import PrimaryButton from '~/driven/utils/components/buttons/primary-button/PrimaryButton';
|
||||||
|
import Notification from '~/driven/utils/components/Notification/Notification';
|
||||||
import { ICreatePlaceProps } from './protocol';
|
import { ICreatePlaceProps } from './protocol';
|
||||||
|
|
||||||
export default function CreatePlaceView(props: ICreatePlaceProps) {
|
export default function CreatePlaceView(props: ICreatePlaceProps) {
|
||||||
const { formStateData, inputStateHandlers, inputOptions } = props;
|
const { formStateData, inputStateHandlers, inputOptions, handleSubmitCreatePlaceForm } = props;
|
||||||
const { formState } = formStateData;
|
const { formState, error, setError } = formStateData;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form className='p-4 py-6 flex flex-wrap w-full gap-4'>
|
<>
|
||||||
|
{Boolean(error.message) && (
|
||||||
|
<Notification
|
||||||
|
message={error.message}
|
||||||
|
type={error.type}
|
||||||
|
onCloseCallback={() => setError({ message: '', type: 'error' })}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<form onSubmit={handleSubmitCreatePlaceForm} className='p-4 py-6 flex flex-wrap w-full gap-4'>
|
||||||
<SimpleInput
|
<SimpleInput
|
||||||
inputData={{
|
inputData={{
|
||||||
name: staticMessages.global.PlaceName,
|
name: staticMessages.global.PlaceName,
|
||||||
@ -47,5 +56,6 @@ export default function CreatePlaceView(props: ICreatePlaceProps) {
|
|||||||
<PrimaryButton onClick={() => null} title={staticMessages.global.submit} />
|
<PrimaryButton onClick={() => null} title={staticMessages.global.submit} />
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,19 @@ export type PlaceFormState = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export interface ICreatePlaceProps {
|
export interface ICreatePlaceProps {
|
||||||
|
handleSubmitCreatePlaceForm: (e: React.FormEvent) => Promise<void>;
|
||||||
formStateData: {
|
formStateData: {
|
||||||
formState: PlaceFormState;
|
formState: PlaceFormState;
|
||||||
|
error: {
|
||||||
|
message: string;
|
||||||
|
type: 'error' | 'success';
|
||||||
|
};
|
||||||
|
setError: React.Dispatch<
|
||||||
|
React.SetStateAction<{
|
||||||
|
message: string;
|
||||||
|
type: 'error' | 'success';
|
||||||
|
}>
|
||||||
|
>;
|
||||||
setFormState: React.Dispatch<React.SetStateAction<PlaceFormState>>;
|
setFormState: React.Dispatch<React.SetStateAction<PlaceFormState>>;
|
||||||
};
|
};
|
||||||
inputStateHandlers: {
|
inputStateHandlers: {
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
|
import { AxiosError } from 'axios';
|
||||||
|
import { staticMessages } from '~/driven/utils/constants/staticMessages';
|
||||||
import useGetPlaceList from '../../common/hooks/useGetPlaceList';
|
import useGetPlaceList from '../../common/hooks/useGetPlaceList';
|
||||||
import { PlaceFormState, placeTypes } from '../view/protocol';
|
import { PlaceFormState, placeTypes } from '../view/protocol';
|
||||||
|
import { createPlaceArguments } from '../model/submiCreatePlace';
|
||||||
import { ICreatePlaceVm, initialPlaceFormState } from './protocols';
|
import { ICreatePlaceVm, initialPlaceFormState } from './protocols';
|
||||||
|
|
||||||
const onChangeInputStateHandlers = (setFormState: React.Dispatch<React.SetStateAction<PlaceFormState>>) => {
|
const onChangeInputStateHandlers = (setFormState: React.Dispatch<React.SetStateAction<PlaceFormState>>) => {
|
||||||
@ -25,15 +28,41 @@ const resetParentIdOnChangePlaceType = (setFormState: React.Dispatch<React.SetSt
|
|||||||
};
|
};
|
||||||
|
|
||||||
const useCreatePlaceVm = (dependencies: ICreatePlaceVm) => {
|
const useCreatePlaceVm = (dependencies: ICreatePlaceVm) => {
|
||||||
const { getInputOptions } = dependencies;
|
const { getInputOptions, createPlaceModel } = dependencies;
|
||||||
const { getParentIds, getPlaceType } = getInputOptions;
|
const { getParentIds, getPlaceType } = getInputOptions;
|
||||||
const [formState, setFormState] = useState<PlaceFormState>(initialPlaceFormState);
|
const [formState, setFormState] = useState<PlaceFormState>(initialPlaceFormState);
|
||||||
|
const [error, setError] = useState<{ message: string; type: 'error' | 'success' }>({ message: '', type: 'error' });
|
||||||
|
|
||||||
const { handleNameSetState, handleParentIdSetState, handlePlaceTypeSetState } = useMemo(
|
const { handleNameSetState, handleParentIdSetState, handlePlaceTypeSetState } = useMemo(
|
||||||
() => onChangeInputStateHandlers(setFormState),
|
() => onChangeInputStateHandlers(setFormState),
|
||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const handleSubmitCreatePlaceForm = async (e: React.FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
try {
|
||||||
|
const { parentId, placeName, placeTypes: placeType } = formState;
|
||||||
|
console.log(formState);
|
||||||
|
if (!placeName || !placeName) throw new Error(staticMessages.global.errors.inputPlace);
|
||||||
|
const newPlaceData: createPlaceArguments = {
|
||||||
|
parentId: parentId.value,
|
||||||
|
placeName,
|
||||||
|
placeType,
|
||||||
|
};
|
||||||
|
const response = await createPlaceModel(newPlaceData);
|
||||||
|
if (!response) throw new Error(staticMessages.service.errors[500]);
|
||||||
|
setError({
|
||||||
|
message: staticMessages.global.success.createPlace,
|
||||||
|
type: 'success',
|
||||||
|
});
|
||||||
|
} catch (errorExc) {
|
||||||
|
if (errorExc instanceof AxiosError) {
|
||||||
|
setError({ message: errorExc.response?.data?.description, type: 'error' });
|
||||||
|
} else if (errorExc instanceof Error) {
|
||||||
|
setError({ message: errorExc.message, type: 'error' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
useEffect(() => resetParentIdOnChangePlaceType(setFormState), [formState.placeTypes]);
|
useEffect(() => resetParentIdOnChangePlaceType(setFormState), [formState.placeTypes]);
|
||||||
|
|
||||||
const getPlaceList = useCallback(() => useGetPlaceList()(), []);
|
const getPlaceList = useCallback(() => useGetPlaceList()(), []);
|
||||||
@ -46,8 +75,11 @@ const useCreatePlaceVm = (dependencies: ICreatePlaceVm) => {
|
|||||||
}, [formState.placeTypes, places]);
|
}, [formState.placeTypes, places]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
handleSubmitCreatePlaceForm,
|
||||||
formStateData: {
|
formStateData: {
|
||||||
formState,
|
formState,
|
||||||
|
error,
|
||||||
|
setError,
|
||||||
setFormState,
|
setFormState,
|
||||||
},
|
},
|
||||||
inputStateHandlers: {
|
inputStateHandlers: {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { CreatePlaceType } from '../model/protocols';
|
import { CreatePlaceType } from '../model/protocols';
|
||||||
|
import { createPlaceArguments } from '../model/submiCreatePlace';
|
||||||
import { PlaceFormState, placeTypes } from '../view/protocol';
|
import { PlaceFormState, placeTypes } from '../view/protocol';
|
||||||
|
|
||||||
export const initialPlaceFormState: PlaceFormState = {
|
export const initialPlaceFormState: PlaceFormState = {
|
||||||
@ -9,4 +10,5 @@ export const initialPlaceFormState: PlaceFormState = {
|
|||||||
|
|
||||||
export interface ICreatePlaceVm {
|
export interface ICreatePlaceVm {
|
||||||
getInputOptions: CreatePlaceType['inputOptions'];
|
getInputOptions: CreatePlaceType['inputOptions'];
|
||||||
|
createPlaceModel: (placeData: createPlaceArguments) => Promise<string>;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user