diff --git a/src/music-catalogue-ui/components/addAlbumToCatalogue.js b/src/music-catalogue-ui/components/addAlbumToCatalogue.js new file mode 100644 index 0000000..2a95334 --- /dev/null +++ b/src/music-catalogue-ui/components/addAlbumToCatalogue.js @@ -0,0 +1,27 @@ +import { useCallback } from "react"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faRecordVinyl } from "@fortawesome/free-solid-svg-icons"; +import { apiSetAlbumWishListFlag, apiFetchAlbumsByArtist } from "@/helpers/api"; + +const AddAlbumToWishList = ({ artistId, album, logout, setAlbums }) => { + /* Callback to move an album from the wish list into the catalogue */ + const moveAlbumToCatalogue = useCallback(async () => { + // Move the album to the catalogue + const result = await apiSetAlbumWishListFlag(album, false, logout); + if (result) { + // Successful, so refresh the album list + const fetchedAlbums = await apiFetchAlbumsByArtist( + artistId, + true, + logout + ); + setAlbums(fetchedAlbums); + } + }, [album, artistId, logout, setAlbums]); + + return ( + + ); +}; + +export default AddAlbumToWishList; diff --git a/src/music-catalogue-ui/components/addAlbumToWishList.js b/src/music-catalogue-ui/components/addAlbumToWishList.js new file mode 100644 index 0000000..9143085 --- /dev/null +++ b/src/music-catalogue-ui/components/addAlbumToWishList.js @@ -0,0 +1,27 @@ +import { useCallback } from "react"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faHeartCirclePlus } from "@fortawesome/free-solid-svg-icons"; +import { apiSetAlbumWishListFlag, apiFetchAlbumsByArtist } from "@/helpers/api"; + +const AddAlbumToWishList = ({ artistId, album, logout, setAlbums }) => { + /* Callback to prompt for confirmation and delete an album */ + const moveAlbumToWishList = useCallback(async () => { + // Move the album to the wish list + const result = await apiSetAlbumWishListFlag(album, true, logout); + if (result) { + // Successful, so refresh the album list + const fetchedAlbums = await apiFetchAlbumsByArtist( + artistId, + false, + logout + ); + setAlbums(fetchedAlbums); + } + }, [album, artistId, logout, setAlbums]); + + return ( + + ); +}; + +export default AddAlbumToWishList; diff --git a/src/music-catalogue-ui/components/albumList.js b/src/music-catalogue-ui/components/albumList.js index f55dca1..1cd07c5 100644 --- a/src/music-catalogue-ui/components/albumList.js +++ b/src/music-catalogue-ui/components/albumList.js @@ -1,7 +1,5 @@ -import { useCallback } from "react"; import useAlbums from "@/hooks/useAlbums"; import AlbumRow from "./albumRow"; -import { apiDeleteAlbum, apiFetchAlbumsByArtist } from "@/helpers/api"; /** * Component to render the table of all albums by the specified artist @@ -19,33 +17,10 @@ const AlbumList = ({ artist, isWishList, navigate, logout }) => { ? `Wish List for ${artist.name}` : `Albums by ${artist.name}`; - /* Callback to prompt for confirmation and delete an album */ - const confirmDeleteAlbum = useCallback( - async (e, album) => { - // Prevent the default action associated with the click event - e.preventDefault(); - - // Show a confirmation message and get the user response - const message = `This will delete the album "${album.title}" - click OK to confirm`; - const result = confirm(message); - - // If they've confirmed the deletion ... - if (result) { - // ... delete the album and confirm the API call was successful - const result = await apiDeleteAlbum(album.id, logout); - if (result) { - // Successful, so refresh the album list - const fetchedAlbums = await apiFetchAlbumsByArtist( - artist.id, - isWishList, - logout - ); - setAlbums(fetchedAlbums); - } - } - }, - [artist, isWishList, setAlbums, logout] - ); + // Callback to pass to child components to set the album list + const setAlbumsCallback = (albums) => { + setAlbums(albums); + }; return ( <> @@ -60,6 +35,7 @@ const AlbumList = ({ artist, isWishList, navigate, logout }) => { Genre Released + @@ -71,7 +47,8 @@ const AlbumList = ({ artist, isWishList, navigate, logout }) => { album={a} isWishList={isWishList} navigate={navigate} - deleteAlbum={confirmDeleteAlbum} + logout={logout} + setAlbums={setAlbumsCallback} /> ))} diff --git a/src/music-catalogue-ui/components/albumRow.js b/src/music-catalogue-ui/components/albumRow.js index 851fb21..93c1e48 100644 --- a/src/music-catalogue-ui/components/albumRow.js +++ b/src/music-catalogue-ui/components/albumRow.js @@ -1,6 +1,7 @@ import pages from "@/helpers/navigation"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { faTrashAlt } from "@fortawesome/free-solid-svg-icons"; +import DeleteAlbum from "./deleteAlbum"; +import AddAlbumToWishList from "./addAlbumToWishList"; +import AddAlbumToCatalogue from "./addAlbumToCatalogue"; /** * Component to render a row containing the details of a single album @@ -8,10 +9,18 @@ import { faTrashAlt } from "@fortawesome/free-solid-svg-icons"; * @param {*} album * @param {*} isWishList * @param {*} navigate - * @param {*} deleteAlbum + * @param {*} logout + * @param {*} setAlbums * @returns */ -const AlbumRow = ({ artist, album, isWishList, navigate, deleteAlbum }) => { +const AlbumRow = ({ + artist, + album, + isWishList, + navigate, + logout, + setAlbums, +}) => { return ( navigate(pages.tracks, artist, album, isWishList)}> @@ -27,11 +36,30 @@ const AlbumRow = ({ artist, album, isWishList, navigate, deleteAlbum }) => { {album.released} - deleteAlbum(e, album)} + + + {isWishList == false ? ( + + ) : ( + + )} + ); }; diff --git a/src/music-catalogue-ui/components/deleteAlbum.js b/src/music-catalogue-ui/components/deleteAlbum.js new file mode 100644 index 0000000..bfdc5d6 --- /dev/null +++ b/src/music-catalogue-ui/components/deleteAlbum.js @@ -0,0 +1,43 @@ +import { useCallback } from "react"; +import { apiDeleteAlbum, apiFetchAlbumsByArtist } from "@/helpers/api"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faTrashAlt } from "@fortawesome/free-solid-svg-icons"; + +const DeleteAlbum = ({ album, isWishList, logout, setAlbums }) => { + /* Callback to prompt for confirmation and delete an album */ + const confirmDeleteAlbum = useCallback( + async (e, album) => { + // Prevent the default action associated with the click event + e.preventDefault(); + + // Show a confirmation message and get the user response + const message = `This will delete the album "${album.title}" - click OK to confirm`; + const result = confirm(message); + + // If they've confirmed the deletion ... + if (result) { + // ... delete the album and confirm the API call was successful + const result = await apiDeleteAlbum(album.id, logout); + if (result) { + // Successful, so refresh the album list + const fetchedAlbums = await apiFetchAlbumsByArtist( + artist.id, + isWishList, + logout + ); + setAlbums(fetchedAlbums); + } + } + }, + [isWishList, logout, setAlbums] + ); + + return ( + confirmDeleteAlbum(e, album)} + /> + ); +}; + +export default DeleteAlbum; diff --git a/src/music-catalogue-ui/helpers/api.js b/src/music-catalogue-ui/helpers/api.js index 0bc5da1..604b2fc 100644 --- a/src/music-catalogue-ui/helpers/api.js +++ b/src/music-catalogue-ui/helpers/api.js @@ -307,6 +307,41 @@ const apiLookupAlbum = async (artistName, albumTitle, logout) => { } }; +/** + * Set the wish list flag on an album + * @param {*} album + * @param {*} wishListFlag + * @param {*} logout + * @returns + */ +const apiSetAlbumWishListFlag = async (album, wishListFlag, logout) => { + // Construct the body - the wish list flat needs to be updated before this + // and there's no need to send the track information - an empty array will do + album.isWishListItem = wishListFlag; + album.tracks = []; + const body = JSON.stringify(album); + console.log(body); + + // Call the API to set the wish list flag for a given album + const url = `${config.api.baseUrl}/albums`; + const response = await fetch(url, { + method: "PUT", + headers: apiGetPostHeaders(), + body: body, + }); + + if (response.ok) { + // Get the response content as JSON and return it + const album = await apiReadResponseData(response); + return album; + } else if (response.status == 401) { + // Unauthorized so the token's likely expired - force a login + logout(); + } else { + return null; + } +}; + /** * Request an export of the catalogue * @param {*} fileName @@ -390,6 +425,7 @@ export { apiFetchAlbumById, apiDeleteAlbum, apiLookupAlbum, + apiSetAlbumWishListFlag, apiRequestExport, apiJobStatusReport, };