diff --git a/src/app/components/AddPlaylistButton.tsx b/src/app/components/AddPlaylistButton.tsx index 4b25389..74ccdc7 100644 --- a/src/app/components/AddPlaylistButton.tsx +++ b/src/app/components/AddPlaylistButton.tsx @@ -38,6 +38,7 @@ export default function AddPlaylistButton({ onCreate }: AddPlaylistButtonProps) diff --git a/src/app/components/PlaylistCard.tsx b/src/app/components/PlaylistCard.tsx new file mode 100644 index 0000000..852e798 --- /dev/null +++ b/src/app/components/PlaylistCard.tsx @@ -0,0 +1,39 @@ +import { Box, Typography, useTheme } from "@mui/material"; +import React from "react"; +import { MotionBox } from "./MotionComponents"; +import { MusicNote } from "@mui/icons-material"; + +type PlaylistCardProps = { + name: string; + onClick?: () => void; +}; +export default function PlaylistCard({ name, onClick }: PlaylistCardProps) { + const theme = useTheme(); + return ( + + + + + + New playlist + + + ); +} \ No newline at end of file diff --git a/src/app/pages/Landing.tsx b/src/app/pages/Landing.tsx index 7e71b0b..0969eea 100644 --- a/src/app/pages/Landing.tsx +++ b/src/app/pages/Landing.tsx @@ -1,25 +1,50 @@ import { Box, Typography, useTheme } from "@mui/material"; -import React from "react"; +import React, { useEffect, useState } from "react"; import LoadingCard from "../components/LoadingCard"; import Scroll from "../components/Scroll"; import Page, { PageRoot } from "../components/Page"; import AppHeader from "../components/AppHeader"; import AddPlaylistButton from "../components/AddPlaylistButton"; +import { createPlaylist, getPlaylists, Playlist } from "../utils/MusicServer"; +import useForceUpdate from "../hooks/useForceUpdate"; +import PlaylistCard from "../components/PlaylistCard"; +import useQueue from "../hooks/useQueue"; export default function Landing() { const theme = useTheme(); + const queue = useQueue(); + const [playlists, setPlaylists] = useState([]); + + const updatePlaylists = () => { + getPlaylists().then(setPlaylists); + }; const handleCreatePlaylist = (name: string) => { - console.log(`Creating playlist ${name}`); + createPlaylist(name); + updatePlaylists(); }; + useEffect(() => { + updatePlaylists(); + }, [theme]); + return ( - Playlists + {playlists.map( + playlist => ( + { + if (playlist.songs.length === 0) return alert('There are no any songs in this playlist'); + queue?.setSongs(playlist.songs); + }} + /> + ) + )} diff --git a/src/app/pages/Search.tsx b/src/app/pages/Search.tsx index d9927ac..1487473 100644 --- a/src/app/pages/Search.tsx +++ b/src/app/pages/Search.tsx @@ -3,17 +3,19 @@ import { PageRoot } from "../components/Page"; import AppHeader from "../components/AppHeader"; import repeatArray from "../utils/repeatArray"; import { LoadingSearchSongCard } from "../components/LoadingCard"; -import { saveSong, searchSongs } from "../utils/MusicServer"; -import { Box, IconButton, Snackbar } from "@mui/material"; +import { addSong, getPlaylists, Playlist, removeSong, saveSong, searchSongs, Song } from "../utils/MusicServer"; +import { Box, Checkbox, Dialog, DialogContent, DialogTitle, IconButton, List, ListItem, ListItemButton, ListItemText, Snackbar } from "@mui/material"; import { SearchSongCard } from "../components/SongCard"; import useQueue from "../hooks/useQueue"; -import { Close } from "@mui/icons-material"; +import { Check, Close, PlaylistAdd } from "@mui/icons-material"; export default function Search() { const inputRef = useRef(null); const [results, setResults] = useState([]); const queue = useQueue(); const [snackbar, setSnackbar] = useState(null); + const [addTo, setAddTo] = useState(null); + const [playlists, setPlaylists] = useState([]); const onKeyUp = async (evt: KeyboardEvent) => { if (evt.key !== 'Enter') return; const q = inputRef.current?.value; @@ -35,6 +37,14 @@ export default function Search() { queue?.addSong(song); setSnackbar(`Added "${song.name}" to queue.`); }} + controls={ + { + setAddTo(song); + getPlaylists().then(setPlaylists); + }}> + + + } /> ); } @@ -43,6 +53,37 @@ export default function Search() { return ( <> + setAddTo(null)}> + + Add to playlist + + + + {playlists.map(x => { + const added = x.songs.find(y => y.videoId === addTo?.videoId) ? true : false; + return ( + + { + if (!addTo) return; + if (added) { + removeSong(x.id, addTo); + } else { + addSong(x.id, addTo); + setAddTo(null); + } + }} + checked={added} + /> + + {x.name} + + + ) + })} + + + { - return (await doPost(`/auth/register`, {username, password})).token as string; + return (await doPost(`/auth/register`, { username, password })).token as string; } export async function login(username?: string, password?: string): Promise { - return (await doPost(`/auth/login`, {username, password})).token as string; + return (await doPost(`/auth/login`, { username, password })).token as string; } export async function getLyrics(song: Song): Promise {