started work on playlist ui
This commit is contained in:
@ -71,3 +71,31 @@ pub async fn get_playlists() -> Result<Vec<Playlist>, ServerFnError> {
|
|||||||
|
|
||||||
Ok(results)
|
Ok(results)
|
||||||
}
|
}
|
||||||
|
/// Add a song to a playlist
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `playlist_id` - The id of the playlist
|
||||||
|
/// * `song_id` - The id of the song
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// * `Result<(), ServerFnError>` - An empty result if successful, or an error
|
||||||
|
///
|
||||||
|
#[server(endpoint = "playlists/add-song")]
|
||||||
|
pub async fn add_song(new_playlist_id: Option<i32>, new_song_id: Option<i32>) -> Result<(), ServerFnError> {
|
||||||
|
use crate::schema::playlist_songs::dsl::*;
|
||||||
|
use leptos::server_fn::error::NoCustomError;
|
||||||
|
|
||||||
|
let other_playlist_id = new_playlist_id.ok_or(ServerFnError::<NoCustomError>::ServerError("Playlist id must be present (Some) to add song".to_string()))?;
|
||||||
|
|
||||||
|
let other_song_id = new_song_id.ok_or(ServerFnError::<NoCustomError>::ServerError("Song id must be present (Some) to add song".to_string()))?;
|
||||||
|
|
||||||
|
let db_con = &mut get_db_conn();
|
||||||
|
diesel::insert_into(playlist_songs)
|
||||||
|
.values((playlist_id.eq(other_playlist_id), song_id.eq(other_song_id)))
|
||||||
|
.execute(db_con)
|
||||||
|
.map_err(|e| ServerFnError::<NoCustomError>::ServerError(format!("Error adding song to playlist: {}", e)))?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
@ -3,6 +3,7 @@ use leptos::*;
|
|||||||
use leptos_icons::*;
|
use leptos_icons::*;
|
||||||
use crate::api::playlists::create_playlist;
|
use crate::api::playlists::create_playlist;
|
||||||
use crate::api::playlists::get_playlists;
|
use crate::api::playlists::get_playlists;
|
||||||
|
use crate::models::Playlist;
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn Sidebar(setter: WriteSignal<bool>, active: ReadSignal<bool>) -> impl IntoView {
|
pub fn Sidebar(setter: WriteSignal<bool>, active: ReadSignal<bool>) -> impl IntoView {
|
||||||
@ -66,10 +67,8 @@ pub fn Bottom() -> impl IntoView {
|
|||||||
<CreatePlayList opened=create_playlist_open closer=set_create_playlist_open/>
|
<CreatePlayList opened=create_playlist_open closer=set_create_playlist_open/>
|
||||||
<ul class="playlists">
|
<ul class="playlists">
|
||||||
{
|
{
|
||||||
move || playlists.get().iter().map(|playlist| view! {
|
move || playlists.get().iter().enumerate().map(|(index,playlist)| view! {
|
||||||
<div class="playlist">
|
<Playlist playlist=playlist.clone() />
|
||||||
<h1 class="name">{playlist.name.clone()}</h1>
|
|
||||||
</div>
|
|
||||||
}).collect::<Vec<_>>()
|
}).collect::<Vec<_>>()
|
||||||
}
|
}
|
||||||
</ul>
|
</ul>
|
||||||
@ -116,4 +115,20 @@ pub fn CreatePlayList(opened: ReadSignal<bool>,closer: WriteSignal<bool>) -> imp
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
#[component]
|
||||||
|
pub fn Playlist(playlist: Playlist) -> impl IntoView {
|
||||||
|
let (show_playlist, set_show_playlist) = create_signal(false);
|
||||||
|
|
||||||
|
view! {
|
||||||
|
<div class="playlist" on:click=move|_| set_show_playlist.update(|value| *value=true) >
|
||||||
|
<h1 class="name">{playlist.name.clone()}</h1>
|
||||||
|
<div class="playlist-container" style={move || if show_playlist() {"display: flex"} else {"display: none"}}>
|
||||||
|
<div class="close-button" on:click=move |_| set_show_playlist.update(|value| *value = false)>
|
||||||
|
<Icon icon=icondata::IoCloseSharp />
|
||||||
|
</div>
|
||||||
|
<h1>{playlist.name.clone()}</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
}
|
}
|
@ -320,7 +320,6 @@ impl Playlist {
|
|||||||
#[cfg(feature = "ssr")]
|
#[cfg(feature = "ssr")]
|
||||||
pub fn create_playlist(new_playlist: Playlist, conn: &mut PgPooledConn) -> Result<(), Box<dyn Error>> {
|
pub fn create_playlist(new_playlist: Playlist, conn: &mut PgPooledConn) -> Result<(), Box<dyn Error>> {
|
||||||
use crate::schema::playlists::dsl::*;
|
use crate::schema::playlists::dsl::*;
|
||||||
use crate::models::Playlist;
|
|
||||||
|
|
||||||
let new_playlist = Playlist {
|
let new_playlist = Playlist {
|
||||||
..new_playlist
|
..new_playlist
|
||||||
|
@ -178,6 +178,37 @@
|
|||||||
margin-top: 0.5rem;
|
margin-top: 0.5rem;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
.playlist-container {
|
||||||
|
background-color: red;
|
||||||
|
width: 10rem;
|
||||||
|
height: 10rem;
|
||||||
|
position: fixed;
|
||||||
|
top: 40%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
|
||||||
|
.close-button {
|
||||||
|
position: absolute;
|
||||||
|
top: 5px;
|
||||||
|
right: 5px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 50%;
|
||||||
|
font-size: 1.6rem;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-button:hover {
|
||||||
|
transform: scale(1.1);
|
||||||
|
background-color: rgba(255, 255, 255, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-button:active {
|
||||||
|
transform: scale(0.8);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.playlist:hover {
|
.playlist:hover {
|
||||||
background-color: #adadad36;
|
background-color: #adadad36;
|
||||||
|
Reference in New Issue
Block a user