union_table/
union_table.rs1use html_export::composed::table::from_iterator;
2use html_export::composed::table::AsTable;
3use html_export::elem;
4use html_export::element::*;
5use html_export::head::Head;
6use html_export::tags::*;
7use html_export::thead;
8use html_export::*;
9extern crate html_export;
10
11pub enum Item {
12 BasicItem(BasicItem),
13 DiscountedItem(DiscountedItem),
14}
15
16pub struct BasicItem {
17 name: String,
18 unit_price: f64,
19 quantity: u64,
20}
21
22pub struct DiscountedItem {
23 name: String,
24 unit_price: f64,
25 quantity: u64,
26 unit_discount: f64,
27}
28
29impl BasicItem {
30 pub fn new(name: String, unit_price: f64, quantity: u64) -> Self {
31 Self {
32 name,
33 unit_price,
34 quantity,
35 }
36 }
37
38 pub fn as_row(&self) -> Option<Element> {
39 let mut row = tr!();
40 row += td!() + Element::Text(self.name.clone());
41 row +=
42 td!(attributes = {"colspan" => Some("2")}) + Element::Text(self.unit_price.to_string());
43 row += td!() + Element::Text(self.quantity.to_string());
44 row += td!(attributes = {"colspan" => Some("3")})
45 + Element::Text((self.unit_price * (self.quantity as f64)).to_string());
46 Some(row)
47 }
48}
49
50impl DiscountedItem {
51 pub fn new(name: String, unit_price: f64, quantity: u64, unit_discount: f64) -> Self {
52 Self {
53 name,
54 unit_price,
55 quantity,
56 unit_discount,
57 }
58 }
59 pub fn as_row(&self) -> Option<Element> {
60 let mut row = tr!();
61 row += td!() + Element::Text(self.name.clone());
62 row += td!() + Element::Text(self.unit_price.to_string());
63 row += td!() + Element::Text(self.unit_discount.to_string());
64 row += td!() + Element::Text(self.quantity.to_string());
65 row += td!() + Element::Text((self.unit_price * (self.quantity as f64)).to_string());
66 row += td!() + Element::Text((self.unit_discount * (self.quantity as f64)).to_string());
67 row += td!()
68 + Element::Text(
69 (self.unit_price * (self.quantity as f64)
70 - self.unit_discount * (self.quantity as f64))
71 .to_string(),
72 );
73 Some(row)
74 }
75}
76
77impl AsTable for Item {
78 fn as_table_head(&self) -> Option<html_export::element::Element> {
79 let heading =
80 tr!() + (th!(attributes = {"colspan" => Some("7")}) + (h2!() + text!("Items")));
81 let mut sub_heading = tr!();
82 let mut sub_sub_heading = tr!();
83 sub_heading += th!(attributes = {"rowspan" => Some("2")}) + text!("Name");
84 sub_heading += th!(attributes = {"colspan" => Some("2")}) + text!("Unitary");
85 sub_heading += th!(attributes = {"rowspan" => Some("2")}) + text!("Quantity");
86 sub_heading += th!(attributes = {"colspan" => Some("3")}) + text!("Totals");
87 sub_sub_heading += th!() + text!("Unit price");
88 sub_sub_heading += th!() + text!("Unit discount");
89 sub_sub_heading += th!() + text!("Price");
90 sub_sub_heading += th!() + text!("Discount");
91 sub_sub_heading += th!() + text!("Result");
92
93 Some(thead!() + heading + sub_heading + sub_sub_heading)
94 }
95
96 fn as_table_row(&self) -> Option<html_export::element::Element> {
97 match self {
98 Item::BasicItem(basic_item) => basic_item.as_row(),
99 Item::DiscountedItem(discounted_item) => discounted_item.as_row(),
100 }
101 }
102
103 fn as_table_foot(&self) -> Option<html_export::element::Element> {
104 None
105 }
106}
107
108fn main() {
109 let items = vec![
110 Item::BasicItem(BasicItem::new("Item A".to_string(), 10.0, 3)),
111 Item::BasicItem(BasicItem::new("Item B".to_string(), 11.0, 2)),
112 Item::DiscountedItem(DiscountedItem::new("Item C".to_string(), 20.0, 5, 5.0)),
113 Item::DiscountedItem(DiscountedItem::new("Item D".to_string(), 5.0, 1, 10.0)),
114 Item::BasicItem(BasicItem::new("Item E".to_string(), 100.0, 1)),
115 ];
116 let table = from_iterator(
117 &items,
118 HtmlElementConfig::new_empty(),
119 HtmlElementConfig::new_empty(),
120 )
121 .unwrap();
122 let head = Head::new().with_title("Union table".to_string());
123 export_to_file(
124 "examples_output".to_string(),
125 "union_tables.html".to_string(),
126 head,
127 vec![table],
128 )
129 .unwrap();
130}