create artist

This commit is contained in:
Danny Zou 2024-05-21 22:39:56 -04:00
parent 3ce762ce5b
commit fcc5870824
8 changed files with 190 additions and 38 deletions

39
src/api/artists.rs Normal file
View File

@ -0,0 +1,39 @@
use leptos::*;
use crate::models::Artist;
use cfg_if::cfg_if;
cfg_if! {
if #[cfg(feature = "ssr")] {
use crate::database::get_db_conn;
use diesel::prelude::*;
}
}
/// Add an artist to the database
///
/// # Arguments
///
/// * `artist_name` - The name of the artist to add
///
/// # Returns
/// * `Result<(), Box<dyn Error>>` - A empty result if successful, or an error
///
#[server(endpoint = "artists/add-artist")]
pub async fn add_artist(artist_name: String) -> Result<(), ServerFnError> {
use crate::schema::artists::dsl::*;
use leptos::server_fn::error::NoCustomError;
let new_artist = Artist {
id: None,
name: artist_name,
};
let db = &mut get_db_conn();
diesel::insert_into(artists)
.values(&new_artist)
.execute(db)
.map_err(|e| ServerFnError::<NoCustomError>::ServerError(format!("Error creating playlist: {}", e)))?;
Ok(())
}

1
src/api/mod.rs Normal file
View File

@ -0,0 +1 @@
pub mod artists;

View File

@ -63,6 +63,7 @@ use crate::components::dashboard::*;
use crate::components::search::*; use crate::components::search::*;
use crate::components::personal::*; use crate::components::personal::*;
use crate::components::upload::*; use crate::components::upload::*;
use crate::components::add_artist::AddArtist;
/// Renders the home page of your application. /// Renders the home page of your application.
#[component] #[component]
@ -70,6 +71,7 @@ fn HomePage(play_status: RwSignal<PlayStatus>, upload_open: RwSignal<bool>, add_
view! { view! {
<div class="home-container"> <div class="home-container">
<Upload open=upload_open/> <Upload open=upload_open/>
<AddArtist open=add_artist_open/>
<Sidebar upload_open=upload_open add_artist_open=add_artist_open add_album_open=add_album_open/> <Sidebar upload_open=upload_open add_artist_open=add_artist_open add_album_open=add_album_open/>
// This <Outlet /> will render the child route components // This <Outlet /> will render the child route components
<Outlet /> <Outlet />

View File

@ -1,15 +1,42 @@
use leptos::*; use leptos::*;
use leptos::leptos_dom::log;
use leptos_icons::*; use leptos_icons::*;
use crate::api::artists::add_artist;
#[component] #[component]
pub fn AddArtistBtn(add_artist_open: RwSignal<bool>) -> impl IntoView { pub fn AddArtistBtn(add_artist_open: RwSignal<bool>) -> impl IntoView {
let open_dialog = move |_| { let open_dialog = move |_| {
add_artist_open.set(true); add_artist_open.set(true);
}; };
view! { view! {
<button class="add-artist-btn add-btns" on:click=open_dialog> <button class="add-artist-btn add-btns" on:click=open_dialog>
Add Artist Add Artist
</button> </button>
} }
} }
#[component]
pub fn AddArtist(open: RwSignal<bool>) -> impl IntoView {
let close_dialog = move |ev: leptos::ev::MouseEvent| {
ev.prevent_default();
open.set(false);
};
view! {
<Show when=open fallback=move|| view!{}>
<div class="add-artist-container">
<div class="upload-header">
<h1>Add Artist</h1>
</div>
<div class="close-button" on:click=close_dialog><Icon icon=icondata::IoClose /></div>
<form class="create-artist-form" action="POST">
<div class="input-bx">
<input type="text" name="title" required class="text-input" required/>
<span>Artist Name</span>
</div>
<button type="submit" class="upload-button">Add</button>
</form>
</div>
</Show>
}
}

View File

@ -15,6 +15,7 @@ pub mod fileserv;
pub mod error_template; pub mod error_template;
pub mod upload; pub mod upload;
pub mod util; pub mod util;
pub mod api;
use cfg_if::cfg_if; use cfg_if::cfg_if;

112
style/addArtist.scss Normal file
View File

@ -0,0 +1,112 @@
@import "theme.scss";
.add-artist-container {
position: fixed;
top: 45%;
left: 50%;
transform: translate(-50%, -50%);
width: 30rem;
height: 15rem;
border: 1px solid white;
border-radius: 5px;
padding: 1rem;
padding-top: 0;
z-index: 2;
display: flex;
flex-direction: column;
background-color: #1c1c1c;
.upload-header {
font-size: .7rem;
font-weight: 300;
padding-bottom: 0;
border-bottom: 1px solid white;
font-family: "Roboto", sans-serif;
}
.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;
border: none;
}
.close-button:hover {
transform: scale(1.1);
background-color: rgba(255, 255, 255, 0.1);
}
.close-button:active {
transform: scale(0.8);
}
.create-artist-form {
width:100%;
height: 100%;
position: relative;
.input-bx{
margin-top: 1rem;
width: 300px;
input{
width: 100%;
padding: 10px;
border: 2px solid #7f8fa6;
border-radius: 5px;
outline: none;
font-size: 1rem;
transition: 0.6s;
background-color: transparent;
}
span{
position: absolute;
left: 0;
padding: 10px;
font-size: 1rem;
color: #7f8fa6;
text-transform: uppercase;
pointer-events: none;
transition: 0.6s;
background-color: transparent;
}
input:valid ~ span,
input:focus ~ span{
color: #fff;
transform: translateX(10px) translateY(-7px);
font-size: 0.65rem;
font-weight: 600;
padding: 0 10px;
background: #1c1c1c;
letter-spacing: 0.1rem;
}
input:valid,
input:focus{
color: #fff;
border: 2px solid #fff;
}
}
.upload-button {
position: absolute;
bottom: 5px;
margin-top: 1rem;
padding: 10px;
background-color: #7f8fa6;
color: #fff;
width: 100%;
font-size: 1rem;
font-family: "Roboto", sans-serif;
border: none;
border-radius: 5px;
cursor: pointer;
transition: 0.3s;
&:hover {
background-color: #fff;
color: #7f8fa6;
}
}
}
}

View File

@ -9,6 +9,7 @@
@import 'search.scss'; @import 'search.scss';
@import 'personal.scss'; @import 'personal.scss';
@import 'upload.scss'; @import 'upload.scss';
@import 'addArtist.scss';
body { body {
font-family: sans-serif; font-family: sans-serif;

View File

@ -27,9 +27,7 @@
font-size: 1.6rem; font-size: 1.6rem;
transition: all 0.3s; transition: all 0.3s;
border: none; border: none;
} }
.close-button:hover { .close-button:hover {
transform: scale(1.1); transform: scale(1.1);
background-color: rgba(255, 255, 255, 0.1); background-color: rgba(255, 255, 255, 0.1);
@ -48,6 +46,9 @@
padding: .1rem; padding: .1rem;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
width: 100%;
height: 100%;
position: relative;
.input-bx{ .input-bx{
margin-top: 1rem; margin-top: 1rem;
position: relative; position: relative;
@ -90,42 +91,10 @@
border: 2px solid #fff; border: 2px solid #fff;
} }
} }
.release-date {
margin-top: 1rem;
font-size: 1.2rem;
color: #7f8fa6;
font-family: "Roboto", sans-serif;
display: flex;
align-items: center;
.left {
display: flex;
flex-direction: column;
margin-left: 5px;
margin-right: 10px;
}
span {
font-size: .85rem;
}
input {
padding: 8px;
}
}
.file {
margin-top: .5rem;
display: flex;
align-items: center;
span {
font-size: .9rem;
color: #7f8fa6;
font-family: "Roboto", sans-serif;
margin-left: 5px;
margin-right: 10px;
}
input {
padding: 10px;
}
}
.upload-button { .upload-button {
position: absolute;
bottom: 5px;
width: 100%;
margin-top: 1rem; margin-top: 1rem;
padding: 10px; padding: 10px;
background-color: #7f8fa6; background-color: #7f8fa6;