Some checks failed
Music Collection CI Workflow / test (./backend) (push) Successful in 30s
Music Collection CI Workflow / test (./frontend) (push) Successful in 36s
Music Collection CI Workflow / build-and-push-images (./backend/Dockerfile, git.anatid.net/tabris/music-collection-backend, ./backend) (push) Successful in 50s
Music Collection CI Workflow / build-and-push-images (./frontend/Dockerfile, git.anatid.net/tabris/music-collection-frontend, ./frontend) (push) Failing after 1m32s
Music Collection CI Workflow / deploy (push) Has been skipped
182 lines
5.8 KiB
TypeScript
182 lines
5.8 KiB
TypeScript
'use client';
|
|
|
|
import { FormEvent, MouseEvent, useState, useEffect } from 'react';
|
|
import Link from 'next/link';
|
|
import { Album } from '@/entities/album.entity';
|
|
import { createAlbum, deleteAlbum, getAlbum, getAlbums, updateAlbum } from '@/app/actions';
|
|
import Button from 'react-bootstrap/Button';
|
|
import Modal from 'react-bootstrap/Modal';
|
|
import { IconButton } from '@mui/material';
|
|
import { AddCircleOutline, Delete, Edit } from '@mui/icons-material';
|
|
|
|
export default function Page() {
|
|
const [albums, setAlbums] = useState<Album[]>([]);
|
|
const [show, setShow] = useState(false);
|
|
const handleClose = () => setShow(false);
|
|
const handleShow = () => setShow(true);
|
|
const [formAlbumId, setFormAlbumId] = useState("");
|
|
const [formAlbumTitle, setFormAlbumTitle] = useState("");
|
|
const [formAlbumArtist, setFormAlbumArtist] = useState("");
|
|
const [formAlbumGenre, setFormAlbumGenre] = useState("");
|
|
const [formModalTitle, setFormModalTitle] = useState("Add Album");
|
|
const [formModalButtonLabel, setFormModalButtonLabel] = useState("Add");
|
|
|
|
useEffect(() => {
|
|
async function fetchAlbums() {
|
|
try {
|
|
const data = await getAlbums();
|
|
setAlbums(data);
|
|
} catch (error) {
|
|
console.error("Error getting albums: ", error);
|
|
}
|
|
}
|
|
fetchAlbums();
|
|
});
|
|
|
|
const handleSubmit = async (event: FormEvent<HTMLFormElement>) => {
|
|
event.preventDefault();
|
|
handleClose();
|
|
|
|
const formData = new FormData(event.currentTarget);
|
|
try {
|
|
console.log(formData);
|
|
if (formData.get('id') === "") {
|
|
await createAlbum(formData);
|
|
} else {
|
|
await updateAlbum(formData);
|
|
}
|
|
} catch (error) {
|
|
console.error("Error creating Album: ", error);
|
|
}
|
|
}
|
|
|
|
const handleCreate = async () => {
|
|
setFormModalTitle("Add Album");
|
|
setFormModalButtonLabel("Add");
|
|
setFormAlbumId("");
|
|
setFormAlbumTitle("");
|
|
setFormAlbumArtist("");
|
|
setFormAlbumGenre("");
|
|
handleShow();
|
|
}
|
|
|
|
const handleEdit = async (event: MouseEvent<HTMLElement>) => {
|
|
const id = event.currentTarget.getAttribute('album-id');
|
|
if (id) {
|
|
try {
|
|
const data = await getAlbum(parseInt(id));
|
|
setFormModalTitle("Edit Album");
|
|
setFormModalButtonLabel("Save");
|
|
setFormAlbumId(data.id)
|
|
setFormAlbumTitle(data.title);
|
|
setFormAlbumArtist(data.artist);
|
|
setFormAlbumGenre(data.genre);
|
|
handleShow();
|
|
} catch (error) {
|
|
console.error(`Error getting album with ID ${id}:`, error);
|
|
}
|
|
} else {
|
|
console.error("Couldn't get ID of clicked element");
|
|
}
|
|
}
|
|
|
|
const handleDelete = async (event: MouseEvent<HTMLElement>) => {
|
|
const id = event.currentTarget.getAttribute('album-id');
|
|
if (id) {
|
|
try {
|
|
await deleteAlbum(parseInt(id));
|
|
} catch (error) {
|
|
console.error(`Error deleting album with ID ${id}:`, error);
|
|
}
|
|
} else {
|
|
console.error("Couldn't get ID of clicked element");
|
|
}
|
|
}
|
|
|
|
if (!albums) return <div>Loading...</div>
|
|
|
|
return (
|
|
<>
|
|
<div className="container">
|
|
<IconButton aria-label="Add Album" size="large" onClick={handleCreate}>
|
|
<AddCircleOutline fontSize="inherit" color="success"/>
|
|
</IconButton>
|
|
<table className="u-full-width">
|
|
<thead>
|
|
<tr>
|
|
<th>Title</th>
|
|
<th>Artist</th>
|
|
<th>Genre</th>
|
|
<th>Controls</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{albums.map((album: Album) => (
|
|
<tr key={album.id}>
|
|
<td>
|
|
<Link
|
|
href={{
|
|
pathname: `/album/${album.id}`
|
|
}}>{album.title}
|
|
</Link>
|
|
</td>
|
|
<td>
|
|
{album.artist}
|
|
</td>
|
|
<td>
|
|
{album.genre}
|
|
</td>
|
|
<td>
|
|
<IconButton aria-label="Edit Album" size="small" album-id={album.id.toString()} onClick={handleEdit}>
|
|
<Edit fontSize="inherit" color="success"/>
|
|
</IconButton>
|
|
<IconButton aria-label="Delete Album" size="small" album-id={album.id.toString()} onClick={handleDelete}>
|
|
<Delete fontSize="inherit" color="failure"/>
|
|
</IconButton>
|
|
</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<Modal
|
|
show={show}
|
|
onHide={handleClose}
|
|
backdrop="static"
|
|
keyboard={false}
|
|
>
|
|
<Modal.Header closeButton>
|
|
<Modal.Title>{formModalTitle}</Modal.Title>
|
|
</Modal.Header>
|
|
<Modal.Body>
|
|
<div>
|
|
<form onSubmit={handleSubmit}>
|
|
<input name="id" id="album-id" value={formAlbumId} type="hidden" />
|
|
<div className="row">
|
|
<div className="six columns">
|
|
<label htmlFor="album-title">Album Title</label><input type="text" name="title" id="album-title" defaultValue={formAlbumTitle} />
|
|
</div>
|
|
<div className="six columns">
|
|
<label htmlFor="album-artist">Artist</label><input type="text" name="artist" id="album-artist" defaultValue={formAlbumArtist} />
|
|
</div>
|
|
</div>
|
|
<div className="row">
|
|
<div className="six columns">
|
|
<label htmlFor="album-genre">Genre</label><input type="text" name="genre" id="album-genre" defaultValue={formAlbumGenre} />
|
|
</div>
|
|
</div>
|
|
<Button variant="primary" type="submit">{formModalButtonLabel}</Button>
|
|
</form>
|
|
</div>
|
|
</Modal.Body>
|
|
<Modal.Footer>
|
|
<Button variant="secondary" onClick={handleClose}>
|
|
Close
|
|
</Button>
|
|
</Modal.Footer>
|
|
</Modal>
|
|
</>
|
|
);
|
|
}
|