diff --git a/src/components/App/App.tsx b/src/components/App/App.tsx index e27167f..f669630 100644 --- a/src/components/App/App.tsx +++ b/src/components/App/App.tsx @@ -6,6 +6,8 @@ import { useEffect, useState } from 'react'; import { initialCards } from 'src/services/mock'; import { useAppDispatch, useAppSelector } from 'src/store/hooks'; import Registration from 'src/pages/Registration/Registration'; +import { allowDrop, handleDragStart, handleDrop } from 'src/services/dragAndDrop'; +import { selectMembers } from 'src/store/features/slice/membersSlice'; import { membersProps, RegisterDataProps, @@ -15,8 +17,7 @@ import { selectUsers, setLoggedIn, } from 'src/store/features/slice/userSlice'; -import { allowDrop, handleDragStart, handleDrop } from 'src/services/dragAndDrop'; -import { selectMembers } from 'src/store/features/slice/membersSlice'; + export default function App() { let { loggedIn } = useAppSelector(selectUsers); diff --git a/src/components/Header/Header.tsx b/src/components/Header/Header.tsx index 7b55add..a29194e 100644 --- a/src/components/Header/Header.tsx +++ b/src/components/Header/Header.tsx @@ -10,7 +10,7 @@ import { selectMembers, setIsFilterOpen, } from 'src/store/features/slice/membersSlice'; -import { DroppedCard, membersProps } from 'src/services/types'; +import { membersProps } from 'src/services/types'; import { selectUsers } from 'src/store/features/slice/userSlice'; const cx = cn.bind(styles); diff --git a/src/components/SideBar/SideBar.tsx b/src/components/SideBar/SideBar.tsx index 19ee57d..fc31a9a 100644 --- a/src/components/SideBar/SideBar.tsx +++ b/src/components/SideBar/SideBar.tsx @@ -16,11 +16,14 @@ import { UpOutlined, UserOutlined, } from '@ant-design/icons'; +import { useAppDispatch, useAppSelector } from 'src/store/hooks'; +import { selectMembers, setShortWindow } from 'src/store/features/slice/membersSlice'; const cx = cn.bind(styles); export default function SideBar() { - const [shortWindow, setShortWindow] = useState(false); + let { shortWindow } = useAppSelector(selectMembers); + const dispatch = useAppDispatch(); const [showMore, setShorMore] = useState(true); const location = useLocation(); @@ -142,7 +145,7 @@ export default function SideBar() { className={cx(styles.sideBarButton, { [styles.sideBarButton_short]: shortWindow, })} - onClick={() => setShortWindow(!shortWindow)} + onClick={() => dispatch(setShortWindow(!shortWindow))} > Скрыть {shortWindow ? : } diff --git a/src/pages/Employees/Employees.module.scss b/src/pages/Employees/Employees.module.scss index b2bbe75..d839dea 100644 --- a/src/pages/Employees/Employees.module.scss +++ b/src/pages/Employees/Employees.module.scss @@ -20,6 +20,9 @@ flex-wrap: wrap; gap: 24px; padding-top: 32px; + &_center { + justify-content: center; + } } .pagesContainer { @@ -52,4 +55,8 @@ cursor: not-allowed; } } +} + +.marginLeft { + margin-left: 110px; } \ No newline at end of file diff --git a/src/pages/Employees/Employees.tsx b/src/pages/Employees/Employees.tsx index 425ece6..c1d94bb 100644 --- a/src/pages/Employees/Employees.tsx +++ b/src/pages/Employees/Employees.tsx @@ -14,9 +14,10 @@ import { import cn from 'classnames/bind'; import { itemsPerPage } from 'src/services/const'; -const cx = cn.bind(styles); - export default function Employees() { + let { shortWindow } = useAppSelector(selectMembers); + const cx = cn.bind(styles); + const location = useLocation(); const dispatch = useAppDispatch(); const { members, membersAmount, currentPage } = useAppSelector(selectMembers); @@ -50,8 +51,16 @@ export default function Employees() { return (
-

Всего {membersAmount} сотрудников

-
+

+ Всего {membersAmount} сотрудников +

+
-
+
{members.map((card, index) => ( { + dispatch(fetchGetProfile()); + }, [dispatch]); + + const cx = cn.bind(styles); + return (
- ваше фото + ваше фото
-

Карпов Сергей

- {PROFILE_DATA.map((item, index) => ( -

- {item} -

- ))} -
+

{profile?.full_name}

+

+ {profile?.profile.position} +

+

- Дата рождения 12.12.1987 + Дата рождения {profile?.profile.birthday} +

+

Тел. {profile?.profile.phone}

+

{profile?.email}

+

+ Местонахождение: Санкт-Петербург GMT+3

- - {INFO_DATA.map((item, index) => ( -

- {item} -

- ))}
-
-
    +
    +
      {CHARTS_DATA.map((item, index) => (
    • {item.text}

      @@ -52,18 +79,41 @@ export default function Profile() {
    • ))}
    + {/*
    */}
    - {EVENTS_DATA.map((cont, index) => ( -
    -

    {cont.title}

    -
      - {cont.items.map((item, idx) => ( -
    • {item}
    • - ))} -
    - {cont.link} -
    - ))} + {EVENTS_DATA.map((cont, index) => ( +
    +

    {cont.title}

    +
      + {cont.items.map((item, idx) => ( +
    • + {item} +
    • + ))} +
    + + {cont.link} + +
    + ))} + {PROJECT_DATA.map((cont, index) => ( +
    +

    {cont.title}

    +
      + {cont.items.map((item, idx) => ( +
    • + {item} +
    • + ))} +
    +
    + ))}
    diff --git a/src/services/mock.ts b/src/services/mock.ts index 1bdabae..733e6e7 100644 --- a/src/services/mock.ts +++ b/src/services/mock.ts @@ -13,18 +13,6 @@ export const CHARTS_DATA = [ } ] -export const PROFILE_DATA = [ - 'UX/UI дизайнер', - 'Text', - 'дизайн', -] - -export const INFO_DATA = [ - 'Тел. +7 (919) 891-54-25', - 'E-mail: vanyavanya@mailru', - 'Местонахождение: Санкт-Петербург GMT+3', -] - export const EVENTS_DATA = [ { title: 'Обучения', @@ -39,13 +27,15 @@ export const EVENTS_DATA = [ items: ['4 за последний год'], link: 'Подробнее', }, +] + +export const PROJECT_DATA = [ { title: 'Участие в текущих проектах', items: [ 'Мегапроект «Ямал»', 'Ковыктинское месторождение', ], - link: 'Подробнее', }, ] diff --git a/src/services/types.ts b/src/services/types.ts index 4937f6f..b3fa5be 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -49,3 +49,18 @@ export interface DroppedCard { id: string; cellId: string; } + +export interface ProfileProps { + email: string; + full_name: string; + image: string; + profile: { + phone: string | null; + telegram: string | null; + bio: string; + position: string; + birthday: string | null; + time_zone: number; + }; + projects: any[]; +} \ No newline at end of file diff --git a/src/services/utils.tsx b/src/services/utils.tsx index 433ece4..7f651e7 100644 --- a/src/services/utils.tsx +++ b/src/services/utils.tsx @@ -1,128 +1,128 @@ -export const BASE_URL = 'https://gazprom.hopto.org/api' - -const getResponseData = (res: Response) => { - if (!res.ok) { - return Promise.reject(`Ошибка: ${res.status}`) - } - return res.json() -} - -// const headers = { -// // authorization: `Bearer ${TOKEN}`, -// Accept: 'application/json', -// 'Content-Type': 'application/json', -// } - -// export const registration = ({email, password}: RegisterDataProps) => { -// return fetch(`${BASE_URL}/token/`, { -// method: 'POST', -// headers: { -// Accept: 'application/json', -// 'Content-Type': 'application/json', -// }, -// body: JSON.stringify({ -// email, -// password, -// }), -// }).then(getResponseData) -// } - -export const getMembers = () => { - const TOKEN = localStorage.getItem('token'); - const headers = { - authorization: `Bearer ${TOKEN}`, - Accept: 'application/json', - 'Content-Type': 'application/json', - }; - return fetch(`${BASE_URL}/v1/members/`, { - method: 'GET', - headers, - }).then(getResponseData); -}; - -// export const getTeams = () => { -// return fetch(`${BASE_URL}/members/`, { -// method: 'GET', -// headers, -// }).then(getResponseData); -// }; +// // export const BASE_URL = 'https://gazprom.hopto.org/api' -// export const getCategoryValue = (value) => { -// return fetch(`${BASE_URL}/api/?category=${value}`, { -// method: 'GET', -// }).then(getResponseData); -// }; - - - - -// export const sendSmsPhone = ({ phone_number }) => { -// return fetch(`${BASE_URL}/api/users/send_sms/`, { -// method: 'POST', -// headers: { -// Accept: 'application/json', -// 'Content-Type': 'application/json', -// }, -// body: JSON.stringify({ -// phone_number, -// }), -// }).then(getResponseData) +// const getResponseData = (res: Response) => { +// if (!res.ok) { +// return Promise.reject(`Ошибка: ${res.status}`) +// } +// return res.json() // } -// export const confirmRegistration = ({ phone_number, sms_code }) => { -// return fetch(`${BASE_URL}/api/users/confirm_phone/`, { -// method: 'POST', -// headers: { -// Accept: 'application/json', -// 'Content-Type': 'application/json', -// }, -// body: JSON.stringify({ -// phone_number, -// sms_code, -// }), -// }).then(getResponseData) -// } - -// export const login = ({ username, password }) => { -// return fetch(`${BASE_URL}/api/users/login/`, { -// method: 'POST', -// headers: { -// Accept: 'application/json', -// 'Content-Type': 'application/json', -// }, -// body: JSON.stringify({ -// username, -// password, -// }), -// }) -// .then(getResponseData) -// } - -// export const logout = () => { +// // const headers = { +// // // authorization: `Bearer ${TOKEN}`, +// // Accept: 'application/json', +// // 'Content-Type': 'application/json', +// // } + +// // export const registration = ({email, password}: RegisterDataProps) => { +// // return fetch(`${BASE_URL}/token/`, { +// // method: 'POST', +// // headers: { +// // Accept: 'application/json', +// // 'Content-Type': 'application/json', +// // }, +// // body: JSON.stringify({ +// // email, +// // password, +// // }), +// // }).then(getResponseData) +// // } + +// export const getMembers = () => { // const TOKEN = localStorage.getItem('token'); // const headers = { // authorization: `Bearer ${TOKEN}`, // Accept: 'application/json', // 'Content-Type': 'application/json', // }; -// return fetch(`${BASE_URL}/api/users/logout/`, { -// method: 'POST', -// headers, -// }) -// .then(getResponseData) -// } -// console.log('headers: ', headers); - -// export const getProfile = () => { -// const TOKEN = localStorage.getItem('token'); -// const headers = { -// authorization: `Bearer ${TOKEN}`, -// Accept: 'application/json', -// 'Content-Type': 'application/json', -// }; return fetch(`${BASE_URL}/api/users/me/`, { +// return fetch(`${BASE_URL}/v1/members/`, { // method: 'GET', // headers, -// }).then(getResponseData) -// } +// }).then(getResponseData); +// }; + +// // export const getTeams = () => { +// // return fetch(`${BASE_URL}/members/`, { +// // method: 'GET', +// // headers, +// // }).then(getResponseData); +// // }; + +// // export const getCategoryValue = (value) => { +// // return fetch(`${BASE_URL}/api/?category=${value}`, { +// // method: 'GET', +// // }).then(getResponseData); +// // }; + + + + +// // export const sendSmsPhone = ({ phone_number }) => { +// // return fetch(`${BASE_URL}/api/users/send_sms/`, { +// // method: 'POST', +// // headers: { +// // Accept: 'application/json', +// // 'Content-Type': 'application/json', +// // }, +// // body: JSON.stringify({ +// // phone_number, +// // }), +// // }).then(getResponseData) +// // } + +// // export const confirmRegistration = ({ phone_number, sms_code }) => { +// // return fetch(`${BASE_URL}/api/users/confirm_phone/`, { +// // method: 'POST', +// // headers: { +// // Accept: 'application/json', +// // 'Content-Type': 'application/json', +// // }, +// // body: JSON.stringify({ +// // phone_number, +// // sms_code, +// // }), +// // }).then(getResponseData) +// // } + +// // export const login = ({ username, password }) => { +// // return fetch(`${BASE_URL}/api/users/login/`, { +// // method: 'POST', +// // headers: { +// // Accept: 'application/json', +// // 'Content-Type': 'application/json', +// // }, +// // body: JSON.stringify({ +// // username, +// // password, +// // }), +// // }) +// // .then(getResponseData) +// // } + +// // export const logout = () => { +// // const TOKEN = localStorage.getItem('token'); +// // const headers = { +// // authorization: `Bearer ${TOKEN}`, +// // Accept: 'application/json', +// // 'Content-Type': 'application/json', +// // }; +// // return fetch(`${BASE_URL}/api/users/logout/`, { +// // method: 'POST', +// // headers, +// // }) +// // .then(getResponseData) +// // } +// // console.log('headers: ', headers); + +// // export const getProfile = () => { +// // const TOKEN = localStorage.getItem('token'); +// // const headers = { +// // authorization: `Bearer ${TOKEN}`, +// // Accept: 'application/json', +// // 'Content-Type': 'application/json', +// // }; return fetch(`${BASE_URL}/api/users/me/`, { +// // method: 'GET', +// // headers, +// // }).then(getResponseData) +// // } diff --git a/src/store/api.ts b/src/store/api.ts index b1aca19..f8984ed 100644 --- a/src/store/api.ts +++ b/src/store/api.ts @@ -1,4 +1,4 @@ -export const BASE_URL = 'https://gazprom.hopto.org/api'; +export const BASE_URL = 'https://gazprom.hopto.org'; import { RegisterDataProps } from 'src/services/types'; const TOKEN = localStorage.getItem('token'); const headers = { @@ -37,13 +37,21 @@ export const registration = async ({ email, password }: RegisterDataProps) => { return await request('/token/', options); }; +export const getProfile = async () => { + const options: RequestOptionsType = { + method: 'GET', + headers, + }; + const response = await request('/api/v1/users/me/', options); + return response +}; + export const getMembersAmount = async () => { const options: RequestOptionsType = { method: 'GET', headers, }; - // return await request(`/v1/members/`, options); - const response = await request('/v1/members/', options); + const response = await request('/api/v1/members/', options); return response }; @@ -52,5 +60,5 @@ export const getMembers = async (page: number) => { method: 'GET', headers, }; - return await request(`/v1/members/?page=${page}`, options); + return await request(`/api/v1/members/?page=${page}`, options); }; diff --git a/src/store/features/slice/membersSlice.ts b/src/store/features/slice/membersSlice.ts index 4ea7bc5..e526d07 100644 --- a/src/store/features/slice/membersSlice.ts +++ b/src/store/features/slice/membersSlice.ts @@ -10,6 +10,7 @@ export interface StateType { isFilterOpen: boolean; currentPage: number; membersAmount: number; + shortWindow: boolean; } const initialState: StateType = { @@ -19,6 +20,7 @@ const initialState: StateType = { isFilterOpen: false, currentPage: 1, membersAmount: 0, + shortWindow: false, }; export const fetchGetMembersAmount = createAsyncThunk( @@ -47,6 +49,9 @@ const membersSlice = createSlice({ setCurrentPage(state, action) { state.currentPage = action.payload; }, + setShortWindow(state, action) { + state.shortWindow = action.payload; + }, }, extraReducers: (builder) => { builder @@ -77,6 +82,6 @@ const membersSlice = createSlice({ }, }); -export const { setIsFilterOpen, setCurrentPage } = membersSlice.actions; +export const { setIsFilterOpen, setCurrentPage, setShortWindow } = membersSlice.actions; export const membersReducer = membersSlice.reducer; export const selectMembers = (state: RootStore) => state.members; diff --git a/src/store/features/slice/userSlice.ts b/src/store/features/slice/userSlice.ts index 67b1371..e2724d4 100644 --- a/src/store/features/slice/userSlice.ts +++ b/src/store/features/slice/userSlice.ts @@ -1,6 +1,6 @@ import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'; -import { RegisterDataProps } from 'src/services/types'; -import { registration } from 'src/store/api'; +import { ProfileProps, RegisterDataProps } from 'src/services/types'; +import { getProfile, registration } from 'src/store/api'; import { RootStore } from 'src/store/store'; export interface StateType { @@ -8,6 +8,7 @@ export interface StateType { isLoading: boolean; error: string | null | unknown; loggedIn: boolean; + profile: ProfileProps | null; } const initialState: StateType = { @@ -15,6 +16,7 @@ const initialState: StateType = { isLoading: false, error: null, loggedIn: false, + profile: null, }; // фетч добавить export const registerUser = createAsyncThunk( @@ -24,6 +26,13 @@ export const registerUser = createAsyncThunk( return response; } ); +export const fetchGetProfile = createAsyncThunk( + 'fetch/profile', + async () => { + const response = await getProfile(); + return response; + } +); const userSlice = createSlice({ name: 'user', @@ -48,6 +57,18 @@ const userSlice = createSlice({ .addCase(registerUser.rejected, (state, action) => { state.isLoading = false; state.error = action.error.message; + }) + .addCase(fetchGetProfile.pending, (state) => { + state.isLoading = true; + }) + .addCase(fetchGetProfile.fulfilled, (state, action) => { + state.profile = action.payload; + state.isLoading = false; + state.error = null; + }) + .addCase(fetchGetProfile.rejected, (state, action) => { + state.isLoading = false; + state.error = action.error.message; }); }, });