mirror of
https://github.com/kristoferssolo/cipher-workshop.git
synced 2025-12-20 11:04:38 +00:00
feat(web): add 404 page
This commit is contained in:
parent
a04abffe45
commit
3dc7187910
@ -1,5 +1,7 @@
|
|||||||
use crate::pages::{aes::AesPage, des::DesPage, footer::Footer, header::Header, home::Home};
|
use crate::pages::{
|
||||||
use leptos::prelude::*;
|
aes::AesPage, des::DesPage, footer::Footer, header::Header, home::Home, not_found::NotFound,
|
||||||
|
};
|
||||||
|
use leptos::{prelude::*, svg::view};
|
||||||
use leptos_meta::{MetaTags, Stylesheet, Title, provide_meta_context};
|
use leptos_meta::{MetaTags, Stylesheet, Title, provide_meta_context};
|
||||||
use leptos_router::{
|
use leptos_router::{
|
||||||
StaticSegment,
|
StaticSegment,
|
||||||
@ -43,7 +45,7 @@ pub fn App() -> impl IntoView {
|
|||||||
<div class="app-containter">
|
<div class="app-containter">
|
||||||
<Header />
|
<Header />
|
||||||
<main>
|
<main>
|
||||||
<Routes fallback=|| "Page not found.".into_view()>
|
<Routes fallback=|| view! { <NotFound /> }>
|
||||||
<Route path=StaticSegment("/") view=Home />
|
<Route path=StaticSegment("/") view=Home />
|
||||||
<Route path=StaticSegment("/des") view=DesPage />
|
<Route path=StaticSegment("/des") view=DesPage />
|
||||||
<Route path=StaticSegment("/aes") view=AesPage />
|
<Route path=StaticSegment("/aes") view=AesPage />
|
||||||
|
|||||||
@ -5,9 +5,10 @@ async fn main() {
|
|||||||
use leptos::logging::log;
|
use leptos::logging::log;
|
||||||
use leptos::prelude::*;
|
use leptos::prelude::*;
|
||||||
use leptos_axum::{LeptosRoutes, generate_route_list};
|
use leptos_axum::{LeptosRoutes, generate_route_list};
|
||||||
|
use tokio::net::TcpListener;
|
||||||
use web::app::*;
|
use web::app::*;
|
||||||
|
|
||||||
let conf = get_configuration(None).unwrap();
|
let conf = get_configuration(None).expect("Valid config file");
|
||||||
let addr = conf.leptos_options.site_addr;
|
let addr = conf.leptos_options.site_addr;
|
||||||
let leptos_options = conf.leptos_options;
|
let leptos_options = conf.leptos_options;
|
||||||
// Generate the list of routes in your Leptos App
|
// Generate the list of routes in your Leptos App
|
||||||
@ -24,10 +25,11 @@ async fn main() {
|
|||||||
// run our app with hyper
|
// run our app with hyper
|
||||||
// `axum::Server` is a re-export of `hyper::Server`
|
// `axum::Server` is a re-export of `hyper::Server`
|
||||||
log!("listening on http://{}", &addr);
|
log!("listening on http://{}", &addr);
|
||||||
let listener = tokio::net::TcpListener::bind(&addr).await.unwrap();
|
if let Ok(listener) = TcpListener::bind(&addr).await {
|
||||||
axum::serve(listener, app.into_make_service())
|
axum::serve(listener, app.into_make_service())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.expect("valid serving");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "ssr"))]
|
#[cfg(not(feature = "ssr"))]
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
use leptos::prelude::*;
|
use leptos::prelude::*;
|
||||||
use leptos_router::components::A;
|
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn Footer() -> impl IntoView {
|
pub fn Footer() -> impl IntoView {
|
||||||
@ -12,9 +11,9 @@ pub fn Footer() -> impl IntoView {
|
|||||||
"No data is transmitted to any server. You can verify this by disconnecting your internet connection."
|
"No data is transmitted to any server. You can verify this by disconnecting your internet connection."
|
||||||
</p>
|
</p>
|
||||||
<div class="footer-links">
|
<div class="footer-links">
|
||||||
<A href="https://github.com/kristoferssolo/cipher-workshop" target="_blank">
|
<a href="https://github.com/kristoferssolo/cipher-workshop" target="_blank">
|
||||||
"View Source on GitHub"
|
"View Source on GitHub"
|
||||||
</A>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|||||||
@ -3,3 +3,4 @@ pub mod des;
|
|||||||
pub mod footer;
|
pub mod footer;
|
||||||
pub mod header;
|
pub mod header;
|
||||||
pub mod home;
|
pub mod home;
|
||||||
|
pub mod not_found;
|
||||||
|
|||||||
17
web/src/pages/not_found.rs
Normal file
17
web/src/pages/not_found.rs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
use leptos::prelude::*;
|
||||||
|
#[component]
|
||||||
|
pub fn NotFound() -> impl IntoView {
|
||||||
|
view! {
|
||||||
|
<div class="not-found-container">
|
||||||
|
<div class="error-code">"404"</div>
|
||||||
|
<h1>"Page Not Found"</h1>
|
||||||
|
<p>"The data you are looking for has been encrypted into the void."</p>
|
||||||
|
<div class="binary-decoration">
|
||||||
|
"01000100 01000101 01000001 01000100 00100000 01001100 01001001 01001110 01001011"
|
||||||
|
</div>
|
||||||
|
<a href="/" class="btn-primary btn-link">
|
||||||
|
"Return to Home"
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -150,7 +150,7 @@ main {
|
|||||||
.app-footer {
|
.app-footer {
|
||||||
margin-top: auto;
|
margin-top: auto;
|
||||||
padding: 2rem 0;
|
padding: 2rem 0;
|
||||||
border-top: 1px solid var(--border);
|
border-top: 2px solid var(--border);
|
||||||
background: var(--bg-card);
|
background: var(--bg-card);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
@ -537,3 +537,50 @@ main {
|
|||||||
color: var(--text-main);
|
color: var(--text-main);
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.not-found-container {
|
||||||
|
text-align: center;
|
||||||
|
padding: 4rem 1rem;
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 0 auto;
|
||||||
|
animation: fadeIn 0.5s ease-out;
|
||||||
|
|
||||||
|
.error-code {
|
||||||
|
font-size: 6rem;
|
||||||
|
font-weight: 800;
|
||||||
|
color: var(--error);
|
||||||
|
font-family: "Consolar", "Monaco", monospace;
|
||||||
|
opacity: 0.8;
|
||||||
|
line-height: 1;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
text-shadow: 4px 4px 0px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 2rem;
|
||||||
|
color: var(--text-main);
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
color: var(--text-muted);
|
||||||
|
font-size: 1.1rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.binary-decoration {
|
||||||
|
font-family: "Consolas", "Monaco", monospace;
|
||||||
|
color: var(--text-muted);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
opacity: 0.5;
|
||||||
|
margin-bottom: 2.5rem;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-link {
|
||||||
|
text-decoration: none;
|
||||||
|
display: inline-block;
|
||||||
|
width: auto;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user