diff --git a/axum_server/src/pages/contact.rs b/axum_server/src/pages/contact.rs new file mode 100644 index 0000000..7d7e5f6 --- /dev/null +++ b/axum_server/src/pages/contact.rs @@ -0,0 +1,87 @@ +use askama::Template; +use axum::http::StatusCode; + +use crate::components::{ + site_footer::{render_site_footer, SiteFooter}, + site_header::HeaderProps, +}; + +pub struct ContactLink { + pub href: String, + pub title: String, + pub label: String, + pub svg: String, +} + +#[derive(Template)] +#[template(path = "contact.html")] +pub struct ContactPageTemplate { + pub title: String, + pub site_footer: SiteFooter, + pub header_props: HeaderProps, + pub links: Vec, +} + +pub async fn render_contact() -> Result { + let site_footer = tokio::spawn(render_site_footer()); + let site_footer = site_footer + .await + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; + let links = vec![ + ContactLink { + href: "mailto: michalvankosk@gmail.com".to_string(), + label: "michalvankosk@gmail.com".to_string(), + title: "E-mail address".to_string(), + svg: "mail".to_string(), + }, + ContactLink { + href: "https://twitch.tv/michalvankodev".to_string(), + label: "Twitch".to_string(), + title: "Twitch channel".to_string(), + svg: "twitch".to_string(), + }, + ContactLink { + href: "https://tiktok.com/@michalvankodev".to_string(), + label: "TikTok".to_string(), + title: "TikTok channel".to_string(), + svg: "tiktok".to_string(), + }, + ContactLink { + href: "https://www.youtube.com/@michalvankodev".to_string(), + label: "YouTube".to_string(), + title: "YouTube channel".to_string(), + svg: "youtube".to_string(), + }, + ContactLink { + href: "https://instagram.com/michalvankodev".to_string(), + label: "Instagram".to_string(), + title: "Instagram profile".to_string(), + svg: "instagram".to_string(), + }, + ContactLink { + href: "https://instagram.com/michalvankodev".to_string(), + label: "GitHub".to_string(), + title: "Github profile".to_string(), + svg: "github".to_string(), + }, + ContactLink { + href: "https://www.linkedin.com/in/michal-vanko-dev/".to_string(), + label: "LinkedIn".to_string(), + title: "LinkedIn profile".to_string(), + svg: "linkedin".to_string(), + }, + ContactLink { + href: "https://discord.gg/2cGg7kwZEh".to_string(), + label: "Discord".to_string(), + title: "Discord channel".to_string(), + svg: "discord".to_string(), + }, + ]; + + Ok(ContactPageTemplate { + title: "Contact".to_owned(), + site_footer, + header_props: HeaderProps::default(), + links, + }) +} diff --git a/axum_server/src/pages/mod.rs b/axum_server/src/pages/mod.rs index 6515127..ee745d9 100644 --- a/axum_server/src/pages/mod.rs +++ b/axum_server/src/pages/mod.rs @@ -1,3 +1,4 @@ +pub mod contact; pub mod index; pub mod post; pub mod post_list; diff --git a/axum_server/src/router.rs b/axum_server/src/router.rs index 77c7f68..591d702 100644 --- a/axum_server/src/router.rs +++ b/axum_server/src/router.rs @@ -1,6 +1,9 @@ use crate::{ feed::render_rss_feed, - pages::{index::render_index, post::render_post, post_list::render_post_list}, + pages::{ + contact::render_contact, index::render_index, post::render_post, + post_list::render_post_list, + }, }; use axum::{extract::MatchedPath, http::Request, routing::get, Router}; use tower_http::trace::TraceLayer; @@ -12,6 +15,7 @@ pub fn get_router() -> Router { .route("/blog", get(render_post_list)) .route("/blog/tags/:tag", get(render_post_list)) .route("/blog/:post_id", get(render_post)) + .route("/contact", get(render_contact)) .route("/feed.xml", get(render_rss_feed)) .layer( TraceLayer::new_for_http().make_span_with(|request: &Request<_>| { diff --git a/axum_server/styles/output.css b/axum_server/styles/output.css index 33077f6..06aa446 100644 --- a/axum_server/styles/output.css +++ b/axum_server/styles/output.css @@ -1,5 +1,5 @@ /* -! tailwindcss v3.4.1 | MIT License | https://tailwindcss.com +! tailwindcss v3.4.3 | MIT License | https://tailwindcss.com */ /* @@ -211,6 +211,8 @@ textarea { /* 1 */ line-height: inherit; /* 1 */ + letter-spacing: inherit; + /* 1 */ color: inherit; /* 1 */ margin: 0; @@ -234,9 +236,9 @@ select { */ button, -[type='button'], -[type='reset'], -[type='submit'] { +input:where([type='button']), +input:where([type='reset']), +input:where([type='submit']) { -webkit-appearance: button; /* 1 */ background-color: transparent; @@ -492,6 +494,10 @@ video { --tw-backdrop-opacity: ; --tw-backdrop-saturate: ; --tw-backdrop-sepia: ; + --tw-contain-size: ; + --tw-contain-layout: ; + --tw-contain-paint: ; + --tw-contain-style: ; } ::backdrop { @@ -542,6 +548,10 @@ video { --tw-backdrop-opacity: ; --tw-backdrop-saturate: ; --tw-backdrop-sepia: ; + --tw-contain-size: ; + --tw-contain-layout: ; + --tw-contain-paint: ; + --tw-contain-style: ; } .m-1 { @@ -572,6 +582,21 @@ video { margin-bottom: 0.75rem; } +.my-6 { + margin-top: 1.5rem; + margin-bottom: 1.5rem; +} + +.mx-2 { + margin-left: 0.5rem; + margin-right: 0.5rem; +} + +.my-2 { + margin-top: 0.5rem; + margin-bottom: 0.5rem; +} + .mb-1 { margin-bottom: 0.25rem; } @@ -632,6 +657,10 @@ video { flex-direction: row; } +.place-content-center { + place-content: center; +} + .content-end { align-content: flex-end; } @@ -656,15 +685,28 @@ video { border-radius: 0.25rem; } +.rounded-full { + border-radius: 9999px; +} + .border { border-width: 1px; } +.border-2 { + border-width: 2px; +} + .border-blue-200 { --tw-border-opacity: 1; border-color: rgb(191 219 254 / var(--tw-border-opacity)); } +.border-blue-500 { + --tw-border-opacity: 1; + border-color: rgb(59 130 246 / var(--tw-border-opacity)); +} + .bg-blue-50 { --tw-bg-opacity: 1; background-color: rgb(239 246 255 / var(--tw-bg-opacity)); @@ -698,6 +740,21 @@ video { padding-right: 1.25rem; } +.py-3 { + padding-top: 0.75rem; + padding-bottom: 0.75rem; +} + +.py-4 { + padding-top: 1rem; + padding-bottom: 1rem; +} + +.py-5 { + padding-top: 1.25rem; + padding-bottom: 1.25rem; +} + .pr-3 { padding-right: 0.75rem; } @@ -795,6 +852,12 @@ video { filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); } +.transition-colors { + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + .article-body { h1 { margin-top: 0.5rem; @@ -895,3 +958,13 @@ video { .video-embed { margin: 1rem; } + +.hover\:bg-blue-200:hover { + --tw-bg-opacity: 1; + background-color: rgb(191 219 254 / var(--tw-bg-opacity)); +} + +.hover\:bg-pink-200:hover { + --tw-bg-opacity: 1; + background-color: rgb(251 207 232 / var(--tw-bg-opacity)); +} diff --git a/axum_server/templates/contact.html b/axum_server/templates/contact.html new file mode 100644 index 0000000..39695fc --- /dev/null +++ b/axum_server/templates/contact.html @@ -0,0 +1,25 @@ +{% extends "base.html" %} +{% block content %} + +

+ Contact +

+ + + +{% endblock %} diff --git a/axum_server/templates/site_footer.html b/axum_server/templates/site_footer.html index 67c25f6..5e0ea02 100644 --- a/axum_server/templates/site_footer.html +++ b/axum_server/templates/site_footer.html @@ -1,49 +1,2 @@ -{% macro contact_link(svg, title, href, text) %} - - - - {{text}} - - -{% endmacro %} -