Skip to content

Commit

Permalink
Add ability to move albums from the wish list to the catalogue and vi…
Browse files Browse the repository at this point in the history
…ce versa
  • Loading branch information
davewalker5 committed Nov 10, 2023
1 parent 35b3a23 commit 1e2aeff
Show file tree
Hide file tree
Showing 6 changed files with 175 additions and 37 deletions.
27 changes: 27 additions & 0 deletions src/music-catalogue-ui/components/addAlbumToCatalogue.js
Original file line number Diff line number Diff line change
@@ -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 (
<FontAwesomeIcon icon={faRecordVinyl} onClick={moveAlbumToCatalogue} />
);
};

export default AddAlbumToWishList;
27 changes: 27 additions & 0 deletions src/music-catalogue-ui/components/addAlbumToWishList.js
Original file line number Diff line number Diff line change
@@ -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 (
<FontAwesomeIcon icon={faHeartCirclePlus} onClick={moveAlbumToWishList} />
);
};

export default AddAlbumToWishList;
37 changes: 7 additions & 30 deletions src/music-catalogue-ui/components/albumList.js
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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 (
<>
Expand All @@ -60,6 +35,7 @@ const AlbumList = ({ artist, isWishList, navigate, logout }) => {
<th>Genre</th>
<th>Released</th>
<th />
<th />
</tr>
</thead>
<tbody>
Expand All @@ -71,7 +47,8 @@ const AlbumList = ({ artist, isWishList, navigate, logout }) => {
album={a}
isWishList={isWishList}
navigate={navigate}
deleteAlbum={confirmDeleteAlbum}
logout={logout}
setAlbums={setAlbumsCallback}
/>
))}
</tbody>
Expand Down
42 changes: 35 additions & 7 deletions src/music-catalogue-ui/components/albumRow.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,26 @@
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
* @param {*} artist
* @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 (
<tr>
<td onClick={() => navigate(pages.tracks, artist, album, isWishList)}>
Expand All @@ -27,11 +36,30 @@ const AlbumRow = ({ artist, album, isWishList, navigate, deleteAlbum }) => {
{album.released}
</td>
<td>
<FontAwesomeIcon
icon={faTrashAlt}
onClick={(e) => deleteAlbum(e, album)}
<DeleteAlbum
album={album}
isWishList={isWishList}
logout={logout}
setAlbums={setAlbums}
/>
</td>
<td>
{isWishList == false ? (
<AddAlbumToWishList
artistId={artist.id}
album={album}
logout={logout}
setAlbums={setAlbums}
/>
) : (
<AddAlbumToCatalogue
artistId={artist.id}
album={album}
logout={logout}
setAlbums={setAlbums}
/>
)}
</td>
</tr>
);
};
Expand Down
43 changes: 43 additions & 0 deletions src/music-catalogue-ui/components/deleteAlbum.js
Original file line number Diff line number Diff line change
@@ -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 (
<FontAwesomeIcon
icon={faTrashAlt}
onClick={(e) => confirmDeleteAlbum(e, album)}
/>
);
};

export default DeleteAlbum;
36 changes: 36 additions & 0 deletions src/music-catalogue-ui/helpers/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -390,6 +425,7 @@ export {
apiFetchAlbumById,
apiDeleteAlbum,
apiLookupAlbum,
apiSetAlbumWishListFlag,
apiRequestExport,
apiJobStatusReport,
};

0 comments on commit 1e2aeff

Please sign in to comment.