From 9f341d439f7aa5fd2365024169ead2d6bdc3210c Mon Sep 17 00:00:00 2001 From: "Adam T. Carpenter" Date: Sat, 14 Sep 2024 20:30:05 -0400 Subject: feat: rewrite complete --- about/figure.php | 8 - about/index.php | 99 -------- favicon.ico | Bin 327262 -> 0 bytes footer.php | 26 --- header.php | 315 ------------------------- index.php | 417 ---------------------------------- src/handlers.rs | 34 +++ src/helpers.rs | 5 + src/main.rs | 213 ++--------------- src/posts.rs | 3 + src/posts/abstractions.rs | 2 + src/posts/abstractions/post.rs | 6 + src/posts/abstractions/repo.rs | 5 + src/posts/fs_post.rs | 24 ++ src/posts/fs_post_repo.rs | 23 ++ src/tutors.rs | 3 + src/tutors/abstractions.rs | 2 + src/tutors/abstractions/tutor.rs | 7 + src/tutors/abstractions/tutor_repo.rs | 5 + src/tutors/fs_tutor.rs | 48 ++++ src/tutors/fs_tutor_repo.rs | 29 +++ src/views.rs | 5 + src/views/about.rs | 17 ++ src/views/brochure.rs | 6 + src/views/index.rs | 6 + src/views/policies.rs | 6 + src/views/posts.rs | 17 ++ static/favicon.ico | Bin 0 -> 327262 bytes tutors/email/index.php | 150 ------------ 29 files changed, 267 insertions(+), 1214 deletions(-) delete mode 100644 about/figure.php delete mode 100644 about/index.php delete mode 100644 favicon.ico delete mode 100644 footer.php delete mode 100644 header.php delete mode 100644 index.php create mode 100644 src/handlers.rs create mode 100644 src/helpers.rs create mode 100644 src/posts.rs create mode 100644 src/posts/abstractions.rs create mode 100644 src/posts/abstractions/post.rs create mode 100644 src/posts/abstractions/repo.rs create mode 100644 src/posts/fs_post.rs create mode 100644 src/posts/fs_post_repo.rs create mode 100644 src/tutors.rs create mode 100644 src/tutors/abstractions.rs create mode 100644 src/tutors/abstractions/tutor.rs create mode 100644 src/tutors/abstractions/tutor_repo.rs create mode 100644 src/tutors/fs_tutor.rs create mode 100644 src/tutors/fs_tutor_repo.rs create mode 100644 src/views.rs create mode 100644 src/views/about.rs create mode 100644 src/views/brochure.rs create mode 100644 src/views/index.rs create mode 100644 src/views/policies.rs create mode 100644 src/views/posts.rs create mode 100644 static/favicon.ico delete mode 100644 tutors/email/index.php diff --git a/about/figure.php b/about/figure.php deleted file mode 100644 index c6cee51..0000000 --- a/about/figure.php +++ /dev/null @@ -1,8 +0,0 @@ -
- - - - <?php include(" src="" /> - -
-
diff --git a/about/index.php b/about/index.php deleted file mode 100644 index b821726..0000000 --- a/about/index.php +++ /dev/null @@ -1,99 +0,0 @@ - - - -
-

-

- School is tricky, and there is no universal pathway to success. I started - Carpenter Tutoring for those seeking a little help finding their way. -

-

-
- -
-
- - - - Amy Carpenter - -
Amy Carpenter, M.Ed.
-
- -
-

- I received my B.A. from The College of William and Mary in 2018 and received - my M.Ed. from W&M in 2020. As an undergraduate, I worked and was trained - as a tutor at W&M's peer tutoring center, the TutorZone. During - this period, I conducted over 150 one-on-one appointments with W&M - students in 26 different content areas. I earned lifetime Advanced Tutor - Certification, the highest level W&M can grant, through the College - Reading and Learning Association, and I was trained as a time management - consultant. I took on leadership roles within the TutorZone until I was - working alongside its director. As a graduate student, I became one of the - Graduate Assistants helping oversee the TutorZone as well as an academic - coach to students with high need for academic support. -

- -

- I loved getting to work with the TutorZone tutors, but I realized that - I missed being the tutor. There's just nothing like watching the light bulb - of understanding go off or seeing students who had struggled with material - master it! With that realization, I decided to dedicate my life to my - passion -- helping students of all ages learn, succeed, and believe in - themselves. -

- -

- My instructional approach focuses on meeting students where they are and - supporting them through any hesitations or discomforts from which academic - difficulties may arise. Whether your student only has to brush up on a few - concepts or is resistant to completing coursework, I will come to each - session with patience, understanding, and just the right amount of - discipline. I truly believe that excellent educational relationships begin - with mutual respect, and I work to build meaningful relationships with all - of my clients. -

- -

Thank you for considering Carpenter Tutoring.

-
- -
- -
- - -
- - - -
- -
- - - diff --git a/favicon.ico b/favicon.ico deleted file mode 100644 index 8ba4c15..0000000 Binary files a/favicon.ico and /dev/null differ diff --git a/footer.php b/footer.php deleted file mode 100644 index 3a89f89..0000000 --- a/footer.php +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - diff --git a/header.php b/header.php deleted file mode 100644 index fc3ac25..0000000 --- a/header.php +++ /dev/null @@ -1,315 +0,0 @@ - - - - - - Tutoring Excellence Online and in Suffolk, VA - Carpenter Tutoring, LLC - - - - - - - - - - - - - - - - - - - - - -
diff --git a/index.php b/index.php deleted file mode 100644 index 530544a..0000000 --- a/index.php +++ /dev/null @@ -1,417 +0,0 @@ - - - - - -
-
-

- Welcome, and thank you for your interest in Carpenter Tutoring! -

- -

Carpenter Tutoring is a private tutoring service based in Suffolk, - Virginia. We offer high-engagement remote appointments through Zoom. A limited - number of in-person appointments with me are also available for students in the Harbour - View region of Suffolk, VA. Most of our offerings are one-on-one, and siblings - and pre-existing groups of students may opt for group meetings. No matter your - budget, I am confident that we can find an arrangement that will provide your - student services without creating financial strain.

- -

- I invite you to explore and learn more about the services we offer, Carpenter Tutoring's background, - and some of our policies. Thank you for visiting, and - please do not hesitate to reach out with any questions. We will be thrilled to - assist you! -

- -
- - - - Amy's signature - -
- -
- -
- - - - Amy Carpenter - -
Amy Carpenter, M.Ed.
-
-
- - - - - - - - - - - - - - - - - - - - - - - -
- -
-

Subject Tutoring

-

Tutoring for specific courses or disciplines -

- expand Learn more -
- -
-

Time Management

-

- Personalized plans for managing academics, extracurriculars, and - other commitments -

- expand Learn more -
- -
-

Study Skills

-

Learn how to make the most of your study time

- expand Learn more -
- -
-

Academic Coaching

-

- Time management and study skills blended with continuing - accountability -

- expand Learn more -
- -
-

College Application Assistance

-

- Assistance with generating a college list and crafting application - essays -

- expand Learn more -
- -
-

College-Level Writing

-

Get a head start on meeting professors' expectations

- expand Learn more -
- -
-

Dissertation Coaching

-

Ensure your research is communicated effectively and eloquently

- expand Learn more -
- -
-

Standardized Test Prep

-

- Tailored assistance in preparing for a variety of standardized tests -

- expand Learn more -
- -
-

Music Lessons

-

Instrument and/or composition lessons for students of all ages

- expand Learn more -
- -
-

Proof of Progress Evaluations

-

- Two levels of portfolio-based evaluations for homeschool families - looking to satisfy Proof of Progress or gain insight into their - child's learning -

- expand Learn more -
- -
- -
- Click here to view an interactive brochure of our offerings -
- - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Pricing Guide - Remote*

-
- Single Subject, Time Management, Study Skills Tutoring, Music Lessons - $60/hr
- Multi-Subject, Academic Coaching, Dissertation Coaching, Test Prep, College - Application Assistance - $70/hr
Small Group Sessions, Group Lessons$40/hr/student
Simplified Homeschool Evaluations$45
Detailed Homeschool Evaluations$80+
- -

-

*In-person pricing for students in the Harbour View region of Suffolk is $10/hr more in each category.

- See a list of our policies and procedures regarding scheduling, - payment, and booking. -

- -
- - -
- -
-

C.L. Cannon

-
- I hired Amy to complete an end-of-the-year evaluation for both of my Elementary aged sons. This being our first year of independent home instruction, the task of testing and/or evaluation was daunting! Amy put my fears to rest! She was super easy to work with, had great communication skills, and answered all my questions in a timely and informative manner! I would highly recommend her services! -
-

- View on Google - or - leave a review. -

- star - star - star - star - star -
- -
-

Lee Crabtree

-
- Amy is a wonderful tutor who helped my child (who does not like help at all) though some difficult classes where the teacher was not providing the support my child needed. Highly recommended. -
-

- View on Google - or - leave a review. -

- star - star - star - star - star -
- -
-

Connor Fenton

-
- I was a Graduate student at the College of William and Mary who needed to pass a Latin Language test as part of my degree requirements. I was struggling with refreshing my Latin after a few years out of the classroom and Amy was both professional and helpful. With her tutoring I was able to pass my test and finish my degree. She is very considerate and easy to work with. -
-

- View on Google - or - leave a review. -

- star - star - star - star - star -
- -
- diff --git a/src/handlers.rs b/src/handlers.rs new file mode 100644 index 0000000..db5cf7c --- /dev/null +++ b/src/handlers.rs @@ -0,0 +1,34 @@ +use askama::Template; +use crate::views::posts::PostsView; +use crate::posts::abstractions::repo::PostRepo; +use crate::views::policies::PoliciesTemplate; +use crate::views::index::IndexTemplate; +use crate::views::brochure::BrochureTemplate; +use crate::views::about::AboutView; +use crate::tutors::abstractions::tutor_repo::TutorRepo; +use std::sync::Arc; +use axum::response::Html; +use axum::extract::State; + +pub async fn about_handler(State(repo): State>) -> Html { + let view = AboutView::with_tutors(repo.load()); + Html(view.render().unwrap()) +} + +pub async fn brochure_handler() -> Html { + Html(BrochureTemplate{}.render().unwrap()) +} + +pub async fn index_handler() -> Html { + Html(IndexTemplate {}.render().unwrap()) +} + +pub async fn policies_handler() -> Html { + Html(PoliciesTemplate{}.render().unwrap()) +} + +pub async fn posts_handler(State(repo): State>) -> Html { + let view = PostsView::with_posts(repo.load()); + Html(view.render().unwrap()) +} + diff --git a/src/helpers.rs b/src/helpers.rs new file mode 100644 index 0000000..c7509de --- /dev/null +++ b/src/helpers.rs @@ -0,0 +1,5 @@ +use chrono::{prelude::*, Utc}; + +pub fn current_year() -> i32 { + Utc::now().year() +} diff --git a/src/main.rs b/src/main.rs index 7b5ddfc..fb15e51 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,199 +1,14 @@ -use std::cmp::Ordering; -use std::borrow::Cow; -use tower_http::services::ServeDir; -use axum::response::Html; -use axum::extract::State; -use std::sync::Arc; -use askama_axum::Template; use axum::{routing::get, Router}; -use std::fmt; -use std::fs; -use std::path::PathBuf; -use chrono::Datelike; - -fn current_year() -> i32 { - chrono::Utc::now().year() -} - -trait Post: fmt::Debug { - fn get_title(&self) -> &str; - fn get_article(&self) -> Cow; -} - -#[derive(Debug)] -struct FsPost { - file: PathBuf, -} - -impl Post for FsPost { - fn get_title(&self) -> &str { - self.file.file_name().unwrap().to_str().unwrap() - } - - fn get_article(&self) -> Cow { - let article = fs::read_to_string(&self.file).unwrap(); - Cow::Owned(article) - } -} - -trait PostRepo { - fn load(&self) -> impl IntoIterator; -} - -struct FsPostRepo { - dir: PathBuf, -} - -impl FsPostRepo { - fn with_dir(path: impl Into) -> Self { - Self { - dir: path.into() - } - } -} - -impl PostRepo for FsPostRepo { - fn load(&self) -> impl IntoIterator { - let files = fs::read_dir(&self.dir).unwrap(); - files - .flatten() - .filter(|d| !d.file_name().to_string_lossy().starts_with('.')) - .map(|d| FsPost { file: d.path() }) - } -} - - -#[derive(Template)] -#[template(path = "posts.html")] -struct PostsView { - posts: Vec

-} - -impl PostsView

{ - fn with_posts(posts: impl IntoIterator) -> Self { - Self { - posts: posts.into_iter().collect() - } - } -} - -async fn posts_handler(State(repo): State>) -> Html { - let view = PostsView::with_posts(repo.load()); - Html(view.render().unwrap()) -} - -trait Tutor: fmt::Debug + Ord { - fn get_name(&self) -> &str; - fn get_id(&self) -> &str; - fn get_blurb(&self) -> Cow; -} - -#[derive(Debug, Eq)] -struct FsTutor { - dir: PathBuf -} - -impl Tutor for FsTutor { - fn get_id(&self) -> &str { - self.dir.file_name().unwrap().to_str().unwrap() - } - - fn get_name(&self) -> &str { - self.get_id() - } - - fn get_blurb(&self) -> Cow { - let mut path = self.dir.to_owned(); - path.push(format!("{}.md", self.get_id())); - let blurb = fs::read_to_string(path).unwrap(); - Cow::Owned(blurb) - } -} - -impl Ord for FsTutor { - fn cmp(&self, other: &Self) -> Ordering { - self.get_id().cmp(other.get_id()) - } -} - -impl PartialOrd for FsTutor { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl PartialEq for FsTutor { - fn eq(&self, other: &Self) -> bool { - self.get_id() == other.get_id() - } -} - -trait TutorRepo { - fn load(&self) -> impl IntoIterator; -} - -struct FsTutorRepo { - dir: PathBuf -} - -impl FsTutorRepo { - fn with_dir(path: impl Into) -> Self { - Self { - dir: path.into() - } - } -} - - -impl TutorRepo for FsTutorRepo { - fn load(&self) -> impl IntoIterator { - let dirs = fs::read_dir(&self.dir).unwrap(); - dirs.flatten().filter(|d| !d.path().file_stem().unwrap().to_str().unwrap_or_default().starts_with('.')).map(|d| FsTutor { dir: d.path() }) - } -} - - -#[derive(Template)] -#[template(path = "about/index.html")] -struct AboutView { - tutors: Vec, -} -impl AboutView { - fn with_tutors(tutors: impl IntoIterator) -> Self { - let mut tutors: Vec = tutors.into_iter().collect(); - tutors.sort(); - Self { tutors } - } -} - -async fn about_handler(State(repo): State>) -> Html { - let view = AboutView::with_tutors(repo.load()); - Html(view.render().unwrap()) -} - -#[derive(Template)] -#[template(path = "index.html")] -struct IndexTemplate; - -async fn index_handler() -> Html { - Html(IndexTemplate {}.render().unwrap()) -} - -#[derive(Template)] -#[template(path = "policies.html")] -struct PoliciesTemplate; - -async fn policies_handler() -> Html { - Html(PoliciesTemplate{}.render().unwrap()) -} - -#[derive(Template)] -#[template(path = "brochure/index.html")] -struct BrochureTemplate; +use tutors::fs_tutor_repo::FsTutorRepo; +use std::sync::Arc; +use tower_http::services::ServeDir; +use posts::fs_post_repo::FsPostRepo; -async fn brochure_handler() -> Html { - Html(BrochureTemplate{}.render().unwrap()) -} +mod helpers; +mod posts; +mod tutors; +mod views; +mod handlers; #[tokio::main] async fn main() { @@ -201,12 +16,12 @@ async fn main() { let tutors = Arc::new(FsTutorRepo::with_dir(format!("/data/ct/{}", "team"))); let app = Router::new() - .route("/", get(index_handler)) - .route("/posts", get(posts_handler)) + .route("/", get(handlers::index_handler)) + .route("/posts", get(handlers::posts_handler)) .with_state(posts) - .route("/policies", get(policies_handler)) - .route("/brochure", get(brochure_handler)) - .route("/about", get(about_handler)) + .route("/policies", get(handlers::policies_handler)) + .route("/brochure", get(handlers::brochure_handler)) + .route("/about", get(handlers::about_handler)) .with_state(tutors) .nest_service("/assets", ServeDir::new("/data/ct/assets")) .nest_service("/team", ServeDir::new("/data/ct/team")) diff --git a/src/posts.rs b/src/posts.rs new file mode 100644 index 0000000..7f2c217 --- /dev/null +++ b/src/posts.rs @@ -0,0 +1,3 @@ +pub mod abstractions; +pub mod fs_post; +pub mod fs_post_repo; diff --git a/src/posts/abstractions.rs b/src/posts/abstractions.rs new file mode 100644 index 0000000..96c8ced --- /dev/null +++ b/src/posts/abstractions.rs @@ -0,0 +1,2 @@ +pub mod post; +pub mod repo; diff --git a/src/posts/abstractions/post.rs b/src/posts/abstractions/post.rs new file mode 100644 index 0000000..6d504db --- /dev/null +++ b/src/posts/abstractions/post.rs @@ -0,0 +1,6 @@ +use std::{borrow::Cow, fmt}; + +pub trait Post: fmt::Debug { + fn get_title(&self) -> &str; + fn get_article(&self) -> Cow; +} diff --git a/src/posts/abstractions/repo.rs b/src/posts/abstractions/repo.rs new file mode 100644 index 0000000..6fcb385 --- /dev/null +++ b/src/posts/abstractions/repo.rs @@ -0,0 +1,5 @@ +use crate::posts::abstractions::post::Post; + +pub trait PostRepo { + fn load(&self) -> impl IntoIterator; +} diff --git a/src/posts/fs_post.rs b/src/posts/fs_post.rs new file mode 100644 index 0000000..e767803 --- /dev/null +++ b/src/posts/fs_post.rs @@ -0,0 +1,24 @@ +use crate::posts::abstractions::post::Post; +use std::{borrow::Cow, fs, path::PathBuf}; + +#[derive(Debug)] +pub struct FsPost { + file: PathBuf, +} + +impl FsPost { + pub fn with_path(path: PathBuf) -> Self { + Self { file: path } + } +} + +impl Post for FsPost { + fn get_title(&self) -> &str { + self.file.file_name().unwrap().to_str().unwrap() + } + + fn get_article(&self) -> Cow { + let article = fs::read_to_string(&self.file).unwrap(); + Cow::Owned(article) + } +} diff --git a/src/posts/fs_post_repo.rs b/src/posts/fs_post_repo.rs new file mode 100644 index 0000000..eb37a6a --- /dev/null +++ b/src/posts/fs_post_repo.rs @@ -0,0 +1,23 @@ +use crate::posts::abstractions::repo::PostRepo; +use crate::posts::fs_post::FsPost; +use std::{fs, path::PathBuf}; + +pub struct FsPostRepo { + dir: PathBuf, +} + +impl FsPostRepo { + pub fn with_dir(path: impl Into) -> Self { + Self { dir: path.into() } + } +} + +impl PostRepo for FsPostRepo { + fn load(&self) -> impl IntoIterator { + let files = fs::read_dir(&self.dir).unwrap(); + files + .flatten() + .filter(|d| !d.file_name().to_string_lossy().starts_with('.')) + .map(|d| FsPost::with_path(d.path())) + } +} diff --git a/src/tutors.rs b/src/tutors.rs new file mode 100644 index 0000000..d90ef99 --- /dev/null +++ b/src/tutors.rs @@ -0,0 +1,3 @@ +pub mod abstractions; +pub mod fs_tutor; +pub mod fs_tutor_repo; diff --git a/src/tutors/abstractions.rs b/src/tutors/abstractions.rs new file mode 100644 index 0000000..a93c25d --- /dev/null +++ b/src/tutors/abstractions.rs @@ -0,0 +1,2 @@ +pub mod tutor; +pub mod tutor_repo; diff --git a/src/tutors/abstractions/tutor.rs b/src/tutors/abstractions/tutor.rs new file mode 100644 index 0000000..f36da3d --- /dev/null +++ b/src/tutors/abstractions/tutor.rs @@ -0,0 +1,7 @@ +use std::{borrow::Cow, fmt}; + +pub trait Tutor: fmt::Debug + Ord { + fn get_name(&self) -> &str; + fn get_id(&self) -> &str; + fn get_blurb(&self) -> Cow; +} diff --git a/src/tutors/abstractions/tutor_repo.rs b/src/tutors/abstractions/tutor_repo.rs new file mode 100644 index 0000000..e017806 --- /dev/null +++ b/src/tutors/abstractions/tutor_repo.rs @@ -0,0 +1,5 @@ +use crate::tutors::abstractions::tutor::Tutor; + +pub trait TutorRepo { + fn load(&self) -> impl IntoIterator; +} diff --git a/src/tutors/fs_tutor.rs b/src/tutors/fs_tutor.rs new file mode 100644 index 0000000..dc8a635 --- /dev/null +++ b/src/tutors/fs_tutor.rs @@ -0,0 +1,48 @@ +use crate::tutors::abstractions::tutor::Tutor; +use std::{borrow::Cow, cmp::Ordering, fs, path::PathBuf}; + +#[derive(Debug, Eq)] +pub struct FsTutor { + dir: PathBuf, +} + +impl FsTutor { + pub fn with_dir(path: PathBuf) -> Self { + Self { dir: path } + } +} + +impl Tutor for FsTutor { + fn get_id(&self) -> &str { + self.dir.file_name().unwrap().to_str().unwrap() + } + + fn get_name(&self) -> &str { + self.get_id() + } + + fn get_blurb(&self) -> Cow { + let mut path = self.dir.to_owned(); + path.push(format!("{}.md", self.get_id())); + let blurb = fs::read_to_string(path).unwrap(); + Cow::Owned(blurb) + } +} + +impl Ord for FsTutor { + fn cmp(&self, other: &Self) -> Ordering { + self.get_id().cmp(other.get_id()) + } +} + +impl PartialOrd for FsTutor { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl PartialEq for FsTutor { + fn eq(&self, other: &Self) -> bool { + self.get_id() == other.get_id() + } +} diff --git a/src/tutors/fs_tutor_repo.rs b/src/tutors/fs_tutor_repo.rs new file mode 100644 index 0000000..9b9a8d9 --- /dev/null +++ b/src/tutors/fs_tutor_repo.rs @@ -0,0 +1,29 @@ +use crate::tutors::abstractions::tutor_repo::TutorRepo; +use crate::tutors::fs_tutor::FsTutor; +use std::{fs, path::PathBuf}; + +pub struct FsTutorRepo { + dir: PathBuf, +} + +impl FsTutorRepo { + pub fn with_dir(path: impl Into) -> Self { + Self { dir: path.into() } + } +} + +impl TutorRepo for FsTutorRepo { + fn load(&self) -> impl IntoIterator { + let dirs = fs::read_dir(&self.dir).unwrap(); + dirs.flatten() + .filter(|d| { + !d.path() + .file_stem() + .unwrap() + .to_str() + .unwrap_or_default() + .starts_with('.') + }) + .map(|d| FsTutor::with_dir(d.path())) + } +} diff --git a/src/views.rs b/src/views.rs new file mode 100644 index 0000000..b986f56 --- /dev/null +++ b/src/views.rs @@ -0,0 +1,5 @@ +pub mod about; +pub mod brochure; +pub mod index; +pub mod policies; +pub mod posts; diff --git a/src/views/about.rs b/src/views/about.rs new file mode 100644 index 0000000..349c9de --- /dev/null +++ b/src/views/about.rs @@ -0,0 +1,17 @@ +use crate::helpers::*; +use crate::tutors::abstractions::tutor::Tutor; +use askama::Template; + +#[derive(Template)] +#[template(path = "about/index.html")] +pub struct AboutView { + tutors: Vec, +} + +impl AboutView { + pub fn with_tutors(tutors: impl IntoIterator) -> Self { + let mut tutors: Vec = tutors.into_iter().collect(); + tutors.sort(); + Self { tutors } + } +} diff --git a/src/views/brochure.rs b/src/views/brochure.rs new file mode 100644 index 0000000..0d2f8fc --- /dev/null +++ b/src/views/brochure.rs @@ -0,0 +1,6 @@ +use crate::helpers::*; +use askama::Template; + +#[derive(Template)] +#[template(path = "brochure/index.html")] +pub struct BrochureTemplate; diff --git a/src/views/index.rs b/src/views/index.rs new file mode 100644 index 0000000..3ced24d --- /dev/null +++ b/src/views/index.rs @@ -0,0 +1,6 @@ +use crate::helpers::*; +use askama::Template; + +#[derive(Template)] +#[template(path = "index.html")] +pub struct IndexTemplate; diff --git a/src/views/policies.rs b/src/views/policies.rs new file mode 100644 index 0000000..3d9787d --- /dev/null +++ b/src/views/policies.rs @@ -0,0 +1,6 @@ +use crate::helpers::*; +use askama::Template; + +#[derive(Template)] +#[template(path = "policies.html")] +pub struct PoliciesTemplate; diff --git a/src/views/posts.rs b/src/views/posts.rs new file mode 100644 index 0000000..2ce69f8 --- /dev/null +++ b/src/views/posts.rs @@ -0,0 +1,17 @@ +use crate::helpers::*; +use crate::posts::abstractions::post::Post; +use askama::Template; + +#[derive(Template)] +#[template(path = "posts.html")] +pub struct PostsView { + posts: Vec

, +} + +impl PostsView

{ + pub fn with_posts(posts: impl IntoIterator) -> Self { + Self { + posts: posts.into_iter().collect(), + } + } +} diff --git a/static/favicon.ico b/static/favicon.ico new file mode 100644 index 0000000..8ba4c15 Binary files /dev/null and b/static/favicon.ico differ diff --git a/tutors/email/index.php b/tutors/email/index.php deleted file mode 100644 index 7ea8211..0000000 --- a/tutors/email/index.php +++ /dev/null @@ -1,150 +0,0 @@ - - -

- -
-
-

- Every tutor is expected to use a @carpentertutoring.com email address to facilitate client communication. This guide will walk you through setting up your email from scratch and configuring your mail client to use it. -

- -

- You have two options for using your new email address. The first is standalone which allows you to use the mail client of your choice to send and receive mail. Some popular desktop clients are Apple's Mail app, Mozilla Thunderbird, and Microsoft Outlook. Popular mobile mail clients include the iOS Mail app and K-9 Mail for Android. Your mailbox will remain on the Carpenter Tutoring mail server and in no way interact with any personal or private mail accounts you have on other systems. -

- -

- Your second choice is forwarding, where all of your Carpenter Tutoring mail will forward to a personal email address of your choice. Your personal email provider will need to be configured to send mail as your Carpenter Tutoring address for any client communication. The amount of setup is the same, but this method allows you to use a client such as GMail for managing mail. -

- -

- Remember you can change your decision anytime. See "Getting help" below. -

- - -

Create a mail account

-
- - - - - - - -
- - - array('pipe', 'r'), - 1 => array('file', '/var/ct_logins', 'a'), - 2 => array('file', '/var/log/ct_mail_submit.log', 'a') - ); - $process = proc_open('smtpctl encrypt', $descriptorspec, $pipes); - fwrite($pipes[0], $_POST['password']); - fclose($pipes[0]); - - // include name and generated email in logins queue - $logins_queue = fopen('/var/ct_logins', 'a'); - fprintf($logins_queue, '\n%s\n', $_POST['name']); - - $names = explode(' ', strtolower($_POST['name'])); - - $last = $names[1][0]; - $first = $names[0]; - $email = "$first$last@carpentertutoring.com"; - fprintf($logins_queue, '%s\n\n', $email); - - // close queue - fclose($logins_queue); - } - ?> -

Configuring your mail client

-

- You may choose to use a third-party mail app to check your mail, forward your mail to a GMail address, or use another third-party webmail client. Follow the instructions below for the option you chose when you created your password. The connection settings remain the same either way. -

- -

Connection details

-
-SMTP server: mail.53hor.net
-Connection security: STARTTLS
-Authentication method: normal password
-SMTP port: 587
-SMTP password: (use the password you just submitted)
-SMTP username: (full carpenter tutoring email address)
-
-
-IMAP server: mail.53hor.net
-Connection security: STARTTLS
-Authentication method: normal password
-IMAP port: 143
-IMAP password: (use the password you just submitted)
-IMAP username: (full carpenter tutoring email address)
-
-

Gmail forwarding

- -

- Once your @carpentertutoring.com email address is created, you will begin receiving forwarded email in your Gmail inbox. Sending mail from your @carpentertutoring.com address via Gmail requires a small amount of setup. -

- -

- -

    -
  1. On your computer, open Gmail.
  2. -
  3. In the top right, click settings (⚙️) and then See all settings.
  4. -
  5. Click the Accounts and import or Accounts tab.
  6. -
  7. In the "Send mail as" section, click Add another email address.
  8. -
  9. Enter your name and the address you want to send from. This will be your @carpentertutoring.com address. Leave the "Treat as an alias" box checked.
  10. -
  11. Click Next Step.
  12. -
  13. For the "SMTP server" enter mail.53hor.net. Select 587 for the port.
  14. -
  15. For the username and password you will enter your new Carpenter Tutoring address (with "@carpentertutoring.com" suffix) and the password you submitted in the previous step.
  16. -
  17. Check "Secured connection using TLS (recommended)" and click Add Account.
  18. -
  19. Gmail will prompt you to verify your new address. You should receive a confirmation code in your inbox, forwarded from your @carpentertutoring.com address. Use it to complete the alias setup.
  20. -
  21. Return to the "Send mail as" section on the settings page and look for "When replying to a message." Check "Reply from the same address the message was sent to." This will ensure you respond to tutoring inquiries with your Carpenter Tutoring address and personal mail with your Gmail address.
  22. - -
-

- -

Native mail clients

-

-

-

- -

Other webmail clients

- -

- Setup instructions for other popular webmail clients are largely the same. The configuration options for IMAP and SMTP should be identical. Below is a list of setup instructions for common providers. -

-

-

-

-

Getting help

-

- If you encounter difficulty or have questions throughout any part of this process, please reach out to webmaster@carpentertutoring.com and we'll get in touch to help. -

-
- -
- - -- cgit v1.2.3