Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/contacts - Исправление раздела "Контакты" #206

Merged
merged 17 commits into from
Jun 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
3f5ad9e
feat: подключить бэкенд для загрузки контактов, добавить редактирован…
IvannaBalanyuk Jun 12, 2024
788a7f4
fix: исправить верстку, реализовать адаптивность
IvannaBalanyuk Jun 12, 2024
8e11927
Merge branch 'develop' of github.com:ya-pomogau/frontend into fix/con…
IvannaBalanyuk Jun 12, 2024
ecd7ab9
fix: исправить импорт для TContacts
IvannaBalanyuk Jun 12, 2024
6a845a2
fix: вернуть usePermission к исходному состоянию
IvannaBalanyuk Jun 12, 2024
2474682
hotfix: вынести повторяющийся блок верстки в функцию getContactContainer
IvannaBalanyuk Jun 12, 2024
4505018
hotfix: убрать слайс для contacts и его применение
IvannaBalanyuk Jun 12, 2024
c709164
hotfix: для инпутов применить useForm вместо useState
IvannaBalanyuk Jun 12, 2024
2d0fa42
hotfix: убрать условную конструкцию if из onSubmit
IvannaBalanyuk Jun 12, 2024
e066e90
Merge branch 'develop' of github.com:ya-pomogau/frontend into fix/con…
IvannaBalanyuk Jun 12, 2024
888d280
fix: вернуть usePermission к исходному состоянию
IvannaBalanyuk Jun 12, 2024
d700dba
hotfix: поправить паддинги у container (поправка на разницу в высоте …
IvannaBalanyuk Jun 12, 2024
aab1c45
fix: перенести useUpdateContactsMutation в adminApi
IvannaBalanyuk Jun 12, 2024
c083ab0
fix: внести правки в части обновления контактов (добавить id в запрос)
IvannaBalanyuk Jun 13, 2024
27f716e
hotfix: добавить валидацию из useform, убрать передачу id в params пр…
IvannaBalanyuk Jun 13, 2024
d7f8d83
fix: вернуть usePermission к исходному состоянию
IvannaBalanyuk Jun 13, 2024
d6dcb68
hotfix: вернуть setValues из useForm, применить в useEffect в Contact…
IvannaBalanyuk Jun 13, 2024
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
3 changes: 3 additions & 0 deletions src/app/store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { configureStore } from '@reduxjs/toolkit';
import { userModel } from 'entities/user/model';
import { createRequestModel } from 'features/create-request/model/create-request';
import { usersApi } from 'services/user-api';
import { contactsApi } from 'services/contacts-api';
import { tasksApi } from 'services/tasks-api';
import { authAdminApi } from 'services/auth-admin-api';
import { categoriesApi } from 'services/categories-api';
Expand All @@ -19,6 +20,7 @@ export const store = configureStore({
createRequest: createRequestModel.reducer,
system: systemSliceReducer,
[usersApi.reducerPath]: usersApi.reducer,
[contactsApi.reducerPath]: contactsApi.reducer,
[tasksApi.reducerPath]: tasksApi.reducer,
[userTasksApi.reducerPath]: userTasksApi.reducer,
[authAdminApi.reducerPath]: authAdminApi.reducer,
Expand All @@ -29,6 +31,7 @@ export const store = configureStore({
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware()
.concat(usersApi.middleware)
.concat(contactsApi.middleware)
.concat(tasksApi.middleware)
.concat(authAdminApi.middleware)
.concat(categoriesApi.middleware)
Expand Down
215 changes: 122 additions & 93 deletions src/pages/contacts/contacts.tsx
Original file line number Diff line number Diff line change
@@ -1,118 +1,147 @@
import React, { ChangeEvent, SyntheticEvent } from 'react';
import { SyntheticEvent, useEffect, useState } from 'react';
import classNames from 'classnames';
import { Icon } from 'shared/ui/icons';
import { SmartHeader } from 'shared/ui/smart-header';

import styles from './styles.module.css';
import { SmartHeader } from '../../shared/ui/smart-header';
import { Icon } from '../../shared/ui/icons';
import { Button } from '../../shared/ui/button';
import usePermission from 'shared/hooks/use-permission';
import { UserRole, UserStatus } from 'shared/types/common.types';
import usePermission from '../../shared/hooks/use-permission';
import {
UserRole,
UserStatus,
TContacts,
} from '../../shared/types/common.types';
import useForm from '../../shared/hooks/use-form';
import { useGetContactsQuery } from '../../services/contacts-api';
import { useUpdateContactsMutation } from '../../services/admin-api';

const initialContactsValues = {
email: null,
socialNetwork: null,
};

export function ContactsPage() {
const roleChecker = usePermission([UserStatus.VERIFIED], UserRole.ADMIN);
const isEditAllowed = usePermission([UserStatus.VERIFIED], UserRole.ADMIN);
const [updateContacts, { isLoading }] = useUpdateContactsMutation();

const [userData, setUserData] = React.useState({
userEmail: 'www@yandex.ru',
userVKLink: 'https://vk.com/me2help',
});
const { data } = useGetContactsQuery();

const [enableEdit, setEnableEdit] = React.useState(false);
const { values, setValues, handleChange, isValid } = useForm<TContacts>(
initialContactsValues
);

const onSubmit = (e: SyntheticEvent) => {
e.preventDefault();
setEnableEdit(false);
console.log(
`Данные email:${userData.userEmail} и VK:${userData.userVKLink} отправлены на сервер`
);
};
const handleEnableEdit = () => {
setEnableEdit(true);
useEffect(() => {
setValues({
email: data?.email,
socialNetwork: data?.socialNetwork,
});
}, [data]);

const [editingInput, setEditingInput] = useState<
'email' | 'socialNetwork' | null
>(null);

const editBoxHandler = (inputName: 'email' | 'socialNetwork') => {
setEditingInput(inputName);
};

const onChange = (e: ChangeEvent<HTMLInputElement>) => {
setUserData({ ...userData, [e.target.name]: e.target.value });
const isButtonDisabled = editingInput === null || !isValid;

const onSubmit = async (e: SyntheticEvent) => {
e.preventDefault();
try {
await updateContacts(values);
} catch (error) {
console.error('Ошибка при сохранении данных:', error);
values.email = data?.email;
values.socialNetwork = data?.socialNetwork;
} finally {
setEditingInput(null);
}
};

return (
<>
<SmartHeader
text="Контакты"
icon={<Icon color="blue" icon="ContactsIcon" size="54" />}
/>
<form onSubmit={onSubmit}>
<div className={styles.container}>
<div className={styles.element_box}>
<h2
className={classNames(
'text',
'text_size_large',
'text_type_regular',
styles.title
)}
>
Эл. почта
</h2>
<input
type="text"
className={styles.input}
onChange={onChange}
name="userEmail"
defaultValue={userData.userEmail}
readOnly={!enableEdit}
onClick={(e) => {
if (!enableEdit) {
e.preventDefault();
window.location.href = `mailto:${userData.userEmail}`;
}
}}
/>
</div>
{roleChecker && (
<div onClick={handleEnableEdit} className={styles.edit_box}>
<Icon color="blue" icon="EditIcon" />
<p className={styles.edit_text}>Изменить данные</p>
</div>
)}
const getContactContainer = (inputName: 'email' | 'socialNetwork') => {
const titleText = inputName === 'email' ? 'Эл. почта' : 'Соцсети';
const editBoxText =
inputName === 'email' ? 'Изменить эл. почту' : 'Изменить соцсети';
const inputHref =
inputName === 'email'
? `mailto:${values.email}`
: `${values.socialNetwork}`;
const inputType = inputName === 'email' ? 'email' : 'url';

return (
<div className={styles.container}>
<div className={styles.element_box}>
<h2
className={classNames(
'text',
'text_size_large',
'text_type_regular',
'm-0',
styles.title
)}
>
{titleText}
</h2>
<input
type={inputType}
className={`${styles.input} ${
editingInput === inputName
? styles.input_mode_edit
: styles.input_mode_link
}`}
onChange={handleChange}
name={inputName}
value={values[inputName] || ''}
readOnly={editingInput !== inputName}
onClick={(e) => {
if (editingInput !== inputName) {
e.preventDefault();
window.location.href = inputHref;
}
}}
/>
</div>
<div className={styles.container}>
<div className={styles.element_box}>
<h2
{isEditAllowed && (
<div
onClick={() => editBoxHandler(inputName)}
className={
editingInput === inputName
? styles.edit_box_hidden
: styles.edit_box
}
>
<Icon color="blue" icon="EditIcon" />
<p
className={classNames(
'text',
'text_size_large',
'text_size_small',
'text_type_regular',
styles.title
'm-0'
)}
>
Страница VK
</h2>
<input
type="text"
className={styles.input}
onChange={onChange}
name="userVKLink"
defaultValue={userData.userVKLink}
readOnly={!enableEdit}
onClick={(e) => {
if (!enableEdit) {
e.preventDefault();
window.location.href = `${userData.userVKLink}`;
}
}}
/>
{editBoxText}
</p>
</div>
{roleChecker && (
<div onClick={handleEnableEdit} className={styles.edit_box}>
<Icon color="blue" icon="EditIcon" />
<p className={styles.edit_text}>Изменить данные</p>
</div>
)}
</div>
{roleChecker && (
)}
</div>
);
};

return (
<>
<SmartHeader
text="Контакты"
icon={<Icon color="blue" icon="ContactsIcon" size="54" />}
/>
<form className={styles.form} onSubmit={onSubmit}>
{getContactContainer('email')}
{getContactContainer('socialNetwork')}
{isEditAllowed && (
<Button
buttonType="primary"
label="Сохранить"
disabled={!enableEdit}
disabled={isButtonDisabled}
type="submit"
/>
)}
Expand Down
96 changes: 55 additions & 41 deletions src/pages/contacts/styles.module.css
Original file line number Diff line number Diff line change
@@ -1,75 +1,89 @@
.header {
height: 90px;
.form {
padding: 0px 30px;
display: flex;
flex-direction: column;
align-items: flex-start;
row-gap: 20px;
}

.container {
display: flex;
justify-content: space-between;
margin: 10px 0 30px 30px;
padding-bottom: 20px;
width: 100%;
padding: 13px 0px 20px;
border-bottom: 1px solid;
border-image-source: var(--colors-interface-line);
border-image-slice: 1;
flex-wrap: wrap;
align-items: center;
}

.title {
color: var(--colors-interface-primary-additional);
margin: 0;
margin-bottom: 20px;
position: relative;
}

.link {
text-decoration: none;
color: var(--colors-interface-primary);
}

.form {
max-width: 600px;
margin-left: 30px;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: flex-end;
}

.text_area {
margin-bottom: 20px;
height: 122px;
width: 100%;
}

.button {
width: 94px;
}

.element_box {
display: flex;
flex-direction: column;
justify-content: flex-end;
row-gap: 20px;
}

.title {
color: var(--colors-interface-primary-additional);
}

.input {
color: var(--colors-interface-primary);
font-size: 24px;
border: none;
background-color: transparent;
outline: none;
}

.input:hover {
.input_mode_link {
color: var(--colors-interface-primary);
}

.input_mode_link:hover {
cursor: pointer;
}

.input_mode_edit {
color: #000000;
}

.input_mode_edit:hover {
cursor: text;
}

.edit_box {
color: var(--colors-interface-primary);
display: flex;
align-items: center;
align-items: flex-end;
gap: 10px;
}

.edit_box:hover {
cursor: pointer;
}

.edit_text {
color: var(--colors-interface-primary);
.edit_box_hidden {
display: none;
}


@media (max-width: 600px) {
.form {
padding: 0;
}

.container {
padding-bottom: 0;
border: none;
flex-direction: column;
align-items: flex-start;
}

.element_box {
width: 100%;
padding-bottom: 20px;
border-bottom: 1px solid;
border-image-source: var(--colors-interface-line);
border-image-slice: 1;
}
}
Loading