import * as React from "react"; import {useCallback, useEffect, useRef, useState} from "react"; import useAlbumsApi from "../services/albums-api"; import { AddAPhoto, KeyboardArrowRight, MoveDown, MoveUp } from "@mui/icons-material"; import {Link, useNavigate} from "react-router-dom"; import Loader from "../components/Loader"; import {Button, TextField} from "@mui/material"; import {Album} from "../models/album"; import "./portfolio-manager.scss" import {useInstances} from "../services/instances/use-instances"; function PortfolioManager() { const navigate = useNavigate(); const {selectedInstance} = useInstances(); const [apiError, setApiError] = useState(null); const {fetchAlbums, patchAlbum, deleteAlbum, moveAlbumDown, moveAlbumUp} = useAlbumsApi(); const [albums, setAlbums] = useState(null); const [isLoading, setIsLoading] = useState(false); const [albumsToUpdate, setAlbumsToUpdate] = useState(null); const fetchedRef = useRef(false) const fetchData = useCallback(async () => { try { setIsLoading(true); setApiError(null); const albums = await fetchAlbums(selectedInstance); setAlbums(albums); setAlbumsToUpdate(albums.map(a => new Album(a))); } catch (err) { console.error("Could not fetch albums", err); setApiError("An error occurred trying to fetch your albums, please contact the system administrator"); setAlbums([]); } finally { setIsLoading(false); } }, [fetchAlbums, selectedInstance]) useEffect(() => { if (selectedInstance && !fetchedRef.current) { fetchData(); fetchedRef.current = true; } }, [selectedInstance, fetchData]); const handleAlbumNameChange = (albumIndex, e) => { albumsToUpdate[albumIndex].name = e.target.value; setAlbumsToUpdate([...albumsToUpdate]); } const handleAlbumDescriptionChange = (albumIndex, e) => { albumsToUpdate[albumIndex].description = e.target.value; setAlbumsToUpdate([...albumsToUpdate]); } const albumHasChanges = (idx) => { return albumsToUpdate[idx].name !== albums[idx].name || albumsToUpdate[idx].description !== albums[idx].description; } const handleSaveAlbum = async (idx) => { try { setIsLoading(true); if (albumHasChanges(idx)) { albumsToUpdate[idx] = await patchAlbum(selectedInstance, albumsToUpdate[idx]); setAlbums([ ...albumsToUpdate.map(a => new Album(a)) ]); } } catch (err) { if (typeof err === "string" && err.toLowerCase().indexOf("duplicate") >= 0) { setApiError("Name already in use"); } else { console.error(err); navigate(`/${selectedInstance.instanceId}/albums`, {state: {error: err}}); } } finally { setIsLoading(false); } } const handleDeleteAlbum = async (e, albumId) => { try { setIsLoading(true); const updatedAlbums = await deleteAlbum(selectedInstance, albumId); setAlbums(updatedAlbums); setAlbumsToUpdate(albumsToUpdate.filter(a => a.albumId !== albumId)); } catch (err) { console.error(err); } finally { setIsLoading(false); } } const handleMoveAlbumDown = async (idx) => { try { setIsLoading(true); const updatedAlbums = await moveAlbumDown(selectedInstance, albumsToUpdate[idx].albumId); const origAlbum = albumsToUpdate[idx]; albumsToUpdate[idx] = albumsToUpdate[idx + 1]; albumsToUpdate[idx + 1] = origAlbum; setAlbums(updatedAlbums); } catch (err) { console.error(err); } finally { setIsLoading(false); } } const handleMoveAlbumUp = async (idx) => { try { setIsLoading(true); const updatedAlbums = await moveAlbumUp(selectedInstance, albumsToUpdate[idx].albumId); const origAlbum = albumsToUpdate[idx]; albumsToUpdate[idx] = albumsToUpdate[idx - 1]; albumsToUpdate[idx - 1] = origAlbum; setAlbums(updatedAlbums); } catch (err) { console.error(err); } finally { setIsLoading(false); } } return