From 402556cf83bee950bf1f5ca4a151d6e7fa36bbe4 Mon Sep 17 00:00:00 2001 From: Edouard DUPIN Date: Mon, 26 Aug 2024 22:19:27 +0200 Subject: [PATCH] [FEAT] add album direct diaplay --- front2/package.json | 32 +++--- front2/src/components/DisplayTrack.tsx | 42 +++++++ front2/src/components/EmptyEnd.tsx | 13 +++ front2/src/components/album/DisplayAlbum.tsx | 62 ++++++++++ .../src/components/album/DisplayAlbumId.tsx | 10 ++ front2/src/scene/App.tsx | 2 + front2/src/scene/album/AlbumDetailPage.tsx | 106 ++++++++++++++++++ front2/src/scene/album/AlbumRoutes.tsx | 16 +++ front2/src/scene/album/AlbumsPage.tsx | 57 ++++++++++ .../scene/artist/ArtistAlbumDetailPage.tsx | 75 +++---------- front2/src/scene/artist/ArtistDetailPage.tsx | 61 ++-------- front2/src/service/Track.ts | 6 +- 12 files changed, 354 insertions(+), 128 deletions(-) create mode 100644 front2/src/components/DisplayTrack.tsx create mode 100644 front2/src/components/EmptyEnd.tsx create mode 100644 front2/src/components/album/DisplayAlbum.tsx create mode 100644 front2/src/components/album/DisplayAlbumId.tsx create mode 100644 front2/src/scene/album/AlbumDetailPage.tsx create mode 100644 front2/src/scene/album/AlbumRoutes.tsx create mode 100644 front2/src/scene/album/AlbumsPage.tsx diff --git a/front2/package.json b/front2/package.json index a6a6b78..c5fc7cf 100644 --- a/front2/package.json +++ b/front2/package.json @@ -35,11 +35,11 @@ "@dnd-kit/modifiers": "7.0.0", "@dnd-kit/sortable": "8.0.0", "@dnd-kit/utilities": "3.2.2", - "@emotion/react": "11.13.0", + "@emotion/react": "11.13.3", "@emotion/styled": "11.13.0", "allotment": "1.20.2", "css-mediaquery": "0.1.2", - "dayjs": "1.11.12", + "dayjs": "1.11.13", "history": "5.3.0", "react": "18.3.1", "react-color-palette": "7.2.2", @@ -48,13 +48,13 @@ "react-day-picker": "9.0.8", "react-dom": "18.3.1", "react-error-boundary": "4.0.13", - "react-focus-lock": "2.12.1", + "react-focus-lock": "2.13.2", "react-icons": "5.3.0", "react-popper": "2.3.0", "react-router-dom": "6.26.1", "react-select": "5.8.0", - "react-simple-keyboard": "3.7.144", - "react-sticky-el": "2.1.0", + "react-simple-keyboard": "3.7.147", + "react-sticky-el": "2.1.1", "react-use": "17.5.1", "react-use-draggable-scroll": "0.4.7", "react-virtuoso": "4.10.1", @@ -65,7 +65,7 @@ }, "devDependencies": { "@chakra-ui/styled-system": "2.9.2", - "@playwright/test": "1.46.0", + "@playwright/test": "1.46.1", "@storybook/addon-actions": "8.2.9", "@storybook/addon-essentials": "8.2.9", "@storybook/addon-links": "8.2.9", @@ -73,19 +73,19 @@ "@storybook/react": "8.2.9", "@storybook/react-vite": "8.2.9", "@storybook/theming": "8.2.9", - "@testing-library/jest-dom": "6.4.8", + "@testing-library/jest-dom": "6.5.0", "@testing-library/react": "16.0.0", "@testing-library/user-event": "14.5.2", "@trivago/prettier-plugin-sort-imports": "4.3.0", "@types/jest": "29.5.12", - "@types/node": "22.3.0", - "@types/react": "18.3.3", + "@types/node": "22.5.0", + "@types/react": "18.3.4", "@types/react-dom": "18.3.0", "@types/react-sticky-el": "1.0.7", - "@typescript-eslint/eslint-plugin": "8.1.0", - "@typescript-eslint/parser": "8.1.0", + "@typescript-eslint/eslint-plugin": "8.2.0", + "@typescript-eslint/parser": "8.2.0", "@vitejs/plugin-react": "4.3.1", - "eslint": "9.9.0", + "eslint": "9.9.1", "eslint-plugin-codeceptjs": "1.3.0", "eslint-plugin-import": "2.29.1", "eslint-plugin-react": "7.35.0", @@ -93,16 +93,16 @@ "eslint-plugin-storybook": "0.8.0", "jest": "29.7.0", "jest-environment-jsdom": "29.7.0", - "knip": "5.27.2", + "knip": "5.27.4", "lint-staged": "15.2.9", "prettier": "3.3.3", - "puppeteer": "23.1.0", + "puppeteer": "23.1.1", "react-is": "18.3.1", "storybook": "8.2.9", "ts-node": "10.9.2", "typescript": "5.5.4", - "vite": "5.4.1", + "vite": "5.4.2", "vitest": "2.0.5", - "npm-check-updates": "^17.0.6" + "npm-check-updates": "^17.1.0" } } diff --git a/front2/src/components/DisplayTrack.tsx b/front2/src/components/DisplayTrack.tsx new file mode 100644 index 0000000..b4b95ff --- /dev/null +++ b/front2/src/components/DisplayTrack.tsx @@ -0,0 +1,42 @@ +import { Flex, Text } from '@chakra-ui/react'; +import { LuMusic2 } from 'react-icons/lu'; + +import { Track } from '@/back-api'; +import { Covers } from '@/components/Cover'; + +export type DisplayTrackProps = { + track: Track; +}; +export const DisplayTrack = ({ track }: DisplayTrackProps) => { + return ( + + } + /> + + + [{track.track}] {track.name} + + + + ); +}; diff --git a/front2/src/components/EmptyEnd.tsx b/front2/src/components/EmptyEnd.tsx new file mode 100644 index 0000000..bb19d2e --- /dev/null +++ b/front2/src/components/EmptyEnd.tsx @@ -0,0 +1,13 @@ +import { Box } from '@chakra-ui/react'; + +export const EmptyEnd = () => { + return ( + + ); +}; diff --git a/front2/src/components/album/DisplayAlbum.tsx b/front2/src/components/album/DisplayAlbum.tsx new file mode 100644 index 0000000..5eff5fc --- /dev/null +++ b/front2/src/components/album/DisplayAlbum.tsx @@ -0,0 +1,62 @@ +import { Flex, Text } from '@chakra-ui/react'; +import { LuDisc3 } from 'react-icons/lu'; + +import { Album } from '@/back-api'; +import { Covers } from '@/components/Cover'; +import { useCountTracksWithAlbumId } from '@/service/Track'; + +export type DisplayAlbumProps = { + dataAlbum?: Album; +}; +export const DisplayAlbum = ({ dataAlbum }: DisplayAlbumProps) => { + const { countTracksOfAnAlbum } = useCountTracksWithAlbumId(dataAlbum?.id); + if (!dataAlbum) { + return ( + + Fail to retrieve Album Data. + + ); + } + return ( + + } + /> + + + {dataAlbum?.name} + + + {countTracksOfAnAlbum} track{countTracksOfAnAlbum >= 1 && 's'} + + + + ); +}; diff --git a/front2/src/components/album/DisplayAlbumId.tsx b/front2/src/components/album/DisplayAlbumId.tsx new file mode 100644 index 0000000..fd887ea --- /dev/null +++ b/front2/src/components/album/DisplayAlbumId.tsx @@ -0,0 +1,10 @@ +import { DisplayAlbum } from '@/components/album/DisplayAlbum'; +import { useSpecificAlbum } from '@/service/Album'; + +export type DisplayAlbumIdProps = { + id: number; +}; +export const DisplayAlbumId = ({ id }: DisplayAlbumIdProps) => { + const { dataAlbum } = useSpecificAlbum(id); + return ; +}; diff --git a/front2/src/scene/App.tsx b/front2/src/scene/App.tsx index 5cbb69e..6108e72 100644 --- a/front2/src/scene/App.tsx +++ b/front2/src/scene/App.tsx @@ -8,6 +8,7 @@ import { import { AudioPlayer } from '@/components/AudioPlayer'; import { Error404 } from '@/errors'; import { ErrorBoundary } from '@/errors/ErrorBoundary'; +import { AlbumRoutes } from '@/scene/album/AlbumRoutes'; import { ArtistRoutes } from '@/scene/artist/ArtistRoutes'; import { HomePage } from '@/scene/home/HomePage'; import { SSORoutes } from '@/scene/sso/SSORoutes'; @@ -24,6 +25,7 @@ export const App = () => { } /> } /> + } /> } /> } /> diff --git a/front2/src/scene/album/AlbumDetailPage.tsx b/front2/src/scene/album/AlbumDetailPage.tsx new file mode 100644 index 0000000..753ee4b --- /dev/null +++ b/front2/src/scene/album/AlbumDetailPage.tsx @@ -0,0 +1,106 @@ +import { Box, Flex, Text } from '@chakra-ui/react'; +import { LuDisc3 } from 'react-icons/lu'; +import { useParams } from 'react-router-dom'; + +import { Covers } from '@/components/Cover'; +import { DisplayTrack } from '@/components/DisplayTrack'; +import { EmptyEnd } from '@/components/EmptyEnd'; +import { PageLayout } from '@/components/Layout/PageLayout'; +import { PageLayoutInfoCenter } from '@/components/Layout/PageLayoutInfoCenter'; +import { TopBar } from '@/components/TopBar/TopBar'; +import { useActivePlaylistService } from '@/service/ActivePlaylist'; +import { useSpecificAlbum } from '@/service/Album'; +import { useTracksOfAnAlbum } from '@/service/Track'; +import { useThemeMode } from '@/utils/theme-tools'; + +export const AlbumDetailPage = () => { + const { albumId } = useParams(); + const albumIdInt = albumId ? parseInt(albumId, 10) : undefined; + const { mode } = useThemeMode(); + const { playInList } = useActivePlaylistService(); + const { dataAlbum } = useSpecificAlbum(albumIdInt); + const { tracksOnAnAlbum } = useTracksOfAnAlbum(albumIdInt); + const onSelectItem = (trackId: number) => { + //navigate(`/artist/${artistIdInt}/album/${albumId}`); + let currentPlay = 0; + const listTrackId: number[] = []; + for (let iii = 0; iii < tracksOnAnAlbum.length; iii++) { + listTrackId.push(tracksOnAnAlbum[iii].id); + if (tracksOnAnAlbum[iii].id === trackId) { + currentPlay = iii; + } + } + playInList(currentPlay, listTrackId); + }; + + console.log(`dataAlbum = ${JSON.stringify(dataAlbum, null, 2)}`); + if (!dataAlbum) { + return ( + <> + + + Fail to load artist id: {albumId} + + + ); + } + return ( + <> + + + + } + /> + + + {dataAlbum?.name} + + {dataAlbum?.description && ( + Description: {dataAlbum?.description} + )} + {dataAlbum?.publication && ( + first name: {dataAlbum?.publication} + )} + + + + + {tracksOnAnAlbum?.map((data) => ( + onSelectItem(data.id)} + > + + + ))} + + + + + ); +}; diff --git a/front2/src/scene/album/AlbumRoutes.tsx b/front2/src/scene/album/AlbumRoutes.tsx new file mode 100644 index 0000000..90c1db5 --- /dev/null +++ b/front2/src/scene/album/AlbumRoutes.tsx @@ -0,0 +1,16 @@ +import { Navigate, Route, Routes } from 'react-router-dom'; + +import { Error404 } from '@/errors'; +import { AlbumDetailPage } from '@/scene/album/AlbumDetailPage'; +import { AlbumsPage } from '@/scene/album/AlbumsPage'; + +export const AlbumRoutes = () => { + return ( + + } /> + } /> + } /> + } /> + + ); +}; diff --git a/front2/src/scene/album/AlbumsPage.tsx b/front2/src/scene/album/AlbumsPage.tsx new file mode 100644 index 0000000..b95a899 --- /dev/null +++ b/front2/src/scene/album/AlbumsPage.tsx @@ -0,0 +1,57 @@ +import { Text, Wrap, WrapItem } from '@chakra-ui/react'; +import { useNavigate } from 'react-router-dom'; + +import { PageLayout } from '@/components/Layout/PageLayout'; +import { PageLayoutInfoCenter } from '@/components/Layout/PageLayoutInfoCenter'; +import { TopBar } from '@/components/TopBar/TopBar'; +import { DisplayAlbum } from '@/components/album/DisplayAlbum'; +import { useAlbumService } from '@/service/Album'; +import { useThemeMode } from '@/utils/theme-tools'; + +export const AlbumsPage = () => { + const { store } = useAlbumService(); + const { mode } = useThemeMode(); + const navigate = useNavigate(); + const onSelectItem = (albumId: number) => { + navigate(`/album/${albumId}`); + }; + + if (store.isLoading) { + return ( + <> + + No Album available + + ); + } + return ( + <> + + + All Albums: + + + {store.data?.map((data) => ( + onSelectItem(data.id)} + > + + + ))} + + + + ); +}; diff --git a/front2/src/scene/artist/ArtistAlbumDetailPage.tsx b/front2/src/scene/artist/ArtistAlbumDetailPage.tsx index 34057db..917f2a1 100644 --- a/front2/src/scene/artist/ArtistAlbumDetailPage.tsx +++ b/front2/src/scene/artist/ArtistAlbumDetailPage.tsx @@ -1,66 +1,19 @@ -import { Box, Flex, Text, Wrap, WrapItem } from '@chakra-ui/react'; -import { LuDisc3, LuFileAudio, LuMusic2, LuUser } from 'react-icons/lu'; -import { useNavigate, useParams } from 'react-router-dom'; +import { Box, Flex, Text } from '@chakra-ui/react'; +import { LuDisc3, LuUser } from 'react-icons/lu'; +import { useParams } from 'react-router-dom'; -import { Album, Artist, Track } from '@/back-api'; import { Covers } from '@/components/Cover'; +import { DisplayTrack } from '@/components/DisplayTrack'; +import { EmptyEnd } from '@/components/EmptyEnd'; import { PageLayout } from '@/components/Layout/PageLayout'; import { PageLayoutInfoCenter } from '@/components/Layout/PageLayoutInfoCenter'; import { TopBar } from '@/components/TopBar/TopBar'; import { useActivePlaylistService } from '@/service/ActivePlaylist'; import { useSpecificAlbum } from '@/service/Album'; -import { useArtistService, useSpecificArtist } from '@/service/Artist'; -import { useAlbumIdsOfAnArtist, useTracksOfAnAlbum } from '@/service/Track'; +import { useSpecificArtist } from '@/service/Artist'; +import { useTracksOfAnAlbum } from '@/service/Track'; import { useThemeMode } from '@/utils/theme-tools'; -export type DisplayTrackProps = { - track: Track; -}; -export const DisplayTrack = ({ track }: DisplayTrackProps) => { - return ( - - } - /> - - - [{track.track}] {track.name} - - - - ); -}; -export const EmptyEnd = () => { - return ( - - ); -}; - export const ArtistAlbumDetailPage = () => { const { artistId, albumId } = useParams(); const artistIdInt = artistId ? parseInt(artistId, 10) : undefined; @@ -85,12 +38,14 @@ export const ArtistAlbumDetailPage = () => { console.log(`dataAlbum = ${JSON.stringify(dataAlbum, null, 2)}`); if (!dataAlbum) { - <> - - - Fail to load artist id: {artistId} - - ; + return ( + <> + + + Fail to load artist id: {artistId} + + + ); } return ( <> diff --git a/front2/src/scene/artist/ArtistDetailPage.tsx b/front2/src/scene/artist/ArtistDetailPage.tsx index 8be02fb..47351f8 100644 --- a/front2/src/scene/artist/ArtistDetailPage.tsx +++ b/front2/src/scene/artist/ArtistDetailPage.tsx @@ -1,55 +1,16 @@ import { Flex, Text, Wrap, WrapItem } from '@chakra-ui/react'; -import { LuDisc3, LuUser } from 'react-icons/lu'; +import { LuUser } from 'react-icons/lu'; import { useNavigate, useParams } from 'react-router-dom'; -import { Album, Artist } from '@/back-api'; import { Covers } from '@/components/Cover'; import { PageLayout } from '@/components/Layout/PageLayout'; import { PageLayoutInfoCenter } from '@/components/Layout/PageLayoutInfoCenter'; import { TopBar } from '@/components/TopBar/TopBar'; -import { useSpecificAlbum } from '@/service/Album'; -import { useArtistService, useSpecificArtist } from '@/service/Artist'; +import { DisplayAlbumId } from '@/components/album/DisplayAlbumId'; +import { useSpecificArtist } from '@/service/Artist'; import { useAlbumIdsOfAnArtist } from '@/service/Track'; import { useThemeMode } from '@/utils/theme-tools'; -export type DisplayAlbumProps = { - id: number; -}; -export const DisplayAlbum = ({ id }: DisplayAlbumProps) => { - const { dataAlbum } = useSpecificAlbum(id); - return ( - - } - /> - - - {dataAlbum?.name} - - - - ); -}; - export const ArtistDetailPage = () => { const { artistId } = useParams(); const artistIdInt = artistId ? parseInt(artistId, 10) : undefined; @@ -62,12 +23,14 @@ export const ArtistDetailPage = () => { const { albumIdsOfAnArtist } = useAlbumIdsOfAnArtist(artistIdInt); if (!dataArtist) { - <> - - - Fail to load artist id: {artistId} - - ; + return ( + <> + + + Fail to load artist id: {artistId} + + + ); } return ( <> @@ -116,7 +79,7 @@ export const ArtistDetailPage = () => { }} onClick={() => onSelectItem(data)} > - + ))} diff --git a/front2/src/service/Track.ts b/front2/src/service/Track.ts index 7818569..6bed003 100644 --- a/front2/src/service/Track.ts +++ b/front2/src/service/Track.ts @@ -139,10 +139,10 @@ export const useTracksOfAnAlbum = (idAlbum?: number) => { * @param AlbumId - Id of the album. * @returns The number of element present in this season */ -export const useCountTracksWithAlbumId = (albumId: number) => { +export const useCountTracksWithAlbumId = (albumId?: number) => { const { tracksOnAnAlbum } = useTracksOfAnAlbum(albumId); - const countTracksOnAnArtist = tracksOnAnAlbum.length; - return { countTracksOnAnArtist }; + const countTracksOfAnAlbum = tracksOnAnAlbum.length; + return { countTracksOfAnAlbum }; }; /**