Skip to main content

module salix::demo::shop::Shop

rascal-0.34.0
salix-core-0.2.3

Usage

import salix::demo::shop::Shop;

Source code

http://github.com/usethesource/salix-core/src/main/rascal/salix/demo/shop/Shop.rsc

Dependencies

import salix::HTML;
import salix::App;
import salix::Index;
import String;
import List;
import util::UUID;

data Article

data Article  
= article(str name, real price, loc id, str newName = "", real newPrice = 0.0)
;

data Entry

data Entry  
= entry(loc id, int amount)
;

alias Cart

list[Entry]

alias Model

tuple[   list[Article] articles,    Cart cart,   str newName,   real newPrice ]

function init

Model init() = <
[Article::article("Funny Bunnies", 17.63, bunnyId),
Article::article("Awesome React", 23.95, uuid()),
Article::article("Second hand Netbook", 50.00, uuid())],
[entry(bunnyId, 1)],
"",
0.0
>
when loc bunnyId := uuid();

function shopApp

SalixApp[Model] shopApp(str id = "shopDemo") 
= makeApp(id, init, withIndex("Shop", id, shopDemoView, css = ["/salix/demo/shop/test.css"]), update);

function shopWebApp

App[Model] shopWebApp()
= webApp(
shopApp(),
|project://salix/src/main/rascal|
);

data Msg

data Msg  
= editName(int idx, str name)
| editPrice(int idx, str price)
| save(int idx)
| addToCart(int idx)
| removeFromCart(int idx)
| newPrice(str price)
| newName(str name)
| newArticle()
| updateSome()
| createLots()
;

function editName

Msg(str) editName(int idx) = Msg(str s) { return editName(idx, s); };

function editPrice

Msg(str) editPrice(int idx) = Msg(str s) { return editPrice(idx, s); };

function findArticle

Article findArticle(loc id, Model m) = [ a | Article a <- m.articles, a.id == id][0];

function update

Model update(Msg msg, Model m) {
switch (msg) {

case editName(int idx, str name):
m.articles[idx].newName = name;

case editPrice(int idx, str price):
m.articles[idx].newPrice = toReal(price);

case save(int idx): {
m.articles[idx].price = m.articles[idx].newPrice;
m.articles[idx].name = m.articles[idx].newName;
}

case addToCart(int idx): {
Article a = m.articles[idx];
if (int i <- [0..size(m.cart)], m.cart[i].id == a.id) {
m.cart[i] = m.cart[i][amount = m.cart[i].amount + 1];
}
else {
m.cart += [entry(m.articles[idx].id, 1)];
}
}

case removeFromCart(int idx): {
Entry e = m.cart[idx];
if (e.amount == 1) {
m.cart = delete(m.cart, idx);
}
else {
e.amount -= 1;
m.cart[idx] = e;
}
}

case newPrice(str price):
m.newPrice = toReal(price);

case newName(str name):
m.newName = name;

case newArticle():
m.articles += [Article::article(m.newName, m.newPrice, uuid())];
}

return m;
}

function shopDemoView

void shopDemoView(Model m) {
div(id("header"), () {
h1("Salix shopping cart demo");
});
table(() {
tbody(() {
tr(() {
td(colspan(2), () {
button(onClick(updateSome()), "update some items");
button(onClick(createLots()), "create a lot of items");
});
});
tr(() {
td(() {
h2("Available items");
articlesView(m);
});
td(() {
h2("Your shopping cart");
cartView(m);
});
});
});
});
}

function articlesView

void articlesView(Model m) {
div(() {
p("Article name ");
input(\type("text"), \value(m.newName), onInput(newName));
p("Price (a number) ");
input(\type("text"), \value("<m.newPrice>"), onInput(newPrice));
button(onClick(newArticle()), "new article");
ul(() {
for (int i <- [0..size(m.articles)]) {
articleView(m.articles[i], i);
}
});
});
}

function articleView

void articleView(Article a, int i) {
li(() {
span(a.name);
button(onClick(addToCart(i)), "\>\>");
span(class("price"), "€ <a.price>");
});
}

function cartView

void cartView(Model m) {
div(() {
ul(() {
for (int i <- [0..size(m.cart)]) {
li(() {
button(onClick(removeFromCart(i)), "\<\<");
span(findArticle(m.cart[i].id, m).name);
span(class("price"), "<m.cart[i].amount>x");
});
}
});
real total = ( 0.0 | it + e.amount * findArticle(e.id, m).price | Entry e <- m.cart);
span("Total: € <total>");
});
}