From 977eddcfe628355ee1fef6e5c74b9bc4154cc419 Mon Sep 17 00:00:00 2001 From: Tatiana Bocharova Date: Thu, 21 Nov 2024 10:00:52 +0300 Subject: [PATCH 1/7] signin/up mobile version --- src/pages/sign-in/ui/SignIn.hbs | 4 +- src/pages/sign-in/ui/SignIn.scss | 68 +++++++++++++++++++++++++++----- src/pages/sign-up/ui/SignUp.scss | 61 ++++++++++++++++++++++++++-- 3 files changed, 117 insertions(+), 16 deletions(-) diff --git a/src/pages/sign-in/ui/SignIn.hbs b/src/pages/sign-in/ui/SignIn.hbs index 55c20ad..6c12d7a 100644 --- a/src/pages/sign-in/ui/SignIn.hbs +++ b/src/pages/sign-in/ui/SignIn.hbs @@ -27,9 +27,7 @@ required />
- -
-
+
Нет аккаунта? diff --git a/src/pages/sign-in/ui/SignIn.scss b/src/pages/sign-in/ui/SignIn.scss index 48277e0..230e3be 100644 --- a/src/pages/sign-in/ui/SignIn.scss +++ b/src/pages/sign-in/ui/SignIn.scss @@ -31,7 +31,6 @@ } &__info { - margin-bottom: 35px; color: #f1f1f1; font-size: 16px; font-weight: 400; @@ -72,10 +71,11 @@ color: red; font-size: 16px; margin-top: 10px; + text-align: center; } &__submit_btn { - margin-top: 28px; + margin-top: 25px; width: 450px; height: 50px; padding: 10px; @@ -83,18 +83,11 @@ border-radius: 9px; border: none; color: #f1f1f1; - font-size: 24px; + font-size: 25px; font-weight: 400; text-align: center; } - &__checkbox { - width: 20px; - height: 20px; - margin-right: 5px; - accent-color: #FF5F0F; - } - &__additional { margin-top: 10px; color: #f1f1f1; @@ -109,6 +102,7 @@ &__register_site { text-decoration: none; font-weight: 700; + color: #f1f1f1; &:visited { color: #f1f1f1; @@ -118,4 +112,58 @@ text-decoration: underline; } } + + @media (pointer: coarse) { + &__register_site { + text-decoration: underline; + } + } + + @media (max-width: 768px) { + &__input { + width: calc(60vw - 20px); + } + + &__submit_btn { + width: 60vw; + } + + &__additional { + margin-top: 25px; + flex-direction: column; + row-gap: 10px; + } + } + + @media (max-width: 480px) { + &__form { + margin-top: 41px; + } + + &__intro { + min-height: 100px; + } + + &__title { + font-size: 24px; + } + + &__subtitle { + font-size: 18px; + } + + &__info { + font-size: 14px; + } + + &__input { + width: calc(100% - 20px); + font-size: 16px; + } + + &__submit_btn { + width: 100%; + font-size: 18px; + } + } } diff --git a/src/pages/sign-up/ui/SignUp.scss b/src/pages/sign-up/ui/SignUp.scss index e9c6063..9024e33 100644 --- a/src/pages/sign-up/ui/SignUp.scss +++ b/src/pages/sign-up/ui/SignUp.scss @@ -31,7 +31,6 @@ } &__info { - margin-bottom: 35px; color: #f1f1f1; font-size: 16px; font-weight: 400; @@ -72,10 +71,11 @@ color: red; font-size: 16px; margin-top: 15px; + text-align: center; } &__submit_btn { - margin-top: 28px; + margin-top: 25px; width: 450px; height: 50px; padding: 10px; @@ -83,7 +83,7 @@ border-radius: 9px; border: none; color: #f1f1f1; - font-size: 24px; + font-size: 25px; font-weight: 400; text-align: center; } @@ -102,6 +102,7 @@ &__enter_account { text-decoration: none; font-weight: 700; + color: #f1f1f1; &:visited { color: #f1f1f1; @@ -111,4 +112,58 @@ text-decoration: underline; } } + + @media (pointer: coarse) { + &__enter_account { + text-decoration: underline; + } + } + + @media (max-width: 768px) { + &__input { + width: calc(60vw - 20px); + } + + &__submit_btn { + width: 60vw; + } + + &__additional { + margin-top: 25px; + flex-direction: column; + row-gap: 10px; + } + } + + @media (max-width: 480px) { + &__form { + margin-top: 41px; + } + + &__intro { + min-height: 100px; + } + + &__title { + font-size: 24px; + } + + &__subtitle { + font-size: 18px; + } + + &__info { + font-size: 14px; + } + + &__input { + width: calc(100% - 20px); + font-size: 16px; + } + + &__submit_btn { + width: 100%; + font-size: 18px; + } + } } From 83af9d690d54630b2785f215c4aa079d2aff31f2 Mon Sep 17 00:00:00 2001 From: Tatiana Bocharova Date: Thu, 21 Nov 2024 22:17:04 +0300 Subject: [PATCH 2/7] album carousel --- src/pages/artist/ui/Artist.js | 9 +- src/pages/more-albums/ui/MoreAlbums.js | 2 +- src/pages/more-artists/ui/MoreArtists.js | 2 +- src/pages/search/ui/Search.js | 4 +- src/widgets/albumCarousel/api/api.js | 46 ++++++ src/widgets/albumCarousel/index.js | 2 + .../albumCarousel/ui/albumCarousel.hbs | 19 +++ src/widgets/albumCarousel/ui/albumCarousel.js | 151 ++++++++++++++++++ .../albumCarousel/ui/albumCarousel.scss | 109 +++++++++++++ src/widgets/albumList/api/api.js | 8 +- src/widgets/albumList/ui/albumList.hbs | 7 +- src/widgets/albumList/ui/albumList.js | 24 +-- src/widgets/albumList/ui/albumList.scss | 17 +- .../artistCarousel/ui/artistCarousel.hbs | 6 +- .../artistCarousel/ui/artistCarousel.js | 2 +- .../artistCarousel/ui/artistCarousel.scss | 7 + src/widgets/artistList/ui/artistList.hbs | 7 +- src/widgets/artistList/ui/artistList.js | 11 +- src/widgets/artistList/ui/artistList.scss | 17 +- src/widgets/trackList/ui/trackList.hbs | 4 +- src/widgets/trackList/ui/trackList.js | 2 +- 21 files changed, 379 insertions(+), 77 deletions(-) create mode 100644 src/widgets/albumCarousel/api/api.js create mode 100644 src/widgets/albumCarousel/index.js create mode 100644 src/widgets/albumCarousel/ui/albumCarousel.hbs create mode 100644 src/widgets/albumCarousel/ui/albumCarousel.js create mode 100644 src/widgets/albumCarousel/ui/albumCarousel.scss diff --git a/src/pages/artist/ui/Artist.js b/src/pages/artist/ui/Artist.js index 8b2e09e..b51ff66 100644 --- a/src/pages/artist/ui/Artist.js +++ b/src/pages/artist/ui/Artist.js @@ -1,8 +1,7 @@ import { TrackListAPI } from '../../../widgets/trackList/index.js'; -import { AlbumListAPI } from '../../../widgets/albumList/index.js'; import { ArtistCardView } from '../../../widgets/artistCard/index.js'; import { TrackListView } from '../../../widgets/trackList/index.js'; -import { AlbumListView } from '../../../widgets/albumList/index.js'; +import { AlbumCarouselView } from '../../../widgets/albumCarousel/index.js'; import { FooterPlayerView } from '../../../widgets/footerPlayer/index.js'; import { userStore } from '../../../entities/user/model/store.js'; import { player } from '../../../shared/player/model/store.js'; @@ -29,10 +28,8 @@ export class ArtistPage { player.setTracks(tracks); - const albumListAPI = new AlbumListAPI(this.artistId); - const albumListView = new AlbumListView(this.parent, this.artistId); - const albums = await albumListAPI.get(); - await albumListView.render(albums.slice(0, 5)); + const albumCarouselView = new AlbumCarouselView(this.parent, this.artistId); + await albumCarouselView.render(); const footPlayerView = new FooterPlayerView(this.parent); const user = userStore.storage.user; diff --git a/src/pages/more-albums/ui/MoreAlbums.js b/src/pages/more-albums/ui/MoreAlbums.js index 4726e3f..f0de908 100644 --- a/src/pages/more-albums/ui/MoreAlbums.js +++ b/src/pages/more-albums/ui/MoreAlbums.js @@ -21,6 +21,6 @@ export class MoreAlbumsPage { const albumListAPI = new AlbumListAPI(this.artistId); const albums = await albumListAPI.get(); const albumListView = new AlbumListView(this.parent, this.artistId); - await albumListView.render(albums, false); + await albumListView.render(albums); } } diff --git a/src/pages/more-artists/ui/MoreArtists.js b/src/pages/more-artists/ui/MoreArtists.js index 7ac4e81..70d1572 100644 --- a/src/pages/more-artists/ui/MoreArtists.js +++ b/src/pages/more-artists/ui/MoreArtists.js @@ -15,6 +15,6 @@ export class MoreArtistsPage { const artistListAPI = new ArtistListAPI(); const artists = await artistListAPI.get(); const artistListView = new ArtistListView(this.parent); - await artistListView.render(artists, false); + await artistListView.render(artists); } } diff --git a/src/pages/search/ui/Search.js b/src/pages/search/ui/Search.js index 34e3207..b44eb8c 100644 --- a/src/pages/search/ui/Search.js +++ b/src/pages/search/ui/Search.js @@ -44,7 +44,7 @@ export class SearchPage { } const artistListView = new ArtistListView(this.parent); - await artistListView.render(artists, false); + await artistListView.render(artists); } async handleFoundAlbums(albums) { @@ -58,7 +58,7 @@ export class SearchPage { } const albumListView = new AlbumListView(this.parent); - await albumListView.render(albums, false); + await albumListView.render(albums); } async handleFoundTracks(tracks) { diff --git a/src/widgets/albumCarousel/api/api.js b/src/widgets/albumCarousel/api/api.js new file mode 100644 index 0000000..90adfdd --- /dev/null +++ b/src/widgets/albumCarousel/api/api.js @@ -0,0 +1,46 @@ +import { API_URL } from '../../../shared/config/index.js'; +import { GET } from '../../../shared/api/index.js'; + +export class AlbumCarouselAPI { + /** + * Url path to backend api which returns albums/ + * + */ + url; + + /** + * Initializes the AlbumCarouselAPI. + * + */ + constructor(artistId = null) { + if (artistId) { + this.url = `${API_URL}/api/v1/albums/byArtistId/${artistId}`; + } else { + this.url = `${API_URL}/api/v1/albums`; + } + } + + async get() { + try { + const response = await GET(this.url); + if (!response.error) { + return response.data; + } else { + // this.displayMessage( + // messageBox, + // response.body.error || 'Не удалось загрузить музыкантов', + // 'error', + // ); + // console.error('Error during albums loading:', error); + console.log('Error during AlbumCarousel loading:'); + } + } catch (error) { + // this.displayMessage( + // messageBox, + // 'Возникла ошибка при загрузке плейлиста. Попробуйте позже.', + // 'error', + // ); + console.error(error); + } + } +} diff --git a/src/widgets/albumCarousel/index.js b/src/widgets/albumCarousel/index.js new file mode 100644 index 0000000..42886ef --- /dev/null +++ b/src/widgets/albumCarousel/index.js @@ -0,0 +1,2 @@ +export { AlbumCarouselView } from './ui/albumCarousel.js'; +export { AlbumCarouselAPI } from './api/api.js'; diff --git a/src/widgets/albumCarousel/ui/albumCarousel.hbs b/src/widgets/albumCarousel/ui/albumCarousel.hbs new file mode 100644 index 0000000..7888d88 --- /dev/null +++ b/src/widgets/albumCarousel/ui/albumCarousel.hbs @@ -0,0 +1,19 @@ +
+
+
+
+ Альбомы +
+ Показать еще +
+ +
+
diff --git a/src/widgets/albumCarousel/ui/albumCarousel.js b/src/widgets/albumCarousel/ui/albumCarousel.js new file mode 100644 index 0000000..e3c6cc7 --- /dev/null +++ b/src/widgets/albumCarousel/ui/albumCarousel.js @@ -0,0 +1,151 @@ +import { AlbumView } from '../../../entities/album/index.js'; +import { AlbumCarouselAPI } from '../api/api.js'; +import { eventBus } from '../../../shared/lib/eventbus.js'; +import template from './albumCarousel.hbs'; +import './albumCarousel.scss'; + +export class AlbumCarouselView { + /** + * The parent HTML element. + * @type {HTMLElement} + */ + parent; + + /** + * Initializes the AlbumView. + * + */ + constructor(parent, artistId = null) { + this.parent = parent ? parent : document.querySelector('#root'); + this.position = 0; + this.artistId = artistId; + } + + /** + * Renders the playlist view. + */ + async render() { + const albumCarouselAPI = new AlbumCarouselAPI(this.artistId); + let albums = await albumCarouselAPI.get(); + + const albumCarouselElement = document.createElement('div'); + albumCarouselElement.classList.add('albums'); + + let titleText; + let showMoreHref; + if (this.artistId) { + showMoreHref = `/more_albums/${"artist"}/${this.artistId}`; + titleText = "Альбомы исполнителя"; + } else { + showMoreHref = `/more_albums/popular`; + titleText = "Популярные альбомы"; + } + + albumCarouselElement.innerHTML = template({ showMoreHref }); + this.parent.appendChild(albumCarouselElement); + + const albumsBlock = document.getElementById('albums-carousel'); + Array.from(albums).forEach((album) => { + const albumCarouselElement = document.createElement('div'); + albumCarouselElement.classList.add('carousel__item'); + const albumView = new AlbumView(albumCarouselElement); + albumView.render(album); + albumsBlock.appendChild(albumCarouselElement); + }); + + await this.getElements(); + + this.onEvents(); + this.addEvents(); + this.setTitle(titleText); + } + + setTitle(titleText) { + const title = document.querySelector('.albums__recommend_text'); + title.textContent = titleText; + } + + onEvents() { + eventBus.on('carousel:next', this.handleGoNext); + eventBus.on('carousel:prev', this.handleGoPrev); + } + + offEvents() { + eventBus.off('carousel:next', this.handleGoNext); + eventBus.off('carousel:prev', this.handleGoPrev); + } + + addEvents() { + this.nextBtn.addEventListener('click', this.handleNextBtn); + this.prevBtn.addEventListener('click', this.handlePrevBtn); + + const links = this.parent.querySelectorAll('.link_more_albums'); + links.forEach((link) => { + link.addEventListener('click', (event) => this.handleLink(event)); + }); + } + + deleteEvents() { + this.nextBtn.removeEventListener('click', this.handleNextBtn); + this.prevBtn.removeEventListener('click', this.handlePrevBtn); + + const links = this.parent.querySelectorAll('.link_more_albums'); + links.forEach((link) => { + link.removeEventListener('click', (event) => this.handleLink(event)); + }); + } + + async getElements() { + this.carouselInner = document.querySelector('.carousel__inner'); + this.carouselItems = document.querySelectorAll('.carousel__item'); + this.carouselArea = document.querySelector('.carousel__area'); + this.nextBtn = document.querySelector('.carousel__button--next'); + this.prevBtn = document.querySelector('.carousel__button--prev'); + + this.itemWidth = this.carouselItems[0]?.offsetWidth ?? 0; + this.carouselAreaWidth = this.carouselArea.offsetWidth; + this.carouselInnerWidth = this.carouselInner.offsetWidth; + + this.maxPosition = -(this.carouselInnerWidth - this.carouselAreaWidth); + } + + handleLink(event) { + event.preventDefault(); + const href = event.target.getAttribute('href'); + eventBus.emit('navigate', href); + } + + handleGoNext = () => { + const remainingWidth = + this.carouselInnerWidth + this.position - this.carouselAreaWidth; + + if (remainingWidth > this.itemWidth) { + this.position -= this.itemWidth; + } else if (remainingWidth > 0) { + this.position -= remainingWidth; + } + + this.carouselInner.style.transform = `translateX(${this.position}px)`; + }; + + handleGoPrev = () => { + if (this.position < 0) { + this.position += + this.position + this.itemWidth > 0 ? -this.position : this.itemWidth; + this.carouselInner.style.transform = `translateX(${this.position}px)`; + } + }; + + handleNextBtn = () => { + eventBus.emit('carousel:next'); + }; + + handlePrevBtn = () => { + eventBus.emit('carousel:prev'); + }; + + destructor() { + this.deleteEvents(); + this.offEvents(); + } +} diff --git a/src/widgets/albumCarousel/ui/albumCarousel.scss b/src/widgets/albumCarousel/ui/albumCarousel.scss new file mode 100644 index 0000000..8637463 --- /dev/null +++ b/src/widgets/albumCarousel/ui/albumCarousel.scss @@ -0,0 +1,109 @@ +.albums { + &__container { + max-width: 1280px; + margin: 0 auto; + } + + &__block { + margin: 0 auto; + padding: 10px; + background-color: rgba(241.39, 241.39, 241.39, 0.1); + border-radius: 9px; + margin-top: 12px; + } + + &__upper_wrapper { + padding: 0 10px; + display: flex; + justify-content: space-between; + } + + &__recommend_text { + display: flex; + justify-content: space-between; + align-items: center; + color: #f1f1f1; + font-size: 24px; + font-weight: 400; + } + + &__show_more { + text-decoration: none; + color: #f1f1f1; + font-size: 24px; + + &:visited { + color: #f1f1f1; + } + + &:hover { + text-decoration: underline; + } + } + + &__list { + margin-top: 10px; + display: flex; + justify-content: space-around; + } +} + +.carousel { + &__container { + position: relative; + width: 100%; + padding: 10px 60px; + /* background-color: #eee; */ + /* border: 2px solid #ccc; */ + border-radius: 10px; + overflow: hidden; + box-sizing: border-box; + } + + &__area { + width: 100%; + overflow: hidden; + border-radius: 10px; + display: flex; + justify-content: start; + } + + &__inner { + display: flex; + /* gap: 10px; */ + transition: transform 0.5s ease; + text-align: left; + } + + &__item { + display: flex; + padding: 10px; + flex-direction: column; + align-items: center; + /* width: 210px; */ + height: fit-content; + flex-shrink: 0; + } + + &__button { + position: absolute; + top: 50%; + transform: translateY(-50%); + background-color: rgba(0, 0, 0, 0.5); + color: #fff; + border: none; + cursor: pointer; + border-radius: 50%; + width: 35px; + height: 35px; + font-size: 18px; + + &--prev { + left: 10px; + } + + &--next { + right: 10px; + } + } +} diff --git a/src/widgets/albumList/api/api.js b/src/widgets/albumList/api/api.js index dad11da..fac23bf 100644 --- a/src/widgets/albumList/api/api.js +++ b/src/widgets/albumList/api/api.js @@ -4,8 +4,12 @@ import { GET } from '../../../shared/api/index.js'; export class AlbumListAPI { url; - constructor() { - this.url = `${API_URL}/api/v1/albums`; + constructor(artistId = null) { + if (artistId) { + this.url = `${API_URL}/api/v1/albums/byArtistId/${artistId}`; + } else { + this.url = `${API_URL}/api/v1/albums`; + } } async get() { diff --git a/src/widgets/albumList/ui/albumList.hbs b/src/widgets/albumList/ui/albumList.hbs index 56ae464..ace8bd2 100644 --- a/src/widgets/albumList/ui/albumList.hbs +++ b/src/widgets/albumList/ui/albumList.hbs @@ -1,10 +1,7 @@
-
- Альбомы - {{#if showMoreHref}} - Показать еще - {{/if}} +
+ Альбомы
diff --git a/src/widgets/albumList/ui/albumList.js b/src/widgets/albumList/ui/albumList.js index 13abfc4..88cdca4 100644 --- a/src/widgets/albumList/ui/albumList.js +++ b/src/widgets/albumList/ui/albumList.js @@ -21,22 +21,19 @@ export class AlbumListView { /** * Renders the album view. */ - async render(albums, needsShowMoreHref = true) { + async render(albums) { const albumListElement = document.createElement('div'); albumListElement.classList.add('albums'); - if (needsShowMoreHref) { - let showMoreHref; - if (this.artistId) { - showMoreHref = `/more_albums/${"artist"}/${this.artistId}`; - } else { - showMoreHref = `/more_albums/popular`; - } - albumListElement.innerHTML = template({showMoreHref }); + let titleText; + if (this.artistId) { + titleText = "Альбомы исполнителя"; } else { - albumListElement.innerHTML = template({}); + titleText = "Популярные альбомы"; } + albumListElement.innerHTML = template({}); + this.parent.appendChild(albumListElement); const albumsBlock = document.getElementById('albums'); @@ -44,5 +41,12 @@ export class AlbumListView { const albumView = new AlbumView(albumsBlock); albumView.render(album); }); + + this.setTitle(titleText); + } + + setTitle(titleText) { + const title = document.querySelector('.albums__recommend_text'); + title.textContent = titleText; } } diff --git a/src/widgets/albumList/ui/albumList.scss b/src/widgets/albumList/ui/albumList.scss index f033581..a5b4c3b 100644 --- a/src/widgets/albumList/ui/albumList.scss +++ b/src/widgets/albumList/ui/albumList.scss @@ -12,7 +12,7 @@ margin-top: 12px; } - &__text { + &__recommend_text { display: flex; justify-content: space-between; align-items: center; @@ -21,23 +21,10 @@ font-weight: 400; } - &__show_more { - text-decoration: none; - color: #f1f1f1; - - &:visited { - color: #f1f1f1; - } - - &:hover { - text-decoration: underline; - } - } - &__list { margin-top: 10px; display: flex; - justify-content: flex-start; + justify-content: space-around; flex-wrap: wrap; gap: 15px; } diff --git a/src/widgets/artistCarousel/ui/artistCarousel.hbs b/src/widgets/artistCarousel/ui/artistCarousel.hbs index e5f010f..ff2d001 100644 --- a/src/widgets/artistCarousel/ui/artistCarousel.hbs +++ b/src/widgets/artistCarousel/ui/artistCarousel.hbs @@ -1,7 +1,9 @@