>,
) -> Recipe {
let mut directions_list: Vec<(u16, String)> = Vec::new();
for i in 0..directions.len() {
directions_list.push((i.try_into().unwrap(), directions[i].to_string()));
}
Recipe {
id: Uuid::new_v4(),
name: name.clone(),
shortcode: construct_shortcode(name.clone()),
prep_time,
cooking_time,
servings,
ingredients,
directions: directions_list,
attribution,
posted_date: Utc::now(),
edited_date: None,
tags,
}
}
pub fn construct_page(&self) {
// Create the footer
let footer = Container::new(ContainerType::Footer)
.with_raw(r#"
"#) // Line seperator
.with_link("/", "home") // Link to the root page
.with_link("/submit.html", "submit recipe") // Link to submission form
.with_link("/rss.xml", "rss") // Link the the Atom feed
// License info
.with_paragraph("Software licensed under the CNPLv7+")
.with_paragraph("Recipes under Public Domain");
// Metadata
let meta = Container::new(ContainerType::UnorderedList)
.with_attributes(vec![("class", "recipe")])
.with_paragraph(format!(
"⏲️ Preparation time: {} {}",
&self.prep_time.0, &self.prep_time.1
))
.with_paragraph(format!(
"🍳 Cooking time: {} {}",
&self.cooking_time.0, &self.cooking_time.1
))
.with_paragraph(format!("🍽️ Servings: {}", &self.servings));
// Ingredients
let mut ingredients_container =
Container::new(ContainerType::UnorderedList).with_attributes(vec![("class", "recipe")]);
for i in &self.ingredients {
let ingredient = format!("{} {} {}", &i.0, &i.1, &i.2);
ingredients_container.add_paragraph(ingredient);
}
// Directions
let mut directions_container =
Container::new(ContainerType::OrderedList).with_attributes(vec![("class", "recipe")]);
for n in &self.directions {
directions_container.add_paragraph(&n.1);
}
// Tags
let mut tags_html = String::new();
tags_html.push_str(r#"Tags: "#);
match &self.tags {
Some(list) => {
for x in 0..list.len() {
if x != list.len() - 1 {
tags_html.push_str(
format!("#{},", list[x].1, list[x].1).as_str(),
);
} else {
tags_html.push_str(
format!("#{}", list[x].1, list[x].1).as_str(),
);
}
}
}
None => {
tags_html.push_str(r#"no tags!! :o"#);
}
}
tags_html.push_str(r#"
"#);
// Date
let edit_date = match &self.edited_date {
Some(date) => {
format!(
"Last edited on: {}-{}-{}
",
date.year(),
date.month(),
date.day()
)
}
None => "No edits
".to_string(),
};
// Construct Main Page
let recipe_page = build_html::HtmlPage::new()
.with_head_link("/favicon.ico", "icon") // Favicon
.with_stylesheet("/style.css") // Link stylesheet
.with_meta(vec![("charset", "UTF-8")])
.with_meta(vec![
("name", "viewport"),
("content", "width=device-width, initial-scale=1"),
]) // Display stuff
.with_meta(vec![("name", "description"), ("content", DESCRIPTION)]) // Add the description
.with_title(TITLE)
.with_header(1, &self.name)
.with_raw(r#"
"#)
.with_container(meta)
.with_header(2, r#"Ingredients:"#)
.with_container(ingredients_container)
.with_header(2, r#"Directions:"#)
.with_container(directions_container)
.with_header(2, r#"Misc."#)
.with_raw(format!("Author: {}
", &self.attribution).as_str())
.with_raw(tags_html)
.with_raw(format!(
"Recipe added on: {}-{}-{}
",
&self.posted_date.year(),
&self.posted_date.month(),
&self.posted_date.day()
))
.with_raw(edit_date)
.with_container(footer);
write_html(recipe_page.to_html_string(), "en", Some(&self.shortcode));
}
}
pub fn construct_shortcode(full_name: String) -> String {
let mut prev_name = full_name;
prev_name.make_ascii_lowercase();
return prev_name
.chars()
.map(|x| match x {
' ' => '-',
_ => x,
})
.collect();
}
// Struct for the users answer to a captcha
#[derive(Clone, Debug, FromForm)]
pub struct CaptchaAnswer {
pub text: String,
}