git.fiddlerwoaroof.com
react-demo/render.js
cc733b08
 import React from "react";
 import * as gf from "../src/genfuns";
 import * as m from "./Model";
a00b5a50
 
 class Summary {
cc733b08
   constructor(wrapper = "span") {
a00b5a50
     this.wrapper = wrapper;
   }
 }
cc733b08
 class Detail {}
a00b5a50
 
cc733b08
 const total_receipt = items =>
   items.reduce((acc, item) => acc + item.subtotal, 0);
a00b5a50
 const subtotal = items => items.reduce((acc, item) => acc + item.price, 0);
 const total_tax = items => items.reduce((acc, item) => acc + item.tax, 0);
 
 const display_money = amount => amount.toFixed(2);
 
 const ItemLabel = ({ desc, amount, wrapper, ...restProps }) =>
cc733b08
   React.createElement(wrapper, restProps, [
     <span className="desc" key="0">
       {" "}
       {desc}:{" "}
     </span>,
     <span className="price" key="1">
       {display_money(amount)}
     </span>,
   ]);
a00b5a50
 
cc733b08
 export const Items = gf
   .defgeneric("Items", "animaltorender")
a00b5a50
   .primary([gf.Shape("items", "view")], ({ items, view }) => Items(items, view))
   .primary([Array, Summary], (items, view) => (
     <>
cc733b08
       <ItemLabel
         desc="Subtotal"
         amount={subtotal(items)}
         wrapper={view.wrapper}
       />
a00b5a50
       <ItemLabel desc="Tax" amount={total_tax(items)} wrapper={view.wrapper} />
cc733b08
       <ItemLabel
         desc="Total"
         amount={total_receipt(items)}
         wrapper={view.wrapper}
       />
a00b5a50
     </>
   ))
   .primary([Array, Detail], items => (
     <ul>
cc733b08
       {items.map(
         (a, idx) => (
           <Item item={a} key={idx} />
         ),
         items
       )}
       <Items items={items} view={new Summary("li")} />
a00b5a50
     </ul>
cc733b08
   )).fn;
a00b5a50
 
cc733b08
 export const Item = gf
   .defgeneric("Item", "itemtorender")
a00b5a50
   .primary([gf.Shape("item")], ({ item }) => Item(item))
   .around([m.Item], function (_) {
     const [desc, price] = this.call_next_method();
cc733b08
     return <ItemLabel desc={desc} amount={price} wrapper="li" />;
a00b5a50
   })
   .primary([m.NonFood], item => ["Non-food Item", item.price])
   .primary([m.NormalFood], item => ["Food", item.price])
cc733b08
   .primary([m.AlcoholicBeverage], item => ["Alcohol", item.price]).fn;
a00b5a50
 
cc733b08
 export const Receipt = ({ items }) => (
a00b5a50
   <div>
cc733b08
     <h1>
       <Items {...{ items }} view={new Summary()} />
     </h1>
a00b5a50
     <Items {...{ items }} view={new Detail()} />
   </div>
 );