Render products page

This commit is contained in:
~erin 2022-04-01 13:01:43 -04:00
parent 3928f50be5
commit 1a1a5a3451
No known key found for this signature in database
GPG Key ID: DA70E064A8C70F44
2 changed files with 169 additions and 29 deletions

View File

@ -1,3 +1,5 @@
use crate::database::read_all_products;
use crate::structures::{Product, ProductClass};
use serde::{Deserialize, Serialize};
use std::io::{Read, Write};
use std::sync::atomic::{AtomicBool, Ordering};
@ -39,7 +41,14 @@ struct Page {
title: String,
}
pub fn render_pages() {
struct PageBase {
config: Config,
tera: Tera,
nav_elements: Vec<NavLink>,
product_classes: Vec<NavLink>,
}
fn build_base() -> PageBase {
// Read in TOML
let mut config_file = std::fs::File::open("config.toml").unwrap();
let mut contents = String::new();
@ -58,22 +67,22 @@ pub fn render_pages() {
// Setup basic elements
let nav_home = NavLink {
href: config.index.href,
href: config.index.href.clone(),
text: config.index.label.clone(),
active: AtomicBool::new(true),
};
let nav_about = NavLink {
href: config.about.href,
href: config.about.href.clone(),
text: config.about.label.clone(),
active: AtomicBool::new(false),
};
let nav_products = NavLink {
href: config.products.href,
href: config.products.href.clone(),
text: config.products.label.clone(),
active: AtomicBool::new(false),
};
let nav_contact = NavLink {
href: config.contact.href,
href: config.contact.href.clone(),
text: config.contact.label.clone(),
active: AtomicBool::new(false),
};
@ -81,66 +90,99 @@ pub fn render_pages() {
let nav_elements = vec![nav_home, nav_about, nav_products, nav_contact];
let estrogens = NavLink {
href: config.products.estrogens.href,
href: config.products.estrogens.href.clone(),
text: config.products.estrogens.label.clone(),
active: AtomicBool::new(false),
};
let aa = NavLink {
href: config.products.anti_androgens.href,
href: config.products.anti_androgens.href.clone(),
text: config.products.anti_androgens.label.clone(),
active: AtomicBool::new(false),
};
let progestogens = NavLink {
href: config.products.progestogens.href,
href: config.products.progestogens.href.clone(),
text: config.products.progestogens.label.clone(),
active: AtomicBool::new(false),
};
let product_classes = vec![estrogens, aa, progestogens];
return PageBase {
config,
tera,
nav_elements,
product_classes,
};
}
pub fn render_pages() {
let base = build_base();
// Render pages
let index_render = RenderObject {
url: "index.html".to_string(),
tera: tera.clone(),
subtitle: &config.index.title,
active_page: &config.index.label,
title: &config.title,
description: &config.description,
tera: base.tera.clone(),
subtitle: &base.config.index.title,
active_page: &base.config.index.label,
title: &base.config.title,
description: &base.config.description,
products: None,
};
render_page(
// Home
index_render,
&nav_elements,
&product_classes,
&base.nav_elements,
&base.product_classes,
);
let about_render = RenderObject {
url: "about/index.html".to_string(),
tera: tera.clone(),
subtitle: &config.about.title,
active_page: &config.about.label,
title: &config.title,
description: &config.description,
tera: base.tera.clone(),
subtitle: &base.config.about.title,
active_page: &base.config.about.label,
title: &base.config.title,
description: &base.config.description,
products: None,
};
render_page(
// About
about_render,
&nav_elements,
&product_classes,
&base.nav_elements,
&base.product_classes,
);
let contact_render = RenderObject {
url: "contact/index.html".to_string(),
tera: tera.clone(),
subtitle: &config.contact.title,
active_page: &config.contact.label,
title: &config.title,
description: &config.description,
tera: base.tera.clone(),
subtitle: &base.config.contact.title,
active_page: &base.config.contact.label,
title: &base.config.title,
description: &base.config.description,
products: None,
};
render_page(
// About
contact_render,
&nav_elements,
&product_classes,
&base.nav_elements,
&base.product_classes,
);
let products_vec: Option<Vec<Product>>;
match read_all_products() {
Ok(prods) => products_vec = Some(prods),
Err(err) => products_vec = None,
}
let products_render = RenderObject {
url: "products/index.html".to_string(),
tera: base.tera.clone(),
subtitle: &base.config.products.title,
active_page: &base.config.products.label,
title: &base.config.title,
description: &base.config.description,
products: products_vec,
};
render_page(
// Products
products_render,
&base.nav_elements,
&base.product_classes,
);
}
@ -151,12 +193,14 @@ struct RenderObject<'a> {
active_page: &'a str,
title: &'a str,
description: &'a str,
products: Option<Vec<Product>>,
}
fn render_page(data: RenderObject, nav_elements: &[NavLink], product_classes: &[NavLink]) {
let mut output_file =
std::fs::File::create(format!("static/{}", data.url)).expect("create failed");
// Change the active NavLink
for i in nav_elements {
if i.text == data.active_page {
i.active.store(true, Ordering::Relaxed);
@ -165,10 +209,12 @@ fn render_page(data: RenderObject, nav_elements: &[NavLink], product_classes: &[
}
}
// Create the context
let mut context = Context::new();
context.insert("title", data.title);
context.insert("description", data.description);
context.insert("subtitle", &data.subtitle);
// Insert navigation elements
for i in nav_elements {
context.insert(&i.text.to_ascii_lowercase(), &i);
}
@ -178,7 +224,25 @@ fn render_page(data: RenderObject, nav_elements: &[NavLink], product_classes: &[
} else {
context.insert("is_contact", &false);
}
// Fill out products page
match data.products {
None => info!("no product"),
Some(p) => {
let mut estrogens = Vec::new();
let mut anti_androgens = Vec::new();
for i in p {
match i.class {
ProductClass::Estrogens => estrogens.push(i),
ProductClass::AntiAndrogens => anti_androgens.push(i),
ProductClass::Progestogens => todo!(),
}
}
context.insert("estrogens", &estrogens);
context.insert("anti_androgens", &anti_androgens);
}
}
// Write it to the file
output_file
.write_all(data.tera.render(&data.url, &context).unwrap().as_bytes())
.expect("write failed");

View File

@ -0,0 +1,76 @@
<!DOCTYPE html>
<html lang="en">
<head>
{# head content #}
<title>{{ title }}</title>
<!-- css style -->
<link rel="preload" href="/style.css" as="style">
<link rel="stylesheet" href="/style.css">
<!-- metadata -->
<meta charset="UTF-8">
<meta name="description" content="{{ description }}">
<!-- link preview card -->
<meta name="og:title" content="{{ title }}">
<meta name="twitter:title" content="{{ title }}">
<meta name="og:description" content="{{ description }}">
<meta name="twitter:description" content="{{ description }}">
<!-- display settings & favicon -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="/assets/pill.svg">
</head>
<body>
<h1>{{ title }}</h1>
{# Navigation #}
<nav class="menu">
<ul>
<li><a {% if home.active %}class="active"{% endif %} href="{{ home.href }}">{{ home.text }}</a></li>
<li><a {% if about.active %}class="active"{% endif %} href="{{ about.href }}">{{ about.text }}</a></li>
<li class="dropdown">
<a {% if products.active %}class="active"{% endif %} href="{{ products.href }}" class="dropbtn">{{ products.text }}</a>
<div class="dropdown-content">
{% for product in product_classes %}
<a href="{{product.href}}">{{product.text}}</a>
{% endfor %}
</div>
</li>
<li><a {% if contact.active %}class="active"{% endif %} href="{{ contact.href }}">{{ contact.text }}</a></li>
</ul>
</nav>
<h2>{{ subtitle }}</h2>
{# articles #}
{% if estrogens %}
<h3 id="estrogens">Estrogens</h3>
<div class="images">
{% for product in estrogens %}
<div class="gallery">
<a target="_blank" href="/products/{{product.short_name}}">
<img src="/assets/products/{{product.short_name}}.webp" width="600" height="400">
</a>
<div class="desc">{{ product.full_name }}</div>
</div>
{% endfor %}
</div>
{% endif %}
{% if anti_androgens %}
<h3 id="anti_androgens">Anti-Androgens</h3>
<div class="images">
{% for product in anti_androgens %}
<div class="gallery">
<a target="_blank" href="/products/{{product.short_name}}">
<img src="/assets/products/{{product.short_name}}.webp" width="600" height="400">
</a>
<div class="desc">{{ product.full_name }}</div>
</div>
{% endfor %}
</div>
{% endif %}
</html>