add stat cards to index page, new pattern, misc

This commit is contained in:
2025-10-09 19:32:51 +02:00
parent d3a71827e1
commit 3b83bc89a0
8 changed files with 104 additions and 17 deletions

8
src/days.rs Normal file
View File

@@ -0,0 +1,8 @@
use chrono::{NaiveDate, Utc};
pub fn days_of_community_existence() -> i64 {
let formation = NaiveDate::from_ymd_opt(2020, 6, 7).unwrap();
let today = Utc::now().date_naive();
today.signed_duration_since(formation).num_days()
}

View File

@@ -12,8 +12,7 @@ pub fn init_service(ctx: &Context, guild_id: &GuildId) {
info!("Initialising discord member count service..."); info!("Initialising discord member count service...");
if guild_id != MAIN_GUILD_ID { if guild_id != MAIN_GUILD_ID {
info!("Guild member count service not initialised; Bot not running on main guild."); info!("Guild member count service initialised, but bot not running on main guild.");
return;
} }
tokio::spawn(async move { tokio::spawn(async move {

View File

@@ -1,11 +1,14 @@
use std::error::Error; use std::error::Error;
use tokio::net::TcpListener; use tokio::net::TcpListener;
mod days;
mod discordbot; mod discordbot;
mod router; mod router;
mod setup; mod setup;
mod website; mod website;
const SHRUG: &'static str = "¯\\_(ツ)_/¯";
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> { async fn main() -> Result<(), Box<dyn Error>> {
setup::dotenv_and_tracing(); setup::dotenv_and_tracing();

View File

@@ -1,8 +1,9 @@
use axum::{Router, http::StatusCode, routing::get}; use axum::{Router, http::StatusCode, routing::get};
use chrono::{NaiveDate, Utc};
use tower::service_fn; use tower::service_fn;
use crate::{router::redirects::redirects, website::website_service}; use crate::{
days::days_of_community_existence, router::redirects::redirects, website::website_service,
};
mod redirects; mod redirects;
@@ -28,7 +29,7 @@ async fn api_fallback() -> (StatusCode, String) {
async fn get_member_count() -> (StatusCode, String) { async fn get_member_count() -> (StatusCode, String) {
match crate::discordbot::get_member_count().await { match crate::discordbot::get_member_count().await {
Some(count) => (StatusCode::OK, format!("{count}")), Some(count) => (StatusCode::OK, count.to_string()),
None => ( None => (
StatusCode::INTERNAL_SERVER_ERROR, StatusCode::INTERNAL_SERVER_ERROR,
format!("An error occured - could not fetch discord member count."), format!("An error occured - could not fetch discord member count."),
@@ -37,9 +38,5 @@ async fn get_member_count() -> (StatusCode, String) {
} }
async fn get_days_since_community_formation() -> String { async fn get_days_since_community_formation() -> String {
let formation = NaiveDate::from_ymd_opt(2020, 6, 7).unwrap(); days_of_community_existence().to_string()
let today = Utc::now().date_naive();
let days = today.signed_duration_since(formation).num_days();
days.to_string()
} }

View File

@@ -4,14 +4,30 @@ use axum::{
response::{Html, IntoResponse, Response}, response::{Html, IntoResponse, Response},
}; };
use crate::website::pages::INTERNAL_SERVER_ERROR_MSG; use crate::{
SHRUG, days::days_of_community_existence, discordbot::get_member_count,
website::pages::INTERNAL_SERVER_ERROR_MSG,
};
#[derive(Template)] #[derive(Template)]
#[template(path = "index.html")] #[template(path = "index.html")]
struct PageIndex; struct PageIndex {
/// approximate discord server member count
dsc_members: String,
days_community: i64,
}
pub async fn page_index() -> Response { pub async fn page_index() -> Response {
let a = PageIndex; let a = PageIndex {
dsc_members: match get_member_count().await {
Some(count) => match count {
..=512 => format!("{count}"),
_ => format!("~{count}"),
},
None => SHRUG.into(),
},
days_community: days_of_community_existence(),
};
match a.render() { match a.render() {
Ok(res) => (StatusCode::OK, Html(res)).into_response(), Ok(res) => (StatusCode::OK, Html(res)).into_response(),
Err(_e) => (StatusCode::INTERNAL_SERVER_ERROR, INTERNAL_SERVER_ERROR_MSG).into_response(), Err(_e) => (StatusCode::INTERNAL_SERVER_ERROR, INTERNAL_SERVER_ERROR_MSG).into_response(),

View File

@@ -1,10 +1,11 @@
{% extends "base.html" %} {# # # # # # # # # # # # # # # # # # # # # # # # # #} {% extends "base.html" %} {# # # # # # # # # # # # # # # # # # # # # # # # # #}
{%- import "statcard.html" as statcard -%} {# # # # # # # # # # # # # # # # # #}
{% block title %}gractwo.pl | Witamy!{% endblock %} {% block pagecontent %} {% block title %}gractwo.pl | Witamy!{% endblock %} {% block pagecontent %}
<div <div
class="bg-gractwo-index-light flex flex-col items-center text-center w-full h-full flex-1 pb-48" class="bg-gractwo-index-light flex flex-col items-center text-center w-full h-full flex-1"
> >
<div class="mt-16 md:mt-60 mx-auto [&>svg]:size-24"> <div class="mt-16 md:mt-56 mx-auto [&>svg]:size-24">
{% include "gractwo.svg" %} {% include "gractwo.svg" %}
</div> </div>
<h1 <h1
@@ -50,7 +51,12 @@
YouTube</a YouTube</a
> >
</div> </div>
<div class="my-16 flex flex-col sm:flex-row gap-4">
{%call statcard::statcard(dsc_members, "członków na discordzie")%}
{%call statcard::statcard(days_community, "dni istnienia
społeczności")%}
<!--{% call statcard::statcard("0", "dni od powstania stowarzyszenia") %}-->
</div>
</div> </div>
{% include "footer.html" %} {# # # # # # # # # # # # # # # # # # # # # # # # #} {% include "footer.html" %} {% endblock %}
{% endblock %}

View File

@@ -16,6 +16,56 @@
linear-gradient(to right, #ff637e 15%, #00d3f2 100%); linear-gradient(to right, #ff637e 15%, #00d3f2 100%);
} }
.dashed-top-fade-grid {
position: absolute;
inset: 0;
z-index: 0;
background-image:
linear-gradient(to right, #e7e5e4 1px, transparent 1px),
linear-gradient(to bottom, #e7e5e4 1px, transparent 1px);
background-size: 20px 20px;
background-position:
0 0,
0 0;
mask-image:
repeating-linear-gradient(
to right,
black 0px,
black 3px,
transparent 3px,
transparent 8px
),
repeating-linear-gradient(
to bottom,
black 0px,
black 3px,
transparent 3px,
transparent 8px
),
radial-gradient(ellipse 70% 60% at 50% 0%, #000 60%, transparent 100%);
-webkit-mask-image:
repeating-linear-gradient(
to right,
black 0px,
black 3px,
transparent 3px,
transparent 8px
),
repeating-linear-gradient(
to bottom,
black 0px,
black 3px,
transparent 3px,
transparent 8px
),
radial-gradient(ellipse 70% 60% at 50% 0%, #000 60%, transparent 100%);
mask-composite: intersect;
-webkit-mask-composite: source-in;
}
.dashed-bottom-fade-grid { .dashed-bottom-fade-grid {
position: absolute; position: absolute;
inset: 0; inset: 0;

8
web/statcard.html Normal file
View File

@@ -0,0 +1,8 @@
{% macro statcard(number, description) %}
<div
class="min-w-64 flex-1 p-4 bg-neutral-100 border border-neutral-300 shadow rounded"
>
<h1 class="font-bold text-2xl">{{ number }}</h1>
<p class="text-neutral-500 whitespace-nowrap">{{ description }}</p>
</div>
{% endmacro %}