249 lines
7.9 KiB
Rust
249 lines
7.9 KiB
Rust
use dioxus::prelude::*;
|
|
use dioxus_i18n::t;
|
|
|
|
use crate::components::{H4, HR};
|
|
|
|
#[component]
|
|
pub fn CV() -> Element {
|
|
rsx! {
|
|
div {
|
|
class: "flex flex-col",
|
|
div {
|
|
class: "flex flex-col sm:flex-row justify-center items-center sm:space-x-8 space-y-8 sm:space-y-0",
|
|
img {
|
|
class: "rounded-full w-24 h-24",
|
|
alt: "headshot",
|
|
src: asset!("./assets/pictures/headshot.webp")
|
|
}
|
|
Introduction {},
|
|
Socials {}
|
|
},
|
|
|
|
HR {}
|
|
div {
|
|
class: "flex flex-col justify-between sm:flex-row",
|
|
WorkExperience {},
|
|
Miscellaneous {},
|
|
},
|
|
HR {},
|
|
}
|
|
}
|
|
}
|
|
|
|
fn Introduction() -> Element {
|
|
rsx! {
|
|
div {
|
|
class: "flex",
|
|
P { { t!("cv_introduction_0") } },
|
|
},
|
|
}
|
|
}
|
|
|
|
fn WorkExperience() -> Element {
|
|
rsx! {
|
|
div {
|
|
class: "ms-8 max-w-3/4",
|
|
H4 { { t!("cv_workexperience_title") } },
|
|
ol {
|
|
class:"relative border-s border-gray-700",
|
|
CVEntry {time: t!("cv_workexperience_dd_devops_time"), title: t!("cv_workexperience_dd_devops_title"),
|
|
technologies: vec!["Kubenertes".to_string(), "ArgoCD".to_string(), "Ansible".to_string(), "Azure".to_string(), "Docker".to_string(), "ELK".to_string()],
|
|
description: t!("cv_workexperience_dd_devops_description")
|
|
},
|
|
CVEntry {time: t!("cv_workexperience_ra_ude_time"), title: t!("cv_workexperience_ra_ude_title"),
|
|
technologies: vec!["Rust".to_string(), "Python".to_string(), "P4".to_string(), "Linux".to_string(), "Docker".to_string(), "Kubernetes".to_string()],
|
|
description: t!("cv_workexperience_ra_ude_description")
|
|
},
|
|
CVEntry {time: t!("cv_workexperience_mentoring_ude_time"), title: t!("cv_workexperience_mentoring_ude_title"),
|
|
technologies: vec!["Powerpoint".to_string()],
|
|
description: t!("cv_workexperience_mentoring_ude_description")
|
|
},
|
|
CVEntry {time: t!("cv_workexperience_se2_gefeba_time"), title: t!("cv_workexperience_se2_gefeba_title"),
|
|
technologies: vec!["C#".to_string(), "Angular".to_string(), "bootstrap".to_string(), "Entity Framework".to_string()],
|
|
description: t!("cv_workexperience_se2_gefeba_description")
|
|
},
|
|
CVEntry {time: t!("cv_workexperience_student_fse_time"), title: t!("cv_workexperience_student_fse_title"),
|
|
technologies: vec!["Linux".to_string(), "Networking".to_string(), "LaTeX".to_string()],
|
|
description: t!("cv_workexperience_student_fse_description")
|
|
},
|
|
CVEntry {time: t!("cv_workexperience_se1_gefeba_time"), title: t!("cv_workexperience_se1_gefeba_title"),
|
|
technologies: vec!["C#".to_string(), "HTML".to_string(), "Javascript".to_string(), "CSS".to_string()],
|
|
description: t!("cv_workexperience_se1_gefeba_description")
|
|
},
|
|
}
|
|
},
|
|
}
|
|
}
|
|
|
|
fn Miscellaneous() -> Element {
|
|
rsx! {
|
|
div {
|
|
class: "",
|
|
Education {},
|
|
Skills {},
|
|
Languages {},
|
|
Interests {},
|
|
}
|
|
}
|
|
}
|
|
|
|
fn Education() -> Element {
|
|
rsx! {
|
|
div {
|
|
H4 { { t!("cv_education_title") } },
|
|
Entry {
|
|
title: t!("cv_education_bachelor_title"),
|
|
time { class:"mb-1 text-sm font-normal leading-none text-gray-500", { t!("cv_education_bachelor_time") } },
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
fn Skills() -> Element {
|
|
rsx! {
|
|
div {
|
|
H4 { { t!("cv_skills_title") }},
|
|
Entry {
|
|
title: t!("cv_skills_devops_title"),
|
|
P { { t!("cv_skills_devops_ansible") } },
|
|
P { { t!("cv_skills_devops_kubernetes") } },
|
|
P { { t!("cv_skills_devops_gitops") } },
|
|
}
|
|
Entry {
|
|
title: t!("cv_skills_software_engineering_title"),
|
|
P { { t!("cv_skills_software_engineering_rust") } },
|
|
P { { t!("cv_skills_software_engineering_python") } },
|
|
P { { t!("cv_skills_software_engineering_csharp") } },
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn Languages() -> Element {
|
|
rsx! {
|
|
div {
|
|
H4 { { t!("cv_languages_title") } },
|
|
Entry {
|
|
P { {t!("cv_languages_german") } },
|
|
P { {t!("cv_languages_english") } },
|
|
P { {t!("cv_languages_vietnamese") } },
|
|
P { {t!("cv_languages_japanese") } },
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn Interests() -> Element {
|
|
rsx! {
|
|
div {
|
|
H4 { { t!("cv_interests_title") } },
|
|
Entry {
|
|
P { { t!("cv_interests_coffee") } },
|
|
P { { t!("cv_interests_tech_it") } },
|
|
P { { t!("cv_interests_guitar") } },
|
|
P { { t!("cv_interests_mechanical_keyboards") } },
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(PartialEq, Props, Clone)]
|
|
struct EntryProps {
|
|
#[props(default = "mb-4".to_string())]
|
|
class: String,
|
|
#[props(default = "".to_string())]
|
|
title: String,
|
|
children: Element,
|
|
}
|
|
|
|
fn Entry(props: EntryProps) -> Element {
|
|
rsx! {
|
|
div {
|
|
class: "{props.class}",
|
|
h6 { class: "font-semibold text-white", "{props.title}"}
|
|
{props.children},
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(PartialEq, Props, Clone)]
|
|
struct CVEntryProps {
|
|
#[props(default = "mb-10 ms-4".to_string())]
|
|
class: String,
|
|
time: String,
|
|
title: String,
|
|
technologies: Vec<String>,
|
|
#[props(default = "".to_string())]
|
|
description: String,
|
|
children: Element,
|
|
}
|
|
|
|
fn CVEntry(props: CVEntryProps) -> Element {
|
|
rsx! {
|
|
li {
|
|
class: "max-w-xl",
|
|
class: "{props.class}",
|
|
div { class:"absolute w-3 h-3 rounded-full mt-1.5 -start-1.5 border border-gray-900 bg-gray-700"},
|
|
time { class:"mb-1 text-sm font-normal leading-none text-gray-500", "{props.time}"},
|
|
h6 { class: "text-lg font-semibold text-white", "{props.title}"}
|
|
ul {
|
|
class: "flex flex-wrap gap-2",
|
|
for (index, value) in props.technologies.iter().enumerate() {
|
|
li { key: "{index}", RandomBadge { text: "{value}"} }
|
|
}
|
|
}
|
|
p { class:"text-base font-normal text-gray-400", "{props.description}"},
|
|
{props.children}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[component]
|
|
fn RandomBadge(text: String) -> Element {
|
|
let badge_color = random_badge_color(text.len());
|
|
rsx! {
|
|
span {
|
|
class:"text-xs font-medium me-2 px-2.5 py-0.5 rounded {badge_color}",
|
|
"{text}"
|
|
}
|
|
}
|
|
}
|
|
|
|
fn random_badge_color(seed: usize) -> String {
|
|
let colors = [
|
|
"bg-blue-900 text-blue-300",
|
|
"bg-gray-700 text-gray-300",
|
|
"bg-red-900 text-red-300",
|
|
"bg-green-900 text-green-300",
|
|
"bg-yellow-900 text-yellow-300",
|
|
"bg-indigo-900 text-indigo-300",
|
|
"bg-purple-900 text-purple-300",
|
|
"bg-pink-900 text-pink-300",
|
|
];
|
|
|
|
colors[seed % colors.len()].to_string()
|
|
}
|
|
|
|
fn Socials() -> Element {
|
|
rsx! {
|
|
div {
|
|
class: "ms-8 max-w-3/4",
|
|
H4 { { t!("cv_socials_title") } },
|
|
div {
|
|
class: "flex justify-center items-center space-x-4",
|
|
P { Link { to:"https://www.linkedin.com/in/tudattr/", class:"hover:underline", new_tab: true, img { class: "h-8", src:asset!("./assets/pictures/LI-Bug.svg.original.svg"), alt:"LinkedIn Logo" } }},
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[component]
|
|
fn P(children: Element) -> Element {
|
|
rsx! {
|
|
p {
|
|
class: "text-base font-normal text-gray-400",
|
|
{children},
|
|
}
|
|
}
|
|
}
|