Changeset db5fb23 for frontend/src/pages


Ignore:
Timestamp:
02/12/26 11:27:23 (5 months ago)
Author:
Filip Gavrilovski <filipgavrilovski28@…>
Branches:
main
Children:
d85e8e3
Parents:
92db381
Message:

add endpoint for publishing songs and albums

File:
1 edited

Legend:

Unmodified
Added
Removed
  • frontend/src/pages/PublishSong.tsx

    r92db381 rdb5fb23  
    2323        const [genre, setGenre] = useState("");
    2424        const [link, setLink] = useState("");
    25         const [_coverFile, setCoverFile] = useState<File | null>(null); // TODO: Use in API call
     25        const [coverFile, setCoverFile] = useState<File | null>(null);
    2626        const [coverPreview, setCoverPreview] = useState<string | null>(null);
    2727        const [contributors, setContributors] = useState<Contributor[]>([]);
     
    9393                                `/users/search?type=ARTIST&q=${encodeURIComponent(query)}&limit=5`,
    9494                        );
    95 
    9695                        const filtered = response.data.filter(
    9796                                (artist: ArtistSearchResult) =>
     
    129128                }
    130129
    131                 if (contributors.some((c) => c.username === artist.username)) {
     130                if (contributors.some((c) => c.id === artist.id)) {
    132131                        toast.error("This contributor is already added");
    133132                        return;
     
    137136                        ...contributors,
    138137                        {
    139                                 username: artist.username,
     138                                id: artist.id,
    140139                                fullName: artist.fullName,
    141140                                role: selectedContributorRole,
     
    148147
    149148        // Remove contributor
    150         const handleRemoveContributor = (username: string) => {
    151                 setContributors(contributors.filter((c) => c.username !== username));
     149        const handleRemoveContributor = (id: number) => {
     150                setContributors(contributors.filter((c) => c.id !== id));
    152151        };
    153152
     
    242241                }
    243242
    244                 if (song.contributors.some((c) => c.username === artist.username)) {
     243                if (song.contributors.some((c) => c.id === artist.id)) {
    245244                        toast.error("This contributor is already added");
    246245                        return;
     
    249248                const role = albumSongSelectedRole[songIndex] || ROLE_OPTIONS[0].value;
    250249                const newContributor: Contributor = {
    251                         username: artist.username,
     250                        id: artist.id,
    252251                        fullName: artist.fullName,
    253252                        role,
     
    263262        };
    264263
    265         const handleRemoveAlbumSongContributor = (
    266                 songIndex: number,
    267                 username: string,
    268         ) => {
     264        const handleRemoveAlbumSongContributor = (songIndex: number, id: number) => {
    269265                const song = albumSongs[songIndex];
    270266                handleAlbumSongChange(
    271267                        songIndex,
    272268                        "contributors",
    273                         song.contributors.filter((c) => c.username !== username),
     269                        song.contributors.filter((c) => c.id !== id),
    274270                );
    275271        };
    276272
    277         // Form submission
    278273        const handleSubmit = async (e: React.FormEvent) => {
    279274                e.preventDefault();
    280275
    281                 // Validation
    282276                if (!title.trim()) {
    283277                        toast.error("Please enter a title");
     
    295289                        }
    296290                } else {
    297                         // Album validation
    298291                        for (let i = 0; i < albumSongs.length; i++) {
    299292                                if (!albumSongs[i].title.trim()) {
     
    311304
    312305                try {
    313                         // TODO: replace with API call
    314                         // const formData = new FormData();
    315                         // formData.append('title', title);
    316                         // formData.append('genre', genre);
    317                         // if (coverFile) formData.append('cover', coverFile);
    318                         // ...
    319 
    320                         // Simulate API call
    321                         await new Promise((resolve) => setTimeout(resolve, 1000));
     306                        const formData = new FormData();
     307                        formData.append("title", title);
     308                        formData.append("genre", genre);
     309                        if (coverFile) formData.append("cover", coverFile);
     310
     311                        // Helper to append contributors in indexed format for Spring @ModelAttribute
     312                        const appendContributors = (
     313                                formData: FormData,
     314                                contributors: Contributor[],
     315                                prefix: string,
     316                        ) => {
     317                                contributors.forEach((c, i) => {
     318                                        formData.append(`${prefix}[${i}].id`, c.id.toString());
     319                                        formData.append(`${prefix}[${i}].artistName`, c.fullName);
     320                                        formData.append(`${prefix}[${i}].role`, c.role);
     321                                });
     322                        };
     323
     324                        if (releaseType === "album") {
     325                                // Append album songs in indexed format
     326                                albumSongs.forEach((song, songIndex) => {
     327                                        formData.append(`albumSongs[${songIndex}].title`, song.title);
     328                                        formData.append(`albumSongs[${songIndex}].link`, song.link);
     329                                        // Append nested contributors for each song
     330                                        song.contributors.forEach((c, contribIndex) => {
     331                                                formData.append(
     332                                                        `albumSongs[${songIndex}].contributors[${contribIndex}].id`,
     333                                                        c.id.toString(),
     334                                                );
     335                                                formData.append(
     336                                                        `albumSongs[${songIndex}].contributors[${contribIndex}].artistName`,
     337                                                        c.fullName,
     338                                                );
     339                                                formData.append(
     340                                                        `albumSongs[${songIndex}].contributors[${contribIndex}].role`,
     341                                                        c.role,
     342                                                );
     343                                        });
     344                                });
     345                                await axiosInstance.post("/musical-entity/publish/album", formData, {
     346                                        headers: { "Content-Type": "multipart/form-data" },
     347                                });
     348                        } else {
     349                                formData.append("link", link);
     350                                appendContributors(formData, contributors, "contributors");
     351                                await axiosInstance.post("/musical-entity/publish/song", formData, {
     352                                        headers: { "Content-Type": "multipart/form-data" },
     353                                });
     354                        }
    322355
    323356                        toast.success(
     
    612645                                                                        {contributors.map((contributor) => (
    613646                                                                                <div
    614                                                                                         key={contributor.username}
     647                                                                                        key={contributor.id}
    615648                                                                                        className="flex items-center gap-2 bg-[#282828] rounded-full py-1.5 px-3"
    616649                                                                                >
     
    626659                                                                                        <button
    627660                                                                                                type="button"
    628                                                                                                 onClick={() =>
    629                                                                                                         handleRemoveContributor(contributor.username)
    630                                                                                                 }
     661                                                                                                onClick={() => handleRemoveContributor(contributor.id)}
    631662                                                                                                className="text-gray-400 hover:text-red-400 transition-colors"
    632663                                                                                        >
     
    687718                                                                                                        searchResults.map((artist) => (
    688719                                                                                                                <button
    689                                                                                                                         key={artist.username}
     720                                                                                                                        key={artist.id}
    690721                                                                                                                        type="button"
    691722                                                                                                                        onClick={() => handleAddContributor(artist)}
     
    808839                                                                                                {song.contributors.map((contributor) => (
    809840                                                                                                        <div
    810                                                                                                                 key={contributor.username}
     841                                                                                                                key={contributor.id}
    811842                                                                                                                className="flex items-center gap-2 bg-[#1a1a2e] rounded-full py-1 px-2.5 text-sm"
    812843                                                                                                        >
     
    826857                                                                                                                                handleRemoveAlbumSongContributor(
    827858                                                                                                                                        index,
    828                                                                                                                                         contributor.username,
     859                                                                                                                                        contributor.id,
    829860                                                                                                                                )
    830861                                                                                                                        }
     
    902933                                                                                                                                                (artist) => (
    903934                                                                                                                                                        <button
    904                                                                                                                                                                 key={artist.username}
     935                                                                                                                                                                key={artist.id}
    905936                                                                                                                                                                type="button"
    906937                                                                                                                                                                onClick={() =>
Note: See TracChangeset for help on using the changeset viewer.