feature/get-places-api #2

Merged
behnam merged 26 commits from feature/get-places-api into develop 2023-05-23 09:23:56 +00:00
12 changed files with 90 additions and 19 deletions
Showing only changes of commit 8b0687d945 - Show all commits

View File

@ -3,6 +3,7 @@ VITE_API_AUTH_ORIGIN = https://auth.dev.dipal.ru/api/v1/auth
VITE_API_AUTH_PHONENUMBER = /start-challenge VITE_API_AUTH_PHONENUMBER = /start-challenge
VITE_API_AUTH_LOGIN = /login VITE_API_AUTH_LOGIN = /login
VITE_API_AUTH_REFRESH = /refresh-token VITE_API_AUTH_REFRESH = /refresh-token
VITE_API_CREATE_MEMBER = /user_place/members
VITE_API_PLACES = /place VITE_API_PLACES = /place
VITE_API_USERS = /profile VITE_API_USERS = /profile
VITE_API_USERS_ACCOUNT = /account VITE_API_USERS_ACCOUNT = /account

View File

@ -7,8 +7,8 @@ import { apiUrls } from '~/driven/utils/configs/appConfig';
import { HttpOptionsType } from './protocols'; import { HttpOptionsType } from './protocols';
interface IUserTokens { interface IUserTokens {
accessToken: string | null; accessToken: string | null | undefined;
refreshToken: string | null; refreshToken: string | null | undefined;
} }
export class HTTPPovider { export class HTTPPovider {
private userTokens: IUserTokens; private userTokens: IUserTokens;

View File

@ -32,6 +32,7 @@ export const apiUrls = {
getUsers: `${baseApiUrl}${ENVs.apiGetUsers}`, getUsers: `${baseApiUrl}${ENVs.apiGetUsers}`,
createUserAccount: `${baseApiUrl}${ENVs.apiCreateUserAccount}`, createUserAccount: `${baseApiUrl}${ENVs.apiCreateUserAccount}`,
createUserProfile: `${baseApiUrl}${ENVs.apiCreateUserProfile}`, createUserProfile: `${baseApiUrl}${ENVs.apiCreateUserProfile}`,
createMember: `${baseApiUrl}${ENVs.apiCreateMember}`,
}, },
generic: { generic: {
authPhonenumber: `${ENVs.apiAuthOrigin}${ENVs.apiAuthPhonenumber}`, authPhonenumber: `${ENVs.apiAuthOrigin}${ENVs.apiAuthPhonenumber}`,

View File

@ -8,4 +8,5 @@ export const ENVs = {
apiGetUsers: process.env.VITE_API_USERS, apiGetUsers: process.env.VITE_API_USERS,
apiCreateUserAccount: process.env.VITE_API_USERS_ACCOUNT, apiCreateUserAccount: process.env.VITE_API_USERS_ACCOUNT,
apiCreateUserProfile: process.env.VITE_API_USERS_PROFILE, apiCreateUserProfile: process.env.VITE_API_USERS_PROFILE,
apiCreateMember: process.env.VITE_API_CREATE_MEMBER,
}; };

View File

@ -22,6 +22,7 @@ export const staticMessages = {
enterOtpCode: 'Enter your Otp Code', enterOtpCode: 'Enter your Otp Code',
success: { success: {
createUser: 'user created successfully', createUser: 'user created successfully',
createMember: 'member created successfully',
}, },
}, },
service: { service: {

View File

@ -34,9 +34,7 @@ const useCreateUserVM = (dependencies: IUseCreateUserVm): ICreateUserViewProps =
await handleSubmitForm(inputsValue); await handleSubmitForm(inputsValue);
setError({ message: staticMessages.global.success.createUser, type: 'success' }); setError({ message: staticMessages.global.success.createUser, type: 'success' });
} catch (errorExc) { } catch (errorExc) {
console.log('herere', errorExc);
if (errorExc instanceof AxiosError) { if (errorExc instanceof AxiosError) {
console.log('herere', errorExc);
setError({ message: errorExc.response?.data?.description, type: 'error' }); setError({ message: errorExc.response?.data?.description, type: 'error' });
} else if (errorExc instanceof Error) { } else if (errorExc instanceof Error) {
setError({ message: errorExc.message, type: 'error' }); setError({ message: errorExc.message, type: 'error' });

View File

@ -19,12 +19,18 @@ const prepareTheLogicForModel = () => {
return { getingPlacesLogic, url }; return { getingPlacesLogic, url };
}; };
export default function PlacessList() { export interface IPlacesListProps {
selectedRowId: string;
setSelectedRowId: React.Dispatch<React.SetStateAction<string>>;
}
export default function PlacessList(props: IPlacesListProps) {
const { selectedRowId, setSelectedRowId } = props;
const { getingPlacesLogic, url } = prepareTheLogicForModel(); const { getingPlacesLogic, url } = prepareTheLogicForModel();
const placesModel = async () => await placesListModel(getingPlacesLogic); const placesModel = async () => await placesListModel(getingPlacesLogic);
const useGetPlacesList = prepareStateManagementForVM<PlacesModel>(url, placesModel); const useGetPlacesList = prepareStateManagementForVM<PlacesModel>(url, placesModel);
const { selectedRowId, setSelectedRowId, placesData } = usePlacesListVM({ const { placesData } = usePlacesListVM({
useGetPlacesList, useGetPlacesList,
}); });
return <PlacesListView placesList={placesData} selectedRowId={selectedRowId} setSelectedRowId={setSelectedRowId} />; return <PlacesListView placesList={placesData} selectedRowId={selectedRowId} setSelectedRowId={setSelectedRowId} />;

View File

@ -19,11 +19,16 @@ const usePrepareTheLogicForModel = () => {
return { getingusersLogic, url }; return { getingusersLogic, url };
}; };
export default function UsersList() { export interface IUsersListProps {
selectedRowId: string;
setSelectedRowId: React.Dispatch<React.SetStateAction<string>>;
}
export default function UsersList(props: IUsersListProps) {
const { selectedRowId, setSelectedRowId } = props;
const { getingusersLogic, url } = usePrepareTheLogicForModel(); const { getingusersLogic, url } = usePrepareTheLogicForModel();
const usersModel = async () => await usersListModel(getingusersLogic); const usersModel = async () => await usersListModel(getingusersLogic);
const useGetusersList = prepareStateManagementForVM<UsersModel>(url, usersModel); const useGetusersList = prepareStateManagementForVM<UsersModel>(url, usersModel);
const { selectedRowId, setSelectedRowId, usersData } = useUsersListVM({ const { usersData } = useUsersListVM({
useGetusersList, useGetusersList,
}); });
return <UsersListView usersList={usersData} selectedRowId={selectedRowId} setSelectedRowId={setSelectedRowId} />; return <UsersListView usersList={usersData} selectedRowId={selectedRowId} setSelectedRowId={setSelectedRowId} />;

View File

@ -1,11 +1,14 @@
import React from 'react'; import React from 'react';
import { Link, useLocation } from 'react-router-dom'; import { Link, useLocation, useNavigate } from 'react-router-dom';
import { routesData } from '~/driven/utils/configs/appConfig'; import { routesData } from '~/driven/utils/configs/appConfig';
import { icons } from '~/driven/utils/constants/assertUrls'; import { icons } from '~/driven/utils/constants/assertUrls';
import { useUser } from '~/driven/utils/helpers/contexts/userContext';
import { navigateToAuth } from '~/driven/utils/helpers/globalHelpers';
export default function Sidebar() { export default function Sidebar() {
const isCurrentPage = useLocation(); const isCurrentPage = useLocation();
const userCTX = useUser();
const navigator = useNavigate();
const pages = Object.keys(routesData).map((routeKey) => { const pages = Object.keys(routesData).map((routeKey) => {
const key = routeKey as keyof typeof routesData; const key = routeKey as keyof typeof routesData;
return ( return (
@ -27,7 +30,12 @@ export default function Sidebar() {
<div className='logo'> <div className='logo'>
<img src={icons.logo} alt='logo icon' /> <img src={icons.logo} alt='logo icon' />
</div> </div>
<div className='mt-14 flex flex-col items-baseline'>{pages}</div> <div className='mt-14 flex flex-col items-baseline'>
{pages}
<div className='mt-auto text-white px-3 absolute bottom-5'>
<button onClick={() => navigateToAuth(userCTX, navigator)}>Log out</button>
</div>
</div>
</aside> </aside>
); );
} }

View File

@ -1,21 +1,73 @@
import React from 'react'; import { AxiosError } from 'axios';
import React, { useState } from 'react';
import { HTTPPovider } from '~/driven/boundaries/http-boundary/httpBoundary';
import { HttpOptionsType } from '~/driven/boundaries/http-boundary/protocols';
import Notification from '~/driven/utils/components/Notification/Notification';
import PrimaryButton from '~/driven/utils/components/buttons/primary-button/PrimaryButton'; import PrimaryButton from '~/driven/utils/components/buttons/primary-button/PrimaryButton';
import PageTitle from '~/driven/utils/components/page-title/pageTitle'; import PageTitle from '~/driven/utils/components/page-title/pageTitle';
import { apiUrls } from '~/driven/utils/configs/appConfig';
import { staticMessages } from '~/driven/utils/constants/staticMessages'; import { staticMessages } from '~/driven/utils/constants/staticMessages';
import useGetNavigatorAndTokenUpdater from '~/driven/utils/helpers/hooks/getNavigatorAndAccessTokenUpdator';
import PlacesList from '~/driving/application/core/places-list'; import PlacesList from '~/driving/application/core/places-list';
import UsersList from '~/driving/application/core/users-list'; import UsersList from '~/driving/application/core/users-list';
export default function index() { export default function index() {
const [selectedUserRowId, setSelectedUserRowId] = useState<string>('');
const [selectedPlaceRowId, setSelectedPlaceRowId] = useState<string>('');
const { accessTokenUpdateHandler, notLoginAuth, userData } = useGetNavigatorAndTokenUpdater();
const [error, setError] = useState<{ message: string; type: 'error' | 'success' }>({ message: '', type: 'error' });
const onSubmitMember = async (e: React.FormEvent) => {
e.preventDefault();
try {
const url = apiUrls.core.createMember;
const data = {
place_id: selectedPlaceRowId,
account_id: selectedUserRowId,
};
const options: HttpOptionsType = {
url,
data,
headers: {
'Content-Type': 'application/json',
},
method: 'POST',
};
const userTokens = {
accessToken: userData.user?.adminUserData.accessToken || null,
refreshToken: userData.user?.adminUserData.refreshToken || null,
};
const httpProvider = new HTTPPovider(userTokens, accessTokenUpdateHandler, notLoginAuth);
await httpProvider.request(options);
setError({ message: staticMessages.global.success.createMember, 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' });
}
}
};
return ( return (
<> <>
{Boolean(error.message) && (
<Notification
message={error.message}
type={error.type}
onCloseCallback={() => setError({ message: '', type: 'error' })}
/>
)}
<PageTitle className='px-4 py-5' title={staticMessages.global.users} /> <PageTitle className='px-4 py-5' title={staticMessages.global.users} />
<div className='container mx-auto px-4'> <div className='container mx-auto px-4'>
<div className='w-full flex flex-row-reverse items-center py-2 sticky top-0'> <form onSubmit={onSubmitMember} className='w-full flex flex-row-reverse items-center py-2 sticky top-0'>
<PrimaryButton className='text-sm' title={staticMessages.global.submit} onClick={() => null} /> <PrimaryButton className='text-sm' title={staticMessages.global.submit} onClick={() => null} />
</div> </form>
<div className='md:grid-cols-2 gap-x-4 grid grid-cols-1 mx-auto'> <div className='md:grid-cols-2 gap-x-4 grid grid-cols-1 mx-auto'>
<UsersList /> <UsersList selectedRowId={selectedUserRowId} setSelectedRowId={setSelectedUserRowId} />
<PlacesList /> <PlacesList selectedRowId={selectedPlaceRowId} setSelectedRowId={setSelectedPlaceRowId} />
</div> </div>
</div> </div>
</> </>

View File

@ -11,7 +11,6 @@ import Sidebar from '~/driving/application/support/sidebar';
*/ */
export default function MainPageLayout() { export default function MainPageLayout() {
const { user, setUser } = useUser(); const { user, setUser } = useUser();
console.log('hi');
useEffect(() => { useEffect(() => {
const storage = StorageService.localStorage<AdminUserModel>(); const storage = StorageService.localStorage<AdminUserModel>();
const currentUser = storage.getData(appConfig.adminUserStorageKey); const currentUser = storage.getData(appConfig.adminUserStorageKey);
@ -22,7 +21,7 @@ export default function MainPageLayout() {
return ( return (
<div className='flex flex-nowrap min-h-screen'> <div className='flex flex-nowrap min-h-screen'>
<Sidebar /> <Sidebar />
<main className='dipal-panel w-full text-black bg-white h-fit'> <main className='dipal-panel w-full text-black bg-white h-screen overflow-auto'>
<Outlet /> <Outlet />
</main> </main>
</div> </div>

View File

@ -5,7 +5,6 @@ import { useUser } from '~/driven/utils/helpers/contexts/userContext';
export default function UserLoginLayout() { export default function UserLoginLayout() {
const { user } = useUser(); const { user } = useUser();
console.log('hhhh');
if (user && user.adminUserData.accessToken) return <Navigate to={routes.usersList} replace />; if (user && user.adminUserData.accessToken) return <Navigate to={routes.usersList} replace />;
return <Outlet />; return <Outlet />;
} }