Compare commits
10 Commits
f2e479acc7
...
fdea3d2f15
Author | SHA1 | Date | |
---|---|---|---|
fdea3d2f15 | |||
03082a1904 | |||
8ab01ca725 | |||
05cb8cfc73 | |||
b79c109876 | |||
4d1e45359c | |||
33c933d455 | |||
c5fa636b39 | |||
c286ebaa5f | |||
25238dea05 |
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -3040,7 +3040,7 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
|
||||
|
||||
[[package]]
|
||||
name = "personal_site"
|
||||
version = "0.1.0"
|
||||
version = "1.0.0"
|
||||
dependencies = [
|
||||
"dioxus",
|
||||
]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "personal_site"
|
||||
version = "0.1.0"
|
||||
version = "1.0.0"
|
||||
authors = ["darkicewolf50 <brock.tomlinson@ucalgary.ca>"]
|
||||
edition = "2021"
|
||||
|
||||
|
@ -1,8 +1,36 @@
|
||||
#blog {
|
||||
margin-top: 50px;
|
||||
margin-top: 50px;
|
||||
}
|
||||
|
||||
#blog a {
|
||||
color: #ffffff;
|
||||
margin-top: 50px;
|
||||
}
|
||||
color: #ffffff;
|
||||
margin-top: 50px;
|
||||
}
|
||||
|
||||
#blogs {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 80svh;
|
||||
}
|
||||
|
||||
#blogs h1 {
|
||||
border-bottom: var(--underlineTitle);
|
||||
border-radius: var(--underlineTitleBorderRadius);
|
||||
}
|
||||
|
||||
#blogs button {
|
||||
background-color: var(--card-background-color);
|
||||
border-radius: var(--card-border-radius);
|
||||
border: none;
|
||||
color: #ffffff;
|
||||
font-size: xx-large;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
#blogs a {
|
||||
text-decoration: none;
|
||||
background-color: var(--card-background-color);
|
||||
border-radius: var(--card-border-radius);
|
||||
}
|
||||
|
@ -3,20 +3,27 @@
|
||||
flex-direction: row;
|
||||
gap: 2svw;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#contact img {
|
||||
flex: 1 1 50%;
|
||||
border-radius: 100%;
|
||||
max-width: 40%;
|
||||
object-fit: cover;
|
||||
max-height: 250px;
|
||||
display: block;
|
||||
background-color: var(--card-background-color);
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
#contact div {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
/* flex: 0 0 48%; */
|
||||
}
|
||||
|
||||
#contact div div {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
flex-basis: auto;
|
||||
}
|
||||
|
||||
#contact div ul {
|
||||
@ -46,9 +53,14 @@
|
||||
}
|
||||
|
||||
#contact div ul li {
|
||||
justify-content: flex-start;
|
||||
|
||||
border: 1px solid whitesmoke;
|
||||
/* display: flex;
|
||||
justify-content: flex-start; */
|
||||
/* text-wrap: nowrap; */
|
||||
padding-right: 1svw;
|
||||
background-color: var(--card-background-color);
|
||||
border-radius: var(--card-border-radius);
|
||||
/* border: 1px solid whitesmoke; */
|
||||
padding: 0.5svh 1svw;
|
||||
}
|
||||
|
||||
#contact div ul li a {
|
||||
@ -68,7 +80,22 @@
|
||||
}
|
||||
|
||||
#contact ul li img {
|
||||
height: 80px;
|
||||
height: var(--img-width);
|
||||
width: var(--img-height);
|
||||
object-fit: contain;
|
||||
border-radius: 0px;
|
||||
background-color: transparent;
|
||||
filter: invert() hue-rotate(180deg);
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 500px) {
|
||||
#contact ul li img {
|
||||
display: none;
|
||||
}
|
||||
#contact img {
|
||||
border-radius: 100%;
|
||||
max-width: 100%;
|
||||
max-height: 250px;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
@ -3,26 +3,28 @@ footer {
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
|
||||
background-color: #d3d3d3;
|
||||
background-color: var(--card-background-color);
|
||||
border-radius: var(--card-border-radius);
|
||||
|
||||
/* background-color: #d3d3d3; */
|
||||
}
|
||||
|
||||
footer div {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex: 1 1 2;
|
||||
justify-content: space-between;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
footer img {
|
||||
height: 100px;
|
||||
height: 60px;
|
||||
filter: invert() hue-rotate(180deg);
|
||||
}
|
||||
|
||||
footer a {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
border: 1px solid lightgray;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
86
assets/styling/experience.css
Normal file
86
assets/styling/experience.css
Normal file
@ -0,0 +1,86 @@
|
||||
.experience-comp {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: wrap;
|
||||
|
||||
/* flex-basis: 50%; */
|
||||
}
|
||||
|
||||
.experience-comp h3 {
|
||||
display: flex;
|
||||
/* width: 90%; */
|
||||
border-bottom: var(--underlineTitle);
|
||||
border-radius: var(--underlineTitleBorderRadius);
|
||||
margin: 2svh 2svw;
|
||||
padding: 0svh 2svw;
|
||||
padding-bottom: 1svh;
|
||||
}
|
||||
|
||||
.experience-comp table {
|
||||
border-collapse: separate;
|
||||
border-spacing: 0svh 0px;
|
||||
}
|
||||
|
||||
.experience-comp td {
|
||||
position: relative;
|
||||
margin: 0px;
|
||||
padding: 0.25svh 2svw;
|
||||
}
|
||||
.experience-comp tr:nth-child(even) td {
|
||||
padding-bottom: 2svh;
|
||||
}
|
||||
|
||||
.postion {
|
||||
text-wrap: nowrap;
|
||||
}
|
||||
.date-location {
|
||||
text-wrap: nowrap;
|
||||
}
|
||||
.symbol {
|
||||
position: relative;
|
||||
width: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.symbol[rowspan]::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
width: 2px;
|
||||
background-color: rgb(120, 120, 120);
|
||||
transform: translateX(-50%);
|
||||
z-index: 0;
|
||||
}
|
||||
.symbol::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.dot {
|
||||
display: inline-block;
|
||||
background-color: rgb(120, 120, 120);
|
||||
border-radius: 100%;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
line-height: 16px;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
tr:nth-child(1) > .symbol::before {
|
||||
top: 50%;
|
||||
}
|
||||
|
||||
tr:nth-last-child(2) > .symbol::before {
|
||||
bottom: 50%;
|
||||
}
|
53
assets/styling/home.css
Normal file
53
assets/styling/home.css
Normal file
@ -0,0 +1,53 @@
|
||||
#home-intro {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 90%;
|
||||
margin-top: 2svh;
|
||||
background-color: var(--card-background-color);
|
||||
border-radius: var(--card-border-radius);
|
||||
}
|
||||
|
||||
#home-intro h1 {
|
||||
border-bottom: var(--underlineTitle);
|
||||
border-radius: var(--underlineTitleBorderRadius);
|
||||
display: flex;
|
||||
margin: 2svh 2svw;
|
||||
padding: 0svh 2svw;
|
||||
padding-bottom: 1svh;
|
||||
}
|
||||
|
||||
#home-intro p {
|
||||
margin: 1svh 4svw;
|
||||
padding: 0svh 2svw;
|
||||
padding-bottom: 1svh;
|
||||
}
|
||||
|
||||
.technologies {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.technologies-cat {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
justify-content: space-between;
|
||||
column-gap: 1svw;
|
||||
row-gap: 1svh;
|
||||
}
|
||||
|
||||
#experience {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-bottom: 4svh;
|
||||
background-color: var(--card-background-color);
|
||||
border-radius: var(--card-border-radius);
|
||||
}
|
||||
|
||||
#experience div {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-evenly;
|
||||
background-color: var(--card-background-color);
|
||||
border-radius: var(--card-border-radius);
|
||||
margin: 4svh 0px;
|
||||
}
|
@ -5,13 +5,21 @@ body {
|
||||
margin: 20px;
|
||||
}
|
||||
h2 {
|
||||
width: 80%;
|
||||
border-bottom: var(--underlineTitle);
|
||||
border-radius: var(--underlineTitleBorderRadius);
|
||||
display: flex;
|
||||
margin: 2svh 2svw;
|
||||
padding: 0svh 2svw;
|
||||
padding-bottom: 1svh;
|
||||
}
|
||||
/*
|
||||
p {
|
||||
width: 90%;
|
||||
margin: 2svh 0px;
|
||||
margin-left: 2svw;
|
||||
padding-left: 2svw;
|
||||
padding-bottom: 1svh;
|
||||
}
|
||||
} */
|
||||
|
||||
#hero {
|
||||
margin: 0;
|
||||
|
@ -1,16 +1,16 @@
|
||||
#navbar {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
#navbar a {
|
||||
color: #ffffff;
|
||||
margin-right: 20px;
|
||||
text-decoration: none;
|
||||
transition: color 0.2s ease;
|
||||
color: #ffffff;
|
||||
margin-right: 20px;
|
||||
text-decoration: none;
|
||||
transition: color 0.2s ease;
|
||||
}
|
||||
|
||||
#navbar a:hover {
|
||||
cursor: pointer;
|
||||
color: #91a4d2;
|
||||
}
|
||||
cursor: pointer;
|
||||
color: #91a4d2;
|
||||
}
|
||||
|
27
assets/styling/notFound.css
Normal file
27
assets/styling/notFound.css
Normal file
@ -0,0 +1,27 @@
|
||||
#not-found {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 80svh;
|
||||
}
|
||||
|
||||
#not-found h1 {
|
||||
border-bottom: var(--underlineTitle);
|
||||
border-radius: var(--underlineTitleBorderRadius);
|
||||
}
|
||||
|
||||
#not-found button {
|
||||
background-color: var(--card-background-color);
|
||||
border-radius: var(--card-border-radius);
|
||||
border: none;
|
||||
color: #ffffff;
|
||||
font-size: xx-large;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
#not-found a {
|
||||
text-decoration: none;
|
||||
background-color: var(--card-background-color);
|
||||
border-radius: var(--card-border-radius);
|
||||
}
|
99
assets/styling/projectCards.css
Normal file
99
assets/styling/projectCards.css
Normal file
@ -0,0 +1,99 @@
|
||||
.project-section {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
column-gap: 1svw;
|
||||
}
|
||||
.project-card {
|
||||
flex: 0 1 30%;
|
||||
margin-bottom: 3svh;
|
||||
background-color: var(--card-background-color);
|
||||
border-radius: var(--card-border-radius);
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 800px) {
|
||||
.project-card {
|
||||
flex: 0 1 auto;
|
||||
}
|
||||
}
|
||||
|
||||
.project-card img {
|
||||
max-width: 96%;
|
||||
max-height: 200px;
|
||||
|
||||
justify-self: center;
|
||||
|
||||
margin: 0svh 1svw;
|
||||
padding-top: 1svh;
|
||||
object-fit: contain;
|
||||
color: transparent;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.project-title-info {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
height: 50px;
|
||||
|
||||
border-bottom: var(--underlineTitle);
|
||||
border-radius: var(--underlineTitleBorderRadius);
|
||||
margin: 0px 2svw;
|
||||
padding: 0px 2svw;
|
||||
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
.project-title-info h3 {
|
||||
margin: 0px;
|
||||
text-align: start;
|
||||
white-space: nowrap;
|
||||
align-self: center;
|
||||
font-weight: normal;
|
||||
text-wrap: wrap;
|
||||
border-radius: var(--underlineTitleBorderRadius);
|
||||
}
|
||||
|
||||
.project-title-info img {
|
||||
height: var(--img-width);
|
||||
width: var(--img-height);
|
||||
margin: 1svh 6px;
|
||||
padding: 0px;
|
||||
filter: invert() hue-rotate(180deg);
|
||||
}
|
||||
|
||||
.project-title-info div {
|
||||
display: flex;
|
||||
gap: 1svw;
|
||||
justify-content: flex-end;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.project-card div p {
|
||||
display: flex;
|
||||
width: 90%;
|
||||
justify-self: center;
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
.project-tech-logos {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
align-items: center;
|
||||
align-self: center;
|
||||
width: 90%;
|
||||
justify-content: flex-start;
|
||||
column-gap: 0.5svw;
|
||||
row-gap: 1svw;
|
||||
padding-left: 2svw;
|
||||
padding-bottom: 1svh;
|
||||
}
|
||||
|
||||
.project-tech-logos img {
|
||||
aspect-ratio: 1;
|
||||
height: var(--img-width);
|
||||
width: var(--img-height);
|
||||
|
||||
/* flex: 0 1 19%; */
|
||||
}
|
@ -1,3 +1,8 @@
|
||||
:root {
|
||||
--underlineTitle: 4px solid purple;
|
||||
--underlineTitleBorderRadius: 4px;
|
||||
--img-width: 32px;
|
||||
--img-height: 32px;
|
||||
--card-background-color: rgba(38, 38, 38, 0.5);
|
||||
--card-border-radius: 0.5rem;
|
||||
}
|
||||
|
@ -2,45 +2,55 @@
|
||||
--tech-gap: 4svw;
|
||||
}
|
||||
.tech-cat {
|
||||
border: 1px solid salmon;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-left: 4svw;
|
||||
/* border: 1px solid salmon; */
|
||||
padding: 0px 1svw;
|
||||
padding-bottom: 2svh;
|
||||
margin-bottom: 3svh;
|
||||
flex: 1 1 auto;
|
||||
background-color: var(--card-background-color);
|
||||
border-radius: var(--card-border-radius);
|
||||
}
|
||||
|
||||
.tech-cat h3 {
|
||||
display: flex;
|
||||
width: 80%;
|
||||
border-bottom: var(--underlineTitle);
|
||||
margin: 2svh 0px;
|
||||
margin-left: 4svw;
|
||||
padding-left: 2svw;
|
||||
border-radius: var(--underlineTitleBorderRadius);
|
||||
display: flex;
|
||||
margin: 2svh 2svw;
|
||||
padding: 0svh 2svw;
|
||||
padding-bottom: 1svh;
|
||||
}
|
||||
|
||||
.tech-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--tech-gap);
|
||||
flex-flow: row wrap;
|
||||
justify-content: space-evenly;
|
||||
/* column-gap: 0.5svw; */
|
||||
row-gap: 1svh;
|
||||
}
|
||||
|
||||
.tech-card {
|
||||
border: 1px solid whitesmoke;
|
||||
flex: 0 1 calc(33.3% - var(--tech-gap));
|
||||
/* border: 1px solid whitesmoke; */
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
|
||||
margin-bottom: 1svh;
|
||||
flex: 0 1 70px;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
padding: 0px 0.5svw;
|
||||
padding-top: 2svh;
|
||||
padding-bottom: 0.5svh;
|
||||
background-color: var(--card-background-color);
|
||||
border-radius: var(--card-border-radius);
|
||||
}
|
||||
|
||||
.tech-card img {
|
||||
/* height: 40px; */
|
||||
padding-top: 2svh;
|
||||
|
||||
height: 100px;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
aspect-ratio: 1;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.tech-card progress {
|
||||
@ -49,6 +59,15 @@
|
||||
overflow: hidden;
|
||||
appearance: none;
|
||||
border-radius: 999px;
|
||||
justify-self: flex-end;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.tech-card h4 {
|
||||
margin: 1svh 0.5svw;
|
||||
width: 80px;
|
||||
text-align: center;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
/* for chromium browsers */
|
||||
@ -62,3 +81,5 @@
|
||||
background-color: steelblue;
|
||||
/* border-radius: 999px; */
|
||||
}
|
||||
|
||||
/* 48.19 , 68.58*/
|
||||
|
116
src/components/experience.rs
Normal file
116
src/components/experience.rs
Normal file
@ -0,0 +1,116 @@
|
||||
use dioxus::prelude::*;
|
||||
|
||||
const EXPERIENCE_CSS: Asset = asset!("/assets/styling/experience.css");
|
||||
|
||||
#[component]
|
||||
pub fn Experience(professional_jobs: bool) -> Element {
|
||||
let experience: [ExpDes; 4] = match professional_jobs {
|
||||
true => EXPERIENCE_JOBS,
|
||||
false => EXPERIENCE_VOL,
|
||||
};
|
||||
rsx! {
|
||||
div { class: "experience-comp",
|
||||
document::Link { rel: "stylesheet", href: EXPERIENCE_CSS }
|
||||
if professional_jobs {
|
||||
h3 { "Professional" }
|
||||
} else {
|
||||
h3 { "Volunteering" }
|
||||
}
|
||||
table {
|
||||
colgroup {
|
||||
col { class: "symbol" }
|
||||
col { class: "postion" }
|
||||
col { class: "date-location" }
|
||||
}
|
||||
tbody {
|
||||
for exp in experience {
|
||||
tr {
|
||||
td { class: "symbol", rowspan: 2,
|
||||
span { class: "dot", "" }
|
||||
}
|
||||
td { "{exp.postition}" }
|
||||
td { "{exp.start_month} - {exp.end_month}" }
|
||||
}
|
||||
tr {
|
||||
// td { "" }
|
||||
td { "{exp.company}" }
|
||||
td { "{exp.location}" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Props, Clone)]
|
||||
struct ExpDes {
|
||||
pub postition: &'static str,
|
||||
pub company: &'static str,
|
||||
pub location: &'static str,
|
||||
pub start_month: &'static str,
|
||||
pub end_month: &'static str,
|
||||
}
|
||||
|
||||
const EXPERIENCE_JOBS: [ExpDes; 4] = [
|
||||
ExpDes {
|
||||
postition: "Project Coordinator",
|
||||
company: "Rally Engineering",
|
||||
location: "Ab",
|
||||
start_month: "Jan 2025",
|
||||
end_month: "May 2025",
|
||||
},
|
||||
ExpDes {
|
||||
postition: "Project Controller Student",
|
||||
company: "Rally Engineering",
|
||||
location: "Ab",
|
||||
start_month: "May 2024",
|
||||
end_month: "Jan 2025",
|
||||
},
|
||||
ExpDes {
|
||||
postition: "Staff",
|
||||
company: "Red Deer Farmer's Market",
|
||||
location: "Ab",
|
||||
start_month: "Mar 2013",
|
||||
end_month: "Present",
|
||||
},
|
||||
ExpDes {
|
||||
postition: "Staff",
|
||||
company: "Ghostrider Storage",
|
||||
location: "BC",
|
||||
start_month: "Mar 2020",
|
||||
end_month: "Present",
|
||||
},
|
||||
];
|
||||
|
||||
const EXPERIENCE_VOL: [ExpDes; 4] = [
|
||||
ExpDes {
|
||||
postition: "Software Subteam Lead",
|
||||
company: "UCalgary Baja",
|
||||
location: "Ab",
|
||||
start_month: "Sept 2024",
|
||||
end_month: "Present",
|
||||
},
|
||||
ExpDes {
|
||||
postition: "Software, Logistics and Business Sub Team Lead",
|
||||
company: "Schulich Off-Road",
|
||||
location: "Ab",
|
||||
start_month: "May 2023",
|
||||
end_month: "Sept 2024",
|
||||
},
|
||||
ExpDes {
|
||||
postition: "Chassis Junior Member",
|
||||
company: "Schulich Off-Road",
|
||||
location: "Ab",
|
||||
start_month: "Sept 2022",
|
||||
end_month: "May 2023",
|
||||
},
|
||||
ExpDes {
|
||||
postition: "Coaching with Elk Valley Special Olympics",
|
||||
company: "Elk Valley Dolphins",
|
||||
location: "BC",
|
||||
start_month: "May 2019",
|
||||
end_month: "May 2019",
|
||||
},
|
||||
];
|
35
src/components/footer.rs
Normal file
35
src/components/footer.rs
Normal file
@ -0,0 +1,35 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::helper_fun::{tech_table_lookup, TechDes};
|
||||
use dioxus::prelude::*;
|
||||
|
||||
const ENDER_CSS: Asset = asset!("/assets/styling/ender.css");
|
||||
|
||||
#[component]
|
||||
pub fn Ender() -> Element {
|
||||
// gets list of items to get
|
||||
let footer_info_to_get = vec!["Github", "Email", "LinkedIn", "Twitch", "Youtube"];
|
||||
|
||||
// used so that I dont need to copy paste the same link/info everywhere
|
||||
let mut footer_info: HashMap<&str, TechDes> = HashMap::new();
|
||||
for used_tech_item in footer_info_to_get {
|
||||
footer_info.insert(used_tech_item, *tech_table_lookup(used_tech_item));
|
||||
}
|
||||
rsx! {
|
||||
document::Link { rel: "stylesheet", href: ENDER_CSS }
|
||||
footer {
|
||||
p { "Brock Tomlinson © 2025" }
|
||||
div {
|
||||
for (footer_name , footer_item) in footer_info {
|
||||
a { href: "{footer_item.project_site}",
|
||||
img {
|
||||
src: "{footer_item.tech_logo}",
|
||||
alt: "{footer_name}'s logo/icon",
|
||||
}
|
||||
p { "{footer_name}" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -6,4 +6,10 @@ mod hero;
|
||||
pub use hero::Hero;
|
||||
|
||||
mod techs;
|
||||
pub use techs::{TechCat, TechDes};
|
||||
pub use techs::TechCat;
|
||||
|
||||
mod footer;
|
||||
pub use footer::Ender;
|
||||
|
||||
mod experience;
|
||||
pub use experience::Experience;
|
||||
|
@ -1,6 +1,4 @@
|
||||
use std::collections::HashMap;
|
||||
use std::hash::{BuildHasherDefault, DefaultHasher};
|
||||
|
||||
use crate::helper_fun::tech_table_lookup;
|
||||
use dioxus::prelude::*;
|
||||
|
||||
const TECHS_CSS: Asset = asset!("/assets/styling/techs.css");
|
||||
@ -11,7 +9,7 @@ pub fn TechCard(tech_props: &'static str) -> Element {
|
||||
|
||||
rsx! {
|
||||
a { class: "tech-card", href: "{props_tech.project_site}",
|
||||
img { src: "{props_tech.lang_logo}", alt: "{tech_props}'s logo" }
|
||||
img { src: "{props_tech.tech_logo}", alt: "{tech_props}'s logo" }
|
||||
h4 { "{tech_props}" }
|
||||
progress { value: props_tech.skill_level, max: 100 }
|
||||
}
|
||||
@ -19,81 +17,18 @@ pub fn TechCard(tech_props: &'static str) -> Element {
|
||||
}
|
||||
|
||||
#[component]
|
||||
pub fn TechCat(cat: String, tech_vec: Vec<&'static str>) -> Element {
|
||||
pub fn TechCat(cat: &'static str, tech_vec: Vec<&'static str>) -> Element {
|
||||
rsx! {
|
||||
document::Link { rel: "stylesheet", href: TECHS_CSS }
|
||||
div { class: "tech-cat",
|
||||
div {
|
||||
h3 { "{cat}" }
|
||||
}
|
||||
h3 { "{cat}" }
|
||||
div { class: "tech-row",
|
||||
for tech in tech_vec {
|
||||
TechCard { tech_props: tech }
|
||||
TechCard {
|
||||
tech_props: tech,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Props, Clone, Copy)]
|
||||
pub struct TechDes {
|
||||
// to be removed soon
|
||||
pub lang_logo: &'static str,
|
||||
pub project_site: &'static str,
|
||||
pub skill_level: u8,
|
||||
}
|
||||
|
||||
pub fn tech_table_lookup(to_lookup: &str) -> TechDes {
|
||||
let techs_tools_frameworks_lookup = HashMap::from([
|
||||
(
|
||||
"Rust",
|
||||
TechDes {
|
||||
lang_logo: "https://www.rust-lang.org/static/images/rust-logo-blk.svg",
|
||||
project_site: "https://www.rust-lang.org",
|
||||
skill_level: 40,
|
||||
},
|
||||
),
|
||||
(
|
||||
"Python",
|
||||
TechDes {
|
||||
lang_logo: "https://www.svgrepo.com/show/452091/python.svg",
|
||||
project_site: "https://www.python.org",
|
||||
skill_level: 50,
|
||||
},
|
||||
),
|
||||
(
|
||||
"JavaScript",
|
||||
TechDes {
|
||||
lang_logo: "https://www.svgrepo.com/show/303206/javascript-logo.svg",
|
||||
project_site: "https://www.python.org",
|
||||
skill_level: 60,
|
||||
},
|
||||
),
|
||||
(
|
||||
"YAML",
|
||||
TechDes {
|
||||
lang_logo: "https://yaml.org/favicon.svg",
|
||||
project_site: "https://yaml.org",
|
||||
skill_level: 95,
|
||||
},
|
||||
),
|
||||
(
|
||||
"C",
|
||||
TechDes {
|
||||
lang_logo: "https://www.c-language.org/logo.svg",
|
||||
project_site: "https://www.c-language.org",
|
||||
skill_level: 30,
|
||||
},
|
||||
),
|
||||
(
|
||||
"C++",
|
||||
TechDes {
|
||||
lang_logo: "https://www.svgrepo.com/show/452183/cpp.svg",
|
||||
project_site: "https://cplusplus.com",
|
||||
skill_level: 30,
|
||||
},
|
||||
),
|
||||
]);
|
||||
|
||||
techs_tools_frameworks_lookup[to_lookup]
|
||||
}
|
||||
|
272
src/helper_fun.rs
Normal file
272
src/helper_fun.rs
Normal file
@ -0,0 +1,272 @@
|
||||
use dioxus::prelude::*;
|
||||
use std::{collections::HashMap, rc::Rc};
|
||||
|
||||
#[component]
|
||||
pub fn get_tech_logos_from_str(used_tech: &'static str) -> Element {
|
||||
let raw_data: TechDes = *tech_table_lookup(used_tech);
|
||||
rsx! {
|
||||
img { src: "{raw_data.tech_logo}", alt: "{used_tech}'s logo/icon" }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Props, Clone, Copy)]
|
||||
pub struct TechDes {
|
||||
pub tech_name: &'static str,
|
||||
pub tech_logo: &'static str,
|
||||
pub project_site: &'static str,
|
||||
pub skill_level: u8,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Props, Clone)]
|
||||
pub struct ProjectDes {
|
||||
website_prop: Option<&'static str>,
|
||||
github_prop: Option<&'static str>,
|
||||
project_name: &'static str,
|
||||
techs_used: Vec<&'static str>,
|
||||
project_des: &'static str,
|
||||
}
|
||||
|
||||
pub fn tech_table_lookup(to_lookup: &str) -> Rc<TechDes> {
|
||||
let mut tech_to_return: TechDes = TechDes {
|
||||
tech_name: "Not in table",
|
||||
tech_logo: "",
|
||||
project_site: "",
|
||||
skill_level: 0,
|
||||
};
|
||||
|
||||
for tech in TECH_TABLE {
|
||||
if tech.tech_name == to_lookup {
|
||||
tech_to_return = tech.into();
|
||||
}
|
||||
}
|
||||
tech_to_return.into()
|
||||
}
|
||||
|
||||
const TECH_TABLE:[TechDes; 37] = [
|
||||
TechDes {
|
||||
tech_name: "Rust",
|
||||
tech_logo: "https://www.svgrepo.com/show/374056/rust.svg",
|
||||
project_site: "https://www.rust-lang.org",
|
||||
skill_level: 60,
|
||||
},
|
||||
TechDes {
|
||||
tech_name: "Python",
|
||||
tech_logo: "https://www.svgrepo.com/show/452091/python.svg",
|
||||
project_site: "https://www.python.org",
|
||||
skill_level: 50,
|
||||
},
|
||||
|
||||
TechDes {
|
||||
tech_name: "JavaScript",
|
||||
tech_logo: "https://www.svgrepo.com/show/303206/javascript-logo.svg",
|
||||
project_site: "https://www.python.org",
|
||||
skill_level: 60,
|
||||
},
|
||||
|
||||
TechDes {
|
||||
tech_name: "YAML",
|
||||
tech_logo: "https://yaml.org/favicon.svg",
|
||||
project_site: "https://yaml.org",
|
||||
skill_level: 95,
|
||||
},
|
||||
TechDes {
|
||||
tech_name: "Github",
|
||||
tech_logo: "https://www.svgrepo.com/show/512317/github-142.svg",
|
||||
project_site: "https://github.com/darkicewolf50",
|
||||
skill_level: 80,
|
||||
},
|
||||
TechDes {
|
||||
tech_name: "Email",
|
||||
tech_logo: "https://www.svgrepo.com/show/491226/email.svg",
|
||||
project_site: "mailto:darkicewolf50@gmail.com",
|
||||
skill_level: 100,
|
||||
},
|
||||
|
||||
TechDes {
|
||||
tech_name: "LinkedIn",
|
||||
tech_logo: "https://www.svgrepo.com/show/521725/linkedin.svg",
|
||||
project_site: "https://www.linkedin.com/in/brock-tomlinson/",
|
||||
skill_level: 40,
|
||||
},
|
||||
TechDes {
|
||||
tech_name: "Twitch",
|
||||
tech_logo: "https://www.svgrepo.com/show/519925/twitch.svg",
|
||||
project_site: "https://www.twitch.tv/darkicewolf50",
|
||||
skill_level: 60,
|
||||
},
|
||||
TechDes {
|
||||
tech_name: "Youtube",
|
||||
tech_logo: "https://www.svgrepo.com/show/521936/youtube.svg",
|
||||
project_site: "https://www.youtube.com/@darkicewolf50",
|
||||
skill_level: 40,
|
||||
},
|
||||
TechDes {
|
||||
tech_name: "Internet",
|
||||
tech_logo: "https://www.svgrepo.com/show/490809/internet.svg",
|
||||
project_site: "https://google.com",
|
||||
skill_level: 99,
|
||||
},
|
||||
TechDes {
|
||||
tech_name: "React",
|
||||
tech_logo: "https://www.svgrepo.com/show/452092/react.svg",
|
||||
project_site: "https://react.dev",
|
||||
skill_level: 70,
|
||||
},
|
||||
TechDes {
|
||||
tech_name: "Docker",
|
||||
tech_logo: "https://www.svgrepo.com/show/448221/docker.svg",
|
||||
project_site: "https://www.docker.com",
|
||||
skill_level: 70,
|
||||
},
|
||||
TechDes {
|
||||
tech_name: "FastAPI",
|
||||
tech_logo: "https://fastapi.tiangolo.com/img/favicon.png",
|
||||
project_site: "https://fastapi.tiangolo.com",
|
||||
skill_level: 80,
|
||||
},
|
||||
|
||||
TechDes {
|
||||
tech_name: "Actix",
|
||||
tech_logo: "https://actix.rs/img/logo.png",
|
||||
project_site: "https://actix.rs",
|
||||
skill_level: 20,
|
||||
},
|
||||
TechDes {
|
||||
tech_name: "HTML5",
|
||||
tech_logo: "https://www.svgrepo.com/show/452228/html-5.svg",
|
||||
project_site: "https://google.com",
|
||||
skill_level: 90,
|
||||
},
|
||||
TechDes {
|
||||
tech_name: "CSS",
|
||||
tech_logo: "https://www.svgrepo.com/show/452185/css-3.svg",
|
||||
project_site: "https://google.com",
|
||||
skill_level: 65,
|
||||
},
|
||||
TechDes {
|
||||
tech_name: "Git",
|
||||
tech_logo: "https://www.svgrepo.com/show/452210/git.svg",
|
||||
project_site: "https://git-scm.com",
|
||||
skill_level: 55,
|
||||
},
|
||||
TechDes {
|
||||
tech_name: "Github Actions",
|
||||
tech_logo: "https://cdn.simpleicons.org/githubactions/2088FF",
|
||||
project_site: "https://github.com/",
|
||||
skill_level: 50,
|
||||
},
|
||||
TechDes {
|
||||
tech_name: "Vs Code",
|
||||
tech_logo: "https://www.svgrepo.com/show/452129/vs-code.svg",
|
||||
project_site: "https://code.visualstudio.com",
|
||||
skill_level: 60,
|
||||
},
|
||||
TechDes {
|
||||
tech_name: "Gitea",
|
||||
tech_logo: "https://about.gitea.com/gitea.png",
|
||||
project_site: "https://about.gitea.com",
|
||||
skill_level: 85,
|
||||
},
|
||||
TechDes {
|
||||
tech_name: "AWS",
|
||||
tech_logo: "https://www.svgrepo.com/show/448266/aws.svg",
|
||||
project_site: "https://aws.amazon.com",
|
||||
skill_level: 30,
|
||||
},
|
||||
TechDes {
|
||||
tech_name: "Firefox",
|
||||
tech_logo: "https://www.svgrepo.com/show/378808/firefox-developer-edition-57-70.svg",
|
||||
project_site: "https://www.mozilla.org/en-CA/firefox/developer/",
|
||||
skill_level: 80,
|
||||
},
|
||||
TechDes {
|
||||
tech_name: "Markdown",
|
||||
tech_logo: "https://www.svgrepo.com/show/510065/markdown.svg",
|
||||
project_site: "https://www.markdownguide.org",
|
||||
skill_level: 90,
|
||||
},
|
||||
TechDes {
|
||||
tech_name: "Prettier",
|
||||
tech_logo: "https://prettier.io/icon.png",
|
||||
project_site: "https://prettier.io",
|
||||
skill_level: 90,
|
||||
},
|
||||
TechDes {
|
||||
tech_name: "Cloudflare",
|
||||
tech_logo: "https://qualified-production.s3.us-east-1.amazonaws.com/uploads/3b522ef84c409e4457032e4b4e3b984abbc92522c6f100f4ccc55c0ccfd3062b.png",
|
||||
project_site: "https://www.cloudflare.com/en-ca/",
|
||||
skill_level: 65,
|
||||
},
|
||||
TechDes {
|
||||
tech_name: "Netlify",
|
||||
tech_logo: "https://qualified-production.s3.us-east-1.amazonaws.com/uploads/0f63ae7280d8d193e346973a1915bf99aea8c63e254eb062bad0bde99b43a9b7.png",
|
||||
project_site: "https://www.netlify.com",
|
||||
skill_level: 60,
|
||||
},
|
||||
TechDes {
|
||||
tech_name: "Vercel",
|
||||
tech_logo: "https://www.svgrepo.com/show/361653/vercel-logo.svg",
|
||||
project_site: "https://vercel.com/home",
|
||||
skill_level: 60,
|
||||
},
|
||||
TechDes {
|
||||
tech_name: "Dioxus",
|
||||
tech_logo: "https://dioxuslabs.com/assets/smalllogo-b1926fd214dc8427.png",
|
||||
project_site: "https://dioxuslabs.com",
|
||||
skill_level: 70,
|
||||
},
|
||||
TechDes {
|
||||
tech_name: "Vue",
|
||||
tech_logo: "https://vuejs.org/logo.svg",
|
||||
project_site: "https://vuejs.org",
|
||||
skill_level: 1,
|
||||
},
|
||||
TechDes {
|
||||
tech_name: "Mongodb",
|
||||
tech_logo: "https://www.svgrepo.com/show/331488/mongodb.svg",
|
||||
project_site: "https://www.mongodb.com",
|
||||
skill_level: 10,
|
||||
},
|
||||
TechDes {
|
||||
tech_name: "Sqlite",
|
||||
tech_logo: "https://www.svgrepo.com/show/374094/sqlite.svg",
|
||||
project_site: "https://www.sqlite.org",
|
||||
skill_level: 10,
|
||||
},
|
||||
TechDes {
|
||||
tech_name: "PostgreSQL",
|
||||
tech_logo: "https://www.svgrepo.com/show/303301/postgresql-logo.svg",
|
||||
project_site: "https://www.postgresql.org",
|
||||
skill_level: 10,
|
||||
},
|
||||
TechDes {
|
||||
tech_name: "DynamoDB",
|
||||
tech_logo: "https://www.svgrepo.com/show/473526/amazondynamodb.svg",
|
||||
project_site: "https://aws.amazon.com/dynamodb/",
|
||||
skill_level: 70,
|
||||
},
|
||||
TechDes {
|
||||
tech_name: "Diesel",
|
||||
tech_logo: "https://res.cloudinary.com/dpgrgsh7g/image/upload/v1745443276/diesel_logo_ujtvia.png",
|
||||
project_site: "https://diesel.rs",
|
||||
skill_level: 10,
|
||||
},
|
||||
TechDes {
|
||||
tech_name: "Kubernetes",
|
||||
tech_logo: "https://kubernetes.io/images/kubernetes.png",
|
||||
project_site: "https://kubernetes.io",
|
||||
skill_level: 5,
|
||||
},
|
||||
TechDes {
|
||||
tech_name: "Terraform",
|
||||
tech_logo: "https://www.svgrepo.com/show/448253/terraform.svg",
|
||||
project_site: "https://www.terraform.io",
|
||||
skill_level: 15,
|
||||
},
|
||||
TechDes {
|
||||
tech_name: "Traefik",
|
||||
tech_logo: "https://hub.docker.com/api/media/repos_logo/v1/library%2Ftraefik",
|
||||
project_site: "https://traefik.io/traefik/",
|
||||
skill_level: 60,
|
||||
},
|
||||
];
|
39
src/lib.rs
39
src/lib.rs
@ -1,13 +1,16 @@
|
||||
use dioxus::prelude::*;
|
||||
|
||||
// use components::Hero;
|
||||
use views::{Blog, Home, Navbar, NewHome};
|
||||
use views::{Blog, Blogs, Contact, Home, Navbar, NewHome, Projects};
|
||||
|
||||
/// Define a components module that contains all shared components for our app.
|
||||
mod components;
|
||||
/// Define a views module that contains the UI for all Layouts and Routes for our app.
|
||||
mod views;
|
||||
|
||||
/// Defines where to place all helper functions
|
||||
mod helper_fun;
|
||||
|
||||
/// 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.
|
||||
///
|
||||
@ -25,23 +28,39 @@ pub enum Route {
|
||||
Home {},
|
||||
// The route attribute can include dynamic parameters that implement [`std::str::FromStr`] and [`std::fmt::Display`] with the `:` syntax.
|
||||
// In this case, id will match any integer like `/blog/123` or `/blog/-456`.
|
||||
#[route("/blog/:id")]
|
||||
#[route("/blogs/:id")]
|
||||
// Fields of the route variant will be passed to the component as props. In this case, the blog component must accept
|
||||
// an `id` prop of type `i32`.
|
||||
Blog { id: i32 },
|
||||
Blogs { id: i32 },
|
||||
|
||||
#[route("/test")]
|
||||
Hello {},
|
||||
#[route("/blogs/:blog_title")]
|
||||
Blog {blog_title: String},
|
||||
|
||||
#[route("/projects")]
|
||||
Projects {},
|
||||
|
||||
#[route("/contact")]
|
||||
Contact {},
|
||||
|
||||
#[route("/new_home")]
|
||||
NewHome {},
|
||||
// PageNotFound is a catch all route that will match any route and placing the matched segments in the route field
|
||||
#[route("/:..route")]
|
||||
PageNotFound { route: Vec<String> },
|
||||
}
|
||||
|
||||
const NOT_FOUND_CSS: Asset = asset!("/assets/styling/notFound.css");
|
||||
|
||||
#[component]
|
||||
fn Hello() -> Element {
|
||||
rsx!(
|
||||
div {
|
||||
h1 { "hello" }
|
||||
fn PageNotFound(route: Vec<String>) -> Element {
|
||||
rsx! {
|
||||
document::Link { rel: "stylesheet", href: NOT_FOUND_CSS }
|
||||
div { id: "not-found",
|
||||
h1 { "Page not found" }
|
||||
p { "We are terribly sorry, but the page you requested doesn't exist." }
|
||||
dioxus::prelude::Link { to: Route::Home {},
|
||||
button { "Return Home Here" }
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::Route;
|
||||
use dioxus::prelude::*;
|
||||
use dioxus::{document::Link, prelude::*};
|
||||
|
||||
const BLOG_CSS: Asset = asset!("/assets/styling/blog.css");
|
||||
|
||||
@ -8,31 +8,43 @@ const BLOG_CSS: Asset = asset!("/assets/styling/blog.css");
|
||||
/// The component takes a `id` prop of type `i32` from the route enum. Whenever the id changes, the component function will be
|
||||
/// re-run and the rendered HTML will be updated.
|
||||
#[component]
|
||||
pub fn Blog(id: i32) -> Element {
|
||||
pub fn Blog(blog_title: String) -> Element {
|
||||
rsx! {
|
||||
document::Link { rel: "stylesheet", href: BLOG_CSS }
|
||||
|
||||
div {
|
||||
id: "blog",
|
||||
div { id: "blog",
|
||||
|
||||
// Content
|
||||
h1 { "This is blog #{id}!" }
|
||||
p { "In blog #{id}, we show how the Dioxus router works and how URL parameters can be passed as props to our route components." }
|
||||
|
||||
// Navigation links
|
||||
// The `Link` component lets us link to other routes inside our app. It takes a `to` prop of type `Route` and
|
||||
// any number of child nodes.
|
||||
Link {
|
||||
// The `to` prop is the route that the link should navigate to. We can use the `Route` enum to link to the
|
||||
// blog page with the id of -1. Since we are using an enum instead of a string, all of the routes will be checked
|
||||
// at compile time to make sure they are valid.
|
||||
to: Route::Blog { id: id - 1 },
|
||||
"Previous"
|
||||
h1 { "This is blog #{blog_title}!" }
|
||||
p {
|
||||
"In blog #{blog_title}, we show how the Dioxus router works and how URL parameters can be passed as props to our route components."
|
||||
}
|
||||
span { " <---> " }
|
||||
Link {
|
||||
to: Route::Blog { id: id + 1 },
|
||||
"Next"
|
||||
|
||||
// // Navigation links
|
||||
// // The `Link` component lets us link to other routes inside our app. It takes a `to` prop of type `Route` and
|
||||
// // any number of child nodes.
|
||||
// Link {
|
||||
// // The `to` prop is the route that the link should navigate to. We can use the `Route` enum to link to the
|
||||
// // blog page with the id of -1. Since we are using an enum instead of a string, all of the routes will be checked
|
||||
// // at compile time to make sure they are valid.
|
||||
// to: Route::Blog { id: id - 1 },
|
||||
// "Previous"
|
||||
// }
|
||||
// span { " <---> " }
|
||||
// Link { to: Route::Blog { id: id + 1 }, "Next" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[component]
|
||||
pub fn Blogs(id: i32) -> Element {
|
||||
rsx! {
|
||||
document::Link { rel: "stylesheet", href: BLOG_CSS }
|
||||
div { id: "blogs",
|
||||
h1 { "Page Under Development" }
|
||||
p { "Please Try Again Later" }
|
||||
dioxus::prelude::Link { to: Route::Home {},
|
||||
button { "Home" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,76 +9,81 @@ pub fn Contact() -> Element {
|
||||
document::Link { href: CONTACT_CSS, rel: "stylesheet" }
|
||||
h2 { "Contact" }
|
||||
div { id: "contact",
|
||||
img {
|
||||
src: PROFESSIONAL_PHOTO_JPG,
|
||||
alt: "Borck's professional photo",
|
||||
div {
|
||||
div {
|
||||
img {
|
||||
src: PROFESSIONAL_PHOTO_JPG,
|
||||
alt: "Borck's professional photo",
|
||||
}
|
||||
}
|
||||
}
|
||||
div {
|
||||
h4 { "Brock Tomlinson" }
|
||||
ul {
|
||||
li { "FullStack Webdev and Student Software Engineer" }
|
||||
li {
|
||||
a { href: "mailto:darkicewolf50@gmail.com",
|
||||
img {
|
||||
src: "https://www.svgrepo.com/show/491226/email.svg",
|
||||
alt: "Email icon/logo",
|
||||
}
|
||||
div {
|
||||
p { "Email I check:" }
|
||||
p { "darkicewolf50@gmail.com" }
|
||||
div {
|
||||
h4 { "Brock Tomlinson" }
|
||||
ul {
|
||||
li { "FullStack Webdev and Student Software Engineer" }
|
||||
li {
|
||||
a { href: "mailto:darkicewolf50@gmail.com",
|
||||
img {
|
||||
src: "https://www.svgrepo.com/show/491226/email.svg",
|
||||
alt: "Email icon/logo",
|
||||
}
|
||||
div {
|
||||
p { "Email I check:" }
|
||||
p { "darkicewolf50@gmail.com" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
li {
|
||||
a { href: "mailto:brock@eatsleepski.com",
|
||||
img {
|
||||
src: "https://www.svgrepo.com/show/491226/email.svg",
|
||||
alt: "Email icon/logo",
|
||||
}
|
||||
div {
|
||||
p { "Professional Email:" }
|
||||
p { "brock@eatsleepski.com" }
|
||||
li {
|
||||
a { href: "mailto:brock@eatsleepski.com",
|
||||
img {
|
||||
src: "https://www.svgrepo.com/show/491226/email.svg",
|
||||
alt: "Email icon/logo",
|
||||
}
|
||||
div {
|
||||
p { "Professional Email:" }
|
||||
p { "brock@eatsleepski.com" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
li {
|
||||
a {
|
||||
img {
|
||||
src: "https://www.svgrepo.com/show/512317/github-142.svg",
|
||||
alt: "Github logo",
|
||||
li {
|
||||
a {
|
||||
img {
|
||||
src: "https://www.svgrepo.com/show/512317/github-142.svg",
|
||||
alt: "Github logo",
|
||||
}
|
||||
p { "darkicewolf50" }
|
||||
}
|
||||
p { "darkicewolf50" }
|
||||
}
|
||||
}
|
||||
li {
|
||||
a {
|
||||
img {
|
||||
src: "https://www.svgrepo.com/show/521725/linkedin.svg",
|
||||
alt: "LinkedIn logo",
|
||||
li {
|
||||
a {
|
||||
img {
|
||||
src: "https://www.svgrepo.com/show/521725/linkedin.svg",
|
||||
alt: "LinkedIn logo",
|
||||
}
|
||||
p { "Brock Tomlinson" }
|
||||
}
|
||||
p { "Brock Tomlinson" }
|
||||
}
|
||||
}
|
||||
li {
|
||||
a {
|
||||
img {
|
||||
src: "https://www.svgrepo.com/show/519925/twitch.svg",
|
||||
alt: "Twitch logo",
|
||||
li {
|
||||
a {
|
||||
img {
|
||||
src: "https://www.svgrepo.com/show/519925/twitch.svg",
|
||||
alt: "Twitch logo",
|
||||
}
|
||||
p { "darkicewolf50" }
|
||||
}
|
||||
p { "darkicewolf50" }
|
||||
}
|
||||
}
|
||||
li {
|
||||
a {
|
||||
img {
|
||||
src: "https://www.svgrepo.com/show/521936/youtube.svg",
|
||||
alt: "Youtube logo",
|
||||
li {
|
||||
a {
|
||||
img {
|
||||
src: "https://www.svgrepo.com/show/521936/youtube.svg",
|
||||
alt: "Youtube logo",
|
||||
}
|
||||
p { "@darkicewolf50" }
|
||||
}
|
||||
p { "@darkicewolf50" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,50 +0,0 @@
|
||||
use dioxus::prelude::*;
|
||||
|
||||
const ENDER_CSS: Asset = asset!("/assets/styling/ender.css");
|
||||
|
||||
#[component]
|
||||
pub fn Ender() -> Element {
|
||||
rsx! {
|
||||
document::Link { rel: "stylesheet", href: ENDER_CSS }
|
||||
footer {
|
||||
p { "Brock Tomlinson © 2025" }
|
||||
div {
|
||||
a { href: "https://github.com/darkicewolf50",
|
||||
img {
|
||||
src: "https://www.svgrepo.com/show/512317/github-142.svg",
|
||||
alt: "Github logo",
|
||||
}
|
||||
p { "Github" }
|
||||
}
|
||||
a { href: "mailto:darkicewolf50@gmail.com",
|
||||
img {
|
||||
src: "https://www.svgrepo.com/show/491226/email.svg",
|
||||
alt: "Email logo/icon",
|
||||
}
|
||||
p { "Email" }
|
||||
}
|
||||
a { href: "https://www.linkedin.com/in/brock-tomlinson/",
|
||||
img {
|
||||
src: "https://www.svgrepo.com/show/521725/linkedin.svg",
|
||||
alt: "LinkedIn logo",
|
||||
}
|
||||
p { "LinkedIn" }
|
||||
}
|
||||
a { href: "https://www.twitch.tv/darkicewolf50",
|
||||
img {
|
||||
src: "https://www.svgrepo.com/show/519925/twitch.svg",
|
||||
alt: "Twitch logo",
|
||||
}
|
||||
p { "Twitch" }
|
||||
}
|
||||
a { href: "https://www.youtube.com/@darkicewolf50",
|
||||
img {
|
||||
src: "https://www.svgrepo.com/show/521936/youtube.svg",
|
||||
alt: "Youtube logo",
|
||||
}
|
||||
p { "Youtube" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,14 +1,87 @@
|
||||
use crate::components::{TechCat, TechDes};
|
||||
use crate::views::Contact;
|
||||
use crate::components::{Experience, TechCat};
|
||||
use crate::views::{Contact, Projects};
|
||||
use crate::Route;
|
||||
use dioxus::prelude::*;
|
||||
|
||||
const HOME_CSS: Asset = asset!("/assets/styling/home.css");
|
||||
|
||||
#[component]
|
||||
pub fn Home() -> Element {
|
||||
let languages: Vec<&'static str> = vec!["Rust", "Python", "JavaScript", "YAML", "C", "C++"];
|
||||
let languages = vec![
|
||||
"Rust",
|
||||
"Python",
|
||||
"YAML",
|
||||
"HTML5",
|
||||
"CSS",
|
||||
"JavaScript",
|
||||
"Markdown",
|
||||
];
|
||||
let backend = vec!["Actix", "FastAPI", "Dioxus", "Diesel"];
|
||||
let frontend = vec!["React", "Dioxus", "Vue"];
|
||||
let databases = vec!["Sqlite", "PostgreSQL", "Mongodb", "DynamoDB"];
|
||||
let tools = vec![
|
||||
"Vs Code",
|
||||
"Git",
|
||||
"Prettier",
|
||||
"Firefox",
|
||||
"Github Actions",
|
||||
"Traefik",
|
||||
"Docker",
|
||||
"Kubernetes",
|
||||
"Terraform",
|
||||
];
|
||||
let platforms = vec!["AWS", "Cloudflare", "Vercel", "Netlify", "Gitea", "Github"];
|
||||
rsx!(
|
||||
h1 { "Hi I'm Brock" }
|
||||
TechCat { cat: "Languages".to_string(), tech_vec: languages }
|
||||
Contact {}
|
||||
document::Link { rel: "stylesheet", href: HOME_CSS }
|
||||
div {
|
||||
div { id: "home-intro",
|
||||
h1 { "Hi I'm Brock" }
|
||||
p {
|
||||
"a fourth year Software Engineering Student specializing in full-stack development with a strong focus on backend technologies.
|
||||
I am developing the language of how to design, develop, and create programs that are to industry standards and reasonably efficent.
|
||||
I bring the lessons learned from each project I have completed,
|
||||
learning from the mistakes I have made and bringing improved versions forward into the next project."
|
||||
}
|
||||
p {
|
||||
"As of writing this I intend to bring the knowledge learned from my time at university in Software Engineering onto a Baja SAE car,
|
||||
where we can collect data remotely and graph data for instantaneous and future analysis,
|
||||
during vechile operation."
|
||||
}
|
||||
p {
|
||||
"I grew up in a small ski town where, I started learning about programming, from of course Minecraft,
|
||||
where I thought the application of this was so futuristic and downright cool that I knew I wanted to persure it further.
|
||||
While living there I spend a majority of my time outside of school swimming competitively, where I ranked top 10 in BC.
|
||||
Along with swimming I spend a lot of time volunteering with fundraising events and coaching the local Special Olympics swim team."
|
||||
}
|
||||
p {
|
||||
"I advore problem solving and building cool stuff, I'm happy to jump in and get started! "
|
||||
Link { to: Route::Contact {}, "Let's create something great together!" }
|
||||
}
|
||||
}
|
||||
div { class: "technologies",
|
||||
|
||||
h2 { "Technology" }
|
||||
p { "Here is what I prefer to use and their self assessed skill" }
|
||||
// p { "Here is what I developed skills in." }
|
||||
div { class: "technologies-cat",
|
||||
TechCat { cat: "Languages", tech_vec: languages }
|
||||
TechCat { cat: "Backend", tech_vec: backend }
|
||||
TechCat { cat: "Frontend", tech_vec: frontend }
|
||||
TechCat { cat: "Databases", tech_vec: databases }
|
||||
TechCat { cat: "Platforms", tech_vec: platforms }
|
||||
TechCat { cat: "Tools", tech_vec: tools }
|
||||
}
|
||||
}
|
||||
Contact {}
|
||||
Projects {}
|
||||
div { id: "experience",
|
||||
h2 { "Experience" }
|
||||
div {
|
||||
Experience { professional_jobs: true }
|
||||
Experience { professional_jobs: false }
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ mod new_home;
|
||||
pub use new_home::NewHome;
|
||||
|
||||
mod blog;
|
||||
pub use blog::Blog;
|
||||
pub use blog::{Blog, Blogs};
|
||||
|
||||
mod navbar;
|
||||
pub use navbar::Navbar;
|
||||
@ -20,10 +20,8 @@ pub use navbar::Navbar;
|
||||
mod home;
|
||||
pub use home::Home;
|
||||
|
||||
mod footer;
|
||||
pub use footer::Ender;
|
||||
|
||||
mod contact;
|
||||
pub use contact::Contact;
|
||||
|
||||
mod projects;
|
||||
pub use projects::{ProjectCards, Projects};
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::views::Ender;
|
||||
use crate::components::Ender;
|
||||
use crate::Route;
|
||||
use dioxus::prelude::*;
|
||||
|
||||
@ -17,8 +17,10 @@ pub fn Navbar() -> Element {
|
||||
document::Link { rel: "stylesheet", href: STD_COLOUR_AND_FONTS_CSS }
|
||||
|
||||
div { id: "navbar",
|
||||
Link { to: Route::NewHome {}, "Home" }
|
||||
Link { to: Route::Blog { id: 1 }, "Blog" }
|
||||
Link { to: Route::Home {}, "Home" }
|
||||
Link { to: Route::Projects {}, "Projects" }
|
||||
Link { to: Route::Blogs { id: 0 }, "Blogs" }
|
||||
Link { to: Route::Contact {}, "Contact" }
|
||||
}
|
||||
|
||||
// The `Outlet` component is used to render the next component inside the layout. In this case, it will render either
|
||||
|
@ -1,7 +1,108 @@
|
||||
use crate::helper_fun::get_tech_logos_from_str;
|
||||
use dioxus::prelude::*;
|
||||
|
||||
#[component]
|
||||
pub fn Projects() -> Element {
|
||||
todo!();
|
||||
rsx! {}
|
||||
rsx! {
|
||||
div {
|
||||
h2 { "Projects" }
|
||||
p { "Top Featured and Recent Projects" }
|
||||
}
|
||||
div { class: "project-section",
|
||||
ProjectCards {
|
||||
project_name: "Portfolio Site",
|
||||
website_prop: "https://darkicewolf50.github.io",
|
||||
github_prop: "https://github.com/darkicewolf50/darkicewolf50.github.io",
|
||||
project_img: "https://res.cloudinary.com/dpgrgsh7g/image/upload/v1745630861/Portfolio_site_k4mhmj.png",
|
||||
techs_used: vec!["Rust", "CSS", "Dioxus", "Github Actions", "Git", "Github"],
|
||||
project_des: "This project was a great test of my newly learned Rust.
|
||||
It was certainly interesting to go through all of the stages of front end web developement, while the orignal and new found scope is not currently achieved, it will be on a later pass through.
|
||||
I am very happy with how it turned out in compairison to my origanl site map, and wireframes.
|
||||
Considering this phase one was accomplished in 3 working days I believe it is an excellent show of my skill.",
|
||||
}
|
||||
ProjectCards {
|
||||
project_name: "UCalgary Baja Backend",
|
||||
project_img: "https://www.svgrepo.com/show/448221/docker.svg",
|
||||
techs_used: vec!["Python", "FastAPI", "Github Actions", "Docker", "Traefik", "Git", "Github"],
|
||||
project_des: "This is going to be extremely cost saving for the non-profit club UCalgary Baja.
|
||||
Using automated uploads and linting to check the Python and FastAPI code was excellent for learning how to self-host a web server.
|
||||
This was then upgraded later with the addition of treafik so that it could be SSL certified, this is also known as supporting HTTPS transmissions.
|
||||
Ultimately it will serve as a great stepping stone for both myself an anyone else in UCalgary Baja Software subteam.
|
||||
This will lead into using Actixs in the migration Soon™ to be.",
|
||||
}
|
||||
ProjectCards {
|
||||
project_name: "UCalgary Baja Website",
|
||||
website_prop: "https://uofcbaja.pages.dev",
|
||||
project_img: "https://res.cloudinary.com/dpgrgsh7g/image/upload/v1745633714/ucalgary-baja-site-April.png",
|
||||
techs_used: vec![
|
||||
"HTML5",
|
||||
"CSS",
|
||||
"JavaScript",
|
||||
"Markdown",
|
||||
"YAML",
|
||||
"React",
|
||||
"Git",
|
||||
"Github",
|
||||
"Cloudflare",
|
||||
],
|
||||
project_des: "The flexibility that we achieved using React,
|
||||
rather than a locked down platform or framework has allows all the Software members of UCalgary Baja to learn infinitely more.
|
||||
This isn't to say that it is faster or have additional perks of using 'non-code website builders'.
|
||||
This is provided massive opportunities to learn teach and save on cost compaired to the website builders.
|
||||
Overall I would say this will be worth it in the long run and opened my eyes to different website hosting providers,
|
||||
with their associated perks and costs.
|
||||
When we change it, it will most likely we re-written in Vue as there is a good non-depreciated way to initalize the framework.",
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const PROJECT_CARDS_CSS: Asset = asset!("/assets/styling/projectCards.css");
|
||||
|
||||
#[component]
|
||||
pub fn ProjectCards(
|
||||
website_prop: Option<&'static str>,
|
||||
github_prop: Option<&'static str>,
|
||||
project_name: &'static str,
|
||||
techs_used: Vec<&'static str>,
|
||||
project_des: &'static str,
|
||||
#[props(default = "https://picsum.photos/200")] project_img: &'static str,
|
||||
) -> Element {
|
||||
rsx! {
|
||||
document::Link { href: PROJECT_CARDS_CSS, rel: "stylesheet" }
|
||||
div { class: "project-card",
|
||||
img {
|
||||
src: "{project_img}",
|
||||
alt: "dashboard of project or the logo of the project",
|
||||
}
|
||||
div { class: "project-title-info",
|
||||
h3 { "{project_name}" }
|
||||
div {
|
||||
if let Some(github_site) = github_prop {
|
||||
a { href: "{github_site}",
|
||||
get_tech_logos_from_str { used_tech: "Github" }
|
||||
}
|
||||
}
|
||||
if let Some(site) = website_prop {
|
||||
a { href: "{site}",
|
||||
get_tech_logos_from_str { used_tech: "Internet" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
div {
|
||||
p { "{project_des}" }
|
||||
}
|
||||
div { class: "project-tech-logos",
|
||||
for tech in techs_used {
|
||||
get_tech_logos_from_str { used_tech: tech }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// img {
|
||||
// src: "https://www.svgrepo.com/show/512317/github-142.svg",
|
||||
// alt: "Github logo",
|
||||
// }
|
||||
|
235
techs.json
Normal file
235
techs.json
Normal file
@ -0,0 +1,235 @@
|
||||
{
|
||||
"Rust": {
|
||||
"tech_logo": "https://www.svgrepo.com/show/374056/rust.svg",
|
||||
"project_site": "https://www.rust-lang.org",
|
||||
"skill_level": 65
|
||||
},
|
||||
|
||||
"Python": {
|
||||
"tech_logo": "https://www.svgrepo.com/show/452091/python.svg",
|
||||
"project_site": "https://www.python.org",
|
||||
"skill_level": 60
|
||||
},
|
||||
|
||||
"JavaScript": {
|
||||
"tech_logo": "https://www.svgrepo.com/show/303206/javascript-logo.svg",
|
||||
"project_site": "https://www.python.org",
|
||||
"skill_level": 60
|
||||
},
|
||||
|
||||
"YAML": {
|
||||
"tech_logo": "https://yaml.org/favicon.svg",
|
||||
"project_site": "https://yaml.org",
|
||||
"skill_level": 95
|
||||
},
|
||||
|
||||
"C": {
|
||||
"tech_logo": "https://www.c-language.org/logo.svg",
|
||||
"project_site": "https://www.c-language.org",
|
||||
"skill_level": 50
|
||||
},
|
||||
|
||||
"C++": {
|
||||
"tech_logo": "https://www.svgrepo.com/show/452183/cpp.svg",
|
||||
"project_site": "https://cplusplus.com",
|
||||
"skill_level": 50
|
||||
},
|
||||
|
||||
"Github": {
|
||||
"tech_logo": "https://www.svgrepo.com/show/512317/github-142.svg",
|
||||
"project_site": "https://github.com/darkicewolf50",
|
||||
"skill_level": 80
|
||||
},
|
||||
|
||||
"Email": {
|
||||
"tech_logo": "https://www.svgrepo.com/show/491226/email.svg",
|
||||
"project_site": "mailto:darkicewolf50@gmail.com",
|
||||
"skill_level": 100
|
||||
},
|
||||
|
||||
"LinkedIn": {
|
||||
"tech_logo": "https://www.svgrepo.com/show/521725/linkedin.svg",
|
||||
"project_site": "https://www.linkedin.com/in/brock-tomlinson/",
|
||||
"skill_level": 4
|
||||
},
|
||||
|
||||
"Twitch": {
|
||||
"tech_logo": "https://www.svgrepo.com/show/519925/twitch.svg",
|
||||
"project_site": "https://www.twitch.tv/darkicewolf50",
|
||||
"skill_level": 6
|
||||
},
|
||||
|
||||
"Youtube": {
|
||||
"tech_logo": "https://www.svgrepo.com/show/521936/youtube.svg",
|
||||
"project_site": "https://www.youtube.com/@darkicewolf50",
|
||||
"skill_level": 4
|
||||
},
|
||||
|
||||
"Internet": {
|
||||
"tech_logo": "https://www.svgrepo.com/show/490809/internet.svg",
|
||||
"project_site": "https://google.com",
|
||||
"skill_level": 99
|
||||
},
|
||||
|
||||
"React": {
|
||||
"tech_logo": "https://www.svgrepo.com/show/452092/react.svg",
|
||||
"project_site": "https://react.dev",
|
||||
"skill_level": 60
|
||||
},
|
||||
|
||||
"Docker": {
|
||||
"tech_logo": "https://www.svgrepo.com/show/448221/docker.svg",
|
||||
"project_site": "https://www.docker.com",
|
||||
"skill_level": 70
|
||||
},
|
||||
|
||||
"FastAPI": {
|
||||
"tech_logo": "https://fastapi.tiangolo.com/img/favicon.png",
|
||||
"project_site": "https://fastapi.tiangolo.com",
|
||||
"skill_level": 80
|
||||
},
|
||||
|
||||
"Actix": {
|
||||
"tech_logo": "https://actix.rs/img/logo.png",
|
||||
"project_site": "https://actix.rs",
|
||||
"skill_level": 20
|
||||
},
|
||||
|
||||
"HTML5": {
|
||||
"tech_logo": "https://www.svgrepo.com/show/452228/html-5.svg",
|
||||
"project_site": "https://google.com",
|
||||
"skill_level": 90
|
||||
},
|
||||
|
||||
"CSS": {
|
||||
"tech_logo": "https://www.svgrepo.com/show/452185/css-3.svg",
|
||||
"project_site": "https://google.com",
|
||||
"skill_level": 60
|
||||
},
|
||||
|
||||
"Git": {
|
||||
"tech_logo": "https://www.svgrepo.com/show/452210/git.svg",
|
||||
"project_site": "https://git-scm.com",
|
||||
"skill_level": 50
|
||||
},
|
||||
|
||||
"Github Actions": {
|
||||
"tech_logo": "https://cdn.simpleicons.org/githubactions/2088FF",
|
||||
"project_site": "https://github.com/",
|
||||
"skill_level": 40
|
||||
},
|
||||
|
||||
"Vs Code": {
|
||||
"tech_logo": "https://www.svgrepo.com/show/452129/vs-code.svg",
|
||||
"project_site": "https://code.visualstudio.com",
|
||||
"skill_level": 60
|
||||
},
|
||||
|
||||
"Gitea": {
|
||||
"tech_logo": "https://about.gitea.com/gitea.png",
|
||||
"project_site": "https://about.gitea.com",
|
||||
"skill_level": 85
|
||||
},
|
||||
|
||||
"AWS": {
|
||||
"tech_logo": "https://www.svgrepo.com/show/448266/aws.svg",
|
||||
"project_site": "https://aws.amazon.com",
|
||||
"skill_level": 40
|
||||
},
|
||||
|
||||
"Firefox": {
|
||||
"tech_logo": "https://www.svgrepo.com/show/378808/firefox-developer-edition-57-70.svg",
|
||||
"project_site": "https://www.mozilla.org/en-CA/firefox/developer/",
|
||||
"skill_level": 80
|
||||
},
|
||||
|
||||
"Markdown": {
|
||||
"tech_logo": "https://www.svgrepo.com/show/510065/markdown.svg",
|
||||
"project_site": "https://www.markdownguide.org",
|
||||
"skill_level": 90
|
||||
},
|
||||
|
||||
"Prettier": {
|
||||
"tech_logo": "https://prettier.io/icon.png",
|
||||
"project_site": "https://prettier.io",
|
||||
"skill_level": 90
|
||||
},
|
||||
|
||||
"DynamoDB": {
|
||||
"tech_logo": "https://www.svgrepo.com/show/353450/aws-dynamodb.svg",
|
||||
"project_site": "https://aws.amazon.com/dynamodb/",
|
||||
"skill_level": 50
|
||||
},
|
||||
|
||||
"Cloudflare": {
|
||||
"tech_logo": "https://qualified-production.s3.us-east-1.amazonaws.com/uploads/3b522ef84c409e4457032e4b4e3b984abbc92522c6f100f4ccc55c0ccfd3062b.png",
|
||||
"project_site": "https://www.cloudflare.com/en-ca/",
|
||||
"skill_level": 40
|
||||
},
|
||||
|
||||
"Netlify": {
|
||||
"tech_logo": "https://qualified-production.s3.us-east-1.amazonaws.com/uploads/0f63ae7280d8d193e346973a1915bf99aea8c63e254eb062bad0bde99b43a9b7.png",
|
||||
"project_site": "https://www.netlify.com",
|
||||
"skill_level": 70
|
||||
},
|
||||
|
||||
"Vercel": {
|
||||
"tech_logo": "https://www.svgrepo.com/show/361653/vercel-logo.svg",
|
||||
"project_site": "https://vercel.com/home",
|
||||
"skill_level": 60
|
||||
},
|
||||
|
||||
"Dioxus": {
|
||||
"tech_logo": "https://dioxuslabs.com/assets/smalllogo-b1926fd214dc8427.png",
|
||||
"project_site": "https://dioxuslabs.com",
|
||||
"skill_level": 60
|
||||
},
|
||||
|
||||
"Vue": {
|
||||
"tech_logo": "https://vuejs.org/logo.svg",
|
||||
"project_site": "https://vuejs.org",
|
||||
"skill_level": 1
|
||||
},
|
||||
|
||||
"Mongodb": {
|
||||
"tech_logo": "https://www.svgrepo.com/show/331488/mongodb.svg",
|
||||
"project_site": "https://www.mongodb.com",
|
||||
"skill_level": 10
|
||||
},
|
||||
|
||||
"Sqlite": {
|
||||
"tech_logo": "https://www.svgrepo.com/show/374094/sqlite.svg",
|
||||
"project_site": "https://www.sqlite.org",
|
||||
"skill_level": 10
|
||||
},
|
||||
|
||||
"PostgreSQL": {
|
||||
"tech_logo": "https://www.svgrepo.com/show/303301/postgresql-logo.svg",
|
||||
"project_site": "https://www.postgresql.org",
|
||||
"skill_level": 10
|
||||
},
|
||||
|
||||
"Diesel": {
|
||||
"tech_logo": "https://res.cloudinary.com/dpgrgsh7g/image/upload/v1745443276/diesel_logo_ujtvia.png",
|
||||
"project_site": "https://diesel.rs",
|
||||
"skill_level": 10
|
||||
},
|
||||
|
||||
"Kubernetes": {
|
||||
"tech_logo": "https://kubernetes.io/images/kubernetes.png",
|
||||
"project_site": "https://kubernetes.io",
|
||||
"skill_level": 5
|
||||
},
|
||||
|
||||
"Terraform": {
|
||||
"tech_logo": "https://www.svgrepo.com/show/448253/terraform.svg",
|
||||
"project_site": "https://www.terraform.io",
|
||||
"skill_level": 10
|
||||
},
|
||||
|
||||
"Traefik": {
|
||||
"tech_logo": "https://hub.docker.com/api/media/repos_logo/v1/library%2Ftraefik",
|
||||
"project_site": "https://traefik.io/traefik/",
|
||||
"skill_level": 60
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user