Navbar copy of the other frontend
This commit is contained in:
commit
f764bd08c0
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
/target
|
||||
/dist
|
||||
.env
|
1829
Cargo.lock
generated
Normal file
1829
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
29
Cargo.toml
Normal file
29
Cargo.toml
Normal file
@ -0,0 +1,29 @@
|
||||
[package]
|
||||
name = "jl-frontend"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
authors = [
|
||||
"Franklin Blanco <me@franklinblanco.dev>"
|
||||
]
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
||||
[dependencies]
|
||||
# yew and core stuff
|
||||
yew = { version = "0.20.0", features = ["csr"] }
|
||||
yew-router = "0.17"
|
||||
stylist = "0.12.0"
|
||||
|
||||
# Wasm/js stuff
|
||||
wasm-logger = "0.2"
|
||||
wasm-bindgen = "0.2.84"
|
||||
wasm-bindgen-futures = "0.4.34"
|
||||
js-sys = "0.3"
|
||||
|
||||
# other libs
|
||||
reqwest = { version = "0.11.11", features = ["rustls-tls", "json", "blocking"], default-features = false }
|
||||
uuid = { version = "1.3.0", features = ["v4", "fast-rng", "macro-diagnostics", "serde", "js"] }
|
||||
log = "0.4"
|
||||
serde_json = "1.0.88"
|
||||
|
||||
# Core
|
||||
jl-types = { path = "../jl-types" }
|
BIN
assets/images/remax-logo.png
Normal file
BIN
assets/images/remax-logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
BIN
css/.DS_Store
vendored
Normal file
BIN
css/.DS_Store
vendored
Normal file
Binary file not shown.
12
css/body.css
Normal file
12
css/body.css
Normal file
@ -0,0 +1,12 @@
|
||||
body {
|
||||
margin: 0; /* Remove body margins */
|
||||
}
|
||||
|
||||
.page-container {
|
||||
padding-top: 75.5px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: stretch;
|
||||
|
||||
}
|
0
css/landing.css
Normal file
0
css/landing.css
Normal file
160
css/navbar.css
Normal file
160
css/navbar.css
Normal file
@ -0,0 +1,160 @@
|
||||
/* Mobile View */
|
||||
.navbar-background {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: end;
|
||||
align-items: center;
|
||||
align-items: stretch;
|
||||
background-color: #252631;
|
||||
min-height: 74px;
|
||||
}
|
||||
|
||||
.navbar-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
align-items: stretch;
|
||||
flex-grow: 1;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.navbar-hamburger {
|
||||
font-size: 20pt;
|
||||
color: white;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-top: 5px;
|
||||
max-height: 35px;
|
||||
min-width: 30px;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.navbar-hamburger:hover {
|
||||
background-color: #ffffff14;
|
||||
font-size: 22pt;
|
||||
font-weight: bold;
|
||||
border-radius: 3px;
|
||||
transition-duration: 0.3s;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.navbar-closed{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
margin-top: 10px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.navbar-open {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.navbar-item {
|
||||
color: white;
|
||||
font-size: 12pt;
|
||||
padding-top: 10px;
|
||||
padding-left: 5px;
|
||||
padding-bottom: 10px;
|
||||
font-family: Source Sans Pro;
|
||||
}
|
||||
|
||||
.navbar-item:hover {
|
||||
background-color: #ffffff14;
|
||||
font-size: 13pt;
|
||||
font-weight: bold;
|
||||
border-radius: 3px;
|
||||
transition-duration: 0.3s;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.navbar-brand-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
max-width: 250px;
|
||||
}
|
||||
|
||||
.navbar-brand-container:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.navbar-title {
|
||||
color: white;
|
||||
font-size: 23pt;
|
||||
font-family: Sacramento;
|
||||
}
|
||||
|
||||
.navbar-image {
|
||||
max-width: 50px;
|
||||
max-height: 50px;
|
||||
}
|
||||
|
||||
/* Desktop view */
|
||||
@media only screen and (min-width: 850px) {
|
||||
.navbar-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.navbar-closed {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
flex-grow: 1;
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
.navbar-open {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
flex-grow: 1;
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
.navbar-item {
|
||||
color: white;
|
||||
font-size: 12pt;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
font-family: Source Sans Pro;
|
||||
}
|
||||
|
||||
.navbar-item:hover {
|
||||
background-color: #ffffff14;
|
||||
font-size: 13pt;
|
||||
font-weight: bold;
|
||||
border-radius: 3px;
|
||||
transition-duration: 0.3s;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.navbar-title {
|
||||
color: white;
|
||||
font-size: 23pt;
|
||||
font-family: Sacramento;
|
||||
}
|
||||
|
||||
.navbar-hamburger {
|
||||
display: none;
|
||||
}
|
||||
}
|
96
css/search.css
Normal file
96
css/search.css
Normal file
@ -0,0 +1,96 @@
|
||||
|
||||
.property-search-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: stretch;
|
||||
align-items: center;
|
||||
padding: 10px 50px;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.property-search-bar-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-width: 300px;
|
||||
max-width: 600px;
|
||||
width: 100%;
|
||||
padding: 0px 20px;
|
||||
min-height: 50px;
|
||||
border: 0.5px solid rgba(0, 0, 0, 0.08);
|
||||
border-radius: 30px;
|
||||
box-shadow: rgba(0, 0, 0, 0.1) 0px 3px 10px;
|
||||
background-color: white;
|
||||
flex-grow: 1;
|
||||
margin-bottom: 15px;
|
||||
|
||||
color: #252631;
|
||||
}
|
||||
|
||||
.property-search-bar {
|
||||
border: 0px;
|
||||
padding: 10px;
|
||||
outline: none;
|
||||
font-family: Source Sans Pro;
|
||||
font-size: 15px;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.search-bar-erase-button {
|
||||
display: none;
|
||||
}
|
||||
.search-bar-erase-button:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.search-bar-filter-button {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 25px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.14);
|
||||
padding: 4px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.search-bar-filter-button:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.property-search-filters-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-evenly;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.property-search-filter-item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
min-width: 75px;
|
||||
|
||||
color: black;
|
||||
padding: 5px 10px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.5);
|
||||
border-radius: 5px;
|
||||
font-family: Open Sans;
|
||||
font-weight: bold;
|
||||
font-size: 15px;
|
||||
|
||||
|
||||
}
|
||||
|
||||
.property-search-results-container {
|
||||
color: purple;
|
||||
}
|
||||
|
||||
.property-search-result-card {
|
||||
color: orange
|
||||
}
|
18
index.html
Normal file
18
index.html
Normal file
@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>JL</title>
|
||||
|
||||
<link data-trunk type="text/css" href="css/body.css" rel="css" />
|
||||
<link data-trunk type="text/css" href="css/navbar.css" rel="css" />
|
||||
<link data-trunk type="text/css" href="css/landing.css" rel="css" />
|
||||
<link data-trunk type="text/css" href="css/search.css" rel="css" />
|
||||
<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css?family=Sacramento" rel="stylesheet">
|
||||
<script src="https://kit.fontawesome.com/fcdfdfe1ad.js" crossorigin="anonymous"></script>
|
||||
|
||||
<base data-trunk-public-url />
|
||||
<link data-trunk rel="copy-dir" href="assets/images/"/>
|
||||
</head>
|
||||
</html>
|
0
src/api/backend/mod.rs
Normal file
0
src/api/backend/mod.rs
Normal file
0
src/api/base.rs
Normal file
0
src/api/base.rs
Normal file
2
src/api/mod.rs
Normal file
2
src/api/mod.rs
Normal file
@ -0,0 +1,2 @@
|
||||
pub mod base;
|
||||
pub mod backend;
|
2
src/components/mod.rs
Normal file
2
src/components/mod.rs
Normal file
@ -0,0 +1,2 @@
|
||||
pub mod nav_bar;
|
||||
pub mod search_filter;
|
57
src/components/nav_bar.rs
Normal file
57
src/components/nav_bar.rs
Normal file
@ -0,0 +1,57 @@
|
||||
use yew::prelude::*;
|
||||
use yew_router::prelude::use_navigator;
|
||||
|
||||
use crate::{routes::main_router::{Route}, constants::{NAVBAR_TITLE, NAVBAR_COL_LANDING, NAVBAR_COL_PROYECTOS_ACABADOS, NAVBAR_COL_CONTACTO, NAVBAR_COL_PROYECTOS_EN_CONSTRUCCION}, pages::search::PropertyState};
|
||||
//use yew_router::prelude::use_navigator;
|
||||
|
||||
|
||||
#[function_component(NavigationBar)]
|
||||
pub fn navigation_bar() -> Html {
|
||||
let navigator = use_navigator().unwrap();
|
||||
let cloned_navigator_1 = navigator.clone();
|
||||
let cloned_navigator_2 = navigator.clone();
|
||||
let cloned_navigator_3 = navigator.clone();
|
||||
let cloned_navigator_4 = navigator.clone();
|
||||
let cloned_navigator_5 = navigator.clone();
|
||||
|
||||
let navbar_toggle = use_state(|| true);
|
||||
let on_click_hamburger = {
|
||||
let navbar_toggle = navbar_toggle.clone();
|
||||
Callback::from(move |_| navbar_toggle.set(!*navbar_toggle))
|
||||
};
|
||||
|
||||
html! {
|
||||
<div class={"navbar-background"}>
|
||||
<div class={"navbar-container"}>
|
||||
<div class={"navbar-brand-container"} onclick={move |_| cloned_navigator_5.push(&Route::LandingPage)}>
|
||||
<img class={"navbar-image"} src="images/remax-logo.png" alt=""/>
|
||||
<div class={"navbar-title"}>
|
||||
{NAVBAR_TITLE}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class={if *navbar_toggle {"navbar-closed"} else {"navbar-open"}}>
|
||||
<div onclick={move |_| cloned_navigator_1.push(&Route::LandingPage)} class={"navbar-item"}>
|
||||
{NAVBAR_COL_LANDING}
|
||||
</div>
|
||||
|
||||
<div onclick={move |_| cloned_navigator_2.push(&Route::Search { property_state: PropertyState::Finished })} class={"navbar-item"}>
|
||||
{NAVBAR_COL_PROYECTOS_ACABADOS}
|
||||
</div>
|
||||
|
||||
<div onclick={move |_| cloned_navigator_3.push(&Route::Search { property_state: PropertyState::InConstruction })} class={"navbar-item"}>
|
||||
{NAVBAR_COL_PROYECTOS_EN_CONSTRUCCION}
|
||||
</div>
|
||||
|
||||
<div onclick={move |_| cloned_navigator_4.push(&Route::Contact)} class={"navbar-item"}>
|
||||
{NAVBAR_COL_CONTACTO}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class={"navbar-hamburger"} onclick={on_click_hamburger}>
|
||||
<i class="fa-solid fa-bars" ></i>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
0
src/components/search_filter.rs
Normal file
0
src/components/search_filter.rs
Normal file
5
src/constants/mod.rs
Normal file
5
src/constants/mod.rs
Normal file
@ -0,0 +1,5 @@
|
||||
pub const NAVBAR_TITLE: &str = "Jorge Ledesma";
|
||||
pub const NAVBAR_COL_LANDING: &str = "Inicio";
|
||||
pub const NAVBAR_COL_PROYECTOS_ACABADOS: &str = "Listos para entrega";
|
||||
pub const NAVBAR_COL_PROYECTOS_EN_CONSTRUCCION: &str = "En construcción";
|
||||
pub const NAVBAR_COL_CONTACTO: &str = "Contacto";
|
22
src/main.rs
Normal file
22
src/main.rs
Normal file
@ -0,0 +1,22 @@
|
||||
pub mod api;
|
||||
pub mod components;
|
||||
pub mod routes;
|
||||
pub mod pages;
|
||||
pub mod constants;
|
||||
|
||||
use yew::prelude::*;
|
||||
use yew_router::{BrowserRouter, Switch};
|
||||
|
||||
use crate::routes::main_router::{Route, switch};
|
||||
|
||||
#[function_component]
|
||||
fn App() -> Html {
|
||||
html! {
|
||||
<BrowserRouter>
|
||||
<Switch<Route> render={switch} /> // <- must be child of <BrowserRouter>
|
||||
</BrowserRouter>
|
||||
}
|
||||
}
|
||||
fn main() {
|
||||
yew::Renderer::<App>::new().render();
|
||||
}
|
16
src/pages/contact.rs
Normal file
16
src/pages/contact.rs
Normal file
@ -0,0 +1,16 @@
|
||||
use yew::prelude::*;
|
||||
|
||||
use crate::components::nav_bar::NavigationBar;
|
||||
|
||||
|
||||
#[function_component(ContactPage)]
|
||||
pub fn contact_page() -> Html {
|
||||
html!{
|
||||
<>
|
||||
<NavigationBar/>
|
||||
<div class={"page-container"}>
|
||||
{"Contact Page"}
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
}
|
8
src/pages/details.rs
Normal file
8
src/pages/details.rs
Normal file
@ -0,0 +1,8 @@
|
||||
use yew::prelude::*;
|
||||
|
||||
#[function_component(DetailsPage)]
|
||||
pub fn details_page() -> Html {
|
||||
html!{
|
||||
<div class={"page-container"}>{"Details Page"}</div>
|
||||
}
|
||||
}
|
16
src/pages/landing.rs
Normal file
16
src/pages/landing.rs
Normal file
@ -0,0 +1,16 @@
|
||||
use yew::prelude::*;
|
||||
|
||||
use crate::components::nav_bar::NavigationBar;
|
||||
|
||||
|
||||
#[function_component(LandingPage)]
|
||||
pub fn landing_page() -> Html {
|
||||
html!{
|
||||
<>
|
||||
<NavigationBar/>
|
||||
<div class={"page-container"}>
|
||||
{"Landing Page"}
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
}
|
5
src/pages/mod.rs
Normal file
5
src/pages/mod.rs
Normal file
@ -0,0 +1,5 @@
|
||||
pub mod landing;
|
||||
pub mod search;
|
||||
pub mod details;
|
||||
pub mod not_found;
|
||||
pub mod contact;
|
15
src/pages/not_found.rs
Normal file
15
src/pages/not_found.rs
Normal file
@ -0,0 +1,15 @@
|
||||
use yew::prelude::*;
|
||||
|
||||
use crate::components::nav_bar::NavigationBar;
|
||||
|
||||
#[function_component(NotFoundPage)]
|
||||
pub fn not_found_page() -> Html {
|
||||
html! {
|
||||
<>
|
||||
<NavigationBar/>
|
||||
<div class={"page-container"}>
|
||||
{"Not found page"}
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
}
|
99
src/pages/search.rs
Normal file
99
src/pages/search.rs
Normal file
@ -0,0 +1,99 @@
|
||||
use std::{fmt::Display, str::FromStr};
|
||||
|
||||
use yew::prelude::*;
|
||||
|
||||
use crate::components::nav_bar::NavigationBar;
|
||||
|
||||
#[function_component(SearchPage)]
|
||||
pub fn search_page(_props: &SearchPageProperties) -> Html {
|
||||
let search_text = use_state(|| String::new());
|
||||
let clear_search_input = {
|
||||
let search_text = search_text.clone();
|
||||
Callback::from(move |_| {
|
||||
search_text.set(String::new())
|
||||
})
|
||||
};
|
||||
html!{
|
||||
<>
|
||||
<NavigationBar/>
|
||||
<div class={"page-container"}>
|
||||
<div class={"property-search-container"}>
|
||||
<div class={"property-search-bar-container"}> // Search bar
|
||||
<i class={"fa-solid fa-magnifying-glass"}></i>
|
||||
<input type={"text"} value={(*search_text).clone()} class={"property-search-bar"} placeholder={"Buscar propiedades..."}/>
|
||||
<div class={"search-bar-erase-button"}>
|
||||
<i class="fa-solid fa-circle-xmark" onclick={clear_search_input}></i>
|
||||
</div>
|
||||
<div class={"search-bar-filter-button"}>
|
||||
<i class="fa-solid fa-sliders"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class={"property-search-filters-container"}> // Filters
|
||||
<div class={"property-search-filter-item"}>
|
||||
<div>{"0"}</div>
|
||||
<i class="fa-solid fa-bed"></i>
|
||||
<div>{"+"}</div>
|
||||
</div>
|
||||
<div class={"property-search-filter-item"}>
|
||||
<div>{"0"}</div>
|
||||
<i class="fa-solid fa-ruler"></i>
|
||||
<div>{"+"}</div>
|
||||
</div>
|
||||
<div class={"property-search-filter-item"}>
|
||||
<div>{"0"}</div>
|
||||
<i class="fa-solid fa-dollar-sign"></i>
|
||||
<div>{"+"}</div>
|
||||
</div>
|
||||
<div class={"property-search-filter-item"}>
|
||||
<div>{"0"}</div>
|
||||
<i class="fa-solid fa-hand-holding-dollar"></i>
|
||||
<div>{"+"}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
//TODO: Add a spacing
|
||||
|
||||
|
||||
<div class={"property-search-results-container"}> // Search Results Content
|
||||
<div class={"property-search-result-card"}></div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Properties)]
|
||||
pub struct SearchPageProperties {
|
||||
pub property_state: PropertyState
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum PropertyState {
|
||||
Finished,
|
||||
#[default]
|
||||
InConstruction,
|
||||
}
|
||||
|
||||
impl Display for PropertyState {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
PropertyState::Finished => write!(f, "Finished"),
|
||||
PropertyState::InConstruction => write!(f, "InConstruction"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for PropertyState {
|
||||
type Err = ();
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"Finished" => Ok(Self::Finished),
|
||||
"InConstruction" => Ok(Self::InConstruction),
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
}
|
32
src/routes/main_router.rs
Normal file
32
src/routes/main_router.rs
Normal file
@ -0,0 +1,32 @@
|
||||
use yew_router::prelude::*;
|
||||
use yew::prelude::*;
|
||||
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{pages::{landing::LandingPage, search::{SearchPage, PropertyState}, details::DetailsPage, not_found::NotFoundPage, contact::ContactPage}};
|
||||
|
||||
#[derive(Clone, Routable, PartialEq)]
|
||||
pub enum Route {
|
||||
#[at("/")]
|
||||
LandingPage,
|
||||
#[at("/search/:property_state")]
|
||||
Search { property_state: PropertyState },
|
||||
#[at("/details/:property_id")]
|
||||
Details { property_id: Uuid },
|
||||
#[at("/contact")]
|
||||
Contact,
|
||||
|
||||
#[not_found]
|
||||
#[at("/404")]
|
||||
NotFound,
|
||||
}
|
||||
|
||||
pub fn switch(routes: Route) -> Html {
|
||||
match routes {
|
||||
Route::LandingPage => html! { <LandingPage/> },
|
||||
Route::Search { property_state } => html! { <SearchPage property_state={property_state}/> },
|
||||
Route::Details { property_id: _ } => html! { <DetailsPage/> },
|
||||
Route::NotFound => html! { <NotFoundPage/> },
|
||||
Route::Contact => html! { <ContactPage/> }
|
||||
}
|
||||
}
|
1
src/routes/mod.rs
Normal file
1
src/routes/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod main_router;
|
Loading…
Reference in New Issue
Block a user