Compare commits

...

3 commits

Author SHA1 Message Date
Yash Karandikar b3f1d08ecf Various UX changes 2022-04-23 16:23:33 -05:00
Yash Karandikar ebd0c3846a Deck editor + export 2022-04-23 16:02:59 -05:00
Yash Karandikar d615c25ec2 Import decks to use 2022-04-23 15:10:51 -05:00
4 changed files with 122 additions and 7 deletions

View file

@ -12,6 +12,6 @@ getrandom = { version = "0.2.6", features = ["js"] }
rand = "0.8.5"
serde = { version = "1.0.136", features = ["derive"] }
serde_json = "1.0.79"
sycamore = "0.8.0-beta.3"
sycamore = "0.8.0-beta.4"
wasm-bindgen = "0.2.80"
web-sys = "0.3.57"

View file

@ -3,3 +3,7 @@ function get_token() {
let token = params.get("deck");
return token;
}
function set_location(l) {
window.location = l;
}

View file

@ -43,6 +43,9 @@ struct Card {
}
wasm_import!(get_token() -> Option<String>);
wasm_import!(prompt(s: &str) -> Option<String>);
wasm_import!(set_location(l: &str));
wasm_import!(alert(s: &str));
wasm_import_with_ns!(console, log(s: &str));
#[component]
@ -57,8 +60,10 @@ fn CardsComponent<G: Html>(ctx: Scope) -> View<G> {
let recompute_current = move |_| {
let prev = *current.get();
let mut genned = rand::thread_rng().gen_range(0..deck_len);
while genned == prev {
genned = rand::thread_rng().gen_range(0..deck_len);
if deck_len > 1 {
while genned == prev {
genned = rand::thread_rng().gen_range(0..deck_len);
}
}
current.set(genned);
@ -75,8 +80,11 @@ fn CardsComponent<G: Html>(ctx: Scope) -> View<G> {
elem.class_list().toggle("flip").unwrap();
};
let go_home = |_| set_location("/");
view! {ctx,
div(class="text-align-center") {
button(on:click=go_home) { "Home" }
button(on:click=recompute_current) { "Next" }
}
({
@ -97,6 +105,98 @@ fn CardsComponent<G: Html>(ctx: Scope) -> View<G> {
}
}
#[component]
fn CreatorComponent<G: Html>(ctx: Scope) -> View<G> {
let do_import = |_| {
let p = prompt("Deck code:");
if let Some(inp) = p {
let stripped = inp
.chars()
.filter(|c| !c.is_whitespace())
.collect::<String>();
let f = format!("/?deck={}", stripped);
set_location(&f);
}
};
let front = create_signal(ctx, String::new());
let back = create_signal(ctx, String::new());
let error_empty = create_signal(ctx, false);
let error_parse = create_signal(ctx, false);
let cards = create_signal(ctx, Vec::new());
let do_add = |_| {
let f = (*front.get()).clone();
let b = (*back.get()).clone();
if f.is_empty() || b.is_empty() {
error_empty.set(true);
return;
}
let c = Card { front: f, back: b };
if !cards.get().contains(&c) {
cards.modify().push(c);
front.set(String::new());
back.set(String::new());
} // skip duplicate cards
};
let do_export = |_| {
let d = Deck((*cards.get()).clone());
if d.is_empty() {
return;
}
let r = serde_json::to_string(&d);
if let Ok(s) = r {
error_parse.set(false);
let e = base64::encode(s.as_bytes());
let f = format!("Your deck code is: {}", e);
alert(&f);
} else {
error_parse.set(true);
}
};
view! {ctx,
div(class="text-align-center") {
button(on:click=do_import) {"Import"}
button(on:click=do_export) {"Export"}
br
input(bind:value=front)
input(bind:value=back)
(if *error_empty.get() {
view! {ctx, p(style="color: red") {"Make sure none of the inputs are empty!"}}
} else {
view! {ctx,}
})
(if *error_parse.get() {
view! {ctx, p(style="color: red") {"Something went wrong. Please try again."}}
} else {
view! {ctx,}
})
button(on:click=do_add) {"Add"}
Indexed {
iterable: cards,
view: |ctx, card| view! {ctx,
div(class="card", style="background-color: white;") {
"Front:"
(card.front)
br
"Back:"
(card.back)
}
}
}
}
}
}
fn main() {
console_error_panic_hook::set_once();
sycamore::render(|ctx| {
@ -104,11 +204,9 @@ fn main() {
div(class="wrapper") {
h1(class="text-align-center") { "Quicksilver" }
(if get_token().is_some() {
view! {ctx, CardsComponent {
}}
view! {ctx, CardsComponent {}}
} else {
view! {ctx, }
view! {ctx, CreatorComponent {}}
})
}
}

View file

@ -25,6 +25,19 @@ button:active {
background-color: #00008B;
}
button + button {
margin-left: 10px;
}
input {
width: 100%;
margin: 5px;
border-radius: 5px;
border: 1px solid black;
padding: 5px
}
.card {
height: 100%;
width: 100%;