Begin add MonParcours + Update css work
This commit is contained in:
parent
1e27d18cb3
commit
f4dba8213d
21 changed files with 1499 additions and 36 deletions
1
.tool-versions
Normal file
1
.tool-versions
Normal file
|
@ -0,0 +1 @@
|
|||
nodejs 19.9.0
|
1138
package-lock.json
generated
Normal file
1138
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
9
package.json
Normal file
9
package.json
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"devDependencies": {
|
||||
"autoprefixer": "^10.4.16",
|
||||
"postcss": "^8.4.31",
|
||||
"postcss-import": "^15.1.0",
|
||||
"postcss-nested": "^6.0.1",
|
||||
"tailwindcss": "^3.3.3"
|
||||
}
|
||||
}
|
8
postcss.config.js
Normal file
8
postcss.config.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
export default {
|
||||
plugins: {
|
||||
'postcss-import': {},
|
||||
'postcss-nested': {},
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
}
|
||||
}
|
|
@ -9,9 +9,9 @@ pub fn Link(
|
|||
children: Children
|
||||
) -> impl IntoView {
|
||||
view! {
|
||||
<a class="flex gap-1 font-semibold italic" href={url} target="_blank">
|
||||
<a class="link" href={url} target="_blank">
|
||||
{ children() }
|
||||
<i class="flex items-center"><Icon icon=Icon::from(FiExternalLink) class="scale-75" /></i>
|
||||
<i><Icon icon=Icon::from(FiExternalLink) /></i>
|
||||
</a>
|
||||
}
|
||||
}
|
|
@ -1,17 +1,27 @@
|
|||
mod tag;
|
||||
|
||||
pub use tag::Tag;
|
||||
|
||||
mod link;
|
||||
|
||||
pub use link::Link;
|
||||
|
||||
mod social_link;
|
||||
|
||||
pub use social_link::{SocialLinkContainer, SocialLink};
|
||||
|
||||
mod top_component;
|
||||
|
||||
pub use top_component::TopComponent;
|
||||
|
||||
mod project;
|
||||
|
||||
pub use project::{ProjectContainer, Project};
|
||||
|
||||
mod timeline;
|
||||
pub use timeline::{Timeline};
|
||||
|
||||
pub use timeline::{Timeline, TimelineElement, TimelineLabel, TimelineCard, TimelineCardTag, TimelineCardContent, TimelineCardSummary};
|
||||
|
||||
mod mon_parcours;
|
||||
|
||||
pub use mon_parcours::{MonParcours};
|
80
src/app/components/mon_parcours.rs
Normal file
80
src/app/components/mon_parcours.rs
Normal file
|
@ -0,0 +1,80 @@
|
|||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
use leptos::*;
|
||||
|
||||
use super::{
|
||||
Tag,
|
||||
Timeline,
|
||||
TimelineElement,
|
||||
TimelineLabel,
|
||||
TimelineCard,
|
||||
TimelineCardSummary,
|
||||
TimelineCardTag,
|
||||
TimelineCardContent
|
||||
};
|
||||
|
||||
// Lang
|
||||
// const CPP_TAG = <Tag name="C++" url="https://isocpp.org/" />
|
||||
//
|
||||
// // Other
|
||||
// const REACT_TAG = <Tag name="React" url="https://fr.legacy.reactjs.org/" />
|
||||
// const SYMFONY_4_TAG = <Tag name="Symfony" url="https://symfony.com/" />
|
||||
// const FLUTTER_TAG = <Tag name="Flutter" url="https://flutter.dev/" />
|
||||
// const RUBY_ON_RAILS_TAG = <Tag name="Ruby on rails" url="https://rubyonrails.org/" />
|
||||
// const HOTWIRED_TAG = <Tag name="Hotwired" url="https://hotwired.dev/" />
|
||||
// const DOCKER_TAG = <Tag name="Docker" url="https://www.docker.com/" />
|
||||
// const STEAM_TAG = <Tag name="Steam API" url="https://partner.steamgames.com/doc/sdk/api/example" />
|
||||
// const GITLAB_CI_TAG = <Tag name="Gitlab CI" url="https://docs.gitlab.com/ee/ci/" />
|
||||
// const UNITY_TAG = <Tag name="Unity 3D" url="https://unity.com/fr" />
|
||||
// const WORDPRESS_TAG = <Tag name="Wordpress" url="https://wordpress.com/fr/" />
|
||||
// const CORDOVA_TAG = <Tag name="Cordova" url="https://cordova.apache.org/" />
|
||||
// const ELECTRON_TAG = <Tag name="Electron" url="https://www.electronjs.org/" />
|
||||
// const LWJGL_TAG = <Tag name="LWJGL" url="https://www.lwjgl.org/" />
|
||||
// const OPENGL_TAG = <Tag name="OpenGL" url="https://www.opengl.org/" />
|
||||
// const VULKAN_TAG = <Tag name="Vulkan" url="https://www.vulkan.org/" />
|
||||
// const MIDI_TAG = <Tag name="MIDI" url="https://fr.wikipedia.org/wiki/Musical_Instrument_Digital_Interface" />
|
||||
// const REQUIREJS_TAG = <Tag name="RequireJS" url="https://requirejs.org/" />
|
||||
// const WEBPACK_TAG = <Tag name="Webpack" url="https://webpack.js.org/" />
|
||||
// const VITE_TAG = <Tag name="Vite" url="https://vitejs.dev/" />
|
||||
// const MAVEN_TAG = <Tag name="Maven" url="https://maven.apache.org/" />
|
||||
// const GRADLE_TAG = <Tag name="Gradle" url="https://gradle.org/" />
|
||||
// const BABYLONJG_TAG = <Tag name="BabylonJS" url="https://www.babylonjs.com/" />
|
||||
// const ROCKET_RS_TAG = <Tag name="Rocket" url="https://rocket.rs/" />
|
||||
// const ACTIX_WEB_TAG = <Tag name="Actix Web" url="https://actix.rs/" />
|
||||
|
||||
#[component]
|
||||
pub fn MonParcours() -> impl IntoView {
|
||||
let tools = Rc::from(HashMap::from([
|
||||
("Rust", "https://www.rust-lang.org/"),
|
||||
("Java", "https://www.java.com/fr/"),
|
||||
("C++", "https://isocpp.org/")
|
||||
]));
|
||||
|
||||
let to_tag = |tools: &HashMap<&str, &str>, lang: &str| {
|
||||
let url = tools.get(lang).unwrap_or(&"");
|
||||
view! { <Tag url=url.to_string()>Rust</Tag> }
|
||||
};
|
||||
|
||||
view! {
|
||||
<div>
|
||||
<Timeline>
|
||||
<TimelineElement slot:elements>
|
||||
<TimelineLabel slot:labels>r"2019 - Aujourd’hui"</TimelineLabel>
|
||||
<TimelineCard slot:cards>
|
||||
<TimelineCardSummary slot:titles>
|
||||
<TimelineCardTag slot:tags>{ to_tag(tools.as_ref(), "Rust") }</TimelineCardTag>
|
||||
r"Développeur d’application Web, Mobile et Système (CDI)"
|
||||
</TimelineCardSummary>
|
||||
<TimelineCardContent slot:cards>
|
||||
<p>r"Développement d’application Symfony, React, Flutter, Rust et Ruby on rails (6 et 7) pour des clients."</p><br />
|
||||
<p>r"Je développe surtout des applications Flutter et Ruby on rails avec l’aide de Hotwired."</p><br />
|
||||
|
||||
<i>Unova France</i><br />
|
||||
<i>11 Septembre 2019 - Toujours en CDI</i>
|
||||
</TimelineCardContent>
|
||||
</TimelineCard>
|
||||
</TimelineElement>
|
||||
</Timeline>
|
||||
</div>
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@ pub fn ProjectContainer(
|
|||
children: Children
|
||||
) -> impl IntoView {
|
||||
view! {
|
||||
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 mt-3">
|
||||
<div class="project_list">
|
||||
{ children() }
|
||||
</div>
|
||||
}
|
||||
|
@ -20,9 +20,9 @@ pub fn Project(
|
|||
url: Option<String>
|
||||
) -> impl IntoView {
|
||||
view! {
|
||||
<a href=url target="_blank" class="rounded-lg p-5 flex flex-col items-center gap-2 bg-primary/10 dark:bg-dark_primary/10 shadow-md shadow-primary/5 dark:shadow-dark_primary/5 hover:bg-primary/20 hover:dark:bg-dark_primary/20 hover:shadow-md hover:shadow-primary/10 hover:dark:shadow-dark_primary/10">
|
||||
{ image_src.map(|src| view! { <img src=src class="h-1/2"/> }) }
|
||||
<div class="flex flex-col justify-center h-full"><p>{ children() }</p></div>
|
||||
<a href=url target="_blank">
|
||||
{ image_src.map(|src| view! { <img src=src/> }) }
|
||||
<div><p>{ children() }</p></div>
|
||||
</a>
|
||||
}
|
||||
}
|
|
@ -6,7 +6,7 @@ pub fn SocialLinkContainer(
|
|||
children: Children
|
||||
) -> impl IntoView {
|
||||
view! {
|
||||
<div class="flex gap-5 justify-center flex-wrap my-5">
|
||||
<div class="social_links">
|
||||
{ children() }
|
||||
</div>
|
||||
}
|
||||
|
@ -20,9 +20,9 @@ pub fn SocialLink(
|
|||
icon: Icon,
|
||||
) -> impl IntoView {
|
||||
view! {
|
||||
<a href=url target="_blank">
|
||||
<Icon icon=icon class="mx-auto scale-150 mb-1" />
|
||||
<span class="text-sm">{ children() }</span>
|
||||
<a class="social_link" href=url target="_blank">
|
||||
<Icon icon=icon />
|
||||
<span>{ children() }</span>
|
||||
</a>
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@ pub fn Tag(
|
|||
children: Children
|
||||
) -> impl IntoView {
|
||||
view! {
|
||||
<a class="rounded-lg px-3 py-1 font-normal text-sm bg-primary dark:bg-dark_primary text-on_primary dark:text-dark_on_primary" href=url target="_blank">
|
||||
<a class="tag" href=url target="_blank">
|
||||
{children()}
|
||||
</a>
|
||||
}
|
||||
|
|
|
@ -4,11 +4,11 @@ use leptos_icons::*;
|
|||
|
||||
#[component]
|
||||
pub fn Timeline(
|
||||
#[prop(default=vec![])] elements: Vec<TimelineElement>,
|
||||
#[prop(default = vec![])] elements: Vec<TimelineElement>,
|
||||
) -> impl IntoView {
|
||||
view! {
|
||||
<div class="w-full px-5">
|
||||
<ul class="list-none py-5 px-0 relative w-full max-w-5xl mx-auto before:top-0 before:bottom-0 before:left-0 before:md:left-1/2 before:absolute before:content-[\"\"] before:w-2 before:bg-primary/10 before:dark:bg-dark_primary/10 before:shadow-md before:shadow-primary/5 before:dark:shadow-dark_primary/5">
|
||||
<div class="timeline">
|
||||
<ul>
|
||||
{ elements.collect_view() }
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -16,11 +16,11 @@ pub fn Timeline(
|
|||
}
|
||||
|
||||
#[slot]
|
||||
pub struct TimelineElementLabel {
|
||||
pub struct TimelineLabel {
|
||||
children: ChildrenFn,
|
||||
}
|
||||
|
||||
impl IntoView for TimelineElementLabel {
|
||||
impl IntoView for TimelineLabel {
|
||||
fn into_view(self) -> View {
|
||||
let view = view! { <>{ (self.children)() }</> };
|
||||
view.into_view()
|
||||
|
@ -29,8 +29,8 @@ impl IntoView for TimelineElementLabel {
|
|||
|
||||
#[slot]
|
||||
pub struct TimelineElement {
|
||||
#[prop(default=vec![])] labels: Vec<TimelineElementLabel>,
|
||||
#[prop(default=vec![])] cards: Vec<TimelineCard>,
|
||||
#[prop(default = vec![])] labels: Vec<TimelineLabel>,
|
||||
#[prop(default = vec![])] cards: Vec<TimelineCard>,
|
||||
}
|
||||
|
||||
impl IntoView for TimelineElement {
|
||||
|
@ -62,9 +62,25 @@ impl IntoView for TimelineCardContent {
|
|||
}
|
||||
|
||||
#[slot]
|
||||
pub struct TimelineCardSummary {
|
||||
pub struct TimelineCardTag {
|
||||
children: ChildrenFn,
|
||||
}
|
||||
|
||||
impl IntoView for TimelineCardTag {
|
||||
fn into_view(self) -> View {
|
||||
let view = view! {
|
||||
<>
|
||||
{ (self.children)() }
|
||||
</>
|
||||
};
|
||||
view.into_view()
|
||||
}
|
||||
}
|
||||
|
||||
#[slot]
|
||||
pub struct TimelineCardSummary {
|
||||
#[prop(default = vec![])] tags: Vec<TimelineCardTag>,
|
||||
children: ChildrenFn,
|
||||
tags: ChildrenFn,
|
||||
}
|
||||
|
||||
impl IntoView for TimelineCardSummary {
|
||||
|
@ -75,7 +91,7 @@ impl IntoView for TimelineCardSummary {
|
|||
{
|
||||
view! {
|
||||
<div class="flex flex-wrap gap-2 mt-2">
|
||||
{ (self.tags)() }
|
||||
{ self.tags.collect_view() }
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
@ -87,13 +103,13 @@ impl IntoView for TimelineCardSummary {
|
|||
|
||||
#[slot]
|
||||
pub struct TimelineCard {
|
||||
#[prop(default=vec![])] titles: Vec<TimelineCardSummary>,
|
||||
#[prop(default=vec![])] cards: Vec<TimelineCardContent>,
|
||||
#[prop(default = vec![])] titles: Vec<TimelineCardSummary>,
|
||||
#[prop(default = vec![])] cards: Vec<TimelineCardContent>,
|
||||
}
|
||||
|
||||
impl IntoView for TimelineCard {
|
||||
fn into_view(self) -> View {
|
||||
let view = view! {
|
||||
let view = view! {
|
||||
<details>
|
||||
<summary>
|
||||
{ self.titles.collect_view() }
|
||||
|
|
|
@ -7,14 +7,14 @@ use super::*;
|
|||
#[component]
|
||||
pub fn TopComponent() -> impl IntoView {
|
||||
view! {
|
||||
<div class="min-h-screen w-full flex flex-col md:flex-row items-center gap-5 relative">
|
||||
<div class="flex-1 p-10 justify-center items-center">
|
||||
<img src="https://devemyhg.lycee-darchicourt.net/wp-content/uploads/2018/01/No-picture.png" alt="Ma photo" class="mx-auto rounded-lg" />
|
||||
<div class="top_component">
|
||||
<div class="top_component__image">
|
||||
<img src="https://devemyhg.lycee-darchicourt.net/wp-content/uploads/2018/01/No-picture.png" alt="Ma photo" />
|
||||
</div>
|
||||
<div class="flex-1 p-10 flex flex-col gap-3">
|
||||
<h1 class="font-bold text-3xl">Florian RICHER</h1>
|
||||
<h4 class="font-semibold text-xl">"Développeur d´application Web et Mobile"</h4>
|
||||
<p class="font-normal text-base">
|
||||
<div class="top_component__presentation">
|
||||
<h1>Florian RICHER</h1>
|
||||
<h4>"Développeur d´application Web et Mobile"</h4>
|
||||
<p>
|
||||
r#"
|
||||
Découvrez mon parcours en développement, où ma passion précoce pour la programmation a débuté avec la
|
||||
création d'applications 3D utilisant OpenGL et s'est étendue à la maîtrise de diverses technologies,
|
||||
|
|
|
@ -24,6 +24,7 @@ fn Home() -> impl IntoView {
|
|||
view! {
|
||||
<main class="m-0 p-0 bg-surface dark:bg-dark_surface text-on_surface dark:text-dark_on_surface">
|
||||
<components::TopComponent/>
|
||||
<components::MonParcours/>
|
||||
</main>
|
||||
}
|
||||
}
|
13
style/link.css
Normal file
13
style/link.css
Normal file
|
@ -0,0 +1,13 @@
|
|||
@layer components {
|
||||
.link {
|
||||
@apply flex gap-1 font-semibold italic;
|
||||
|
||||
& > i {
|
||||
@apply flex items-center;
|
||||
|
||||
& > svg {
|
||||
@apply scale-75;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,3 +1,9 @@
|
|||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
@import "tailwindcss/base";
|
||||
@import "tailwindcss/components";
|
||||
@import "tailwindcss/utilities";
|
||||
|
||||
@import './link.css';
|
||||
@import './social_links.css';
|
||||
@import './tag.css';
|
||||
@import './timeline.css';
|
||||
@import './top_component.css';
|
24
style/project.css
Normal file
24
style/project.css
Normal file
|
@ -0,0 +1,24 @@
|
|||
@layer components {
|
||||
.project_list {
|
||||
@apply grid grid-cols-1 gap-4 md:grid-cols-2 mt-3;
|
||||
|
||||
& > a {
|
||||
@apply rounded-lg p-5 flex flex-col items-center gap-2;
|
||||
@apply bg-primary/10 dark:bg-dark_primary/10;
|
||||
@apply shadow-md shadow-primary/5 dark:shadow-dark_primary/5;
|
||||
|
||||
&:hover {
|
||||
@apply bg-primary/20 dark:bg-dark_primary/20;
|
||||
@apply shadow-md shadow-primary/10 dark:shadow-dark_primary/10;
|
||||
}
|
||||
|
||||
& > img {
|
||||
@apply h-1/2;
|
||||
}
|
||||
|
||||
& > div {
|
||||
@apply flex flex-col justify-center h-full;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
15
style/social_links.css
Normal file
15
style/social_links.css
Normal file
|
@ -0,0 +1,15 @@
|
|||
@layer components {
|
||||
.social_links {
|
||||
@apply flex gap-5 justify-center flex-wrap my-5;
|
||||
|
||||
& > .social_link {
|
||||
& > svg {
|
||||
@apply mx-auto scale-150 mb-1;
|
||||
}
|
||||
|
||||
& > span {
|
||||
@apply text-sm;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
6
style/tag.css
Normal file
6
style/tag.css
Normal file
|
@ -0,0 +1,6 @@
|
|||
@layer components {
|
||||
.tag {
|
||||
@apply rounded-lg px-3 py-1 font-normal text-sm;
|
||||
@apply bg-primary dark:bg-dark_primary text-on_primary dark:text-dark_on_primary;
|
||||
}
|
||||
}
|
102
style/timeline.css
Normal file
102
style/timeline.css
Normal file
|
@ -0,0 +1,102 @@
|
|||
@layer components {
|
||||
.timeline {
|
||||
@apply w-full px-5;
|
||||
|
||||
& > ul {
|
||||
@apply list-none py-5 px-0 relative w-full max-w-5xl mx-auto;
|
||||
|
||||
/* Draw center line */
|
||||
|
||||
&:before {
|
||||
@apply top-0 bottom-0 left-0 md:left-1/2 absolute content-[""] w-2;
|
||||
@apply bg-primary/10 dark:bg-dark_primary/10;
|
||||
@apply shadow-md shadow-primary/5 dark:shadow-dark_primary/5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.timeline-element {
|
||||
@apply relative flex flex-col md:flex-row justify-between;
|
||||
|
||||
/* Place point in center line */
|
||||
|
||||
&:before {
|
||||
@apply content-[""] w-6 h-6 rounded-[50%] absolute top-5 left-0 md:left-1/2 -ml-2 z-50;
|
||||
@apply bg-primary/10 dark:bg-dark_primary/10;
|
||||
@apply shadow-md shadow-primary/5 dark:shadow-dark_primary/5;
|
||||
}
|
||||
|
||||
&:nth-child(even) {
|
||||
@apply md:flex-row-reverse;
|
||||
|
||||
.timeline-element__category {
|
||||
@apply md:flex-row-reverse;
|
||||
}
|
||||
}
|
||||
|
||||
.timeline-element__info, .timeline-element__category {
|
||||
@apply relative w-4/5 md:w-2/5 left-[10%] md:left-0;
|
||||
@apply text-on_surface dark:text-dark_on_surface;
|
||||
}
|
||||
|
||||
.timeline-element__category {
|
||||
@apply top-5 flex md:justify-end mb-12;
|
||||
}
|
||||
|
||||
.timeline-element__info {
|
||||
& > details {
|
||||
@apply mb-12 rounded-xl overflow-hidden relative;
|
||||
@apply bg-primary/10 dark:bg-dark_primary/10;
|
||||
@apply shadow-md shadow-primary/5 dark:shadow-dark_primary/5;
|
||||
|
||||
& > summary, & > div {
|
||||
@apply p-5;
|
||||
}
|
||||
|
||||
& > summary {
|
||||
@apply relative block select-none cursor-pointer outline-none p-5 pr-10 font-semibold;
|
||||
|
||||
&:hover {
|
||||
@apply bg-primary/20 dark:bg-dark_primary/20;
|
||||
}
|
||||
|
||||
i {
|
||||
@apply absolute right-5 h-full top-0 flex items-center;
|
||||
|
||||
& > svg {
|
||||
@apply scale-125;
|
||||
transition: transform 300ms ease;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&[open] {
|
||||
& > summary {
|
||||
& > i > svg {
|
||||
@apply -rotate-180;
|
||||
}
|
||||
|
||||
& ~ * {
|
||||
animation: toggle 0.4s ease-in-out;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes toggle {
|
||||
0% {
|
||||
font-size: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
90% {
|
||||
font-size: 1rem;
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
font-size: 1rem;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
34
style/top_component.css
Normal file
34
style/top_component.css
Normal file
|
@ -0,0 +1,34 @@
|
|||
@layer components {
|
||||
.top_component {
|
||||
@apply min-h-screen w-full flex flex-col md:flex-row items-center gap-5 relative;
|
||||
|
||||
& > div {
|
||||
@apply flex-1 p-10;
|
||||
}
|
||||
|
||||
& > .top_component__image {
|
||||
@apply flex justify-center items-center;
|
||||
|
||||
& > img {
|
||||
@apply mx-auto rounded-lg;
|
||||
}
|
||||
}
|
||||
|
||||
& > .top_component__presentation {
|
||||
@apply flex flex-col gap-3;
|
||||
|
||||
& > h1 {
|
||||
@apply font-bold text-3xl;
|
||||
}
|
||||
|
||||
& > h4 {
|
||||
@apply font-semibold text-xl;
|
||||
}
|
||||
|
||||
& > p {
|
||||
@apply font-normal text-base;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/** @type {import('tailwindcss').Config} */
|
||||
export default {
|
||||
content: {
|
||||
files: ["*.html", "./src/**/*.rs"],
|
||||
files: ["*.html", "./src/**/*.rs", "./style/*.css"],
|
||||
},
|
||||
theme: {
|
||||
extend: {
|
||||
|
|
Loading…
Reference in a new issue