в боковой панели отображается информация о песнях
This commit is contained in:
parent
2fa22ec4c4
commit
a74b994b07
@ -128,7 +128,7 @@
|
|||||||
"id": "9",
|
"id": "9",
|
||||||
"song_name": "Downstairs to Heaven",
|
"song_name": "Downstairs to Heaven",
|
||||||
"band_id": "3",
|
"band_id": "3",
|
||||||
"band_name": "Эйси Диси",
|
"band_name": "AC/DC",
|
||||||
"albumid": "3",
|
"albumid": "3",
|
||||||
"album_name": "Album 3",
|
"album_name": "Album 3",
|
||||||
"source": "http://localhost:3001/songs_sources/acdc.mp3",
|
"source": "http://localhost:3001/songs_sources/acdc.mp3",
|
||||||
|
@ -41,4 +41,24 @@ export async function getAds() {
|
|||||||
|
|
||||||
return await axios.get<IAdvertisement[]>(`${localhost}advertisements`);
|
return await axios.get<IAdvertisement[]>(`${localhost}advertisements`);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getAlbum(id: string) {
|
||||||
|
|
||||||
|
return await axios.get(`${localhost}albums/` + id);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getAlbums() {
|
||||||
|
|
||||||
|
return await axios.get(`${localhost}albums/`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getBand(id: string) {
|
||||||
|
|
||||||
|
return await axios.get(`${localhost}bands/` + id);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getBands() {
|
||||||
|
|
||||||
|
return await axios.get(`${localhost}bands/`);
|
||||||
}
|
}
|
@ -207,4 +207,11 @@
|
|||||||
|
|
||||||
.bg-gradient {
|
.bg-gradient {
|
||||||
background-image: linear-gradient(-45deg, red 0%, orange 25%, orange 51%, #ad0000 100%);
|
background-image: linear-gradient(-45deg, red 0%, orange 25%, orange 51%, #ad0000 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-side-block {
|
||||||
|
font-size: 22px;
|
||||||
|
border-bottom: 2px solid #505050;
|
||||||
|
align-self: flex-start;
|
||||||
|
color: #505050;
|
||||||
}
|
}
|
@ -10,6 +10,9 @@ import { Layout } from './components/layoutComponents/Layout';
|
|||||||
import { CurrentSongProvider } from './contexts/SongContexts/SongContextProvider';
|
import { CurrentSongProvider } from './contexts/SongContexts/SongContextProvider';
|
||||||
import { PlayingProvider } from './contexts/SongContexts/PlayingProvider';
|
import { PlayingProvider } from './contexts/SongContexts/PlayingProvider';
|
||||||
import { VolumeProvider } from './contexts/VolumeContexts/VolumeProvider';
|
import { VolumeProvider } from './contexts/VolumeContexts/VolumeProvider';
|
||||||
|
import { SideBlockProvider } from './contexts/SideBlockContexts/SideBlockProvider';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { IAdvertisement } from './models/IModels';
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
|
|
||||||
@ -19,6 +22,7 @@ function App() {
|
|||||||
<CurrentSongProvider songId=''>
|
<CurrentSongProvider songId=''>
|
||||||
<PlayingProvider isPlaying={false}>
|
<PlayingProvider isPlaying={false}>
|
||||||
<VolumeProvider volumeValue={30}>
|
<VolumeProvider volumeValue={30}>
|
||||||
|
<SideBlockProvider>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path='/' element={<Layout />}>
|
<Route path='/' element={<Layout />}>
|
||||||
<Route index element={<Homepage />} />
|
<Route index element={<Homepage />} />
|
||||||
@ -27,6 +31,7 @@ function App() {
|
|||||||
</Route>
|
</Route>
|
||||||
|
|
||||||
</Routes>
|
</Routes>
|
||||||
|
</SideBlockProvider>
|
||||||
</VolumeProvider>
|
</VolumeProvider>
|
||||||
</PlayingProvider>
|
</PlayingProvider>
|
||||||
</CurrentSongProvider>
|
</CurrentSongProvider>
|
||||||
|
@ -1,13 +1,19 @@
|
|||||||
import React, { useEffect } from "react";
|
import React, { ReactElement, useEffect } from "react";
|
||||||
import { IAdvertisement } from "../../models/IModels";
|
import { IAdvertisement, IAlbum, IBand, ISong } from "../../models/IModels";
|
||||||
import { AdCard } from "../cardComponents/AdCard";
|
import { AdCard } from "../cardComponents/AdCard";
|
||||||
import { getAds } from "../../API/api";
|
import { getAds } from "../../API/api";
|
||||||
|
import { useSideBlockContext } from '../../contexts/SideBlockContexts/SideBlockProvider';
|
||||||
|
import { InformationTemplate } from "../menuComponents/Templates/informationTemplate";
|
||||||
|
|
||||||
export function AdBlock({ads}: {ads: IAdvertisement[]}) {
|
|
||||||
|
export function AdBlock({ advertisements, object }: {object?: IAdvertisement | ISong | IBand | IAlbum | undefined, advertisements?: IAdvertisement[]}) {
|
||||||
|
|
||||||
|
const { contentObject } = useSideBlockContext();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="AdBlock border-solid border-2 border-slate-100" style={{height: 'auto', minHeight: '100%', width: '35%'}}>
|
<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} />)}
|
|
||||||
|
{object && <InformationTemplate obj={object}></InformationTemplate>}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
@ -8,6 +8,8 @@ import { getSongs } from '../../API/api';
|
|||||||
import Title from 'antd/es/typography/Title';
|
import Title from 'antd/es/typography/Title';
|
||||||
import { GetColumns } from './Templates/songsTemplate';
|
import { GetColumns } from './Templates/songsTemplate';
|
||||||
import { GetColumnsWithNumber } from './Templates/numeredSongsTemplate';
|
import { GetColumnsWithNumber } from './Templates/numeredSongsTemplate';
|
||||||
|
import { usePlayingContext } from '../../contexts/SongContexts/PlayingProvider';
|
||||||
|
import { useCurrentSongContext } from '../../contexts/SongContexts/SongContextProvider';
|
||||||
|
|
||||||
// Функция для генерации номеров строк
|
// Функция для генерации номеров строк
|
||||||
const generateRowNumbers = (rows: any[]) =>
|
const generateRowNumbers = (rows: any[]) =>
|
||||||
@ -17,6 +19,9 @@ export function ChartSongsBlock() {
|
|||||||
const [songs, setSongs] = useState<ISong[]>([]);
|
const [songs, setSongs] = useState<ISong[]>([]);
|
||||||
const [numberedSongs, setNumberedSongs] = useState<ISong[]>([]);
|
const [numberedSongs, setNumberedSongs] = useState<ISong[]>([]);
|
||||||
|
|
||||||
|
const currentSongId = useCurrentSongContext();
|
||||||
|
const isPlaying = usePlayingContext();
|
||||||
|
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
const response = await getSongs();
|
const response = await getSongs();
|
||||||
setSongs(response.data);
|
setSongs(response.data);
|
||||||
@ -37,7 +42,7 @@ export function ChartSongsBlock() {
|
|||||||
columns={GetColumnsWithNumber(numberedSongs)}
|
columns={GetColumnsWithNumber(numberedSongs)}
|
||||||
showHeader={false}
|
showHeader={false}
|
||||||
pagination={false}
|
pagination={false}
|
||||||
rowClassName={() => 'song-table-row chart-row'}
|
rowClassName={(record) => isPlaying ? (record.id === currentSongId.songId ? 'song-table-row-active' : 'song-table-row') : 'song-table-row'}
|
||||||
rowKey={(record) => record.id}
|
rowKey={(record) => record.id}
|
||||||
scroll={{ x: true }}
|
scroll={{ x: true }}
|
||||||
/>
|
/>
|
||||||
|
@ -1,26 +1,35 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useContext, useEffect, useState } from 'react';
|
||||||
import { render } from '@testing-library/react';
|
import { render } from '@testing-library/react';
|
||||||
import {ISong} from '../../models/IModels';
|
import {IAlbum, IBand, ISong} from '../../models/IModels';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { Table, Button, Empty } from 'antd';
|
import { Table, Button, Empty } from 'antd';
|
||||||
import { Loading3QuartersOutlined, PlayCircleFilled, PlayCircleOutlined } from '@ant-design/icons';
|
import { Loading3QuartersOutlined, PlayCircleFilled, PlayCircleOutlined } from '@ant-design/icons';
|
||||||
import { getSongs } from '../../API/api';
|
import { getSongs, getBands, getAlbums } from '../../API/api';
|
||||||
import Title from 'antd/es/typography/Title';
|
import Title from 'antd/es/typography/Title';
|
||||||
import { GetColumns } from './Templates/songsTemplate';
|
import { GetColumns } from './Templates/songsTemplate';
|
||||||
import { Spin } from "antd";
|
import { Spin } from "antd";
|
||||||
import { useCurrentSongContext } from '../../contexts/SongContexts/SongContextProvider';
|
import { useCurrentSongContext } from '../../contexts/SongContexts/SongContextProvider';
|
||||||
import { usePlayingContext } from '../../contexts/SongContexts/PlayingProvider';
|
import { usePlayingContext } from '../../contexts/SongContexts/PlayingProvider';
|
||||||
|
import { useSideBlockContext } from '../../contexts/SideBlockContexts/SideBlockProvider';
|
||||||
|
|
||||||
export function NewSongsBlock() {
|
export function NewSongsBlock() {
|
||||||
|
|
||||||
const [songs, setSongs] = useState<ISong[]>([]);
|
const [songs, setSongs] = useState<ISong[]>([]);
|
||||||
|
const [bands, setBands] = useState<IBand[]>([]);
|
||||||
|
const [albums, setAlbums] = useState<IAlbum[]>([]);
|
||||||
|
|
||||||
const currentSongId = useCurrentSongContext();
|
const currentSongId = useCurrentSongContext();
|
||||||
const isPlaying = usePlayingContext();
|
const isPlaying = usePlayingContext();
|
||||||
|
const { setContentObject } = useSideBlockContext();
|
||||||
|
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
const response = getSongs();
|
const responseSongs = getSongs();
|
||||||
setSongs((await response).data);
|
const responseBands = getBands();
|
||||||
|
const responseAlbums = getAlbums();
|
||||||
|
|
||||||
|
setSongs((await responseSongs).data);
|
||||||
|
setBands((await responseBands).data);
|
||||||
|
setAlbums((await responseAlbums).data);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -42,6 +51,26 @@ export function NewSongsBlock() {
|
|||||||
rowClassName={(record) => isPlaying ? (record.id === currentSongId.songId ? 'song-table-row-active' : 'song-table-row') : 'song-table-row'}
|
rowClassName={(record) => isPlaying ? (record.id === currentSongId.songId ? 'song-table-row-active' : 'song-table-row') : 'song-table-row'}
|
||||||
rowKey={(s: ISong) => s.id}
|
rowKey={(s: ISong) => s.id}
|
||||||
rowHoverable={false}
|
rowHoverable={false}
|
||||||
|
onRow={(record) => ({
|
||||||
|
onClick: (event) => {
|
||||||
|
if (event.target instanceof HTMLTableCellElement && event.target.tagName === 'TD') {
|
||||||
|
let song = songs.find((s: ISong) => s.id === record.id)
|
||||||
|
switch (event.target.cellIndex) {
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
setContentObject(song);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
setContentObject(bands.find((b: IBand) => b.id === song?.band_id));
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
setContentObject(albums.find((a: IAlbum) => a.id === song?.albumid));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})}
|
||||||
/>
|
/>
|
||||||
</Spin>
|
</Spin>
|
||||||
</div>
|
</div>
|
||||||
|
@ -0,0 +1,84 @@
|
|||||||
|
import react from "react";
|
||||||
|
import { IAlbum, IBand, ISong, IAdvertisement } from "../../../models/IModels";
|
||||||
|
import { getSong, getAlbum, getBand } from "../../../API/api";
|
||||||
|
import Text from 'antd/es/typography/Text';
|
||||||
|
import { useSideBlockContext } from '../../../contexts/SideBlockContexts/SideBlockProvider';
|
||||||
|
import { AdCard } from "../../cardComponents/AdCard";
|
||||||
|
import { Loading3QuartersOutlined } from "@ant-design/icons";
|
||||||
|
import { Spin } from "antd";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export function InformationTemplate ({obj}: {obj: ISong | IBand | IAlbum | IAdvertisement | undefined}) {
|
||||||
|
|
||||||
|
function isAd(obj: any): obj is IAdvertisement {
|
||||||
|
return Array.isArray(obj) && obj.every(item =>
|
||||||
|
typeof item === 'object' &&
|
||||||
|
item !== null &&
|
||||||
|
'id' in item &&
|
||||||
|
'photo' in item
|
||||||
|
);
|
||||||
|
}
|
||||||
|
function isSong(obj: any): obj is ISong {
|
||||||
|
return typeof obj === 'object' &&
|
||||||
|
obj !== null &&
|
||||||
|
'id' in obj &&
|
||||||
|
'song_name' in obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isAlbum(obj: any): obj is IAlbum {
|
||||||
|
return typeof obj === 'object' &&
|
||||||
|
obj !== null &&
|
||||||
|
'id' in obj &&
|
||||||
|
'name' in obj &&
|
||||||
|
'cover' in obj &&
|
||||||
|
'year' in obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isBand(obj: any): obj is IBand {
|
||||||
|
return typeof obj === 'object' &&
|
||||||
|
obj !== null &&
|
||||||
|
'id' in obj &&
|
||||||
|
'name' in obj &&
|
||||||
|
'city' in obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { contentObject } = useSideBlockContext();
|
||||||
|
|
||||||
|
switch (typeof obj) {
|
||||||
|
case 'object':
|
||||||
|
return (
|
||||||
|
<div className="flex container" style={{ display: 'flex'}}>
|
||||||
|
|
||||||
|
{isAd(obj) && Array.isArray(obj) ? obj.map((ad) => <AdCard ad={ad} key={ad.id} />) : null}
|
||||||
|
{isSong(obj) ?
|
||||||
|
<div>
|
||||||
|
<Text className="title-side-block">ТРЕК</Text>
|
||||||
|
<img
|
||||||
|
src={obj.cover} alt={obj.song_name} className="rounded m-auto" style={{ width: '50%'}}>
|
||||||
|
</img>
|
||||||
|
|
||||||
|
<Text>{obj.song_name}</Text>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
: null}
|
||||||
|
|
||||||
|
|
||||||
|
{isBand(obj) ? <Text>{obj.name}</Text> : null}
|
||||||
|
{isAlbum(obj) ? <Text>{obj.name}</Text> : null}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
case 'undefined':
|
||||||
|
return (
|
||||||
|
<div className="flex container" style={{flexDirection: 'column'}}>
|
||||||
|
<Spin indicator={<Loading3QuartersOutlined spin style={{color: '#9d0000', fontSize: 30}} />}/>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
export interface ISongTemplateInterface {
|
||||||
|
key: number;
|
||||||
|
title: string;
|
||||||
|
artist: string;
|
||||||
|
album: string;
|
||||||
|
image: string;
|
||||||
|
duration: string;
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
import { Button } from "antd";
|
import { Button } from "antd";
|
||||||
import { ISong } from "../../../models/IModels";
|
import { ISong } from "../../../models/IModels";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { height } from "@mui/system";
|
import { height, style } from "@mui/system";
|
||||||
import { useCurrentSongContext } from "../../../contexts/SongContexts/SongContextProvider";
|
import { useCurrentSongContext } from "../../../contexts/SongContexts/SongContextProvider";
|
||||||
import { usePlayingContext } from "../../../contexts/SongContexts/PlayingProvider";
|
import { usePlayingContext } from "../../../contexts/SongContexts/PlayingProvider";
|
||||||
|
|
||||||
@ -43,7 +43,8 @@ const useColumns = (songs: ISong[])=> {
|
|||||||
title: '',
|
title: '',
|
||||||
dataIndex: 'song_name',
|
dataIndex: 'song_name',
|
||||||
key: 'song_name',
|
key: 'song_name',
|
||||||
width: 400
|
width: 400,
|
||||||
|
render: (text: string, song: ISong) => <span style={{cursor: 'default'}}>{text}</span>
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '',
|
title: '',
|
||||||
@ -63,4 +64,4 @@ const useColumns = (songs: ISong[])=> {
|
|||||||
|
|
||||||
export function GetColumns(songs: ISong[]) {
|
export function GetColumns(songs: ISong[]) {
|
||||||
return useColumns(songs);
|
return useColumns(songs);
|
||||||
}
|
}
|
||||||
|
32
src/contexts/SideBlockContexts/SideBlockProvider.tsx
Normal file
32
src/contexts/SideBlockContexts/SideBlockProvider.tsx
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import React, { createContext, useContext, ReactNode, useState, ReactElement } from "react";
|
||||||
|
|
||||||
|
interface SideBlockProviderProps {
|
||||||
|
children: ReactElement;
|
||||||
|
contentObject ?: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SideBlockContextValue {
|
||||||
|
contentObject ?: any;
|
||||||
|
setContentObject: (contentObject: any) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SideBlockContext = createContext<SideBlockContextValue | undefined>(undefined);
|
||||||
|
|
||||||
|
export function SideBlockProvider({ children, contentObject }: SideBlockProviderProps) {
|
||||||
|
const [content, setContent] = useState(contentObject);
|
||||||
|
console.log(content);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SideBlockContext.Provider value={{ contentObject: content, setContentObject: setContent }}>
|
||||||
|
{children}
|
||||||
|
</SideBlockContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useSideBlockContext = function(): SideBlockContextValue {
|
||||||
|
const context = useContext(SideBlockContext);
|
||||||
|
if (context === undefined) {
|
||||||
|
throw new Error("useSideBlockContext must be used within a SideBlockProvider");
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
};
|
@ -5,6 +5,7 @@ import { MenuBlock } from "../components/layoutComponents/MenuBlock";
|
|||||||
import { CurrentTrack } from "../components/songComponents/CurrentTrack";
|
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";
|
||||||
import { useCurrentSongContext } from "../contexts/SongContexts/SongContextProvider";
|
import { useCurrentSongContext } from "../contexts/SongContexts/SongContextProvider";
|
||||||
|
import { useSideBlockContext } from "../contexts/SideBlockContexts/SideBlockProvider";
|
||||||
|
|
||||||
|
|
||||||
export function Homepage() {
|
export function Homepage() {
|
||||||
@ -12,12 +13,13 @@ export function Homepage() {
|
|||||||
const [albums, setAlbums] = useState<IAlbum[]>([]);
|
const [albums, setAlbums] = useState<IAlbum[]>([]);
|
||||||
const [songs, setSongs] = useState<ISong[]>([]);
|
const [songs, setSongs] = useState<ISong[]>([]);
|
||||||
const [ads, setAds] = useState<IAdvertisement[]>([]);
|
const [ads, setAds] = useState<IAdvertisement[]>([]);
|
||||||
|
|
||||||
|
|
||||||
const [playlists, setPlaylist] = React.useState<IPlaylist[]>([]);
|
const [playlists, setPlaylist] = React.useState<IPlaylist[]>([]);
|
||||||
const [genres, setGenres] = React.useState<IGenre[]>([]);
|
const [genres, setGenres] = React.useState<IGenre[]>([]);
|
||||||
|
|
||||||
const currentSongId = useCurrentSongContext();
|
const currentSongId = useCurrentSongContext();
|
||||||
|
const { contentObject, setContentObject } = useSideBlockContext();
|
||||||
|
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
const [responseSongs, responseAds, responsePlaylists, responseGenres] = await Promise.all([
|
const [responseSongs, responseAds, responsePlaylists, responseGenres] = await Promise.all([
|
||||||
@ -35,15 +37,14 @@ export function Homepage() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchData();
|
fetchData();
|
||||||
|
setContentObject(ads);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const currentSong = songs.find(song => song.id === currentSongId.songId);
|
const currentSong = songs.find(song => song.id === currentSongId.songId);
|
||||||
console.log('Айди песни:');
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<MenuBlock playlists={[]} songs={songs} albums={albums} genres={[]}/><AdBlock ads={ads}/>
|
<MenuBlock playlists={[]} songs={songs} albums={albums} genres={[]}/><AdBlock object={contentObject}/>
|
||||||
{currentSong && <CurrentTrack song={currentSong} songs={songs}/>}
|
{currentSong && <CurrentTrack song={currentSong} songs={songs}/>}
|
||||||
|
|
||||||
</>
|
</>
|
||||||
|
Loading…
Reference in New Issue
Block a user