изменена верстка

This commit is contained in:
Аришина) 2024-11-06 12:48:48 +04:00
parent 73954d9d5a
commit ee17998948
18 changed files with 408 additions and 304 deletions

2
.gitignore vendored
View File

@ -13,4 +13,4 @@
*.vsix *.vsix
node_modules node_modules
*storybook.log *storybook.log

View File

@ -15,4 +15,4 @@
5. Валидация форм 5. Валидация форм
Должен был добавить плеер с воспроизведением песен, но из-за ошибок, про которые я написал выше, не удалось. Должен был добавить плеер с воспроизведением песен, но из-за ошибок, про которые я написал выше, не удалось.
Пришлось жестко передать объект песни прямо в коде компонента. Пришлось жестко передать объект песни прямо в коде компонента.

260
data.json
View File

@ -78,7 +78,7 @@
"genre_name": "Rock" "genre_name": "Rock"
}, },
{ {
"id": "1", "id": "6",
"song_name": "Smells Like Poop", "song_name": "Smells Like Poop",
"band_id": "1", "band_id": "1",
"band_name": "Nevroz", "band_name": "Nevroz",
@ -93,7 +93,7 @@
"genre_name": "Rock" "genre_name": "Rock"
}, },
{ {
"id": "2", "id": "7",
"song_name": "Song 3", "song_name": "Song 3",
"band_id": "1", "band_id": "1",
"band_name": "Nevroz", "band_name": "Nevroz",
@ -108,7 +108,7 @@
"genre_name": "Rock" "genre_name": "Rock"
}, },
{ {
"id": "3", "id": "8",
"song_name": "Ругань из-за Стёпы", "song_name": "Ругань из-за Стёпы",
"band_id": "2", "band_id": "2",
"band_name": "noizemchik", "band_name": "noizemchik",
@ -124,7 +124,7 @@
"genre_name": "Rock" "genre_name": "Rock"
}, },
{ {
"id": "4", "id": "9",
"song_name": "Crazy Frog", "song_name": "Crazy Frog",
"band_id": "3", "band_id": "3",
"band_name": "DSPD", "band_name": "DSPD",
@ -138,126 +138,6 @@
"genreid": "1", "genreid": "1",
"genre_name": "Rock" "genre_name": "Rock"
}, },
{
"id": "5",
"song_name": "Кем я стал",
"band_id": "3",
"band_name": "DSPD",
"albumid": "3",
"album_name": "Album 3",
"source": "/src/songs/DSPD feat. даня хренников - Кем я стал_(audio-lord.ru).mp3",
"cover": "https://avatars.yandex.net/get-music-content/10129881/f3cf1afc.a.30561322-1/m1000x1000?webp=falseh",
"playlists": [
"3"
],
"genreid": "1",
"genre_name": "Rock"
},
{
"id": "5",
"song_name": "Кем я стал",
"band_id": "3",
"band_name": "DSPD",
"albumid": "3",
"album_name": "Album 3",
"source": "/src/songs/DSPD feat. даня хренников - Кем я стал_(audio-lord.ru).mp3",
"cover": "https://avatars.yandex.net/get-music-content/10129881/f3cf1afc.a.30561322-1/m1000x1000?webp=falseh",
"playlists": [
"3"
],
"genreid": "1",
"genre_name": "Rock"
},
{
"id": "5",
"song_name": "Кем я стал",
"band_id": "3",
"band_name": "DSPD",
"albumid": "3",
"album_name": "Album 3",
"source": "/src/songs/DSPD feat. даня хренников - Кем я стал_(audio-lord.ru).mp3",
"cover": "https://avatars.yandex.net/get-music-content/10129881/f3cf1afc.a.30561322-1/m1000x1000?webp=falseh",
"playlists": [
"3"
],
"genreid": "1",
"genre_name": "Rock"
},
{
"id": "5",
"song_name": "Кем я стал",
"band_id": "3",
"band_name": "DSPD",
"albumid": "3",
"album_name": "Album 3",
"source": "/src/songs/DSPD feat. даня хренников - Кем я стал_(audio-lord.ru).mp3",
"cover": "https://avatars.yandex.net/get-music-content/10129881/f3cf1afc.a.30561322-1/m1000x1000?webp=falseh",
"playlists": [
"3"
],
"genreid": "1",
"genre_name": "Rock"
},
{
"id": "6",
"song_name": "Кем я стал",
"band_id": "3",
"band_name": "DSPD",
"albumid": "3",
"album_name": "Album 3",
"source": "/src/songs/DSPD feat. даня хренников - Кем я стал_(audio-lord.ru).mp3",
"cover": "https://avatars.yandex.net/get-music-content/10129881/f3cf1afc.a.30561322-1/m1000x1000?webp=falseh",
"playlists": [
"3"
],
"genreid": "1",
"genre_name": "Rock"
},
{
"id": "7",
"song_name": "Кем я стал",
"band_id": "3",
"band_name": "DSPD",
"albumid": "3",
"album_name": "Album 3",
"source": "/src/songs/DSPD feat. даня хренников - Кем я стал_(audio-lord.ru).mp3",
"cover": "https://avatars.yandex.net/get-music-content/10129881/f3cf1afc.a.30561322-1/m1000x1000?webp=falseh",
"playlists": [
"3"
],
"genreid": "1",
"genre_name": "Rock"
},
{
"id": "8",
"song_name": "Кем я стал",
"band_id": "3",
"band_name": "DSPD",
"albumid": "3",
"album_name": "Album 3",
"source": "/src/songs/DSPD feat. даня хренников - Кем я стал_(audio-lord.ru).mp3",
"cover": "https://avatars.yandex.net/get-music-content/10129881/f3cf1afc.a.30561322-1/m1000x1000?webp=falseh",
"playlists": [
"3"
],
"genreid": "1",
"genre_name": "Rock"
},
{
"id": "9",
"song_name": "Кем я стал",
"band_id": "3",
"band_name": "DSPD",
"albumid": "3",
"album_name": "Album 3",
"source": "/src/songs/DSPD feat. даня хренников - Кем я стал_(audio-lord.ru).mp3",
"cover": "https://avatars.yandex.net/get-music-content/10129881/f3cf1afc.a.30561322-1/m1000x1000?webp=falseh",
"playlists": [
"3"
],
"genreid": "1",
"genre_name": "Rock"
},
{ {
"id": "10", "id": "10",
"song_name": "Кем я стал", "song_name": "Кем я стал",
@ -265,14 +145,14 @@
"band_name": "DSPD", "band_name": "DSPD",
"albumid": "3", "albumid": "3",
"album_name": "Album 3", "album_name": "Album 3",
"source": "source_path", "source": "/src/songs/DSPD feat. даня хренников - Кем я стал_(audio-lord.ru).mp3",
"cover": "https://sun9-11.userapi.com/impg/yfCwuWXI6NkFVC2HvMlegM2qWLlenkeiiRyvNQ/jpH8m1wlLqs.jpg?size=604x604&quality=95&sign=60a1d1877b49631fb6078db88715fc88&c_uniq_tag=UKrig2vg02reyBH_ML0OKeqt5gm_2jpwEXD7NJBUXoQ&type=album", "cover": "https://avatars.yandex.net/get-music-content/10129881/f3cf1afc.a.30561322-1/m1000x1000?webp=falseh",
"playlists": [ "playlists": [
"3" "3"
], ],
"genreid": "1", "genreid": "1",
"genre_name": "Rock" "genre_name": "Rock"
}, },
{ {
"id": "11", "id": "11",
"song_name": "Кем я стал", "song_name": "Кем я стал",
@ -280,6 +160,126 @@
"band_name": "DSPD", "band_name": "DSPD",
"albumid": "3", "albumid": "3",
"album_name": "Album 3", "album_name": "Album 3",
"source": "/src/songs/DSPD feat. даня хренников - Кем я стал_(audio-lord.ru).mp3",
"cover": "https://avatars.yandex.net/get-music-content/10129881/f3cf1afc.a.30561322-1/m1000x1000?webp=falseh",
"playlists": [
"3"
],
"genreid": "1",
"genre_name": "Rock"
},
{
"id": "12",
"song_name": "Кем я стал",
"band_id": "3",
"band_name": "DSPD",
"albumid": "3",
"album_name": "Album 3",
"source": "/src/songs/DSPD feat. даня хренников - Кем я стал_(audio-lord.ru).mp3",
"cover": "https://avatars.yandex.net/get-music-content/10129881/f3cf1afc.a.30561322-1/m1000x1000?webp=falseh",
"playlists": [
"3"
],
"genreid": "1",
"genre_name": "Rock"
},
{
"id": "13",
"song_name": "Кем я стал",
"band_id": "3",
"band_name": "DSPD",
"albumid": "3",
"album_name": "Album 3",
"source": "/src/songs/DSPD feat. даня хренников - Кем я стал_(audio-lord.ru).mp3",
"cover": "https://avatars.yandex.net/get-music-content/10129881/f3cf1afc.a.30561322-1/m1000x1000?webp=falseh",
"playlists": [
"3"
],
"genreid": "1",
"genre_name": "Rock"
},
{
"id": "14",
"song_name": "Кем я стал",
"band_id": "3",
"band_name": "DSPD",
"albumid": "3",
"album_name": "Album 3",
"source": "/src/songs/DSPD feat. даня хренников - Кем я стал_(audio-lord.ru).mp3",
"cover": "https://avatars.yandex.net/get-music-content/10129881/f3cf1afc.a.30561322-1/m1000x1000?webp=falseh",
"playlists": [
"3"
],
"genreid": "1",
"genre_name": "Rock"
},
{
"id": "15",
"song_name": "Кем я стал",
"band_id": "3",
"band_name": "DSPD",
"albumid": "3",
"album_name": "Album 3",
"source": "/src/songs/DSPD feat. даня хренников - Кем я стал_(audio-lord.ru).mp3",
"cover": "https://avatars.yandex.net/get-music-content/10129881/f3cf1afc.a.30561322-1/m1000x1000?webp=falseh",
"playlists": [
"3"
],
"genreid": "1",
"genre_name": "Rock"
},
{
"id": "18",
"song_name": "Кем я стал",
"band_id": "3",
"band_name": "DSPD",
"albumid": "3",
"album_name": "Album 3",
"source": "/src/songs/DSPD feat. даня хренников - Кем я стал_(audio-lord.ru).mp3",
"cover": "https://avatars.yandex.net/get-music-content/10129881/f3cf1afc.a.30561322-1/m1000x1000?webp=falseh",
"playlists": [
"3"
],
"genreid": "1",
"genre_name": "Rock"
},
{
"id": "19",
"song_name": "Кем я стал",
"band_id": "3",
"band_name": "DSPD",
"albumid": "3",
"album_name": "Album 3",
"source": "/src/songs/DSPD feat. даня хренников - Кем я стал_(audio-lord.ru).mp3",
"cover": "https://avatars.yandex.net/get-music-content/10129881/f3cf1afc.a.30561322-1/m1000x1000?webp=falseh",
"playlists": [
"3"
],
"genreid": "1",
"genre_name": "Rock"
},
{
"id": "20",
"song_name": "Кем я стал",
"band_id": "3",
"band_name": "DSPD",
"albumid": "3",
"album_name": "Album 3",
"source": "source_path",
"cover": "https://sun9-11.userapi.com/impg/yfCwuWXI6NkFVC2HvMlegM2qWLlenkeiiRyvNQ/jpH8m1wlLqs.jpg?size=604x604&quality=95&sign=60a1d1877b49631fb6078db88715fc88&c_uniq_tag=UKrig2vg02reyBH_ML0OKeqt5gm_2jpwEXD7NJBUXoQ&type=album",
"playlists": [
"3"
],
"genreid": "1",
"genre_name": "Rock"
},
{
"id": "21",
"song_name": "Кем я стал",
"band_id": "3",
"band_name": "DSPD",
"albumid": "3",
"album_name": "Album 3",
"source": "source_path", "source": "source_path",
"cover": "https://avatars.yandex.net/get-music-content/10129881/f3cf1afc.a.30561322-1/m1000x1000?webp=falseh", "cover": "https://avatars.yandex.net/get-music-content/10129881/f3cf1afc.a.30561322-1/m1000x1000?webp=falseh",
"playlists": [ "playlists": [
@ -289,7 +289,7 @@
"genre_name": "Rock" "genre_name": "Rock"
}, },
{ {
"id": "12", "id": "22",
"song_name": "Кем я стал", "song_name": "Кем я стал",
"band_id": "3", "band_id": "3",
"band_name": "DSPD", "band_name": "DSPD",
@ -304,7 +304,7 @@
"genre_name": "Rock" "genre_name": "Rock"
}, },
{ {
"id": "13", "id": "23",
"song_name": "Song 3", "song_name": "Song 3",
"band_id": "1", "band_id": "1",
"band_name": "Nevroz", "band_name": "Nevroz",
@ -319,7 +319,7 @@
"genre_name": "Rock" "genre_name": "Rock"
}, },
{ {
"id": "14", "id": "24",
"song_name": "Song 3", "song_name": "Song 3",
"band_id": "1", "band_id": "1",
"band_name": "Nevroz", "band_name": "Nevroz",

33
package-lock.json generated
View File

@ -24,6 +24,7 @@
"axios": "^1.7.4", "axios": "^1.7.4",
"node-fetch": "^2.6.7", "node-fetch": "^2.6.7",
"react": "^18.3.1", "react": "^18.3.1",
"react-audio-player-component": "^1.2.4",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-dotenv": "^0.1.3", "react-dotenv": "^0.1.3",
"react-google-recaptcha": "^3.1.0", "react-google-recaptcha": "^3.1.0",
@ -24632,6 +24633,32 @@
"react": ">=16.4.1" "react": ">=16.4.1"
} }
}, },
"node_modules/react-audio-player-component": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/react-audio-player-component/-/react-audio-player-component-1.2.4.tgz",
"integrity": "sha512-bW/mJzFagOzDRJouknPSHEkImwzvKwt0JQBf9nuOQ+tF/MYhwHurNWDoLxAZvhWGGG6dQ9kL2RSFBKsDTa3Irg==",
"license": "MIT",
"dependencies": {
"react-audio-visualize": "^1.1.3"
},
"engines": {
"node": ">=18.15.0"
},
"peerDependencies": {
"react": ">=16.2.0",
"react-dom": ">=16.2.0"
}
},
"node_modules/react-audio-visualize": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/react-audio-visualize/-/react-audio-visualize-1.2.0.tgz",
"integrity": "sha512-rfO5nmT0fp23gjU0y2WQT6+ZOq2ZsuPTMphchwX1PCz1Di4oaIr6x7JZII8MLrbHdG7UB0OHfGONTIsWdh67kQ==",
"license": "MIT",
"peerDependencies": {
"react": ">=16.2.0",
"react-dom": ">=16.2.0"
}
},
"node_modules/react-colorful": { "node_modules/react-colorful": {
"version": "5.6.1", "version": "5.6.1",
"resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.6.1.tgz", "resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.6.1.tgz",
@ -27940,9 +27967,9 @@
} }
}, },
"node_modules/tslib": { "node_modules/tslib": {
"version": "2.6.3", "version": "2.8.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz",
"integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==",
"license": "0BSD" "license": "0BSD"
}, },
"node_modules/tsutils": { "node_modules/tsutils": {

View File

@ -19,6 +19,7 @@
"axios": "^1.7.4", "axios": "^1.7.4",
"node-fetch": "^2.6.7", "node-fetch": "^2.6.7",
"react": "^18.3.1", "react": "^18.3.1",
"react-audio-player-component": "^1.2.4",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-dotenv": "^0.1.3", "react-dotenv": "^0.1.3",
"react-google-recaptcha": "^3.1.0", "react-google-recaptcha": "^3.1.0",

View File

@ -90,11 +90,12 @@
} }
.song-table-row { .song-table-row {
margin-top: 50px !important;
margin-bottom: 50px !important;
} }
.song-table-row:hover { .song-table-row:hover {
outline: #9b9b9b solid 1px !important; outline: #9d0000 solid 3px !important;
outline-offset: -1px !important; outline-offset: -1px !important;
} }
@ -133,7 +134,6 @@
.play-song-button:hover:after { .play-song-button:hover:after {
opacity: 1; opacity: 1;
} }
.current-song-cover { .current-song-cover {
object-fit: scale-down; object-fit: scale-down;
} }
@ -180,5 +180,5 @@
} }
.bg-gradient { .bg-gradient {
background-image: linear-gradient(-45deg, red 0%, yellow 25%, yellow 51%, #ad0000 100%); background-image: linear-gradient(-45deg, red 0%, orange 25%, orange 51%, #ad0000 100%);
} }

View File

@ -1,21 +1,6 @@
import React, { useEffect } from 'react';
import { Routes, Route} from 'react-router-dom'; import { Routes, Route} from 'react-router-dom';
import logo from './logo.svg';
import './App.css'; import './App.css';
import { Button } from 'antd';
import {Track} from './components/songComponents/Track';
import {Header} from './components/layoutComponents/Header';
import {Playlist} from './components/cardComponents//Playlist';
import {Footer} from './components/layoutComponents/Footer';
import {CurrentTrack} from './components/songComponents/CurrentTrack';
import {SongsBlock} from './components/menuComponents/SongsBlock';
import { ISong, IAlbum, IGenre, IBand, IPlaylist, IAdvertisement } from './models/IModels';
import axios from 'axios';
import { PlaylistsBlock } from './components/menuComponents/PlaylistsBlock';
import { MenuBlock } from './components/layoutComponents/MenuBlock';
import { getAds, getGenres, getPlaylists, getSongs } from './API/api';
import { AdBlock } from './components/layoutComponents/AdBlock';
import { Homepage } from './pages/Homepage'; import { Homepage } from './pages/Homepage';
import { Loginpage } from './pages/Loginpage'; import { Loginpage } from './pages/Loginpage';
@ -28,16 +13,15 @@ function App() {
return ( return (
<div className="App bg-slate-100"> <div className="App bg-slate-100">
<div id="app" className='bg-gradient'> <div id="app" className='bg-white'>
<Routes> <Routes>
<Route path='/' element={<Layout />}> <Route path='/' element={<Layout />}>
<Route index element={<Homepage />} /> <Route index element={<Homepage song_id='2'/>} />
<Route path='login' element={<Loginpage />} /> <Route path='login' element={<Loginpage />} />
<Route path='register' element={<Registerpage />} /> <Route path='profile' element={<Profilepage />} />
<Route path='profile' element={<Profilepage />} /> </Route>
</Route>
</Routes>
</Routes>
</div> </div>
@ -46,4 +30,4 @@ function App() {
); );
} }
export default App; export default App;

View File

@ -2,7 +2,7 @@ import { IAdvertisement } from "../../models/IModels";
export function AdCard({ad}: {ad: IAdvertisement}) { export function AdCard({ad}: {ad: IAdvertisement}) {
return ( return (
<div className="container mx-auto" style={{padding: 10}}> <div className="container mx-auto" style={{paddingTop: 20, paddingBottom: 60, paddingRight: 60, paddingLeft: 60}}>
<img src={ad.photo} alt={ad.name} className="h-full w-auto rounded m-auto"> <img src={ad.photo} alt={ad.name} className="h-full w-auto rounded m-auto">
</img> </img>
</div> </div>

View File

@ -6,7 +6,7 @@ import { getAds } from "../../API/api";
export function AdBlock({ads}: {ads: IAdvertisement[]}) { export function AdBlock({ads}: {ads: IAdvertisement[]}) {
return ( return (
<div className="AdBlock border-solid border-2 border-slate-100" style={{height: 'auto', minHeight: '100%', width: '30%'}}> <div className="AdBlock border-solid border-2 border-slate-100" style={{height: 'auto', minHeight: '100%', width: '35%'}}>
{ads.map(ad => <AdCard key={ad.id} ad={ad} />)} {ads.map(ad => <AdCard key={ad.id} ad={ad} />)}
</div> </div>
); );

View File

@ -3,9 +3,11 @@ import { Tabs } from 'antd';
import React from 'react'; import React from 'react';
import { PlaylistsBlock } from '../menuComponents/PlaylistsBlock'; import { PlaylistsBlock } from '../menuComponents/PlaylistsBlock';
import { IAlbum, IGenre, IPlaylist, ISong } from '../../models/IModels'; import { IAlbum, IGenre, IPlaylist, ISong } from '../../models/IModels';
import { SongsBlock } from '../menuComponents/SongsBlock'; import { NewSongsBlock } from '../menuComponents/NewSongsBlock';
import { FullPlaylistBlock } from '../menuComponents/FullPlaylistBlock'; import { FullPlaylistBlock } from '../menuComponents/FullPlaylistBlock';
import { width } from '@mui/system'; import { width } from '@mui/system';
import TabPane from 'antd/es/tabs/TabPane';
import { ChartSongsBlock } from '../menuComponents/ChartSongsBlock';
interface MenuBlockProps { interface MenuBlockProps {
playlists?: IPlaylist[], playlists?: IPlaylist[],
@ -15,33 +17,41 @@ interface MenuBlockProps {
} }
export function MenuBlock({playlists, songs, albums, genres}: MenuBlockProps) { export function MenuBlock({playlists, songs, albums, genres}: MenuBlockProps) {
const chartTab = { const newSongsTab = {
label: 'Чарт', label: 'Новинки',
key: 'Chart', key: 'New',
children: songs? <SongsBlock /> : null children: songs? <NewSongsBlock /> : null
}; };
const playlistsTab = { const playlistsTab = {
label: 'Плейлисты', label: 'Плейлисты',
key: 'Playlists', key: 'Playlists',
children: playlists && genres ? <FullPlaylistBlock playlists={playlists} genres={genres}/> : null children: playlists && genres ? <FullPlaylistBlock playlists={playlists} genres={genres}/> : null
}; };
const newSongsTab = {
label: 'Новинки', const chartTab = {
key: 'New', label: 'Чарт',
children: songs? <SongsBlock /> : null key: 'Chart',
children: songs? <ChartSongsBlock /> : null
}; };
const tabs = [chartTab, playlistsTab, newSongsTab];
const recTab = {
label: 'Рекомендации',
key: 'Recomendations',
children: songs? <NewSongsBlock /> : null
};
const tabs = [recTab, newSongsTab, chartTab, playlistsTab];
return ( return (
<div className="flex" style={{display: 'flex', alignSelf: 'flex-start', width: 'fit-content'}}> <div className="flex" style={{display: 'flex', alignSelf: 'flex-start', width: 'fit-content'}}>
<Tabs <Tabs
type="line" type="line"
className='container flex justify-start menu-block' className='container flex justify-start menu-block'
defaultActiveKey="Chart" defaultActiveKey="New"
items={tabs} items={tabs}
style={{padding: '1%'}} style={{padding: '1%'}}
/> >
</Tabs>
</div> </div>

View File

@ -0,0 +1,45 @@
import React, { useEffect, useState } from 'react';
import { render } from '@testing-library/react';
import { ISong } from '../../models/IModels';
import axios from 'axios';
import { Table, Button, Empty } from 'antd';
import { PlayCircleFilled, PlayCircleOutlined } from '@ant-design/icons';
import { getSongs } from '../../API/api';
import Title from 'antd/es/typography/Title';
import { GetColumns } from './Templates/songsTemplate';
import { getColumnsWithNumber } from './Templates/numeredSongsTemplate';
// Функция для генерации номеров строк
const generateRowNumbers = (rows: any[]) =>
rows.map((_: any, index: number) => ({ ..._, number: index + 1 }));
export function ChartSongsBlock() {
const [songs, setSongs] = useState<ISong[]>([]);
const [numberedSongs, setNumberedSongs] = useState<ISong[]>([]);
const fetchData = async () => {
const response = await getSongs();
setSongs(response.data);
setNumberedSongs(generateRowNumbers(response.data));
};
useEffect(() => {
fetchData();
}, []);
return (
<div className="song-block flex border-slate-100">
<Table
title={() => <Title level={4}>Чарт</Title>}
style={{ width: '100%', backgroundColor: 'transparent' }}
className="songs-table menu-block"
dataSource={numberedSongs}
columns={getColumnsWithNumber(numberedSongs)}
showHeader={false}
pagination={false}
rowClassName={() => 'song-table-row'}
rowKey={(record) => record.id}
/>
</div>
);
};

View File

@ -1,14 +1,15 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { render } from '@testing-library/react'; import { render } from '@testing-library/react';
import {ISong} from '../../models/IModels'; import {ISong} from '../../models/IModels';
import { Track } from '../songComponents/Track';
import axios from 'axios'; import axios from 'axios';
import { Table, Button, Empty } from 'antd'; import { Table, Button, Empty } from 'antd';
import { PlayCircleFilled, PlayCircleOutlined } from '@ant-design/icons'; import { PlayCircleFilled, PlayCircleOutlined } from '@ant-design/icons';
import { getSongs } from '../../API/api'; import { getSongs } from '../../API/api';
import Title from 'antd/es/typography/Title';
import { GetColumns } from './Templates/songsTemplate';
export function SongsBlock() { export function NewSongsBlock() {
const [songs, setSongs] = useState<ISong[]>([]); const [songs, setSongs] = useState<ISong[]>([]);
@ -20,61 +21,21 @@ export function SongsBlock() {
useEffect(() => { useEffect(() => {
fetchData(); fetchData();
}, []); }, []);
const columns = [
{
title: '',
dataIndex: 'play',
key: 'play',
width: 100,
render: (text: string, song: ISong) => (
<Button data-content="▷" className='play-song-button rounded' style={{background: 'transparent', display: 'contents'}}>
<img
className="rounded "
src={song.cover}
alt={song.song_name}
/>
</Button>
),
},
{
title: '',
dataIndex: 'song_name',
key: 'song_name',
width: 400
},
{
title: '',
dataIndex: 'band_name',
key: 'band_name',
width: 400
},
{
title: '',
dataIndex: 'album_name',
key: 'album_name',
width: 400
},
]
return ( return (
<div className="song-block flex border-slate-100"> <div className="song-block flex border-slate-100">
<Table <Table
title={() => <Title level={4}>Горячие новинки</Title>}
style={{width: '100%', backgroundColor: 'transparent'}} style={{width: '100%', backgroundColor: 'transparent'}}
className="songs-table menu-block" className="songs-table menu-block"
dataSource={songs.map((s: ISong) => ({...s, play: ''}))} dataSource={songs.map((s: ISong) => ({...s, play: ''}))}
columns={columns} columns={GetColumns(songs)}
showHeader={false} showHeader={false}
pagination={false} pagination={false}
rowClassName={() => 'song-table-row'} rowClassName={() => 'song-table-row'}
rowKey={(s: ISong) => s.id}
/> />
</div> </div>
); );
}; };

View File

@ -0,0 +1,56 @@
import { Button } from "antd";
import { ISong } from "../../../models/IModels";
import PlayCircleFilled from "@ant-design/icons/lib/icons/PlayCircleFilled";
export function getColumnsWithNumber(songs: ISong[]) {
return [
{
title: '#',
dataIndex: 'number',
key: 'number',
width: 50,
render: (value: any, record: ISong, index: number) => {
return record.number === 1 ? <span style={{ fontSize: '18px', display: 'flex', justifyContent: 'center', alignItems: 'center' }}>👑</span> :
<span style={{ fontSize: '18px', display: 'flex', justifyContent: 'center', alignItems: 'center' }}>{record.number}</span>;
},
},
{
title: 'Play',
dataIndex: 'play',
key: 'play',
width: 100,
render: (text: string, song: ISong) => (
<Button data-content="▷" className='play-song-button rounded' style={{background: 'transparent', display: 'contents'}}>
<img
className="rounded "
src={song.cover}
alt={song.song_name}
/>
</Button>
),
},
{
title: '',
dataIndex: 'song_name',
key: 'song_name',
width: 350
},
{
title: '',
dataIndex: 'band_name',
key: 'band_name',
width: 400
},
{
title: '',
dataIndex: 'album_name',
key: 'album_name',
width: 400
}
]
}

View File

@ -0,0 +1,59 @@
import { Button } from "antd";
import { ISong } from "../../../models/IModels";
import { useState } from "react";
import { PauseCircleFilled, PlayCircleFilled } from "@ant-design/icons";
const useColumns = (songs: ISong[]) => {
const [isPlaying, setIsPlaying] = useState(false);
const handlePlayClick = () => {
setIsPlaying(!isPlaying);
};
return [
{
title: 'Play',
dataIndex: 'play',
key: 'play',
width: 100,
render: (text: string, song: ISong) => (
// Тут в дата-контент вставляется JSON коды иконок
<Button data-content={isPlaying ? "\u23EF\uFE0F" : "▷"} className='play-song-button rounded' style={{background: 'transparent', display: 'contents'}} onClick={handlePlayClick}>
<img
className="rounded "
src={song.cover}
alt={song.song_name}
/>
</Button>
),
},
{
title: '',
dataIndex: 'song_name',
key: 'song_name',
width: 400
},
{
title: '',
dataIndex: 'band_name',
key: 'band_name',
width: 400
},
{
title: '',
dataIndex: 'album_name',
key: 'album_name',
width: 400
}
]
}
export function GetColumns(songs: ISong[]) {
return useColumns(songs);
}

View File

@ -4,7 +4,6 @@ import { BackwardFilled, FastForwardFilled, FastBackwardFilled, PlayCircleFilled
import { ISong, SongProps } from '../../models/IModels'; import { ISong, SongProps } from '../../models/IModels';
import styled from 'styled-components' import styled from 'styled-components'
import useSound from 'use-sound'; import useSound from 'use-sound';
import { getSongs } from '../../API/api';
const Song = styled.div` const Song = styled.div`
align-items: center; align-items: center;
@ -14,33 +13,19 @@ const Song = styled.div`
type CurrentSongProps = { type CurrentSongProps = {
song: ISong song: ISong
isPlayingVariable: boolean
} }
export function CurrentTrack({song, isPlayingVariable}: CurrentSongProps) { export function CurrentTrack({ song }: CurrentSongProps) {
const [isPlaying, setIsPlaying] = useState(false);
const soundUrl = song?.source || ''; // Пустая строка в случае отсутствия source
song = {
"id": "5", const [play, { pause, duration, sound }] = useSound(soundUrl, { volume: 0.5 });
"song_name": "Кем я стал",
"band_id": "3",
"band_name": "DSPD",
"albumid": "3",
"album_name": "Album 3",
"source": "../../songs/DSPD feat. даня хренников - Кем я стал_(audio-lord.ru).mp3",
"cover": "https://avatars.yandex.net/get-music-content/6058982/7e431a83.a.23910092-1/m1000x1000?webp=false",
"playlists": [
"3",
],
genreid: "1",
genre_name: "Rock",
};
const [isPlaying, setIsPlaying] = useState(isPlayingVariable);
const [play, { pause, duration, sound }] = useSound(song.source, {volume: 0.5});
const playingButton = () => { const playingButton = () => {
if (isPlaying) { if (isPlaying) {
pause(); pause();
@ -50,38 +35,39 @@ export function CurrentTrack({song, isPlayingVariable}: CurrentSongProps) {
setIsPlaying(true); setIsPlaying(true);
} }
}; };
useEffect(() => {
if (song) {
play();
setIsPlaying(true);
}
}, [song]);
return ( return (
<Song > <Song>
<div className='current-track'> <div className="current-track">
<Row className='w-full h-full bg-white opacity-90 rounded' style={{display: 'flex', alignItems: 'center'}}> <Row className="w-full h-full bg-white opacity-90 rounded" style={{ display: 'flex', alignItems: 'center' }}>
<Col span={4} className='flex flex-direction-row justify-center'> <Col span={4} className="flex flex-direction-row justify-center">
<Button type='link' icon={<FastBackwardFilled className='player-button' />}></Button> <Button type="link" icon={<FastBackwardFilled className="player-button" />}></Button>
<Button type="link" icon={isPlaying ? <PauseCircleOutlined className='player-button' onClick={playingButton}/> : <PlayCircleOutlined className='player-button' onClick={playingButton}/>}></Button> <Button
<Button type="link" icon={<FastForwardFilled className='player-button' style={{fontSize: 30}} />}></Button> type="link"
icon={isPlaying ? <PauseCircleOutlined className="player-button" onClick={playingButton} /> : <PlayCircleOutlined className="player-button" onClick={playingButton} />}
></Button>
<Button type="link" icon={<FastForwardFilled className="player-button" style={{ fontSize: 30 }} />}></Button>
</Col> </Col>
<Col style={{width: 80}}> <Col style={{ width: 80 }}>
<img src={song.cover} alt={song.cover} className='current-song-cover' /> <img src={song.cover} alt={song.cover} className="current-song-cover" />
</Col> </Col>
<Col span={16}> <Col span={16}>
<Row className='' style={{paddingLeft: 10}}> <Row style={{ paddingLeft: 10 }}>{song.song_name}</Row>
{song.song_name} <Row style={{ paddingLeft: 10 }}>{song.band_name}</Row>
</Row>
<Row className='' style={{paddingLeft: 10}}>
{song.band_name}
</Row>
</Col> </Col>
<Col> <Col>
<Button type='link' icon={<HeartOutlined className='current-track-button' />}></Button> <Button type="link" icon={<HeartOutlined className="current-track-button" />}></Button>
<Button type='link' icon={<ShareAltOutlined className='current-track-button' />}></Button> <Button type="link" icon={<ShareAltOutlined className="current-track-button" />}></Button>
</Col> </Col>
</Row> </Row>
</div> </div>
</Song> </Song>
); );
} }

View File

@ -1,25 +0,0 @@
import { Grid, Col, Row, Button } from 'antd';
import { PlayCircleOutlined } from '@ant-design/icons';
import React from 'react';
import { ISong, SongProps } from '../../models/IModels';
export function Track({ song }: SongProps) {
return (
<span className="flex items-center justify-between p-4 px-6 py-2 border-b border-gray-300 ">
<Row>
<Col span={4}>
<Button type="link"><PlayCircleOutlined /></Button>
</Col>
<Col span={4} className="flex items-center justify-between">
<img src={song.cover} alt={song.song_name} className='list-image-none' />
</Col>
<Col span={8} className="flex items-center justify-between">
<p className="text-md">{song.song_name}</p>
</Col>
<Col span={8} className="flex items-center justify-between">
<p className="text-md">{song.band_name}</p>
</Col>
</Row>
</span>
)
}

View File

@ -22,6 +22,7 @@ export interface IGenre {
} }
export interface ISong { export interface ISong {
number: number;
id: string id: string
song_name: string; song_name: string;
band_id: string; band_id: string;

View File

@ -6,11 +6,10 @@ import { CurrentTrack } from "../components/songComponents/CurrentTrack";
import { IPlaylist, ISong, IAlbum, IGenre, IAdvertisement, IBand } from "../models/IModels"; import { IPlaylist, ISong, IAlbum, IGenre, IAdvertisement, IBand } from "../models/IModels";
export function Homepage() { export function Homepage({song_id = "0"}) {
const [currentSong, setCurrentSong] = useState<ISong | null>(null);
const [albums, setAlbums] = useState<IAlbum[]>([]); const [albums, setAlbums] = useState<IAlbum[]>([]);
const [bands, setBands] = useState<IBand[]>([]);
const [songs, setSongs] = useState<ISong[]>([]); const [songs, setSongs] = useState<ISong[]>([]);
const [ads, setAds] = useState<IAdvertisement[]>([]); const [ads, setAds] = useState<IAdvertisement[]>([]);
@ -39,7 +38,7 @@ export function Homepage() {
return ( return (
<> <>
<MenuBlock playlists={[]} songs={songs} albums={albums} genres={[]}/><AdBlock ads={ads}/> <MenuBlock playlists={[]} songs={songs} albums={albums} genres={[]}/><AdBlock ads={ads}/>
<CurrentTrack song={songs[0]} isPlayingVariable={false} /> {currentSong && <CurrentTrack song={currentSong} />}
</> </>
); );
} }