summaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
authorAdam T. Carpenter <atc@53hor.net>2024-09-09 22:28:33 -0400
committerAdam T. Carpenter <atc@53hor.net>2024-09-09 22:28:33 -0400
commit0213fd2dcd09ca4b1252cdc45415a765a887d679 (patch)
tree975beafb05ac296d87167e40c724cac0f9a9dc86 /src/main.rs
parentf2bd378e1a8cdfa7d1520b3734a748dd1cd9de25 (diff)
downloadcarpentertutoring-0213fd2dcd09ca4b1252cdc45415a765a887d679.tar.xz
carpentertutoring-0213fd2dcd09ca4b1252cdc45415a765a887d679.zip
feat: teams and blurbs but lots of todos
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs110
1 files changed, 100 insertions, 10 deletions
diff --git a/src/main.rs b/src/main.rs
index ca0a3d9..d07d201 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -11,6 +11,11 @@ use std::fs;
use std::io::*;
use std::path::Path;
use std::path::PathBuf;
+use chrono::Datelike;
+
+fn current_year() -> i32 {
+ chrono::Utc::now().year()
+}
trait Post: fmt::Debug {
fn dump(&self);
@@ -18,6 +23,12 @@ trait Post: fmt::Debug {
fn get_content(&self) -> Cow<str>;
}
+trait Tutor: fmt::Debug {
+ fn id(&self) -> &str;
+ fn display_name(&self) -> &str;
+ fn blurb(&self) -> &str;
+}
+
struct MdFilePost {
path: PathBuf,
name: OsString,
@@ -56,7 +67,11 @@ impl fmt::Debug for MdFilePost {
}
trait Posts {
- fn get_posts(&self) -> impl Iterator<Item = impl Post>;
+ fn get_posts(&self) -> impl IntoIterator<Item = impl Post>;
+}
+
+trait Tutors {
+ fn get_tutors(&self) -> impl IntoIterator<Item = impl Tutor>;
}
struct FsDirPosts {
@@ -71,10 +86,29 @@ impl FsDirPosts {
}
}
+struct FsDirTutors {
+ path: PathBuf,
+}
+
+impl Tutors for FsDirTutors {
+ fn get_tutors(&self) -> impl IntoIterator<Item = impl Tutor> {
+ let test: Vec<MdTutor> = Vec::new();
+ test
+ }
+}
+
+impl FsDirTutors {
+ fn new(path: &str) -> Self {
+ Self {
+ path: PathBuf::from(path),
+ }
+ }
+}
+
impl Posts for FsDirPosts {
- fn get_posts(&self) -> impl Iterator<Item = impl Post> {
- let dirs = fs::read_dir(&self.path).unwrap();
- dirs.flatten().map(|d| MdFilePost::new(&d.path()))
+ fn get_posts(&self) -> impl IntoIterator<Item = impl Post> {
+ let files = fs::read_dir(&self.path).unwrap();
+ files.flatten().filter(|d| !d.path().file_stem().unwrap().to_str().unwrap_or_default().starts_with('.')).map(|d| MdFilePost::new(&d.path()))
}
}
@@ -105,16 +139,59 @@ struct PostsView {
impl PostsView {
fn with_posts(posts: &impl Posts) -> Self {
Self {
- post_titles: posts.get_posts().map(|p| p.display_name().into_owned()).map(String::from).collect()
+ post_titles: posts.get_posts().into_iter().map(|p| p.display_name().into_owned()).map(String::from).collect()
}
}
}
+// TODO: one single Markdown struct with id, name, and content can take over for both MdTutor and
+// MdPost if it implements the Tutor and Post traits
+// With this, I could have a repo which does all the same loading but returns things of a generic T
+// as long as that T is provided it'll map values into those fields?
+
async fn posts_handler(State(posts): State<Arc<impl Posts>>) -> Html<String> {
let view = PostsView::with_posts(&*posts);
Html(view.render().unwrap())
}
+#[derive(Debug)]
+struct MdTutor {
+ id: String,
+ name: String,
+ blurb: String,
+}
+
+impl Tutor for MdTutor {
+ fn id(&self) -> &str {
+ self.id.as_str()
+ }
+
+ fn display_name(&self) -> &str {
+ self.name.as_str()
+ }
+
+ fn blurb(&self) -> &str {
+ self.blurb.as_str()
+ }
+}
+
+#[derive(Template)]
+#[template(path = "about/index.html")]
+struct AboutView<T: Tutor> {
+ tutors: Vec<T>,
+}
+
+impl<T: Tutor> AboutView<T> {
+ fn with_tutors(tutors: &impl Tutors) -> Self {
+ todo!()
+ }
+}
+
+async fn about_handler(State(tutors): State<Arc<impl Tutors>>) -> Html<String> {
+ let view: AboutView<MdTutor> = AboutView::with_tutors(&*tutors);
+ Html(view.render().unwrap())
+}
+
#[derive(Template)]
#[template(path = "index.html")]
struct IndexTemplate;
@@ -131,17 +208,30 @@ async fn policies_handler() -> Html<String> {
Html(PoliciesTemplate{}.render().unwrap())
}
+#[derive(Template)]
+#[template(path = "brochure/index.html")]
+struct BrochureTemplate;
+
+async fn brochure_handler() -> Html<String> {
+ Html(BrochureTemplate{}.render().unwrap())
+}
+
#[tokio::main]
async fn main() {
- let repo = Arc::new(FsDirPosts::new(&format!("/data/ct/{}", "blog")));
+ let posts = Arc::new(FsDirPosts::new(&format!("/data/ct/{}", "blog")));
+ let tutors = Arc::new(FsDirTutors::new(&format!("/data/ct/{}", "team")));
let app = Router::new()
- .nest_service("/static", ServeDir::new("static"))
- .nest_service("/assets", ServeDir::new("/data/ct/assets"))
+ .route("/", get(index_handler))
.route("/posts", get(posts_handler))
+ .with_state(posts)
.route("/policies", get(policies_handler))
- .route("/", get(index_handler))
- .with_state(repo);
+ .route("/brochure", get(brochure_handler))
+ .route("/about", get(about_handler))
+ .with_state(tutors)
+ .nest_service("/assets", ServeDir::new("/data/ct/assets"))
+ .nest_service("/team", ServeDir::new("/data/ct/team"))
+ .fallback_service(ServeDir::new("static"));
let listener = tokio::net::TcpListener::bind("0.0.0.0:8000").await.unwrap();
axum::serve(listener, app).await.unwrap();