fix: merge conflicts
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
use crate::Route;
|
||||
use dioxus::prelude::*;
|
||||
|
||||
#[component]
|
||||
pub fn BottomSheetMenu(show: bool, on_close: EventHandler<()>) -> Element {
|
||||
rsx! {
|
||||
// Overlay - positioned behind the menu
|
||||
if show {
|
||||
div {
|
||||
class: "bottom-sheet-overlay",
|
||||
onclick: move |_| on_close.call(()),
|
||||
}
|
||||
}
|
||||
|
||||
// Menu Body
|
||||
div {
|
||||
class: format_args!(
|
||||
"bottom-sheet-menu {}",
|
||||
if show { "visible" } else { "hidden" }
|
||||
),
|
||||
onclick: move |evt| {
|
||||
evt.stop_propagation();
|
||||
},
|
||||
|
||||
// Menu Header
|
||||
div {
|
||||
class: "menu-header",
|
||||
label {
|
||||
class: "flex items-center",
|
||||
div {
|
||||
class: "menu-handle"
|
||||
}
|
||||
}
|
||||
p {
|
||||
class: "menu-title",
|
||||
"Menu"
|
||||
}
|
||||
button {
|
||||
class: "menu-close",
|
||||
onclick: move |_| on_close.call(()),
|
||||
title: "Close",
|
||||
div {
|
||||
class: "menu-close-icon"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Menu Links
|
||||
div {
|
||||
class: "menu-links",
|
||||
Link {
|
||||
class: "menu-link",
|
||||
to: Route::Home{},
|
||||
"Home"
|
||||
}
|
||||
Link {
|
||||
class: "menu-link",
|
||||
to: Route::Skills {},
|
||||
"Skills"
|
||||
}
|
||||
Link {
|
||||
class: "menu-link",
|
||||
to: Route::Experiences{},
|
||||
"Experiences"
|
||||
}
|
||||
}
|
||||
|
||||
// Menu Contact
|
||||
div {
|
||||
class: "menu-contact",
|
||||
a {
|
||||
class: "menu-contact-item",
|
||||
href: "tel:+639",
|
||||
svg {
|
||||
class: "menu-contact-icon",
|
||||
xmlns: "http://www.w3.org/2000/svg",
|
||||
fill: "currentColor",
|
||||
height: "24",
|
||||
view_box: "0 0 24 24",
|
||||
width: "24",
|
||||
path {
|
||||
d: "M0 0h24v24H0z",
|
||||
fill: "none"
|
||||
}
|
||||
path {
|
||||
d: "M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z"
|
||||
}
|
||||
}
|
||||
span {
|
||||
"Call"
|
||||
}
|
||||
}
|
||||
a {
|
||||
class: "menu-contact-item",
|
||||
href: "mailto:portfolio.dc@sent.com",
|
||||
svg {
|
||||
class: "menu-contact-icon",
|
||||
xmlns: "http://www.w3.org/2000/svg",
|
||||
fill: "currentColor",
|
||||
height: "24",
|
||||
view_box: "0 0 24 24",
|
||||
width: "24",
|
||||
path {
|
||||
d: "M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"
|
||||
}
|
||||
path {
|
||||
d: "M0 0h24v24H0z",
|
||||
fill: "none"
|
||||
}
|
||||
}
|
||||
span {
|
||||
"Email"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[component]
|
||||
pub fn QuickMenuButton(on_click: EventHandler<()>) -> Element {
|
||||
rsx! {
|
||||
button {
|
||||
class: "quick-menu-button",
|
||||
onclick: move |_| on_click.call(()),
|
||||
div {
|
||||
class: "quick-menu-hamburger",
|
||||
div {
|
||||
class: "quick-menu-hamburger-line"
|
||||
}
|
||||
}
|
||||
"Quick Menu"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,271 @@
|
||||
use crate::components::{
|
||||
skill_data::{self},
|
||||
Skill, SkillDisplayMode, SkillList,
|
||||
};
|
||||
use dioxus::prelude::*;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct Experience {
|
||||
title: &'static str,
|
||||
company: &'static str,
|
||||
location: &'static str,
|
||||
employment_type: &'static str,
|
||||
start_date: &'static str,
|
||||
end_date: &'static str,
|
||||
duration: &'static str,
|
||||
description: &'static str,
|
||||
skills: Vec<Skill>,
|
||||
border_color: &'static str,
|
||||
drop_color: &'static str,
|
||||
bg_color: &'static str,
|
||||
}
|
||||
|
||||
#[component]
|
||||
pub fn ExperienceList() -> Element {
|
||||
let experiences = vec![
|
||||
Experience {
|
||||
title: " Senior Full Stack Developer ",
|
||||
company: "Startechup Inc.",
|
||||
location: "Cebu, Philippines ",
|
||||
employment_type: "Full Time ",
|
||||
start_date: " September 2022",
|
||||
end_date: "Present",
|
||||
duration: " 2 yrs & 10 months",
|
||||
description: "Successfully managed projects on schedule, optimized AWS for 50% cost savings, modernized backend systems, enhanced security, and promoted technical excellence through mentoring and code reviews.",
|
||||
skills: vec![
|
||||
skill_data::php_skill(),
|
||||
skill_data::python_skill(),
|
||||
skill_data::sql_skill(),
|
||||
skill_data::html_skill(),
|
||||
skill_data::css_skill(),
|
||||
skill_data::javascript_skill(),
|
||||
skill_data::laravel_skill(),
|
||||
skill_data::fastapi_skill(),
|
||||
skill_data::tailwindcss_skill(),
|
||||
skill_data::aws_skill(),
|
||||
skill_data::gcp_skill(),
|
||||
skill_data::git_skill(),
|
||||
skill_data::docker_skill(),
|
||||
skill_data::terraform_skill(),
|
||||
],
|
||||
border_color: "#EF5A6A",
|
||||
drop_color: "#EF5A6A",
|
||||
bg_color: "#EF5A6A",
|
||||
},
|
||||
Experience {
|
||||
title: "Technical Lead/Full Stack Developer",
|
||||
company: "Herohub Inc.",
|
||||
location: "San Juan, Philippines",
|
||||
employment_type: "Full Time",
|
||||
start_date: "April 2017",
|
||||
end_date: "January 2021",
|
||||
duration: "3 yrs & 10 months ",
|
||||
description: "Aligned technology with business goals, implemented low-code platforms for rapid app development, maintained core infrastructure, mentored teams, and collaborated on the long-term roadmap.",
|
||||
skills: vec![
|
||||
skill_data::javascript_skill(),
|
||||
skill_data::php_skill(),
|
||||
skill_data::sql_skill(),
|
||||
skill_data::html_skill(),
|
||||
skill_data::css_skill(),
|
||||
skill_data::laravel_skill(),
|
||||
skill_data::reactjs_skill(),
|
||||
skill_data::bootstrap_skill(),
|
||||
skill_data::semanticui_skill(),
|
||||
skill_data::aws_skill(),
|
||||
skill_data::gcp_skill(),
|
||||
skill_data::git_skill(),
|
||||
skill_data::outsystem_skill(),
|
||||
skill_data::plsql_skill(),
|
||||
skill_data::docker_skill(),
|
||||
],
|
||||
border_color: "#E88F4D",
|
||||
drop_color: "#E88F4D",
|
||||
bg_color: "#E88F4D",
|
||||
},
|
||||
Experience {
|
||||
title: "Full Stack Developer",
|
||||
company: "Fountainhead Technologies Inc.",
|
||||
location: "Quezon City, Philippines",
|
||||
employment_type: "Full Time",
|
||||
start_date: "December 2013",
|
||||
end_date: "January 2017",
|
||||
duration: "3 yrs & 2 months ",
|
||||
description: "Managed and motivated developers for project success. Handled large SQL databases, owned the development lifecycle, gathered requirements, created flow proposals, coded and tested modules, and integrated APIs.",
|
||||
skills: vec![
|
||||
skill_data::javascript_skill(),
|
||||
skill_data::php_skill(),
|
||||
skill_data::sql_skill(),
|
||||
skill_data::html_skill(),
|
||||
skill_data::css_skill(),
|
||||
skill_data::laravel_skill(),
|
||||
skill_data::reactjs_skill(),
|
||||
skill_data::bootstrap_skill(),
|
||||
skill_data::semanticui_skill(),
|
||||
skill_data::aws_skill(),
|
||||
skill_data::git_skill(),
|
||||
skill_data::phaserio_skill(),
|
||||
skill_data::plsql_skill(),
|
||||
skill_data::sass_skill(),
|
||||
],
|
||||
border_color: "#7CB768",
|
||||
drop_color: "#7CB768",
|
||||
bg_color: "#7CB768",
|
||||
},
|
||||
Experience {
|
||||
title: "Web Developer",
|
||||
company: "Mindblow Internet Ideas",
|
||||
location: "Mandaluyong, Philippines",
|
||||
employment_type: "Full Time",
|
||||
start_date: "May 2012",
|
||||
end_date: "August 2013",
|
||||
duration: "1 yr & 4 months ",
|
||||
description: "Participated in client meetings to understand project requirements. Managed small-to-medium projects, including CMS and e-commerce deployments, integrated APIs, collaborated with teams, trained interns, and applied SEO best practices",
|
||||
skills: vec![
|
||||
skill_data::javascript_skill(),
|
||||
skill_data::php_skill(),
|
||||
skill_data::sql_skill(),
|
||||
skill_data::html_skill(),
|
||||
skill_data::css_skill(),
|
||||
skill_data::codeigniter_skill(),
|
||||
skill_data::bootstrap_skill(),
|
||||
],
|
||||
border_color: "#4EA232",
|
||||
drop_color: "#4EA232",
|
||||
bg_color: "#4EA232",
|
||||
},
|
||||
];
|
||||
|
||||
rsx! {
|
||||
div {
|
||||
class: "col items-center relative mt-10 flex-1",
|
||||
|
||||
// Vertical timeline line
|
||||
// div {
|
||||
// class: "w-[0.5px] hidden lg:flex top-0 bottom-0 py-50px bg-[var(--border)] absolute rounded justify-center "
|
||||
// }
|
||||
|
||||
// Experience Items
|
||||
for (index, experience) in experiences.iter().enumerate() {
|
||||
div {
|
||||
class: "relative items-center w-full my-[10px]",
|
||||
|
||||
// Left/Right spacer
|
||||
div {
|
||||
class: "flex-1 hidden lg:flex timeline-spacer ",
|
||||
style: "flex: 0 0 15%;"
|
||||
}
|
||||
|
||||
// Timeline dot
|
||||
// div {
|
||||
// class: "hidden lg:inline p-15px bg-[var(--main)] rounded ",
|
||||
// i {
|
||||
// class: "i-carbon-condition-point "
|
||||
// }
|
||||
// }
|
||||
|
||||
// Experience Card
|
||||
div {
|
||||
class: "experience-card ",
|
||||
style: format!("--border-hover: {}", experience.border_color),
|
||||
// Header section with avatar and title
|
||||
div {
|
||||
class: "flex items-start gap-4",
|
||||
|
||||
// Avatar
|
||||
// div {
|
||||
// class: "experience-avatar ",
|
||||
// div {
|
||||
// class: "experience-avatar-inner "
|
||||
// }
|
||||
// }
|
||||
|
||||
// Content
|
||||
div {
|
||||
class: "col ml-0 md:ml-[20px] gap-3 w-full ",
|
||||
|
||||
// Title
|
||||
div {
|
||||
class: "col",
|
||||
h2 {
|
||||
class: "flex text-[2em] flex-col items-start sm:flex-row sm:items-center justify-between sm:gap-5 md:flex-col md:items-start md:gap-0 lg:flex-row lg:items-center bold",
|
||||
h2 {
|
||||
class: "font-[var(--title-f)] text-2em bold",
|
||||
"{experience.title}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Company, Location, Type tags
|
||||
div {
|
||||
class: "flex flex-wrap gap-2 mb-3",
|
||||
|
||||
// Company tag
|
||||
span {
|
||||
class: "flex items-center gap-1 px-2 py-1 bg-[var(--secondary)] border border-[var(--border)] rounded text-xs text-[var(--secondary-text)]",
|
||||
i { class: "i-carbon-building text-xs " }
|
||||
span { "{experience.company}" }
|
||||
}
|
||||
|
||||
// Location tag
|
||||
span {
|
||||
class: "flex items-center gap-1 px-2 py-1 bg-[var(--secondary)] border border-[var(--border)] rounded text-xs text-[var(--secondary-text)]",
|
||||
i { class: "i-carbon-location text-xs " }
|
||||
span { "{experience.location}" }
|
||||
}
|
||||
|
||||
// Employment type tag
|
||||
span {
|
||||
class: "flex items-center gap-1 px-2 py-1 bg-[var(--secondary)] border border-[var(--border)] rounded text-xs text-[var(--secondary-text)]",
|
||||
i { class: "i-carbon-user text-xs " }
|
||||
span { "{experience.employment_type}" }
|
||||
}
|
||||
}
|
||||
|
||||
// Date and duration info
|
||||
div {
|
||||
class: "text-[var(--text)] text-[0.9em]",
|
||||
|
||||
// Date range
|
||||
div {
|
||||
class: "row items-center gap-2",
|
||||
i { class: "i-carbon-calendar text-1.25em" }
|
||||
"{experience.start_date} - {experience.end_date}"
|
||||
}
|
||||
|
||||
div {
|
||||
class: "bg-[var(--border)] h-1px m-y-10px"
|
||||
}
|
||||
|
||||
// Duration
|
||||
div {
|
||||
class: "row items-center gap-2",
|
||||
i { class: "i-carbon-time text-1.25em" }
|
||||
"{experience.duration}"
|
||||
}
|
||||
|
||||
div {
|
||||
class: "bg-[var(--border)] h-1px m-y-10px"
|
||||
}
|
||||
}
|
||||
|
||||
// Description
|
||||
div {
|
||||
class: "experience-description text-[0.9em] mb-4 mt-4",
|
||||
"{experience.description}"
|
||||
}
|
||||
|
||||
// Skills
|
||||
if !experience.skills.is_empty() {
|
||||
SkillList {
|
||||
skills: experience.skills.clone(),
|
||||
display_mode: SkillDisplayMode::Chips
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+44
-57
@@ -3,73 +3,60 @@ use dioxus::prelude::*;
|
||||
#[component]
|
||||
pub fn Hero() -> Element {
|
||||
rsx! {
|
||||
// We can create elements inside the rsx macro with the element name followed by a block of attributes and children.
|
||||
div {
|
||||
class: "content container mb6t29",
|
||||
div {
|
||||
class: "col self-center flex-1 md:flex-row md:self-stretch justify-center lg:justify-between items-center p-y-0px p-x-10px",
|
||||
div {
|
||||
class: "md:flex-1 gap-10px",
|
||||
div { class: "content container p-15 mt-10",
|
||||
div { class: "flex",
|
||||
div { class: "grid content-center md:flex-1",
|
||||
h1 {
|
||||
class: "font-[var(--title-f)] font-black tracking-[4px] text-center text-2.5em sm:text-[3em] md:text-[3.5em] lg:text-[4em] md:text-left",
|
||||
class: "font-[var(--title-f)] font-black tracking-[4px] text-center text-4em lg:text-[4em] md:text-left",
|
||||
style: "background-image: ; background-position-x: ; background-position-y: ; background-size: ; background-repeat: ; background-attachment: ; background-origin: ; background-clip: text; background-color: ; -webkit-background-clip: text;",
|
||||
"Danilo"
|
||||
" "
|
||||
"Cesa"
|
||||
}
|
||||
p {
|
||||
p {
|
||||
class: "text-[var(--tertiary-text)] text-center md:text-left text-[1.2em] font-extralight",
|
||||
"Lorem ipsum dolor sit, amet consectetur adipisicing elit. Corrupti, rerum. Debitis accusantium deleniti enim iste dignissimos? Similique, exercitationem! Odit vero, numquam quae ratione maxime sunt reiciendis laudantium quaerat iure ipsum!"
|
||||
"Dynamic Full Stack Developer with over a decade of experience in
|
||||
analyzing, designing, developing, and implementing a wide range of
|
||||
software applications. Proven track record in architecting and
|
||||
managing systems. Experienced software development lifecycle
|
||||
and end-to-end project, from concept through to development and
|
||||
delivery.
|
||||
"
|
||||
}
|
||||
}
|
||||
}
|
||||
div { class: "row justify-center md:justify-start p-y-15px p-x-0px gap-2",
|
||||
a {
|
||||
class: "inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md transition duration-300",
|
||||
target: "_blank",
|
||||
href: "https://www.linkedin.com/in/danilocesajr",
|
||||
svg {
|
||||
class: "inline-block",
|
||||
view_box: "0 0 24 24",
|
||||
fill: "var(--accent-text)",
|
||||
height: "20px",
|
||||
width: "20px",
|
||||
path {
|
||||
d: "M20.5 2h-17A1.5 1.5 0 002 3.5v17A1.5 1.5 0 003.5 22h17a1.5 1.5 0 001.5-1.5v-17A1.5 1.5 0 0020.5 2zM8 19H5v-9h3zM6.5 8.25A1.75 1.75 0 118.3 6.5a1.78 1.78 0 01-1.8 1.75zM19 19h-3v-4.74c0-1.42-.6-1.93-1.38-1.93A1.74 1.74 0 0013 14.19a.66.66 0 000 .14V19h-3v-9h2.9v1.3a3.11 3.11 0 012.7-1.4c1.55 0 3.36.86 3.36 3.66z"
|
||||
}
|
||||
}
|
||||
}
|
||||
a {
|
||||
class: "inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md transition duration-300",
|
||||
target: "_blank",
|
||||
href: "https://gitea.dcesa.cc",
|
||||
svg {
|
||||
class: "inline-block",
|
||||
view_box: "0 0 16 16",
|
||||
fill: "var(--accent-text)",
|
||||
height: "20px",
|
||||
width: "20px",
|
||||
path {
|
||||
d: "M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"
|
||||
}
|
||||
}
|
||||
}
|
||||
// h1 {
|
||||
// class: "text-4xl md:text-6xl font-bold mb-4",
|
||||
// "Hey, I'm Dan"
|
||||
// }
|
||||
// p {
|
||||
// class: "text-lg md:text-xl text-gray-400",
|
||||
// "Full Stack Developer"
|
||||
// }
|
||||
}
|
||||
// div {
|
||||
// class: "p-4 rounded-lg hover:border-cyan-500 transition duration-300",
|
||||
// p {
|
||||
// class: "text-gray-400",
|
||||
// "I'm a passionate software developer with a background in computer science and a keen interest in frontend technologies."
|
||||
// }
|
||||
// }
|
||||
// div {
|
||||
// class: "row justify-center md:justify-start p-y-15px p-x-0px gap-2",
|
||||
// a {
|
||||
// class: "inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md transition duration-300",
|
||||
// href: "#contact",
|
||||
// svg {
|
||||
// class: "inline-block",
|
||||
// view_box: "0 0 24 24",
|
||||
// fill: "var(--accent-text)",
|
||||
// height: "20px",
|
||||
// width: "20px",
|
||||
// path {
|
||||
// d: "M20.5 2h-17A1.5 1.5 0 002 3.5v17A1.5 1.5 0 003.5 22h17a1.5 1.5 0 001.5-1.5v-17A1.5 1.5 0 0020.5 2zM8 19H5v-9h3zM6.5 8.25A1.75 1.75 0 118.3 6.5a1.78 1.78 0 01-1.8 1.75zM19 19h-3v-4.74c0-1.42-.6-1.93-1.38-1.93A1.74 1.74 0 0013 14.19a.66.66 0 000 .14V19h-3v-9h2.9v1.3a3.11 3.11 0 012.7-1.4c1.55 0 3.36.86 3.36 3.66z"
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// a {
|
||||
// class: "inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md transition duration-300",
|
||||
// href: "#contact",
|
||||
// svg {
|
||||
// class: "inline-block",
|
||||
// view_box: "0 0 16 16",
|
||||
// fill: "var(--accent-text)",
|
||||
// height: "20px",
|
||||
// width: "20px",
|
||||
// path {
|
||||
// d: "M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,3 +7,15 @@ pub use hero::Hero;
|
||||
|
||||
// mod echo;
|
||||
// pub use echo::Echo;
|
||||
|
||||
mod bottom_sheet_menu;
|
||||
pub use bottom_sheet_menu::{BottomSheetMenu, QuickMenuButton};
|
||||
|
||||
mod experience_list;
|
||||
pub use experience_list::ExperienceList;
|
||||
|
||||
mod skill_components;
|
||||
pub use skill_components::{
|
||||
skill_data, Skill, SkillCard, SkillCategory, SkillCategorySection, SkillChip, SkillDisplayMode,
|
||||
SkillList,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,538 @@
|
||||
use dioxus::prelude::*;
|
||||
|
||||
// Skill data structure
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct Skill {
|
||||
pub name: &'static str,
|
||||
pub abbreviation: &'static str,
|
||||
pub image: Option<Asset>,
|
||||
pub bg_color: &'static str,
|
||||
pub border_color: &'static str,
|
||||
pub drop_color: &'static str,
|
||||
}
|
||||
|
||||
// Skill category structure
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct SkillCategory {
|
||||
pub name: &'static str,
|
||||
pub skills: Vec<Skill>,
|
||||
}
|
||||
|
||||
// Individual skill card component for the skills page
|
||||
#[component]
|
||||
pub fn SkillCard(skill: Skill) -> Element {
|
||||
rsx! {
|
||||
a {
|
||||
class: "card text-inherit decoration-none inline-flex flex-col border-1 border-solid border-[var(--border)] rounded-lg duration relative cursor-pointer decoration-none d1441skb",
|
||||
style: format!(
|
||||
"margin: 0px; --bg-img: url({}); --border-color: {}; --drop-color: {}; --bg-color: {};",
|
||||
skill.image.map(|img| img.to_string()).unwrap_or_default(),
|
||||
skill.border_color,
|
||||
skill.drop_color,
|
||||
skill.bg_color
|
||||
),
|
||||
div {
|
||||
class: "card-bg-img flex-1 flex flex-col p-5 rounded-lg d1441skb",
|
||||
div {
|
||||
class: "text-[var(--tertiary-text)]",
|
||||
"{skill.name}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Small skill chip component for experience cards
|
||||
#[component]
|
||||
pub fn SkillChip(skill: Skill) -> Element {
|
||||
rsx! {
|
||||
div {
|
||||
class: "skill-chip",
|
||||
style: format!("background-color: {}", skill.bg_color),
|
||||
title: "{skill.name}",
|
||||
"{skill.abbreviation}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Skill list component for displaying multiple skills
|
||||
#[component]
|
||||
pub fn SkillList(skills: Vec<Skill>, display_mode: SkillDisplayMode) -> Element {
|
||||
let sorted_skills = match display_mode {
|
||||
SkillDisplayMode::Chips => {
|
||||
let mut skills = skills;
|
||||
skills.sort_by(|a, b| a.abbreviation.len().cmp(&b.abbreviation.len()));
|
||||
skills
|
||||
}
|
||||
_ => skills,
|
||||
};
|
||||
|
||||
rsx! {
|
||||
div {
|
||||
class: match display_mode {
|
||||
SkillDisplayMode::Grid => "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-2 md:gap-3 lg:gap-5 mt-5",
|
||||
SkillDisplayMode::Chips => "experience-skills",
|
||||
},
|
||||
for skill in sorted_skills {
|
||||
match display_mode {
|
||||
SkillDisplayMode::Grid => rsx! { SkillCard { skill: skill } },
|
||||
SkillDisplayMode::Chips => rsx! { SkillChip { skill: skill } },
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Skill category component for the skills page
|
||||
#[component]
|
||||
pub fn SkillCategorySection(category: SkillCategory) -> Element {
|
||||
rsx! {
|
||||
div {
|
||||
class: "col gap-5 mb-7",
|
||||
div {
|
||||
class: "flex row items-center gap-5",
|
||||
div { class: "bg-[var(--main-hover)] h-[1px] w-[20px]" }
|
||||
p {
|
||||
class: "text-[var(--main-close)]",
|
||||
"{category.name}"
|
||||
}
|
||||
div { class: "flex-1 bg-[var(--main-hover)] h-[1px]" }
|
||||
}
|
||||
SkillList {
|
||||
skills: category.skills,
|
||||
display_mode: SkillDisplayMode::Grid
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum SkillDisplayMode {
|
||||
Grid, // For skills page
|
||||
Chips, // For experience cards
|
||||
}
|
||||
|
||||
// Skill data constants and helper functions
|
||||
pub mod skill_data {
|
||||
use super::*;
|
||||
|
||||
// Image assets
|
||||
const JS_IMAGE: Asset = asset!("/assets/images/js.png");
|
||||
const PHP_IMAGE: Asset = asset!("/assets/images/php.jpg");
|
||||
const PYTHON_IMAGE: Asset = asset!("/assets/images/python-logo.png");
|
||||
const SQL_IMAGE: Asset = asset!("/assets/images/sql-logo.jpg");
|
||||
const PLSQL_IMAGE: Asset = asset!("/assets/images/plsql-logo.png");
|
||||
const RUST_IMAGE: Asset = asset!("/assets/images/rust-logo.png");
|
||||
const AUTO_IT_IMAGE: Asset = asset!("/assets/images/autoit-logo.jpg");
|
||||
const HTML_IMAGE: Asset = asset!("/assets/images/html-logo.png");
|
||||
const CSS_IMAGE: Asset = asset!("/assets/images/css-logo.png");
|
||||
const SASS_IMAGE: Asset = asset!("/assets/images/sass-logo.png");
|
||||
const LARAVEL_IMAGE: Asset = asset!("/assets/images/laravel-logo.png");
|
||||
const CODEIGNITER_IMAGE: Asset = asset!("/assets/images/codeigniter-logo.png");
|
||||
const REACTJS_IMAGE: Asset = asset!("/assets/images/reactjs-logo.png");
|
||||
const SVELTE_IMAGE: Asset = asset!("/assets/images/svelte-logo.png");
|
||||
const D3JS_IMAGE: Asset = asset!("/assets/images/d3js-logo.png");
|
||||
const PHASERIO_IMAGE: Asset = asset!("/assets/images/phaser-logo.png");
|
||||
const FASTAPI_IMAGE: Asset = asset!("/assets/images/fastapi-logo.jpg");
|
||||
const DIOXUS_IMAGE: Asset = asset!("/assets/images/dioxus-logo.png");
|
||||
const TAILWINDCSS_IMAGE: Asset = asset!("/assets/images/tailwindcss-logo.png");
|
||||
const BOOTSTRAP_IMAGE: Asset = asset!("/assets/images/bootstrap-logo.png");
|
||||
const SEMANTICUI_IMAGE: Asset = asset!("/assets/images/semanticui-logo.png");
|
||||
const AWS_IMAGE: Asset = asset!("/assets/images/aws-logo.png");
|
||||
const GCP_IMAGE: Asset = asset!("/assets/images/gcp-logo.png");
|
||||
const OVH_IMAGE: Asset = asset!("/assets/images/ovh-logo.png");
|
||||
const CLOUDFLARE_IMAGE: Asset = asset!("/assets/images/cloudflare-logo.png");
|
||||
const GIT_IMAGE: Asset = asset!("/assets/images/git-logo.png");
|
||||
const DOCKER_IMAGE: Asset = asset!("/assets/images/docker-logo.png");
|
||||
const OUTSYSTEMS_IMAGE: Asset = asset!("/assets/images/outsystems-logo.png");
|
||||
const TERRAFORM_IMAGE: Asset = asset!("/assets/images/terraform-logo.png");
|
||||
|
||||
// Helper function to get skill by name/abbreviation
|
||||
pub fn get_skill_by_name(name: &str) -> Option<Skill> {
|
||||
match name.to_lowercase().as_str() {
|
||||
"javascript" | "js" => Some(javascript_skill()),
|
||||
"html" => Some(html_skill()),
|
||||
"css" => Some(css_skill()),
|
||||
"php" => Some(php_skill()),
|
||||
"python" => Some(python_skill()),
|
||||
"sql" => Some(sql_skill()),
|
||||
"rust" => Some(rust_skill()),
|
||||
"laravel" => Some(laravel_skill()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
// Programming
|
||||
pub fn javascript_skill() -> Skill {
|
||||
Skill {
|
||||
name: "JAVASCRIPT",
|
||||
abbreviation: "JS",
|
||||
image: Some(JS_IMAGE),
|
||||
bg_color: "#f7df1e",
|
||||
border_color: "#f7df1e80",
|
||||
drop_color: "#f7df1e26",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn php_skill() -> Skill {
|
||||
Skill {
|
||||
name: "PHP",
|
||||
abbreviation: "PHP",
|
||||
image: Some(PHP_IMAGE),
|
||||
bg_color: "#777bb4",
|
||||
border_color: "#777bb480",
|
||||
drop_color: "#777bb426",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn python_skill() -> Skill {
|
||||
Skill {
|
||||
name: "PYTHON",
|
||||
abbreviation: "PY",
|
||||
image: Some(PYTHON_IMAGE),
|
||||
bg_color: "#3776ab",
|
||||
border_color: "#3776ab80",
|
||||
drop_color: "#3776ab26",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rust_skill() -> Skill {
|
||||
Skill {
|
||||
name: "RUST",
|
||||
abbreviation: "RS",
|
||||
image: Some(RUST_IMAGE),
|
||||
bg_color: "#ce422b",
|
||||
border_color: "#ce422b80",
|
||||
drop_color: "#ce422b26",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sql_skill() -> Skill {
|
||||
Skill {
|
||||
name: "SQL",
|
||||
abbreviation: "SQL",
|
||||
image: Some(SQL_IMAGE),
|
||||
bg_color: "#336791",
|
||||
border_color: "#33679180",
|
||||
drop_color: "#33679126",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn plsql_skill() -> Skill {
|
||||
Skill {
|
||||
name: "PL/SQL",
|
||||
abbreviation: "PLSQL",
|
||||
image: Some(PLSQL_IMAGE),
|
||||
bg_color: "#d6393c",
|
||||
border_color: "#d6393c",
|
||||
drop_color: "#d6393c",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn autoit_skill() -> Skill {
|
||||
Skill {
|
||||
name: "AUTO IT",
|
||||
abbreviation: "AIT",
|
||||
image: Some(AUTO_IT_IMAGE),
|
||||
bg_color: "#ffff0003",
|
||||
border_color: "#ffff0080",
|
||||
drop_color: "#ffff0026",
|
||||
}
|
||||
}
|
||||
|
||||
// Markup & Style
|
||||
pub fn html_skill() -> Skill {
|
||||
Skill {
|
||||
name: "HTML",
|
||||
abbreviation: "HTML",
|
||||
image: Some(HTML_IMAGE),
|
||||
bg_color: "#e34f26",
|
||||
border_color: "#e34f2680",
|
||||
drop_color: "#e34f2626",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn css_skill() -> Skill {
|
||||
Skill {
|
||||
name: "CSS",
|
||||
abbreviation: "CSS",
|
||||
image: Some(CSS_IMAGE),
|
||||
bg_color: "#1572b6",
|
||||
border_color: "#1572b680",
|
||||
drop_color: "#1572b626",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sass_skill() -> Skill {
|
||||
Skill {
|
||||
name: "SASS",
|
||||
abbreviation: "SASS",
|
||||
image: Some(SASS_IMAGE),
|
||||
bg_color: "#B755B1",
|
||||
border_color: "#B755B1",
|
||||
drop_color: "#B755B1",
|
||||
}
|
||||
}
|
||||
|
||||
//Frameworks
|
||||
pub fn laravel_skill() -> Skill {
|
||||
Skill {
|
||||
name: "LARAVEL",
|
||||
abbreviation: "LARAVEL",
|
||||
image: Some(LARAVEL_IMAGE),
|
||||
bg_color: "#f53003",
|
||||
border_color: "#f53003",
|
||||
drop_color: "#f53003",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn codeigniter_skill() -> Skill {
|
||||
Skill {
|
||||
name: "CODEIGNITER",
|
||||
abbreviation: "CI",
|
||||
image: Some(CODEIGNITER_IMAGE),
|
||||
bg_color: "#dd4814",
|
||||
border_color: "#dd4814",
|
||||
drop_color: "#dd4814",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reactjs_skill() -> Skill {
|
||||
Skill {
|
||||
name: "REACTJS",
|
||||
abbreviation: "REACTJS",
|
||||
image: Some(REACTJS_IMAGE),
|
||||
bg_color: "#2D89C9",
|
||||
border_color: "#2D89C9",
|
||||
drop_color: "#2D89C9",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn svelte_skill() -> Skill {
|
||||
Skill {
|
||||
name: "SVELTE",
|
||||
abbreviation: "SVELTE",
|
||||
image: Some(SVELTE_IMAGE),
|
||||
bg_color: "#FF5100",
|
||||
border_color: "#FF5100",
|
||||
drop_color: "#FF5100",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn d3js_skill() -> Skill {
|
||||
Skill {
|
||||
name: "D3.JS",
|
||||
abbreviation: "D3.JS",
|
||||
image: Some(D3JS_IMAGE),
|
||||
bg_color: "#FF7D00",
|
||||
border_color: "#FF7D00",
|
||||
drop_color: "#FF7D00",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn phaserio_skill() -> Skill {
|
||||
Skill {
|
||||
name: "PHASER.IO",
|
||||
abbreviation: "PHASER.IO",
|
||||
image: Some(PHASERIO_IMAGE),
|
||||
bg_color: "#62eff7",
|
||||
border_color: "#62eff7",
|
||||
drop_color: "#62eff7",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fastapi_skill() -> Skill {
|
||||
Skill {
|
||||
name: "FAST API",
|
||||
abbreviation: "FASTAPI",
|
||||
image: Some(FASTAPI_IMAGE),
|
||||
bg_color: "#009485",
|
||||
border_color: "#009485",
|
||||
drop_color: "#009485",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dioxus_skill() -> Skill {
|
||||
Skill {
|
||||
name: "DIOXUS",
|
||||
abbreviation: "DIOXUS",
|
||||
image: Some(DIOXUS_IMAGE),
|
||||
bg_color: "#EF7E2B",
|
||||
border_color: "#EF7E2B",
|
||||
drop_color: "#EF7E2B",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tailwindcss_skill() -> Skill {
|
||||
Skill {
|
||||
name: "TAILWIND CSS",
|
||||
abbreviation: "TAILWINDCSS",
|
||||
image: Some(TAILWINDCSS_IMAGE),
|
||||
bg_color: "#4CADDC",
|
||||
border_color: "#4CADDC",
|
||||
drop_color: "#4CADDC",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bootstrap_skill() -> Skill {
|
||||
Skill {
|
||||
name: "BOOTSTRAP",
|
||||
abbreviation: "BOOTSTRAP",
|
||||
image: Some(BOOTSTRAP_IMAGE),
|
||||
bg_color: "#922BEF",
|
||||
border_color: "#922BEF",
|
||||
drop_color: "#922BEF",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn semanticui_skill() -> Skill {
|
||||
Skill {
|
||||
name: "SEMANTIC UI",
|
||||
abbreviation: "SEMANTIC_UI",
|
||||
image: Some(SEMANTICUI_IMAGE),
|
||||
bg_color: "#15B5B9",
|
||||
border_color: "#15B5B9",
|
||||
drop_color: "#15B5B9",
|
||||
}
|
||||
}
|
||||
|
||||
// Cloud Platforms
|
||||
pub fn aws_skill() -> Skill {
|
||||
Skill {
|
||||
name: "AMAZON (AWS)",
|
||||
abbreviation: "AWS",
|
||||
image: Some(AWS_IMAGE),
|
||||
bg_color: "#EC8439",
|
||||
border_color: "#EC8439",
|
||||
drop_color: "#EC8439",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn gcp_skill() -> Skill {
|
||||
Skill {
|
||||
name: "GOOGLE CLOUD PLATFORM",
|
||||
abbreviation: "GCP",
|
||||
image: Some(GCP_IMAGE),
|
||||
bg_color: "#3984EC",
|
||||
border_color: "#3984EC",
|
||||
drop_color: "#3984EC",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ovh_skill() -> Skill {
|
||||
Skill {
|
||||
name: "OVHCLOUD",
|
||||
abbreviation: "OVH",
|
||||
image: Some(OVH_IMAGE),
|
||||
bg_color: "#1537B9",
|
||||
border_color: "#1537B9",
|
||||
drop_color: "#1537B9",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cloudflare_skill() -> Skill {
|
||||
Skill {
|
||||
name: "CLOUDFLARE",
|
||||
abbreviation: "CF",
|
||||
image: Some(CLOUDFLARE_IMAGE),
|
||||
bg_color: "#ea9f2e",
|
||||
border_color: "#ea9f2e",
|
||||
drop_color: "#ea9f2e",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn git_skill() -> Skill {
|
||||
Skill {
|
||||
name: "GIT",
|
||||
abbreviation: "GIT",
|
||||
image: Some(GIT_IMAGE),
|
||||
bg_color: "#DE570D",
|
||||
border_color: "#DE570D",
|
||||
drop_color: "#DE570D",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn docker_skill() -> Skill {
|
||||
Skill {
|
||||
name: "DOCKER",
|
||||
abbreviation: "DOCKER",
|
||||
image: Some(DOCKER_IMAGE),
|
||||
bg_color: "#1F95DA",
|
||||
border_color: "#1F95DA",
|
||||
drop_color: "#1F95DA",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn outsystem_skill() -> Skill {
|
||||
Skill {
|
||||
name: "OUTSYSTEMS",
|
||||
abbreviation: "OUTSYSTEMS",
|
||||
image: Some(OUTSYSTEMS_IMAGE),
|
||||
bg_color: "#BD2031",
|
||||
border_color: "#BD2031",
|
||||
drop_color: "#BD2031",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn terraform_skill() -> Skill {
|
||||
Skill {
|
||||
name: "TERRAFORM",
|
||||
abbreviation: "TF",
|
||||
image: Some(TERRAFORM_IMAGE),
|
||||
bg_color: "#8179ea",
|
||||
border_color: "#8179ea",
|
||||
drop_color: "#8179ea",
|
||||
}
|
||||
}
|
||||
|
||||
// Get all skill categories for the skills page
|
||||
pub fn get_all_skill_categories() -> Vec<SkillCategory> {
|
||||
vec![
|
||||
SkillCategory {
|
||||
name: "Programming Languages",
|
||||
skills: vec![
|
||||
javascript_skill(),
|
||||
php_skill(),
|
||||
python_skill(),
|
||||
sql_skill(),
|
||||
plsql_skill(),
|
||||
rust_skill(),
|
||||
autoit_skill(),
|
||||
],
|
||||
},
|
||||
SkillCategory {
|
||||
name: "Markup & Style",
|
||||
skills: vec![html_skill(), css_skill(), sass_skill()],
|
||||
},
|
||||
SkillCategory {
|
||||
name: "Frameworks",
|
||||
skills: vec![
|
||||
laravel_skill(),
|
||||
codeigniter_skill(),
|
||||
reactjs_skill(),
|
||||
svelte_skill(),
|
||||
d3js_skill(),
|
||||
phaserio_skill(),
|
||||
fastapi_skill(),
|
||||
dioxus_skill(),
|
||||
tailwindcss_skill(),
|
||||
bootstrap_skill(),
|
||||
semanticui_skill(),
|
||||
],
|
||||
},
|
||||
SkillCategory {
|
||||
name: "Cloud Platforms",
|
||||
skills: vec![aws_skill(), gcp_skill(), ovh_skill(), cloudflare_skill()],
|
||||
},
|
||||
SkillCategory {
|
||||
name: "Other Tools",
|
||||
skills: vec![
|
||||
git_skill(),
|
||||
docker_skill(),
|
||||
outsystem_skill(),
|
||||
terraform_skill(),
|
||||
],
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
+19
-11
@@ -2,7 +2,7 @@
|
||||
// need dioxus
|
||||
use dioxus::prelude::*;
|
||||
|
||||
use views::{Blog, Home, Navbar, Skills, Projects, Experiences};
|
||||
use views::{Blog, Experiences, Home, Navbar, Projects, Skills};
|
||||
|
||||
/// Define a components module that contains all shared components for our app.
|
||||
mod components;
|
||||
@@ -11,7 +11,7 @@ mod views;
|
||||
|
||||
/// The Route enum is used to define the structure of internal routes in our app. All route enums need to derive
|
||||
/// the [`Routable`] trait, which provides the necessary methods for the router to work.
|
||||
///
|
||||
///
|
||||
/// Each variant represents a different URL pattern that can be matched by the router. If that pattern is matched,
|
||||
/// the components for that route will be rendered.
|
||||
#[derive(Debug, Clone, Routable, PartialEq)]
|
||||
@@ -43,14 +43,17 @@ enum Route {
|
||||
|
||||
// We can import assets in dioxus with the `asset!` macro. This macro takes a path to an asset relative to the crate root.
|
||||
// The macro returns an `Asset` type that will display as the path to the asset in the browser or a local path in desktop bundles.
|
||||
const FAVICON: Asset = asset!("/assets/favicon.ico");
|
||||
const FAVICON: Asset = asset!("/assets/favicon/favicon.ico");
|
||||
const FAVICON_16: Asset = asset!("/assets/favicon/favicon-16x16.png");
|
||||
const FAVICON_32: Asset = asset!("/assets/favicon/favicon-32x32.png");
|
||||
const FAVICON_APPLE: Asset = asset!("/assets/favicon/apple-touch-icon.png");
|
||||
const FAVICON_MANIFEST: Asset = asset!("/assets/favicon/site.webmanifest");
|
||||
// The asset macro also minifies some assets like CSS and JS to make bundled smaller
|
||||
const TAILWIND_CSS: Asset = asset!("/assets/tailwind.css");
|
||||
const MEDIA_CSS: Asset = asset!("/assets/styling/media.css");
|
||||
const TAILWIND_CSS: Asset = asset!("/assets/styling/tailwind.css");
|
||||
// const MEDIA_CSS: Asset = asset!("/assets/styling/media.css");
|
||||
const MAIN_CSS: Asset = asset!("/assets/styling/main.css");
|
||||
const ICONS_CSS: Asset = asset!("/assets/styling/icons.css");
|
||||
|
||||
|
||||
fn main() {
|
||||
// The `launch` function is the main entry point for a dioxus app. It takes a component and renders it with the platform feature
|
||||
// you have enabled
|
||||
@@ -68,16 +71,21 @@ fn App() -> Element {
|
||||
rsx! {
|
||||
// In addition to element and text (which we will see later), rsx can contain other components. In this case,
|
||||
// we are using the `document::Link` component to add a link to our favicon and main CSS file into the head of our app.
|
||||
document::Link { rel: "apple-touch-icon", sizes: "180x180", href:FAVICON_APPLE}
|
||||
document::Link { rel: "icon", href: FAVICON }
|
||||
document::Link { rel: "stylesheet", href: TAILWIND_CSS }
|
||||
document::Link { rel: "stylesheet", href: MEDIA_CSS }
|
||||
document::Link { rel: "stylesheet", href: MAIN_CSS }
|
||||
document::Link { rel: "stylesheet", href: ICONS_CSS }
|
||||
document::Link { rel: "icon", href: FAVICON_16, sizes:"16x16" }
|
||||
document::Link { rel: "icon", href: FAVICON_32, sizes:"32x32" }
|
||||
document::Link { rel: "icon", href: FAVICON_MANIFEST}
|
||||
|
||||
document::Stylesheet { rel: "stylesheet", href: TAILWIND_CSS }
|
||||
// document::Link { rel: "stylesheet", href: MEDIA_CSS }
|
||||
document::Stylesheet { rel: "stylesheet", href: MAIN_CSS }
|
||||
document::Stylesheet { rel: "stylesheet", href: ICONS_CSS }
|
||||
|
||||
// The router component renders the route enum we defined above. It will handle synchronization of the URL and render
|
||||
// the layouts and components for the active route.
|
||||
div {
|
||||
class: "body contents mb6t29",
|
||||
class: "body",
|
||||
"data-Theme": if is_dark_theme { "dark" } else { "light" },
|
||||
Router::<Route> {}
|
||||
}
|
||||
|
||||
+17
-120
@@ -1,138 +1,35 @@
|
||||
use crate::components::ExperienceList;
|
||||
use crate::Route;
|
||||
use dioxus::{html::{div, input}, prelude::*};
|
||||
use dioxus::prelude::*;
|
||||
|
||||
// const SKILL_CSS: Asset = asset!("/assets/styling/blog.css");
|
||||
const EXPERIENCE_CSS: Asset = asset!("/assets/styling/experience.css");
|
||||
|
||||
#[component]
|
||||
pub fn Experiences() -> Element {
|
||||
rsx! {
|
||||
div {
|
||||
class: "content container mb6t29",
|
||||
document::Stylesheet { href: EXPERIENCE_CSS }
|
||||
|
||||
div {
|
||||
class: "content",
|
||||
div {
|
||||
class: "flex-1 col gap-5 px-2 sm:px-4 md:px-6 py-4 sm:py-8 md:py-12",
|
||||
|
||||
// Header
|
||||
h1 {
|
||||
class: "font-[var(--title-f)] font-black tracking-[4px] text-center text-2.5em sm:text-[3em] md:text-[3.5em] lg:text-[4em]",
|
||||
"Experiences"
|
||||
"Experience"
|
||||
}
|
||||
|
||||
div {
|
||||
class: "col gap-5 flex-1",
|
||||
|
||||
div { class: "w-100% col flex-1",
|
||||
div { class:"col items-center relative mt-10 flex-1",
|
||||
div {class:"w-[0.5px] hidden lg:flex top-0 bottom-0 py-50px bg-[var(--border)] absolute rounded"}
|
||||
div { class: "flex flex-row-reverse relative items-center w-full my-[10px]",
|
||||
div { class: "flex-1 hidden lg:flex"}
|
||||
div { class: "hidden lg:inline p-15px bg-[var(--main)] rounded",
|
||||
i { class: "i-carbon-condition-point"}
|
||||
}
|
||||
div { class:" flex-1 col items-stretch",
|
||||
a { class:" card text-inherit decoration-none inline-flex flex-col border-1px border-solid border-[var(--border)] rounded-15px duration relative d1441skb",
|
||||
style:" margin: 0px 0px 20px; --border-color: #ff000080; --drop-color: #ff000026; --bg-color: #ff000003;",
|
||||
div { class: "card-bg-img flex-1 flex flex-col p-25px rounded-15px d1441skb",
|
||||
div { class: "col md:flex-row items-start gap-5 md:gap-1",
|
||||
div{ class: "col ml-0 md:ml-[20px] gap-3 w-full",
|
||||
div { class: "col ",
|
||||
h3 { class: "flex text-[0.9em] flex-col items-start sm:flex-row sm:items-center justify-between sm:gap-5 md:flex-col md:items-start md:gap-0 lg:flex-row lg:items-center",
|
||||
h3 { class: "font-[var(--title-f)] text-1.25em",
|
||||
"Experience 1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
div {class: "text-[var(--text)] text-[0.9em]",
|
||||
div {class: "row items-center gap-2",
|
||||
i { class: "i-carbon-calendar text-1.25em"}
|
||||
"Jan 2025 - Present"
|
||||
}
|
||||
|
||||
div { class: "bg-[var(--border)] h-1px m-y-10px"}
|
||||
|
||||
div { class: "row items-center gap-2",
|
||||
i { class: "i-carbon-time text-1.25em" }
|
||||
"4 Years"
|
||||
}
|
||||
|
||||
div { class: "bg-[var(--border)] h-1px m-y-10px"}
|
||||
}
|
||||
|
||||
div { class: "experience-description text-[0.9em]",
|
||||
"Creating awesome tools for developers."
|
||||
}
|
||||
|
||||
div { class: "flex flex-row flex-wrap mt-5",
|
||||
a { class: "chip-icon row-center relative text-inherit decoration-none p-10px m-r-5px m-b-5px border-1px border-solid border-[var(--border)] hover:border-[var(--border-hover)] rounded-10px hover:z-5 cursor-pointer grayscale-65 hover:grayscale-0 d1m94jop",
|
||||
"data-Help": "Rust",
|
||||
img {class: "w-15px h-15px d1m94jop",
|
||||
alt: "Rust"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
div { class: "flex flex-row relative items-center w-full my-[10px]",
|
||||
div { class: "flex-1 hidden lg:flex"}
|
||||
div { class: "hidden lg:inline p-15px bg-[var(--main)] rounded",
|
||||
i { class: "i-carbon-condition-point"}
|
||||
}
|
||||
div { class:" flex-1 col items-stretch",
|
||||
a { class:" card text-inherit decoration-none inline-flex flex-col border-1px border-solid border-[var(--border)] rounded-15px duration relative d1441skb",
|
||||
style:" margin: 0px 0px 20px; --border-color: #ff000080; --drop-color: #ff000026; --bg-color: #ff000003;",
|
||||
div { class: "card-bg-img flex-1 flex flex-col p-25px rounded-15px d1441skb",
|
||||
div { class: "col md:flex-row items-start gap-5 md:gap-1",
|
||||
div{ class: "col ml-0 md:ml-[20px] gap-3 w-full",
|
||||
div { class: "col ",
|
||||
h3 { class: "flex text-[0.9em] flex-col items-start sm:flex-row sm:items-center justify-between sm:gap-5 md:flex-col md:items-start md:gap-0 lg:flex-row lg:items-center",
|
||||
h3 { class: "font-[var(--title-f)] text-1.25em",
|
||||
"Experience 1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
div {class: "text-[var(--text)] text-[0.9em]",
|
||||
div {class: "row items-center gap-2",
|
||||
i { class: "i-carbon-calendar text-1.25em"}
|
||||
"Jan 2025 - Present"
|
||||
}
|
||||
|
||||
div { class: "bg-[var(--border)] h-1px m-y-10px"}
|
||||
|
||||
div { class: "row items-center gap-2",
|
||||
i { class: "i-carbon-time text-1.25em" }
|
||||
"4 Years"
|
||||
}
|
||||
|
||||
div { class: "bg-[var(--border)] h-1px m-y-10px"}
|
||||
}
|
||||
|
||||
div { class: "experience-description text-[0.9em]",
|
||||
"Creating awesome tools for developers."
|
||||
}
|
||||
|
||||
div { class: "flex flex-row flex-wrap mt-5",
|
||||
a { class: "chip-icon row-center relative text-inherit decoration-none p-10px m-r-5px m-b-5px border-1px border-solid border-[var(--border)] hover:border-[var(--border-hover)] rounded-10px hover:z-5 cursor-pointer grayscale-65 hover:grayscale-0 d1m94jop",
|
||||
"data-Help": "Rust",
|
||||
img {class: "w-15px h-15px d1m94jop",
|
||||
alt: "Rust"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Timeline Container
|
||||
div {
|
||||
class: "col gap-2 flex-1",
|
||||
div {
|
||||
class: "w-100% col flex-1",
|
||||
ExperienceList {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Outlet::<Route> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+33
-61
@@ -1,8 +1,10 @@
|
||||
use crate::components::{BottomSheetMenu, QuickMenuButton};
|
||||
use crate::Route;
|
||||
use dioxus::prelude::*;
|
||||
|
||||
// use dioxus_logger::tracing::{Level, info};
|
||||
|
||||
const NAVBAR_CSS: Asset = asset!("/assets/styling/navbar.css");
|
||||
const MAIN_CSS: Asset = asset!("/assets/styling/main.css");
|
||||
|
||||
/// The Navbar component that will be rendered on all pages of our app since every page is under the layout.
|
||||
///
|
||||
@@ -11,39 +13,34 @@ const MAIN_CSS: Asset = asset!("/assets/styling/main.css");
|
||||
/// routes will be rendered under the outlet inside this component
|
||||
#[component]
|
||||
pub fn Navbar() -> Element {
|
||||
let mut show_menu = use_signal(|| false);
|
||||
rsx! {
|
||||
document::Link { rel: "stylesheet", href: NAVBAR_CSS }
|
||||
|
||||
|
||||
div {
|
||||
class: "nav-menu jdc7ud",
|
||||
nav {
|
||||
class: "container flex flex-row items-center text-sm",
|
||||
class: "container md:flex flex-row items-center text-sm hidden",
|
||||
Link {
|
||||
to: Route::Home {},
|
||||
class: "nav-menu-left decoration-none w-auto md:w-150px lg:w-auto row flex flex-row items-center cursor-pointer px-4 text-[var(--secondary-text)] self-stretch hover:bg-[color:var(--main-hover)]",
|
||||
i {
|
||||
class: "i-carbon-code text-2em"
|
||||
class: "i-carbon-code"
|
||||
}
|
||||
span {
|
||||
class: "ml-2 text-md font-bold hidden md:inline overflow-hidden whitespace-nowrap text-ellipsis",
|
||||
span {
|
||||
class: "h2 ml-2 text-md font-bold hidden md:inline overflow-hidden whitespace-nowrap text-ellipsis",
|
||||
"Danilo"
|
||||
" "
|
||||
"Cesa"
|
||||
}
|
||||
}
|
||||
div {
|
||||
class: "flex-1 block overflow-hidden md:hidden whitespace-nowrap text-ellipsis text-center",
|
||||
"Danilo"
|
||||
" "
|
||||
"Cesa"
|
||||
}
|
||||
div {
|
||||
class: "flex-row flex-1 self-center h-full justify-center hidden md:flex",
|
||||
class: "flex-row flex-1 self-center h-full justify-center md:flex hidden",
|
||||
Link {
|
||||
to: Route::Skills {},
|
||||
class: "nav-menu-item !text-[var(--secondary-text)] jdc7ud",
|
||||
i {
|
||||
class: "i-carbon-software-resource-cluster text-1.3em"
|
||||
class: "i-carbon-software-resource-cluster"
|
||||
}
|
||||
span {
|
||||
class: "nav-menu-item-label jdc7ud",
|
||||
@@ -51,17 +48,17 @@ pub fn Navbar() -> Element {
|
||||
}
|
||||
}
|
||||
|
||||
Link {
|
||||
class: "nav-menu-item !text-[var(--secondary-text)] jdc7ud",
|
||||
to: Route::Projects {},
|
||||
i {
|
||||
class: "i-carbon-cube text-1.3em"
|
||||
}
|
||||
span {
|
||||
class: "nav-menu-item-label jdc7ud",
|
||||
"Projects"
|
||||
}
|
||||
}
|
||||
// Link {
|
||||
// class: "nav-menu-item !text-[var(--secondary-text)] jdc7ud",
|
||||
// to: Route::Projects {},
|
||||
// i {
|
||||
// class: "i-carbon-cube text-2em"
|
||||
// }
|
||||
// span {
|
||||
// class: "nav-menu-item-label jdc7ud",
|
||||
// "Projects"
|
||||
// }
|
||||
// }
|
||||
|
||||
Link {
|
||||
class: "nav-menu-item !text-[var(--secondary-text)] jdc7ud",
|
||||
@@ -74,48 +71,23 @@ pub fn Navbar() -> Element {
|
||||
"Experiences"
|
||||
}
|
||||
}
|
||||
|
||||
Link {
|
||||
class: "nav-menu-item !text-[var(--secondary-text)] jdc7ud",
|
||||
to: Route::Home {},
|
||||
i {
|
||||
class: "i-carbon-result text-1.3em"
|
||||
}
|
||||
span {
|
||||
class: "nav-menu-item-label jdc7ud",
|
||||
"Resume"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// div {
|
||||
// class: "row h-full justify-center items-stretch m-l-auto md:m-l-0 w-auto md:w-150px gap-1 text-1.15em",
|
||||
// div {
|
||||
// class: "row hidden md:flex",
|
||||
// // a {
|
||||
// // class: "text-inherit col-center self-stretch px-2 hover:bg-[color:var(--main-hover)]"
|
||||
// // }
|
||||
// // button {
|
||||
// // class: "bg-transparent text-1em border-none cursor-pointer hover:bg-[color:var(--main-hover)] text-[var(--secondary-text)] px-2",
|
||||
// // i {
|
||||
// // class: "i-carbon-moon"
|
||||
// // }
|
||||
// // }
|
||||
// }
|
||||
|
||||
// div {
|
||||
// class: "col-center md:hidden h-full hover:bg-[var(--main-hover)] cursor-pointer",
|
||||
// div {
|
||||
// class: "nav-bar-mobile-btn col-center jdc7ud"
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
if !show_menu() {
|
||||
QuickMenuButton {
|
||||
on_click: move |_| show_menu.set(true)
|
||||
}
|
||||
}
|
||||
|
||||
// Bottom Sheet Menu
|
||||
BottomSheetMenu {
|
||||
show: show_menu(),
|
||||
on_close: move |_| show_menu.set(false)
|
||||
}
|
||||
|
||||
// The `Outlet` component is used to render the next component inside the layout. In this case, it will render either
|
||||
// the [`Home`] or [`Blog`] component depending on the current route.
|
||||
Outlet::<Route> {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
use crate::Route;
|
||||
use dioxus::{html::input, prelude::*};
|
||||
|
||||
// const SKILL_CSS: Asset = asset!("/assets/styling/blog.css");
|
||||
use dioxus::prelude::*;
|
||||
|
||||
#[component]
|
||||
pub fn Projects() -> Element {
|
||||
rsx! {
|
||||
div {
|
||||
div {
|
||||
class: "content container mb6t29",
|
||||
div {
|
||||
class: "flex-1 col gap-5 px-2 sm:px-4 md:px-6 py-4 sm:py-8 md:py-12",
|
||||
@@ -14,10 +12,10 @@ pub fn Projects() -> Element {
|
||||
class: "font-[var(--title-f)] font-black tracking-[4px] text-center text-2.5em sm:text-[3em] md:text-[3.5em] lg:text-[4em]",
|
||||
"Projects"
|
||||
}
|
||||
|
||||
div {
|
||||
|
||||
div {
|
||||
class: "col gap-5 flex-1",
|
||||
div {
|
||||
div {
|
||||
class: "w-100% row",
|
||||
input {
|
||||
class: "text-[inherit] bg-transparent border-[1px] border-solid border-[var(--border)] px-[20px] py-[10px] rounded-[15px] flex-1 text-[1.15em] c0g44u",
|
||||
@@ -77,7 +75,7 @@ pub fn Projects() -> Element {
|
||||
div { class: "row flex-wrap",
|
||||
a { class: "chip-icon row-center relative text-inherit decoration-none p-10px m-r-5px m-b-5px border-1px border-solid border-[var(--border)] hover:border-[var(--border-hover)] rounded-10px hover:z-5 cursor-pointer grayscale-65 hover:grayscale-0 d1m94jop",
|
||||
img { class: "w-15px h-15px d1m94jop",
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -90,4 +88,4 @@ pub fn Projects() -> Element {
|
||||
}
|
||||
Outlet::<Route> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+50
-50
@@ -1,68 +1,68 @@
|
||||
use crate::components::{skill_data, SkillCategorySection};
|
||||
use crate::Route;
|
||||
use dioxus::{html::input, prelude::*};
|
||||
|
||||
// const SKILL_CSS: Asset = asset!("/assets/styling/blog.css");
|
||||
use dioxus::prelude::*;
|
||||
|
||||
#[component]
|
||||
pub fn Skills() -> Element {
|
||||
let skill_categories = skill_data::get_all_skill_categories();
|
||||
let mut search_query = use_signal(|| String::new());
|
||||
|
||||
let filtered_categories = use_memo(move || {
|
||||
let query = search_query.read().to_lowercase();
|
||||
if query.is_empty() {
|
||||
skill_categories.clone()
|
||||
} else {
|
||||
skill_categories
|
||||
.iter()
|
||||
.map(|category| {
|
||||
let filtered_skills: Vec<_> = category
|
||||
.skills
|
||||
.iter()
|
||||
.filter(|skill| skill.name.to_lowercase().contains(&query))
|
||||
.cloned()
|
||||
.collect();
|
||||
|
||||
crate::components::SkillCategory {
|
||||
name: category.name,
|
||||
skills: filtered_skills,
|
||||
}
|
||||
})
|
||||
.filter(|category| !category.skills.is_empty()) // Only show categories with matching skills
|
||||
.collect()
|
||||
}
|
||||
});
|
||||
|
||||
rsx! {
|
||||
div {
|
||||
class: "content container mb6t29",
|
||||
div {
|
||||
class: "flex-1 col gap-5 px-2 sm:px-4 md:px-6 py-4 sm:py-8 md:py-12",
|
||||
div { class: "content",
|
||||
div { class: "flex-1 col gap-5 px-2 sm:px-4 md:px-6 py-4 sm:py-8 md:py-12",
|
||||
h1 {
|
||||
class: "font-[var(--title-f)] font-black tracking-[4px] text-center text-2.5em sm:text-[3em] md:text-[3.5em] lg:text-[4em]",
|
||||
"Skills"
|
||||
}
|
||||
|
||||
div {
|
||||
class: "col gap-5 flex-1",
|
||||
div {
|
||||
class: "w-100% row",
|
||||
|
||||
div { class: "flex-1",
|
||||
div { class: "w-full row",
|
||||
input {
|
||||
class: "text-[inherit] bg-transparent border-[1px] border-solid border-[var(--border)] px-[20px] py-[10px] rounded-[15px] flex-1 text-[1.15em] c0g44u",
|
||||
class: "text-[inherit] bg-transparent border-[1px] border-solid border-[var(--border)] px-[20px] py-[10px] rounded-[15px] flex-1 text-[1.15em] w-full",
|
||||
type: "text",
|
||||
placeholder: "Search skills..."
|
||||
placeholder: "Search skills...",
|
||||
value: "{search_query}",
|
||||
oninput: move |event| {
|
||||
search_query.set(event.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
div { class: "w-100% col flex-1",
|
||||
div { class: "w-full col flex-1",
|
||||
div { class: "col mt-5 gap-7",
|
||||
div { class: "col gap-5 mb-7",
|
||||
div { class: "row items-center gap-5",
|
||||
div { class: "bg-[var(--main-hover)] h-[1px] w-[20px]"}
|
||||
p {
|
||||
class: "text-[var(--main-close)]",
|
||||
"Programming Languages"
|
||||
}
|
||||
div { class: "flex-1 bg-[var(--main-hover)] h-[1px]"}
|
||||
}
|
||||
|
||||
if filtered_categories().is_empty() && !search_query.read().is_empty() {
|
||||
div {
|
||||
class: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-2 md:gap-3 lg:gap-5",
|
||||
a {
|
||||
class: "card text-inherit decoration-none inline-flex flex-col border-1px border-solid border-[var(--border)] rounded-15px duration relative cursor-pointer decoration-none d1441skb",
|
||||
style: "margin: 0px; --bg-img: url(.png); --border-color: #ffff0080; --drop-color: #ffff0026; --bg-color: #ffff0003;",
|
||||
div {
|
||||
class: "card-bg-img flex-1 flex flex-col p-25px rounded-15px d1441skb",
|
||||
div {
|
||||
class: "text-[var(--tertiary-text)]",
|
||||
"Javascript"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
class: "card text-inherit decoration-none inline-flex flex-col border-1px border-solid border-[var(--border)] rounded-15px duration relative cursor-pointer decoration-none d1441skb",
|
||||
style: "margin: 0px; --bg-img: url(.png); --border-color: #ffff0080; --drop-color: #ffff0026; --bg-color: #ffff0003;",
|
||||
div {
|
||||
class: "card-bg-img flex-1 flex flex-col p-25px rounded-15px d1441skb",
|
||||
div {
|
||||
class: "text-[var(--tertiary-text)]",
|
||||
"PHP"
|
||||
}
|
||||
}
|
||||
}
|
||||
class: "text-center py-8 text-[var(--secondary-text)]",
|
||||
"No skills found matching your search."
|
||||
}
|
||||
} else {
|
||||
for category in filtered_categories() {
|
||||
SkillCategorySection { category: category }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -72,4 +72,4 @@ pub fn Skills() -> Element {
|
||||
}
|
||||
Outlet::<Route> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user