diff --git a/data.json b/data.json index 11360b0f..856ecc8a 100644 --- a/data.json +++ b/data.json @@ -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", diff --git a/src/API/api.ts b/src/API/api.ts index 445ac4b4..c0b6e6cf 100644 --- a/src/API/api.ts +++ b/src/API/api.ts @@ -41,4 +41,24 @@ export async function getAds() { return await axios.get(`${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/`); } \ No newline at end of file diff --git a/src/App.css b/src/App.css index 0f26451d..d104cac2 100644 --- a/src/App.css +++ b/src/App.css @@ -207,4 +207,11 @@ .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; } \ No newline at end of file diff --git a/src/App.tsx b/src/App.tsx index 0af3f582..e4135245 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -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() { + }> } /> @@ -27,6 +31,7 @@ function App() { + diff --git a/src/components/layoutComponents/AdBlock.tsx b/src/components/layoutComponents/AdBlock.tsx index 43c2f9a1..4d5e339d 100644 --- a/src/components/layoutComponents/AdBlock.tsx +++ b/src/components/layoutComponents/AdBlock.tsx @@ -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 (
- {ads.map(ad => )} + + {object && }
); } \ No newline at end of file diff --git a/src/components/menuComponents/ChartSongsBlock.tsx b/src/components/menuComponents/ChartSongsBlock.tsx index 3dae5b74..a1432154 100644 --- a/src/components/menuComponents/ChartSongsBlock.tsx +++ b/src/components/menuComponents/ChartSongsBlock.tsx @@ -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([]); const [numberedSongs, setNumberedSongs] = useState([]); + 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 }} /> diff --git a/src/components/menuComponents/NewSongsBlock.tsx b/src/components/menuComponents/NewSongsBlock.tsx index b691f195..a4d8a240 100644 --- a/src/components/menuComponents/NewSongsBlock.tsx +++ b/src/components/menuComponents/NewSongsBlock.tsx @@ -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([]); + const [bands, setBands] = useState([]); + const [albums, setAlbums] = useState([]); 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; + } + + } + }, + })} /> diff --git a/src/components/menuComponents/Templates/informationTemplate.tsx b/src/components/menuComponents/Templates/informationTemplate.tsx new file mode 100644 index 00000000..e6326f24 --- /dev/null +++ b/src/components/menuComponents/Templates/informationTemplate.tsx @@ -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 ( +
+ + {isAd(obj) && Array.isArray(obj) ? obj.map((ad) => ) : null} + {isSong(obj) ? +
+ ТРЕК + {obj.song_name} + + + {obj.song_name} +
+ + : null} + + + {isBand(obj) ? {obj.name} : null} + {isAlbum(obj) ? {obj.name} : null} + +
+ ) + + case 'undefined': + return ( +
+ }/> + + +
+ ) + + } +} + diff --git a/src/components/menuComponents/Templates/songTemplateInterface.tsx b/src/components/menuComponents/Templates/songTemplateInterface.tsx new file mode 100644 index 00000000..14a2de9a --- /dev/null +++ b/src/components/menuComponents/Templates/songTemplateInterface.tsx @@ -0,0 +1,11 @@ +import React from "react"; + +export interface ISongTemplateInterface { + key: number; + title: string; + artist: string; + album: string; + image: string; + duration: string; +} + diff --git a/src/components/menuComponents/Templates/songsTemplate.tsx b/src/components/menuComponents/Templates/songsTemplate.tsx index 83f550bd..a85d67a6 100644 --- a/src/components/menuComponents/Templates/songsTemplate.tsx +++ b/src/components/menuComponents/Templates/songsTemplate.tsx @@ -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) => {text} }, { title: '', @@ -63,4 +64,4 @@ const useColumns = (songs: ISong[])=> { export function GetColumns(songs: ISong[]) { return useColumns(songs); -} \ No newline at end of file +} diff --git a/src/contexts/SideBlockContexts/SideBlockProvider.tsx b/src/contexts/SideBlockContexts/SideBlockProvider.tsx new file mode 100644 index 00000000..d77f47a1 --- /dev/null +++ b/src/contexts/SideBlockContexts/SideBlockProvider.tsx @@ -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(undefined); + +export function SideBlockProvider({ children, contentObject }: SideBlockProviderProps) { + const [content, setContent] = useState(contentObject); + console.log(content); + + return ( + + {children} + + ); +} + +export const useSideBlockContext = function(): SideBlockContextValue { + const context = useContext(SideBlockContext); + if (context === undefined) { + throw new Error("useSideBlockContext must be used within a SideBlockProvider"); + } + return context; +}; \ No newline at end of file diff --git a/src/pages/Homepage.tsx b/src/pages/Homepage.tsx index c5185d06..20cdcf24 100644 --- a/src/pages/Homepage.tsx +++ b/src/pages/Homepage.tsx @@ -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() { @@ -12,12 +13,13 @@ export function Homepage() { const [albums, setAlbums] = useState([]); const [songs, setSongs] = useState([]); const [ads, setAds] = useState([]); - + const [playlists, setPlaylist] = React.useState([]); const [genres, setGenres] = React.useState([]); 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 ( <> - + {currentSong && }