diff --git a/src/music-catalogue-ui/components/albums/albumPurchaseDetails.js b/src/music-catalogue-ui/components/albums/albumPurchaseDetails.js
index 8b18e6a..bc1c52f 100644
--- a/src/music-catalogue-ui/components/albums/albumPurchaseDetails.js
+++ b/src/music-catalogue-ui/components/albums/albumPurchaseDetails.js
@@ -11,7 +11,6 @@ import RetailerSelector from "../retailers/retailerSelector";
* Form to set the album purchase details for an album
* @param {*} artist
* @param {*} album
- * @param {*} isWishList
* @param {*} navigate
* @param {*} logout
*/
@@ -41,7 +40,7 @@ const AlbumPurchaseDetails = ({ artist, album, navigate, logout }) => {
// Construct the values to be passed to the API
const updatedPurchaseDate =
- album.isWishListItem == false ? purchaseDate : null;
+ album.isWishListItem != true ? purchaseDate : null;
const updatedPrice = price != undefined ? price : null;
const updatedRetailerId = retailer != null ? retailer.id : null;
diff --git a/src/music-catalogue-ui/components/componentPicker.js b/src/music-catalogue-ui/components/componentPicker.js
index def9126..d4c9a69 100644
--- a/src/music-catalogue-ui/components/componentPicker.js
+++ b/src/music-catalogue-ui/components/componentPicker.js
@@ -22,6 +22,7 @@ import EquipmentTypeEditor from "./equipmentTypes/equipmentTypeEditor";
import ManufacturerList from "./manufacturers/manufacturerList";
import ManufacturerEditor from "./manufacturers/manufacturerEditor";
import EquipmentList from "./equipment/equipmentList";
+import EquipmentPurchaseDetails from "./equipment/equpimentPurchaseDetails";
/**
* Component using the current context to select and render the current page
@@ -150,6 +151,14 @@ const ComponentPicker = ({ context, navigate, logout }) => {
logout={logout}
/>
);
+ case pages.equipmentPurchaseDetails:
+ return (
+
+ );
case pages.export:
return ;
case pages.artistStatisticsReport:
diff --git a/src/music-catalogue-ui/components/equipment/equipmentEditor.js b/src/music-catalogue-ui/components/equipment/equipmentEditor.js
new file mode 100644
index 0000000..e69de29
diff --git a/src/music-catalogue-ui/components/equipment/equipmentEditor.module.css b/src/music-catalogue-ui/components/equipment/equipmentEditor.module.css
new file mode 100644
index 0000000..d878ad5
--- /dev/null
+++ b/src/music-catalogue-ui/components/equipment/equipmentEditor.module.css
@@ -0,0 +1,27 @@
+.equipmentEditorFormContainer {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.equipmentEditorForm {
+ width: 80%;
+ padding-top: 20px;
+ padding-bottom: 20px;
+}
+
+.equipmentEditorFormLabel {
+ font-size: 14px;
+ font-weight: 600;
+ color: rgb(34, 34, 34);
+}
+
+.equipmentEditorButton {
+ margin-left: 10px;
+ float: right;
+}
+
+.equipmentEditorError {
+ font-weight: bold;
+ color: red;
+}
diff --git a/src/music-catalogue-ui/components/equipment/equipmentList.js b/src/music-catalogue-ui/components/equipment/equipmentList.js
index cdc1e9b..9e7a389 100644
--- a/src/music-catalogue-ui/components/equipment/equipmentList.js
+++ b/src/music-catalogue-ui/components/equipment/equipmentList.js
@@ -12,7 +12,7 @@ import EquipmentRow from "./equipmentRow";
* @returns
*/
const EquipmentList = ({ isWishList, navigate, logout }) => {
- const { equipment, setEquipment } = useEquipment(logout);
+ const { equipment, setEquipment } = useEquipment(isWishList, logout);
const [error, setError] = useState("");
return (
diff --git a/src/music-catalogue-ui/components/equipment/equipmentPurchaseDetails.module.css b/src/music-catalogue-ui/components/equipment/equipmentPurchaseDetails.module.css
new file mode 100644
index 0000000..1fedcba
--- /dev/null
+++ b/src/music-catalogue-ui/components/equipment/equipmentPurchaseDetails.module.css
@@ -0,0 +1,27 @@
+.purchaseDetailsFormContainer {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.purchaseDetailsForm {
+ width: 420px;
+ padding-top: 20px;
+ padding-bottom: 20px;
+}
+
+.purchaseDetailsFormLabel {
+ font-size: 14px;
+ font-weight: 600;
+ color: rgb(34, 34, 34);
+}
+
+.purchaseDetailsButton {
+ margin-left: 10px;
+ float: right;
+}
+
+.purchaseDetailsError {
+ font-weight: bold;
+ color: red;
+}
diff --git a/src/music-catalogue-ui/components/equipment/equipmentRow.js b/src/music-catalogue-ui/components/equipment/equipmentRow.js
index 372f836..4163c52 100644
--- a/src/music-catalogue-ui/components/equipment/equipmentRow.js
+++ b/src/music-catalogue-ui/components/equipment/equipmentRow.js
@@ -1,9 +1,10 @@
import pages from "@/helpers/navigation";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { faPenToSquare } from "@fortawesome/free-solid-svg-icons";
+import { faPenToSquare, faCoins } from "@fortawesome/free-solid-svg-icons";
import DeleteEquipmentActionIcon from "./deleteEquipmentActionIcon";
import DateFormatter from "../common/dateFormatter";
import CurrencyFormatter from "../common/currencyFormatter";
+import EquipmentWishListActionIcon from "./equipmentWishListActionIcon";
/**
* Component to render a row containing the details for a single item of equipment
@@ -70,24 +71,23 @@ const EquipmentRow = ({
/>
- {/* */}
+ setEquipment={setEquipment}
+ />
|
- {/*
navigate({
- page: pages.albumPurchaseDetails,
- artist: artist,
- album: album,
+ page: pages.equipmentPurchaseDetails,
+ equipment: equipment,
})
}
- /> */}
+ />
|
);
diff --git a/src/music-catalogue-ui/components/equipment/equipmentWishListActionIcon.js b/src/music-catalogue-ui/components/equipment/equipmentWishListActionIcon.js
new file mode 100644
index 0000000..9a56588
--- /dev/null
+++ b/src/music-catalogue-ui/components/equipment/equipmentWishListActionIcon.js
@@ -0,0 +1,48 @@
+import { useCallback } from "react";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import {
+ faHeartCirclePlus,
+ faRecordVinyl,
+} from "@fortawesome/free-solid-svg-icons";
+import {
+ apiFetchEquipment,
+ apiSetEquipmentWishListFlag,
+} from "@/helpers/api/apiEquipment";
+
+/**
+ * Icon and associated action to move an item of equipment between the main
+ * registry and wish list
+ * @param {*} equipment
+ * @param {*} isWishList
+ * @param {*} logout
+ * @param {*} setEquipment
+ * @returns
+ */
+const EquipmentWishListActionIcon = ({
+ equipment,
+ isWishList,
+ logout,
+ setEquipment,
+}) => {
+ // Set the icon depending on the direction in which the equipment will move
+ const icon = isWishList ? faRecordVinyl : faHeartCirclePlus;
+
+ /* Callback to move an album between the wish list and catalogue */
+ const setEquipmentWishListFlag = useCallback(async () => {
+ // Move the album to the wish list
+ const result = await apiSetEquipmentWishListFlag(
+ equipment,
+ !isWishList,
+ logout
+ );
+ if (result) {
+ // Successful, so refresh the album list
+ const fetchedEquipment = await apiFetchEquipment(isWishList, logout);
+ setEquipment(fetchedEquipment);
+ }
+ }, [equipment, isWishList, logout, setEquipment]);
+
+ return ;
+};
+
+export default EquipmentWishListActionIcon;
diff --git a/src/music-catalogue-ui/components/equipment/equpimentPurchaseDetails.js b/src/music-catalogue-ui/components/equipment/equpimentPurchaseDetails.js
new file mode 100644
index 0000000..30aa8fd
--- /dev/null
+++ b/src/music-catalogue-ui/components/equipment/equpimentPurchaseDetails.js
@@ -0,0 +1,161 @@
+import styles from "./equipmentPurchaseDetails.module.css";
+import DatePicker from "react-datepicker";
+import { useState, useCallback } from "react";
+import CurrencyInput from "react-currency-input-field";
+import config from "@/config.json";
+import pages from "@/helpers/navigation";
+import RetailerSelector from "../retailers/retailerSelector";
+import { apiSetEquipmentPurchaseDetails } from "@/helpers/api/apiEquipment";
+
+/**
+ * Form to set the equipment purchase details for an item of equipment
+ * @param {*} equipment
+ * @param {*} navigate
+ * @param {*} logout
+ */
+const EquipmentPurchaseDetails = ({ equipment, navigate, logout }) => {
+ // Get the initial retailer selection and purchase date
+ let initialRetailer = null;
+ let initialPurchaseDate = new Date();
+ if (equipment != null) {
+ initialRetailer = equipment.retailer;
+
+ if (equipment.purchased != null) {
+ initialPurchaseDate = new Date(equipment.purchased);
+ }
+ }
+
+ // Set up state
+ const [purchaseDate, setPurchaseDate] = useState(initialPurchaseDate);
+ const [price, setPrice] = useState(equipment.price);
+ const [retailer, setRetailer] = useState(initialRetailer);
+ const [errorMessage, setErrorMessage] = useState("");
+
+ /* Callback to set album purchase details */
+ const setEquipmentPurchaseDetails = useCallback(
+ async (e) => {
+ // Prevent the default action associated with the click event
+ e.preventDefault();
+
+ // Construct the values to be passed to the API
+ const updatedPurchaseDate =
+ equipment.isWishListItem != true ? purchaseDate : null;
+ const updatedPrice = price != undefined ? price : null;
+ const updatedRetailerId = retailer != null ? retailer.id : null;
+
+ // Apply the updates
+ const updatedEquipment = await apiSetEquipmentPurchaseDetails(
+ equipment,
+ updatedPurchaseDate,
+ updatedPrice,
+ updatedRetailerId,
+ logout
+ );
+
+ // If the returned album is valid, navigate back to the albums by artist page.
+ // Otherwise, show an error
+ if (updatedEquipment != null) {
+ navigate({
+ page: pages.equipment,
+ isWishList: updatedEquipment.isWishListItem,
+ });
+ } else {
+ setErrorMessage("Error updating the equipment purchase details");
+ }
+ },
+ [equipment, price, purchaseDate, retailer, logout, navigate]
+ );
+
+ return (
+ <>
+
+
+ {equipment.description} - Purchase Details
+
+
+
+ >
+ );
+};
+
+export default EquipmentPurchaseDetails;
diff --git a/src/music-catalogue-ui/components/equipmentTypes/equipmentTypeSelector.js b/src/music-catalogue-ui/components/equipmentTypes/equipmentTypeSelector.js
new file mode 100644
index 0000000..ad867a9
--- /dev/null
+++ b/src/music-catalogue-ui/components/equipmentTypes/equipmentTypeSelector.js
@@ -0,0 +1,62 @@
+import Select from "react-select";
+import useEquipmentTypes from "@/hooks/useEquipmentTypes";
+import { useState } from "react";
+
+/**
+ * Component to display the equipment type selector
+ * @param {*} initialEquipmentType
+ * @param {*} equipmentTypeChangedCallback
+ * @param {*} logout
+ * @returns
+ */
+const EquipmentTypeSelector = ({
+ initialEquipmentType,
+ equipmentTypeChangedCallback,
+ logout,
+}) => {
+ const { equipmentTypes, setEquipmentTypes } = useEquipmentTypes(logout);
+
+ let options = [];
+ if (equipmentTypes.length > 0) {
+ // Construct the options for the drop-down
+ for (let i = 0; i < equipmentTypes.length; i++) {
+ options = [
+ ...options,
+ { value: equipmentTypes[i].id, label: equipmentTypes[i].name },
+ ];
+ }
+ }
+
+ // Determine the initial selection
+ let selectedOption = null;
+ if (initialEquipmentType != null) {
+ selectedOption = options.find((x) => x.value === initialEquipmentType.id);
+ }
+
+ // Set up state
+ const [equipmentType, setEquipmentType] = useState(selectedOption);
+
+ // Callback to update state and notify the parent component
+ // that the selection has changed
+ const equipmentTypeChanged = (e) => {
+ // Update local state with the selection from the drop-down
+ const updatedSelection = options.find((x) => x.value === e.value);
+ setEquipmentType(updatedSelection);
+
+ // Notify the parent component with an equipment type object
+ equipmentTypeChangedCallback({
+ id: updatedSelection.value,
+ name: updatedSelection.label,
+ });
+ };
+
+ return (
+
+ );
+};
+
+export default EquipmentTypeSelector;
diff --git a/src/music-catalogue-ui/components/manufacturers/manufacturerSelector.js b/src/music-catalogue-ui/components/manufacturers/manufacturerSelector.js
new file mode 100644
index 0000000..0e0cf70
--- /dev/null
+++ b/src/music-catalogue-ui/components/manufacturers/manufacturerSelector.js
@@ -0,0 +1,62 @@
+import Select from "react-select";
+import { useState } from "react";
+import useManufacturers from "@/hooks/useManufacturers";
+
+/**
+ * Component to display the manufacturer selector
+ * @param {*} initialManufacturer
+ * @param {*} manufacturerChangedCallback
+ * @param {*} logout
+ * @returns
+ */
+const ManufacturerSelector = ({
+ initialManufacturer,
+ manufacturerChangedCallback,
+ logout,
+}) => {
+ const { manufacturers, setManufacturers } = useManufacturers(logout);
+
+ let options = [];
+ if (manufacturers.length > 0) {
+ // Construct the options for the drop-down
+ for (let i = 0; i < manufacturers.length; i++) {
+ options = [
+ ...options,
+ { value: manufacturers[i].id, label: manufacturers[i].name },
+ ];
+ }
+ }
+
+ // Determine the initial selection
+ let selectedOption = null;
+ if (initialManufacturer != null) {
+ selectedOption = options.find((x) => x.value === initialManufacturer.id);
+ }
+
+ // Set up state
+ const [manufacturer, setManufacturer] = useState(selectedOption);
+
+ // Callback to update state and notify the parent component
+ // that the selection has changed
+ const manufacturerChanged = (e) => {
+ // Update local state with the selection from the drop-down
+ const updatedSelection = options.find((x) => x.value === e.value);
+ setManufacturer(updatedSelection);
+
+ // Notify the parent component with a manufacturer object
+ manufacturerChangedCallback({
+ id: updatedSelection.value,
+ name: updatedSelection.label,
+ });
+ };
+
+ return (
+
+ );
+};
+
+export default ManufacturerSelector;
diff --git a/src/music-catalogue-ui/components/menuBar.js b/src/music-catalogue-ui/components/menuBar.js
index 720a807..872dfa9 100644
--- a/src/music-catalogue-ui/components/menuBar.js
+++ b/src/music-catalogue-ui/components/menuBar.js
@@ -61,8 +61,20 @@ const MenuBar = ({ navigate, logout }) => {
-
navigate({ page: pages.equipment })}>Equipment
-
Wish List
+
+ navigate({ page: pages.equipment, isWishList: false })
+ }
+ >
+ Equipment
+
+
+ navigate({ page: pages.equipment, isWishList: true })
+ }
+ >
+ Wish List
+
navigate({ page: pages.equipmentTypes })}>
Equipment Types
diff --git a/src/music-catalogue-ui/helpers/navigation.js b/src/music-catalogue-ui/helpers/navigation.js
index 09769e4..4689e45 100644
--- a/src/music-catalogue-ui/helpers/navigation.js
+++ b/src/music-catalogue-ui/helpers/navigation.js
@@ -5,6 +5,7 @@ const pages = {
wishlistArtists: "WishlistArtists",
albums: "Albums",
albumEditor: "AlbumEditor",
+ albumPurchaseDetails: "AlbumPurchaseDetails",
wishlistAlbums: "WishlistAlbums",
tracks: "Tracks",
trackEditor: "TrackEditor",
@@ -17,6 +18,7 @@ const pages = {
manufacturerEditor: "ManufacturerEditor",
equipment: "Equipment",
equipmentEditor: "EquipmentEditor",
+ equipmentPurchaseDetails: "EquipmentPurchaseDetails",
lookup: "Lookup",
export: "Export",
artistStatisticsReport: "ArtistStatisticsReport",
@@ -24,7 +26,6 @@ const pages = {
jobStatusReport: "JobStatusReport",
monthlySpendReport: "MonthlySpendReport",
retailerStatisticsReport: "RetailerStatisticsReport",
- albumPurchaseDetails: "AlbumPurchaseDetails",
};
export default pages;