diff --git a/src/api/UsersServiceAPI.js b/src/api/UsersServiceAPI.js index a29126b..2154513 100644 --- a/src/api/UsersServiceAPI.js +++ b/src/api/UsersServiceAPI.js @@ -31,6 +31,21 @@ class UsersService { return data; } + getMe = async () => { + const {data} = await http.get(`${ROOT_URL}/me`); + return data; + } + + setAvatar = async (avatar, updateOptions) => { + const {data} = await http.post(`${ROOT_URL}/edit-me`, {...updateOptions, avatar}); + return data; + } + + changePassword = async (password, updateOptions) => { + const {data} = await http.post(`${ROOT_URL}/edit-me`, {...updateOptions, password}); + return data; + } + /** * Метод поиска пользователя по Логину * @param {string} login - Логин пользователя diff --git a/src/app.html b/src/app.html index 55286a5..7477aae 100644 --- a/src/app.html +++ b/src/app.html @@ -116,9 +116,9 @@
-
+
avatar -
login_name
+
login_name
diff --git a/src/components/avatar-modal-component/AvatarModal.css b/src/components/avatar-modal-component/AvatarModal.css new file mode 100644 index 0000000..dcb64dc --- /dev/null +++ b/src/components/avatar-modal-component/AvatarModal.css @@ -0,0 +1,12 @@ +.Avatar__img { + width: 100%; + background-size: contain; + background-repeat: no-repeat; + background-position: center; + max-height: 400px; + min-height: 300px; +} +.Avatar__container { + padding: 20px; + overflow-y: auto; +} \ No newline at end of file diff --git a/src/components/avatar-modal-component/AvatarModal.js b/src/components/avatar-modal-component/AvatarModal.js new file mode 100644 index 0000000..37021b5 --- /dev/null +++ b/src/components/avatar-modal-component/AvatarModal.js @@ -0,0 +1,75 @@ +import Modal from '../modal/Modal'; +import {createElement} from '../../utils/elementUtils'; +import FormControl from '../form-control/index'; +import './AvatarModal.css'; +import usersServiceApi from '../../api/UsersServiceAPI'; +import userInfoService from '../../services/UserInfoService'; +import {EVENTS} from '../../consts'; + +class AvatarModal extends Modal { + constructor (parentNode) { + super(parentNode); + + this.header.textContent = 'Основное изображение'; + this.avatar = createElement({ + tagName: 'div', + options: { + className: 'Avatar__img', + } + }); + this.width = this.avatar.scrollWidth; + this.content.append(this.avatar); + this.content.className = 'Avatar__container'; + + this.input = this.createComponent(FormControl, this.content, { + id: 'avatar-url-input', + label: 'URL нового изображения', + placeholder: 'Введите URL', + className: 'Avatar__url-input' + }); + + this.submitBtn = createElement({ + tagName: 'button', + options: { + className: 'Avatar__submit-btn btn btn-outline-primary' + } + }); + this.submitBtn.textContent = 'Применить'; + this.footer.append(this.submitBtn); + this.addEventListener(this.submitBtn, EVENTS.CLICK, () => { + this.submit(); + }); + + this.addSubscribe(this.input, 'input', (evt) => { + this.url = evt.currentTarget.value; + this.changeAvatar(this.url); + }); + + this.init(); + } + + changeAvatar (url) { + this.avatar.style.backgroundImage = `url(${url})`; + } + + init = async () => { + const user = await usersServiceApi.getMe(); + this.changeAvatar(this.url || user.avatar); + } + + openEditor () { + this.show(); + } + + submit = async () => { + if (this.url) { + await usersServiceApi.setAvatar(this.url); + userInfoService.setUserLogin(); + this.hide(); + } else { + this.input.input.placeholder = 'Вы не ввели URL'; + } + + } +} +export default AvatarModal; diff --git a/src/components/form-control/FormControl.js b/src/components/form-control/FormControl.js index f36e3e2..4eaa4bd 100644 --- a/src/components/form-control/FormControl.js +++ b/src/components/form-control/FormControl.js @@ -36,6 +36,9 @@ class FormControl extends Component { this.addEventListener(this.input, 'focus', this.clearError); this.addEventListener(this.input, 'click', this.clearError); this.addEventListener(this.input, 'keydown', this.clearError); + this.addEventListener(this.input, 'input', (evt) => { + this.next('input', evt); + }); } disabled = (value) => { diff --git a/src/components/profile-content/ProfileContent.js b/src/components/profile-content/ProfileContent.js index 266184e..590acb3 100644 --- a/src/components/profile-content/ProfileContent.js +++ b/src/components/profile-content/ProfileContent.js @@ -1,6 +1,6 @@ import Component from '../component/Component'; import FormControl from '../form-control'; -import {FORM_TYPES} from '../../consts'; +import {FORM_TYPES, EVENTS} from '../../consts'; class ProfileContent extends Component { constructor (parentNode) { @@ -10,6 +10,11 @@ class ProfileContent extends Component { this.Password = this.mainNode.querySelector('.Password__inputContainer'); this.profileButton = this.mainNode.querySelector('.Profile__button'); this.title.textContent = 'Смена пароля'; + this.avatar = this.mainNode.querySelector('.Profile__avatar'); + this.addEventListener(this.avatar, EVENTS.CLICK, () => { + this.next(EVENTS.OPEN_MODAL); + }); + this.userName = this.mainNode.querySelector('.Profile__user-name'); this.oldPassword = this.createComponent(FormControl, this.Password, { label: 'Старый пароль:', id: 'oldpass', @@ -32,7 +37,12 @@ class ProfileContent extends Component { required: true, }); - this.addEventListener(this.form, 'submit', this.submit); + this.addEventListener(this.form, EVENTS.SUBMIT, this.submit); + } + + initProfile (user) { + this.avatar.src = user.avatar; + this.userName.textContent = user.login; } disabled = (value) => { diff --git a/src/components/profile-page/ProfilePage.js b/src/components/profile-page/ProfilePage.js index 459f360..74bc3ce 100644 --- a/src/components/profile-page/ProfilePage.js +++ b/src/components/profile-page/ProfilePage.js @@ -1,12 +1,30 @@ import Component from '../component/index'; import ProfileContent from '../profile-content'; import './ProfilePage.css'; +import usersServiceApi from '../../api/UsersServiceAPI'; +import AvatarModal from '../avatar-modal-component/AvatarModal'; +import userInfoService from '../../services/UserInfoService'; +import {EVENTS} from '../../consts'; class ProfilePage extends Component { constructor (mainNodeSelector, parentNode) { super(mainNodeSelector, parentNode); this.form = this.createComponent(ProfileContent, this.mainNode); + this.modal = this.createComponent(AvatarModal, this.mainNode); + this.addSubscribe(this.form, EVENTS.OPEN_MODAL, () => { + this.modal.openEditor(); + }); + this.init(); + + this.addSubscribe(userInfoService, EVENTS.CHANGE_USER_INFO, () => { + this.init(); + }); + } + + init = async () => { + this.user = await usersServiceApi.getMe(); + this.form.initProfile(this.user); } } diff --git a/src/consts.js b/src/consts.js index 27321da..b93d2b5 100644 --- a/src/consts.js +++ b/src/consts.js @@ -52,6 +52,10 @@ export const EVENTS = { ROW_CLICK: 'rowClick', ROW_DOUBLE_CLICK: 'rowDoubleClick', CHANGE_USER_INFO: 'changeUserInfo', + CHANGE_USER_AVATAR: 'changeUserAvatar', + OPEN_MODAL: 'openModal', + CLICK: 'click', + SUBMIT: 'submit' }; export const FORM_TYPES = { diff --git a/src/services/UserInfoService.js b/src/services/UserInfoService.js index c5a2776..38f2cca 100644 --- a/src/services/UserInfoService.js +++ b/src/services/UserInfoService.js @@ -1,6 +1,4 @@ import usersServiceApi from '../api/UsersServiceAPI'; -import tokenApi from '../api/TokenAPI'; -import {parseJwt} from '../utils/jwtDecode'; import {EVENTS} from '../consts'; import EmitService from './EmitService'; @@ -15,10 +13,13 @@ class UserInfoService extends EmitService { } setUserLogin = async () => { - const {login} = parseJwt(tokenApi.getAccessToken()); - this.userInfo = await usersServiceApi.find(login); + this.userInfo = await usersServiceApi.getMe(); this.next(EVENTS.CHANGE_USER_INFO, {...this.userInfo}); } + + changeAllAvatars () { + this.next(EVENTS.CHANGE_USER_AVATAR); + } } const userInfoService = new UserInfoService();