Attempting an edit form
All checks were successful
Music Collection CI Workflow / test (./backend) (push) Successful in 21s
Music Collection CI Workflow / test (./frontend) (push) Successful in 19s
Music Collection CI Workflow / build-and-push-images (./backend/Dockerfile, git.anatid.net/tabris/msuic-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) Successful in 1m18s
Music Collection CI Workflow / deploy (push) Successful in 22s

This commit is contained in:
Phill Pover 2025-04-06 19:33:33 +01:00
parent 4773b74995
commit dc91d52b18
4 changed files with 116 additions and 67 deletions

View File

@ -42,3 +42,46 @@ export async function deleteAlbum(formData: FormData) {
}) })
}); });
} }
export async function createSong(formData: FormData) {
const albumId = formData.get('album-id');
const title = formData.get('title');
const duration = formData.get('duration');
return await fetch("https://api.anatid.net/song", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
albumId: albumId,
title: title,
duration: duration,
})
});
}
export async function updateSong(formData: FormData) {
const id = formData.get('id');
const albumId = formData.get('album-id');
const title = formData.get('title');
const duration = formData.get('duration');
return await fetch("https://api.anatid.net/song", {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
id: id,
albumId: albumId,
title: title,
duration: duration,
})
});
}
export async function deleteSong(formData: FormData) {
const id = formData.get('id');
return await fetch("https://api.anatid.net/song", {
method: "DELETE",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
id: id,
})
});
}

View File

@ -1,13 +1,19 @@
'use client' 'use client'
import { useState, useEffect } from 'react' import { FormEvent, useState, useEffect } from 'react'
import { useParams } from 'next/navigation' import { useParams } from 'next/navigation'
import { Album } from '@/entities/album.entity'; import { Album } from '@/entities/album.entity';
import { Song } from '@/entities/song.entity'; import { Song } from '@/entities/song.entity';
import { TimeUtils } from '@/utils/time.util'; import { TimeUtils } from '@/utils/time.util';
import { createSong } from '@/app/actions';
import Button from 'react-bootstrap/Button';
import Modal from 'react-bootstrap/Modal';
export default function Page() { export default function Page() {
const [album, setAlbum] = useState<Album>(); const [album, setAlbum] = useState<Album>();
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
const params = useParams<{ id: string }>(); const params = useParams<{ id: string }>();
const id = params.id; const id = params.id;
@ -21,14 +27,32 @@ export default function Page() {
fetchAlbum(id); fetchAlbum(id);
}, [id]); }, [id]);
const handleSubmit = async (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
handleClose();
const formData = new FormData(event.currentTarget);
try {
const response = await createSong(formData);
const data = response.json();
console.log(data);
} catch (error) {
console.error('Error creating Song:', error);
}
}
if (!album) return <div>Loading...</div> if (!album) return <div>Loading...</div>
return ( return (
<>
<div className="container"> <div className="container">
<div className="eight columns"> <div className="eight columns">
<div> <div>
<em>{album.title}</em> by {album.artist} ({album.genre}) <em>{album.title}</em> by {album.artist} ({album.genre})
</div> </div>
<Button variant="primary" onClick={handleShow}>
Add Song
</Button>
<table className="u-full-width"> <table className="u-full-width">
<thead> <thead>
<tr> <tr>
@ -47,5 +71,37 @@ export default function Page() {
</table> </table>
</div> </div>
</div> </div>
<Modal
show={show}
onHide={handleClose}
backdrop="static"
keyboard={false}
>
<Modal.Header closeButton>
<Modal.Title>Create Song</Modal.Title>
</Modal.Header>
<Modal.Body>
<div>
<form onSubmit={handleSubmit}>
<div className="row">
<div className="six columns">
<label htmlFor="album-title">Song Title</label><input type="text" name="title" id="song-title" />
</div>
<div className="six columns">
<label htmlFor="album-artist">Duration (seconds)</label><input type="text" name="artist" id="song-duration" />
</div>
</div>
<Button variant="primary" type="submit">Create</Button>
</form>
</div>
</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleClose}>
Close
</Button>
</Modal.Footer>
</Modal>
</>
); );
} }

View File

@ -4,7 +4,6 @@ import { FormEvent, useState, useEffect } from 'react';
import Link from 'next/link'; import Link from 'next/link';
import { Album } from '@/entities/album.entity'; import { Album } from '@/entities/album.entity';
import { createAlbum } from '@/app/actions'; import { createAlbum } from '@/app/actions';
// import CreateAlbumModal from "@/app/components/modals/create-album";
import Button from 'react-bootstrap/Button'; import Button from 'react-bootstrap/Button';
import Modal from 'react-bootstrap/Modal'; import Modal from 'react-bootstrap/Modal';
@ -13,6 +12,7 @@ export default function Page() {
const [show, setShow] = useState(false); const [show, setShow] = useState(false);
const handleClose = () => setShow(false); const handleClose = () => setShow(false);
const handleShow = () => setShow(true); const handleShow = () => setShow(true);
let [formAlbumTitle, formAlbumArtist, formAlbumGenre] = '';
useEffect(() => { useEffect(() => {
async function fetchAlbums() { async function fetchAlbums() {
@ -37,6 +37,13 @@ export default function Page() {
} }
} }
const handleEdit = async () => {
formAlbumTitle = "Monkey";
formAlbumArtist = "Donkey";
formAlbumGenre = "Pop";
handleShow();
}
if (!albums) return <div>Loading...</div> if (!albums) return <div>Loading...</div>
return ( return (
@ -70,7 +77,11 @@ export default function Page() {
<td> <td>
{album.genre} {album.genre}
</td> </td>
<td></td> <td>
<Button variant="edit" onClick={handleEdit}>
Edit
</Button>
</td>
</tr> </tr>
))} ))}
</tbody> </tbody>
@ -92,15 +103,15 @@ export default function Page() {
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
<div className="row"> <div className="row">
<div className="six columns"> <div className="six columns">
<label htmlFor="album-title">Album Title</label><input type="text" name="title" id="album-title" /> <label htmlFor="album-title">Album Title</label><input type="text" name="title" id="album-title" defaultValue={formAlbumTitle} />
</div> </div>
<div className="six columns"> <div className="six columns">
<label htmlFor="album-artist">Artist</label><input type="text" name="artist" id="album-artist" /> <label htmlFor="album-artist">Artist</label><input type="text" name="artist" id="album-artist" defaultValue={formAlbumArtist} />
</div> </div>
</div> </div>
<div className="row"> <div className="row">
<div className="six columns"> <div className="six columns">
<label htmlFor="album-genre">Genre</label><input type="text" name="genre" id="album-genre" /> <label htmlFor="album-genre">Genre</label><input type="text" name="genre" id="album-genre" defaultValue={formAlbumGenre} />
</div> </div>
</div> </div>
<Button variant="primary" type="submit">Create</Button> <Button variant="primary" type="submit">Create</Button>

View File

@ -1,61 +0,0 @@
"use client";
import { FormEvent } from 'react';
import {useSearchParams, usePathname} from "next/navigation";
import Link from "next/link";
import { createAlbum } from '@/app/actions';
import { useRouter } from 'next/navigation';
function CreateAlbumModal() {
const searchParams = useSearchParams();
const modal = searchParams.get("modal");
const pathname = usePathname();
const router = useRouter();
async function onSubmit(event: FormEvent<HTMLFormElement>) {
event.preventDefault();
const formData = new FormData(event.currentTarget);
const response = await createAlbum(formData);
await response.json();
router.refresh();
}
return (
<>
{modal &&
<dialog
className="fixed left-0 top-0 w-full h-full bg-black bg-opacity-50 z-50 overflow-auto backdrop-blur flex justify-center items-center">
<div className="container">
<form onSubmit={onSubmit}>
<div className="row">
<div className="six columns">
<label htmlFor="album-title">Album Title</label><input type="text" name="title" id="album-title" />
</div>
<div className="six columns">
<label htmlFor="album-artist">Artist</label><input type="text" name="artist" id="album-artist" />
</div>
</div>
<div className="row">
<div className="six columns">
<label htmlFor="album-genre">Genre</label><input type="text" name="genre" id="album-genre" />
</div>
</div>
<div className="row">
<div className="six columns">
<button type="submit">Create</button>
</div>
</div>
</form>
<Link href={pathname}>
<button type="button" className="bg-red-500 text-white p-2">Close Modal</button>
</Link>
</div>
</dialog>
}
</>
);
}
export default CreateAlbumModal;