в боковой панели отображается информация о песнях
This commit is contained in:
parent
2fa22ec4c4
commit
a74b994b07
@ -128,7 +128,7 @@
|
||||
"id": "9",
|
||||
"song_name": "Downstairs to Heaven",
|
||||
"band_id": "3",
|
||||
"band_name": "Эйси Диси",
|
||||
"band_name": "AC/DC",
|
||||
"albumid": "3",
|
||||
"album_name": "Album 3",
|
||||
"source": "http://localhost:3001/songs_sources/acdc.mp3",
|
||||
|
@ -42,3 +42,23 @@ export async function getAds() {
|
||||
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/`);
|
||||
}
|
@ -208,3 +208,10 @@
|
||||
.bg-gradient {
|
||||
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 { PlayingProvider } from './contexts/SongContexts/PlayingProvider';
|
||||
import { VolumeProvider } from './contexts/VolumeContexts/VolumeProvider';
|
||||
import { SideBlockProvider } from './contexts/SideBlockContexts/SideBlockProvider';
|
||||
import { useState } from 'react';
|
||||
import { IAdvertisement } from './models/IModels';
|
||||
|
||||
function App() {
|
||||
|
||||
@ -19,6 +22,7 @@ function App() {
|
||||
<CurrentSongProvider songId=''>
|
||||
<PlayingProvider isPlaying={false}>
|
||||
<VolumeProvider volumeValue={30}>
|
||||
<SideBlockProvider>
|
||||
<Routes>
|
||||
<Route path='/' element={<Layout />}>
|
||||
<Route index element={<Homepage />} />
|
||||
@ -27,6 +31,7 @@ function App() {
|
||||
</Route>
|
||||
|
||||
</Routes>
|
||||
</SideBlockProvider>
|
||||
</VolumeProvider>
|
||||
</PlayingProvider>
|
||||
</CurrentSongProvider>
|
||||
|
@ -1,13 +1,19 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { IAdvertisement } from "../../models/IModels";
|
||||
import React, { ReactElement, useEffect } from "react";
|
||||
import { IAdvertisement, IAlbum, IBand, ISong } from "../../models/IModels";
|
||||
import { AdCard } from "../cardComponents/AdCard";
|
||||
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 (
|
||||
<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>
|
||||
);
|
||||
}
|
@ -8,6 +8,8 @@ import { getSongs } from '../../API/api';
|
||||
import Title from 'antd/es/typography/Title';
|
||||
import { GetColumns } from './Templates/songsTemplate';
|
||||
import { GetColumnsWithNumber } from './Templates/numeredSongsTemplate';
|
||||
import { usePlayingContext } from '../../contexts/SongContexts/PlayingProvider';
|
||||
import { useCurrentSongContext } from '../../contexts/SongContexts/SongContextProvider';
|
||||
|
||||
// Функция для генерации номеров строк
|
||||
const generateRowNumbers = (rows: any[]) =>
|
||||
@ -17,6 +19,9 @@ export function ChartSongsBlock() {
|
||||
const [songs, setSongs] = useState<ISong[]>([]);
|
||||
const [numberedSongs, setNumberedSongs] = useState<ISong[]>([]);
|
||||
|
||||
const currentSongId = useCurrentSongContext();
|
||||
const isPlaying = usePlayingContext();
|
||||
|
||||
const fetchData = async () => {
|
||||
const response = await getSongs();
|
||||
setSongs(response.data);
|
||||
@ -37,7 +42,7 @@ export function ChartSongsBlock() {
|
||||
columns={GetColumnsWithNumber(numberedSongs)}
|
||||
showHeader={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}
|
||||
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 {ISong} from '../../models/IModels';
|
||||
import {IAlbum, IBand, ISong} from '../../models/IModels';
|
||||
import axios from 'axios';
|
||||
import { Table, Button, Empty } from 'antd';
|
||||
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 { GetColumns } from './Templates/songsTemplate';
|
||||
import { Spin } from "antd";
|
||||
import { useCurrentSongContext } from '../../contexts/SongContexts/SongContextProvider';
|
||||
import { usePlayingContext } from '../../contexts/SongContexts/PlayingProvider';
|
||||
import { useSideBlockContext } from '../../contexts/SideBlockContexts/SideBlockProvider';
|
||||
|
||||
export function NewSongsBlock() {
|
||||
|
||||
const [songs, setSongs] = useState<ISong[]>([]);
|
||||
const [bands, setBands] = useState<IBand[]>([]);
|
||||
const [albums, setAlbums] = useState<IAlbum[]>([]);
|
||||
|
||||
const currentSongId = useCurrentSongContext();
|
||||
const isPlaying = usePlayingContext();
|
||||
const { setContentObject } = useSideBlockContext();
|
||||
|
||||
const fetchData = async () => {
|
||||
const response = getSongs();
|
||||
setSongs((await response).data);
|
||||
const responseSongs = getSongs();
|
||||
const responseBands = getBands();
|
||||
const responseAlbums = getAlbums();
|
||||
|
||||
setSongs((await responseSongs).data);
|
||||
setBands((await responseBands).data);
|
||||
setAlbums((await responseAlbums).data);
|
||||
};
|
||||
|
||||
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'}
|
||||
rowKey={(s: ISong) => s.id}
|
||||
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>
|
||||
</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 { ISong } from "../../../models/IModels";
|
||||
import { useState } from "react";
|
||||
import { height } from "@mui/system";
|
||||
import { height, style } from "@mui/system";
|
||||
import { useCurrentSongContext } from "../../../contexts/SongContexts/SongContextProvider";
|
||||
import { usePlayingContext } from "../../../contexts/SongContexts/PlayingProvider";
|
||||
|
||||
@ -43,7 +43,8 @@ const useColumns = (songs: ISong[])=> {
|
||||
title: '',
|
||||
dataIndex: 'song_name',
|
||||
key: 'song_name',
|
||||
width: 400
|
||||
width: 400,
|
||||
render: (text: string, song: ISong) => <span style={{cursor: 'default'}}>{text}</span>
|
||||
},
|
||||
{
|
||||
title: '',
|
||||
|
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 { IPlaylist, ISong, IAlbum, IGenre, IAdvertisement, IBand } from "../models/IModels";
|
||||
import { useCurrentSongContext } from "../contexts/SongContexts/SongContextProvider";
|
||||
import { useSideBlockContext } from "../contexts/SideBlockContexts/SideBlockProvider";
|
||||
|
||||
|
||||
export function Homepage() {
|
||||
@ -18,6 +19,7 @@ export function Homepage() {
|
||||
const [genres, setGenres] = React.useState<IGenre[]>([]);
|
||||
|
||||
const currentSongId = useCurrentSongContext();
|
||||
const { contentObject, setContentObject } = useSideBlockContext();
|
||||
|
||||
const fetchData = async () => {
|
||||
const [responseSongs, responseAds, responsePlaylists, responseGenres] = await Promise.all([
|
||||
@ -35,15 +37,14 @@ export function Homepage() {
|
||||
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
setContentObject(ads);
|
||||
}, []);
|
||||
|
||||
const currentSong = songs.find(song => song.id === currentSongId.songId);
|
||||
console.log('Айди песни:');
|
||||
|
||||
|
||||
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}/>}
|
||||
|
||||
</>
|
||||
|
Loading…
Reference in New Issue
Block a user