This commit is contained in:
70
src/lib/elements/AboutMe.svelte
Normal file
70
src/lib/elements/AboutMe.svelte
Normal file
@@ -0,0 +1,70 @@
|
||||
<script lang="ts">
|
||||
import Contacts from './Contacts.svelte';
|
||||
export let currentLanguage: CurrentLanguage = 'it';
|
||||
import { FontAwesomeIcon } from '@fortawesome/svelte-fontawesome';
|
||||
import { faDownload } from '@fortawesome/free-solid-svg-icons';
|
||||
import { library, findIconDefinition } from '@fortawesome/fontawesome-svg-core';
|
||||
library.add(faDownload);
|
||||
const downloadDefinition = findIconDefinition({ prefix: 'fas', iconName: 'download' });
|
||||
import type { CurrentLanguage, LanguagePair } from '$lib/types';
|
||||
const whoIt =
|
||||
"Ciao! Sono Gianmarco Pettinato, mi sono laureato in scienze informatiche e sono uno sviluppatore.\
|
||||
Ho famigliarità con diversi linguaggi e framework, sia front-end che back-end.\
|
||||
Tra le mie competenze, oltre allo sviluppo software e alla manutenzione di sistemi linux, spicca la gestione di ambienti CI/CD, con pipeline automatiche e container come Docker.\
|
||||
Sono interessato in particolar modo all'ambiente dei dispositivi IoT e del wearble tech.\
|
||||
Nel tempo libero mi dedico alla gestione del mio home sever e alla costruzione e manutenzione di computer.";
|
||||
const whoEn =
|
||||
"Hi! I'm Gianmarco Pettinato. I have a bachelor's degree in computer science, and I'm a developer.\
|
||||
I know several languages and frameworks, front-end and back-end.\
|
||||
Among my skill-set, there is the administration of the CI/CD environment with Docker.\
|
||||
I'm interested in the IoT world and Wearable tech. In my free time, I like to manage my GNU/Linux home server and build PCs.";
|
||||
|
||||
const who: LanguagePair = {
|
||||
it: whoIt,
|
||||
en: whoEn
|
||||
};
|
||||
const cvUrl: LanguagePair = { it: '/curriculum_it.pdf', en: '/curriculum_en.pdf' };
|
||||
</script>
|
||||
|
||||
<div class="aboutMe">
|
||||
<div class="title">
|
||||
<h1>Gianmarco Pettinato</h1>
|
||||
<h2>Software developer</h2>
|
||||
</div>
|
||||
|
||||
<Contacts />
|
||||
<div class="whoIAm">
|
||||
<p>
|
||||
{who[currentLanguage]}
|
||||
</p>
|
||||
</div>
|
||||
<!-- <div class="cv">
|
||||
<div>
|
||||
<a rel="external" href={cvUrl[currentLanguage]}
|
||||
>curriculum<i><FontAwesomeIcon icon={downloadDefinition} /></i>
|
||||
</a>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
@import '../../app.scss';
|
||||
|
||||
.whoIAm {
|
||||
margin: auto;
|
||||
text-align: justify;
|
||||
}
|
||||
.aboutMe {
|
||||
background-color: $basecolor2;
|
||||
// border: solid 1px $border-color;
|
||||
border-radius: $default-border-radius;
|
||||
margin-top: 20px;
|
||||
padding: 30px;
|
||||
}
|
||||
.title {
|
||||
display: none;
|
||||
@media (min-width: $min-tablet) {
|
||||
display: unset;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
102
src/lib/elements/Contacts.svelte
Normal file
102
src/lib/elements/Contacts.svelte
Normal file
@@ -0,0 +1,102 @@
|
||||
<script lang="ts">
|
||||
import { FontAwesomeIcon } from '@fortawesome/svelte-fontawesome';
|
||||
import { faAt } from '@fortawesome/free-solid-svg-icons';
|
||||
import { faTelegramPlane, faTwitter, faLinkedin } from '@fortawesome/free-brands-svg-icons';
|
||||
import * as svgCore from '@fortawesome/fontawesome-svg-core';
|
||||
|
||||
svgCore.library.add(faTelegramPlane);
|
||||
svgCore.library.add(faTwitter);
|
||||
svgCore.library.add(faLinkedin);
|
||||
svgCore.library.add(faAt);
|
||||
|
||||
const telegramLookup: svgCore.IconLookup = { prefix: 'fab', iconName: 'telegram-plane' };
|
||||
const twitterLookup: svgCore.IconLookup = { prefix: 'fab', iconName: 'twitter' };
|
||||
const linkedinLookup: svgCore.IconLookup = { prefix: 'fab', iconName: 'linkedin' };
|
||||
const atLookup: svgCore.IconLookup = { prefix: 'fas', iconName: 'at' };
|
||||
|
||||
const telegramIconDefinition: svgCore.IconDefinition = svgCore.findIconDefinition(telegramLookup);
|
||||
const twitterIconDefinition: svgCore.IconDefinition = svgCore.findIconDefinition(twitterLookup);
|
||||
const linkedinIconDefinition: svgCore.IconDefinition = svgCore.findIconDefinition(linkedinLookup);
|
||||
const atIconDefinition: svgCore.IconDefinition = svgCore.findIconDefinition(atLookup);
|
||||
</script>
|
||||
|
||||
<div class="contacts">
|
||||
<img src="/profile_pic.webp" alt="profile" class="profile" />
|
||||
<div class="links">
|
||||
<ul>
|
||||
<li>
|
||||
<a href="mailto://gianmarco@pettinato.eu"
|
||||
><i><FontAwesomeIcon icon={atIconDefinition} /></i> e-mail: gianmarco@pettinato.eu</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://t.me/jatus_93"
|
||||
><i><FontAwesomeIcon icon={telegramIconDefinition} /></i> telegram: @jatus_93</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/jatus_93"
|
||||
><i><FontAwesomeIcon icon={twitterIconDefinition} /></i> twitter: @jatus_93</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://www.linkedin.com/in/gianmarco-pettinato/"
|
||||
><i><FontAwesomeIcon icon={linkedinIconDefinition} /></i> linkedin: Gianmarco Pettinato</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
@import '../../app.scss';
|
||||
|
||||
img.profile {
|
||||
border-radius: 50%;
|
||||
max-width: 150px;
|
||||
// border: solid 1px $border-color;
|
||||
}
|
||||
.contacts {
|
||||
border-radius: $default-border-radius;
|
||||
padding: 30px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-evenly;
|
||||
align-items: center;
|
||||
margin: auto;
|
||||
}
|
||||
.links {
|
||||
text-align: left;
|
||||
ul {
|
||||
padding: 0;
|
||||
list-style-type: none;
|
||||
line-height: 20px;
|
||||
white-space: nowrap;
|
||||
li {
|
||||
padding: 0;
|
||||
margin: 10px;
|
||||
margin-left: 0px;
|
||||
margin-right: 0px;
|
||||
|
||||
a {
|
||||
font-size: 18px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@media (min-width: $min-tablet) {
|
||||
.contacts {
|
||||
flex-direction: row;
|
||||
margin: auto;
|
||||
}
|
||||
.links {
|
||||
ul {
|
||||
li {
|
||||
a {
|
||||
font-size: auto !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
79
src/lib/elements/JobElement.svelte
Normal file
79
src/lib/elements/JobElement.svelte
Normal file
@@ -0,0 +1,79 @@
|
||||
<script lang="ts">
|
||||
import MarkdownIt from 'markdown-it';
|
||||
const md = new MarkdownIt({
|
||||
html: true,
|
||||
xhtmlOut: true,
|
||||
typographer: true,
|
||||
breaks: true,
|
||||
linkify: true
|
||||
});
|
||||
import type { Job } from '$lib/model/job';
|
||||
import type { CurrentLanguage } from '$lib/types';
|
||||
export let job: Job;
|
||||
export let currentLanguage: CurrentLanguage = 'it';
|
||||
</script>
|
||||
|
||||
<div class="job-container">
|
||||
<h3>{job.title[currentLanguage]}</h3>
|
||||
<div class="image-container">
|
||||
{#each job.images as image}
|
||||
<img src={image} alt={image} loading="lazy" />
|
||||
{/each}
|
||||
</div>
|
||||
<div class="text-content">
|
||||
{@html md.render(job.content[currentLanguage])}
|
||||
</div>
|
||||
<div class="added-info">
|
||||
{#if job.year}
|
||||
Date: {job.year.start}{#if job.year.end.length != 0}; {job.year.end} {/if}
|
||||
{/if}
|
||||
<div>
|
||||
{#if job.collaborators.length != 0}
|
||||
Collab:
|
||||
{/if}
|
||||
{#each job.collaborators as collaborator, index}
|
||||
<a href={collaborator.ref}>{collaborator.name} {collaborator.surname}</a>{index !=
|
||||
job.collaborators.length - 1
|
||||
? ', '
|
||||
: ''}
|
||||
{/each}
|
||||
</div>
|
||||
<div>
|
||||
{#if job.languages.length != 0}
|
||||
Lang:
|
||||
{/if}
|
||||
{#each job.languages as language, index}
|
||||
{language}{index != job.languages.length - 1 ? ', ' : ''}
|
||||
{/each}
|
||||
</div>
|
||||
<div>
|
||||
{#if job.tecnologies.length != 0}
|
||||
Tech:
|
||||
{/if}
|
||||
{#each job.tecnologies as tecnology, index}
|
||||
{tecnology}{index != job.tecnologies.length - 1 ? ', ' : ''}
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
@import '../../app.scss';
|
||||
.text-content {
|
||||
margin: auto;
|
||||
text-align: justify;
|
||||
}
|
||||
.added-info {
|
||||
text-align: left;
|
||||
font-size: smaller;
|
||||
}
|
||||
.job-container {
|
||||
width: 100%;
|
||||
img {
|
||||
background-color: $text-color;
|
||||
}
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
44
src/lib/elements/Jobs.svelte
Normal file
44
src/lib/elements/Jobs.svelte
Normal file
@@ -0,0 +1,44 @@
|
||||
<script lang="ts">
|
||||
import type { Job } from '$lib/model/job';
|
||||
import type { CurrentLanguage } from '$lib/types';
|
||||
import JobElement from './JobElement.svelte';
|
||||
export let currentLanguage: CurrentLanguage = 'it';
|
||||
export let jobs: Job[] = [];
|
||||
</script>
|
||||
|
||||
<div class="jobs-container">
|
||||
{#each jobs as job}
|
||||
<div class="job-card"><JobElement {job} {currentLanguage} /></div>
|
||||
{/each}
|
||||
{#if jobs.length % 2 !== 0}
|
||||
<div class="job-card hide" />
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
@import '../../app.scss';
|
||||
.jobs-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.job-card {
|
||||
background-color: $basecolor2;
|
||||
border-radius: $default-border-radius;
|
||||
padding: 25pt 25pt;
|
||||
margin-top: 1%;
|
||||
margin-bottom: 1%;
|
||||
@media (min-width: $min-desktop) {
|
||||
width: 41%;
|
||||
}
|
||||
|
||||
@media (min-width: 1333px) {
|
||||
// width: 420px;
|
||||
width: 42.5%;
|
||||
}
|
||||
display: inline;
|
||||
}
|
||||
.hide {
|
||||
background: transparent;
|
||||
}
|
||||
</style>
|
||||
88
src/lib/elements/LanguageSelector.svelte
Normal file
88
src/lib/elements/LanguageSelector.svelte
Normal file
@@ -0,0 +1,88 @@
|
||||
<script lang="ts">
|
||||
import type { Handle, RequestEvent, ResolveOptions } from '@sveltejs/kit';
|
||||
import type { CurrentLanguage } from '$lib/types';
|
||||
import { FontAwesomeIcon } from '@fortawesome/svelte-fontawesome';
|
||||
import * as svgIcons from '@fortawesome/free-solid-svg-icons';
|
||||
import * as svgCore from '@fortawesome/fontawesome-svg-core';
|
||||
let langSelectOpen = false;
|
||||
let langSelect: Element;
|
||||
export let currentLanguage: CurrentLanguage = 'en';
|
||||
|
||||
function setOpen() {
|
||||
langSelectOpen = !langSelectOpen;
|
||||
|
||||
const animationLanguage = langSelect.animate([{ width: '0px' }, { width: '200px' }], {
|
||||
duration: 100,
|
||||
fill: 'both'
|
||||
});
|
||||
if (langSelectOpen) {
|
||||
animationLanguage.play();
|
||||
// animateConatiner.play();
|
||||
} else {
|
||||
animationLanguage.reverse();
|
||||
// animateConatiner.reverse();
|
||||
}
|
||||
}
|
||||
|
||||
function setLanguage(value: CurrentLanguage) {
|
||||
currentLanguage = value;
|
||||
}
|
||||
|
||||
svgCore.library.add(svgIcons.faGlobeEurope);
|
||||
|
||||
const globeLookup: svgCore.IconLookup = { prefix: 'fas', iconName: 'globe-europe' };
|
||||
const globeDefinition: svgCore.IconDefinition = svgCore.findIconDefinition(globeLookup);
|
||||
</script>
|
||||
|
||||
<div class="language-selector">
|
||||
<button on:click={setOpen}> <FontAwesomeIcon icon={globeDefinition} size="2x" /> </button>
|
||||
<div class="button-container" bind:this={langSelect}>
|
||||
<button
|
||||
class="custom-button {currentLanguage == 'it' ? 'custom-button-active' : ''}"
|
||||
on:click={() => setLanguage('it')}
|
||||
title="attiva lingua italiana">it</button
|
||||
>
|
||||
<button
|
||||
class="custom-button {currentLanguage == 'en' ? 'custom-button-active' : ''}"
|
||||
on:click={() => setLanguage('en')}
|
||||
title="enable english language">en</button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
@import '../../app.scss';
|
||||
.language-selector {
|
||||
display: flex;
|
||||
position: fixed;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
background-color: $basecolor2;
|
||||
border-radius: $default-border-radius;
|
||||
font-size: 50px;
|
||||
border-bottom: solid $border-hover-color 1px;
|
||||
border-left: solid $border-hover-color 1px;
|
||||
bottom: 70px;
|
||||
right: 0;
|
||||
}
|
||||
.button-container {
|
||||
display: flex;
|
||||
justify-content: space-evenly;
|
||||
width: 0px;
|
||||
overflow: hidden;
|
||||
}
|
||||
button {
|
||||
background: none;
|
||||
border: none;
|
||||
width: 60px;
|
||||
height: 50px;
|
||||
}
|
||||
.custom-button {
|
||||
width: 100px;
|
||||
font-size: large;
|
||||
}
|
||||
.custom-button-active {
|
||||
background-color: $default-active-color;
|
||||
outline: solid 1px;
|
||||
}
|
||||
</style>
|
||||
51
src/lib/elements/Menu.svelte
Normal file
51
src/lib/elements/Menu.svelte
Normal file
@@ -0,0 +1,51 @@
|
||||
<script lang="ts">
|
||||
import type { CurrentLanguage } from '$lib/types';
|
||||
import MenuBig from './MenuBig.svelte';
|
||||
import MenuMobile from './MenuMobile.svelte';
|
||||
export let currentLanguage: CurrentLanguage = 'en';
|
||||
</script>
|
||||
|
||||
<div class="menu-container default">
|
||||
<div class="menu menu-desktop">
|
||||
<MenuBig {currentLanguage} />
|
||||
</div>
|
||||
<div class="menu menu-mobile">
|
||||
<MenuMobile {currentLanguage} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
@import '../../app.scss';
|
||||
|
||||
.menu {
|
||||
border-radius: $default-border-radius;
|
||||
|
||||
background-color: $basecolor2;
|
||||
position: sticky;
|
||||
position: -webkit-sticky;
|
||||
top: 0px;
|
||||
border-bottom: solid $border-hover-color 2px;
|
||||
}
|
||||
|
||||
.menu-desktop {
|
||||
display: none;
|
||||
@media (min-width: $min-tablet) {
|
||||
display: unset;
|
||||
}
|
||||
}
|
||||
|
||||
.menu-mobile {
|
||||
@media (min-width: $min-tablet) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.menu-container {
|
||||
border-radius: $default-border-radius;
|
||||
padding: 0px;
|
||||
margin: 10px;
|
||||
position: sticky;
|
||||
position: -webkit-sticky;
|
||||
top: 0px;
|
||||
margin: auto;
|
||||
}
|
||||
</style>
|
||||
143
src/lib/elements/MenuBig.svelte
Normal file
143
src/lib/elements/MenuBig.svelte
Normal file
@@ -0,0 +1,143 @@
|
||||
<script lang="ts">
|
||||
import { FontAwesomeIcon } from '@fortawesome/svelte-fontawesome';
|
||||
import * as svgIcons from '@fortawesome/free-solid-svg-icons';
|
||||
import * as svgCore from '@fortawesome/fontawesome-svg-core';
|
||||
import type { CurrentLanguage, LanguagePair, MenuEntry } from '$lib/types';
|
||||
|
||||
svgCore.library.add(svgIcons.faHome);
|
||||
svgCore.library.add(svgIcons.faUserTie);
|
||||
svgCore.library.add(svgIcons.faGraduationCap);
|
||||
svgCore.library.add(svgIcons.faUserClock);
|
||||
svgCore.library.add(svgIcons.faAddressCard);
|
||||
svgCore.library.add(svgIcons.faBars);
|
||||
svgCore.library.add(svgIcons.faGlobeEurope);
|
||||
|
||||
const homeLookup: svgCore.IconLookup = { prefix: 'fas', iconName: 'home' };
|
||||
const userTieLookup: svgCore.IconLookup = { prefix: 'fas', iconName: 'user-tie' };
|
||||
const graduationCapLookup: svgCore.IconLookup = { prefix: 'fas', iconName: 'graduation-cap' };
|
||||
const userClockLookUp: svgCore.IconLookup = { prefix: 'fas', iconName: 'user-clock' };
|
||||
const addressCardLookUp: svgCore.IconLookup = { prefix: 'fas', iconName: 'address-card' };
|
||||
const homeIconDefinition: svgCore.IconDefinition = svgCore.findIconDefinition(homeLookup);
|
||||
const userTieDefinition: svgCore.IconDefinition = svgCore.findIconDefinition(userTieLookup);
|
||||
const graduationDefinition: svgCore.IconDefinition =
|
||||
svgCore.findIconDefinition(graduationCapLookup);
|
||||
const userClockDefinition: svgCore.IconDefinition = svgCore.findIconDefinition(userClockLookUp);
|
||||
const addressCardDefinition: svgCore.IconDefinition =
|
||||
svgCore.findIconDefinition(addressCardLookUp);
|
||||
|
||||
export let currentLanguage: CurrentLanguage = 'it';
|
||||
const menu: Record<MenuEntry, LanguagePair> = {
|
||||
home: { it: 'Home', en: 'Home' },
|
||||
job: { it: 'Esperienze', en: 'Experiences' },
|
||||
school: { it: 'Formazione', en: 'Training' },
|
||||
blog: { it: 'Blog', en: 'Blog' },
|
||||
portfolio: { it: 'Portfolio', en: 'Portfolio' }
|
||||
};
|
||||
</script>
|
||||
|
||||
<div class="container">
|
||||
<ul>
|
||||
<li>
|
||||
<a class="menu-element" href="#top">
|
||||
<i>
|
||||
<FontAwesomeIcon icon={homeIconDefinition} />
|
||||
</i>
|
||||
<span>{menu.home[currentLanguage]}</span></a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a class="menu-element" href="#jobs"
|
||||
><i>
|
||||
<FontAwesomeIcon icon={userTieDefinition} />
|
||||
</i><span>{menu.job[currentLanguage]}</span></a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a class="menu-element" href="#training"
|
||||
><i>
|
||||
<FontAwesomeIcon icon={graduationDefinition} />
|
||||
</i><span>{menu.school[currentLanguage]}</span></a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a class="menu-element" href="#portfolio"
|
||||
><i>
|
||||
<FontAwesomeIcon icon={userClockDefinition} />
|
||||
</i><span>{menu.portfolio[currentLanguage]}</span></a
|
||||
>
|
||||
</li>
|
||||
<!-- <li>
|
||||
<a class="menu-element" href="/blog"
|
||||
><i>
|
||||
<FontAwesomeIcon icon={addressCardDefinition} />
|
||||
</i><span>{menu.blog[currentLanguage]}</span></a
|
||||
>
|
||||
</li> -->
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
@import '../../app.scss';
|
||||
$menu-size: 1004px;
|
||||
a {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: larger;
|
||||
min-width: 50px;
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
|
||||
i {
|
||||
margin-right: 10%;
|
||||
}
|
||||
}
|
||||
|
||||
a:hover,
|
||||
a:active {
|
||||
background-color: $default-active-color;
|
||||
}
|
||||
|
||||
ul {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
margin: auto;
|
||||
border-radius: $default-border-radius;
|
||||
}
|
||||
|
||||
.container {
|
||||
border-radius: $default-border-radius;
|
||||
width: 100%;
|
||||
border-bottom: solid $border-hover-color 1px;
|
||||
}
|
||||
|
||||
ul li {
|
||||
background-color: $basecolor2;
|
||||
flex: 1;
|
||||
}
|
||||
li:first-of-type {
|
||||
background-color: $basecolor2;
|
||||
border-top-left-radius: $default-border-radius;
|
||||
border-bottom-left-radius: $default-border-radius;
|
||||
a:hover,
|
||||
a:active {
|
||||
border-top-left-radius: $default-border-radius;
|
||||
border-bottom-left-radius: $default-border-radius;
|
||||
}
|
||||
}
|
||||
li:last-of-type {
|
||||
border-top-right-radius: $default-border-radius;
|
||||
border-bottom-right-radius: $default-border-radius;
|
||||
a:hover,
|
||||
a:active {
|
||||
border-top-right-radius: $default-border-radius;
|
||||
border-bottom-right-radius: $default-border-radius;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
175
src/lib/elements/MenuMobile.svelte
Normal file
175
src/lib/elements/MenuMobile.svelte
Normal file
@@ -0,0 +1,175 @@
|
||||
<script lang="ts">
|
||||
import { FontAwesomeIcon } from '@fortawesome/svelte-fontawesome';
|
||||
import * as svgIcons from '@fortawesome/free-solid-svg-icons';
|
||||
import * as svgCore from '@fortawesome/fontawesome-svg-core';
|
||||
import type { CurrentLanguage, LanguagePair, MenuEntry } from '$lib/types';
|
||||
export let currentLanguage: CurrentLanguage = 'it';
|
||||
svgCore.library.add(svgIcons.faBars);
|
||||
|
||||
svgCore.library.add(svgIcons.faHome);
|
||||
svgCore.library.add(svgIcons.faUserTie);
|
||||
svgCore.library.add(svgIcons.faGraduationCap);
|
||||
svgCore.library.add(svgIcons.faUserClock);
|
||||
svgCore.library.add(svgIcons.faAddressCard);
|
||||
svgCore.library.add(svgIcons.faBars);
|
||||
svgCore.library.add(svgIcons.faX);
|
||||
svgCore.library.add(svgIcons.faGlobeEurope);
|
||||
|
||||
const barsLookup: svgCore.IconLookup = { prefix: 'fas', iconName: 'bars' };
|
||||
const globeLookup: svgCore.IconLookup = { prefix: 'fas', iconName: 'globe-europe' };
|
||||
const homeLookup: svgCore.IconLookup = { prefix: 'fas', iconName: 'home' };
|
||||
const userTieLookup: svgCore.IconLookup = { prefix: 'fas', iconName: 'user-tie' };
|
||||
const graduationCapLookup: svgCore.IconLookup = { prefix: 'fas', iconName: 'graduation-cap' };
|
||||
const userClockLookUp: svgCore.IconLookup = { prefix: 'fas', iconName: 'user-clock' };
|
||||
const addressCardLookUp: svgCore.IconLookup = { prefix: 'fas', iconName: 'address-card' };
|
||||
const xLookUp: svgCore.IconLookup = { prefix: 'fas', iconName: 'x' };
|
||||
|
||||
const homeIconDefinition: svgCore.IconDefinition = svgCore.findIconDefinition(homeLookup);
|
||||
const userTieDefinition: svgCore.IconDefinition = svgCore.findIconDefinition(userTieLookup);
|
||||
const graduationDefinition: svgCore.IconDefinition =
|
||||
svgCore.findIconDefinition(graduationCapLookup);
|
||||
const userClockDefinition: svgCore.IconDefinition = svgCore.findIconDefinition(userClockLookUp);
|
||||
const addressCardDefinition: svgCore.IconDefinition =
|
||||
svgCore.findIconDefinition(addressCardLookUp);
|
||||
const barsDefinition: svgCore.IconDefinition = svgCore.findIconDefinition(barsLookup);
|
||||
const xDefinition: svgCore.IconDefinition = svgCore.findIconDefinition(xLookUp);
|
||||
const globeDefinition: svgCore.IconDefinition = svgCore.findIconDefinition(globeLookup);
|
||||
|
||||
const menu: Record<MenuEntry, LanguagePair> = {
|
||||
home: { it: 'Home', en: 'Home' },
|
||||
job: { it: 'Esperienze', en: 'Experiences' },
|
||||
school: { it: 'Formazione', en: 'Training' },
|
||||
blog: { it: 'Blog', en: 'Blog' },
|
||||
portfolio: { it: 'Portfolio', en: 'Portfolio' }
|
||||
};
|
||||
const menuButton: Record<number, LanguagePair> = {
|
||||
1: { it: 'Apri il menu', en: 'Open menu' },
|
||||
0: { it: 'Chiudi il menu', en: 'Close menu' }
|
||||
};
|
||||
let menuContainer: Element;
|
||||
let menuOpen = false;
|
||||
|
||||
function setOpen() {
|
||||
menuOpen = !menuOpen;
|
||||
const animation = menuContainer.animate([{ height: '0px' }, { height: '360px' }], {
|
||||
duration: 100,
|
||||
fill: 'both'
|
||||
});
|
||||
if (menuOpen) animation.play();
|
||||
else animation.reverse();
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="menu-container">
|
||||
<div class="header">
|
||||
<button on:click={setOpen} tabindex="0" title={menuButton[Number(menuOpen)][currentLanguage]}>
|
||||
{#if !menuOpen}<FontAwesomeIcon icon={barsDefinition} size="lg" />
|
||||
{:else}
|
||||
<FontAwesomeIcon icon={xDefinition} size="lg" />
|
||||
{/if}
|
||||
</button>
|
||||
<div class="title">
|
||||
<h1>Gianmarco Pettinato</h1>
|
||||
<h2>Software developer</h2>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="wrapper" bind:this={menuContainer}>
|
||||
<li>
|
||||
<a class="menu-element" href="#top">
|
||||
<i>
|
||||
<FontAwesomeIcon icon={homeIconDefinition} />
|
||||
</i>
|
||||
<span>{menu.home[currentLanguage]}</span></a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a class="menu-element" href="#jobs"
|
||||
><i>
|
||||
<FontAwesomeIcon icon={userTieDefinition} />
|
||||
</i><span>{menu.job[currentLanguage]}</span></a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a class="menu-element" href="#training"
|
||||
><i>
|
||||
<FontAwesomeIcon icon={graduationDefinition} />
|
||||
</i><span>{menu.school[currentLanguage]}</span></a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a class="menu-element" href="#portfolio"
|
||||
><i>
|
||||
<FontAwesomeIcon icon={userClockDefinition} />
|
||||
</i><span>{menu.portfolio[currentLanguage]}</span></a
|
||||
>
|
||||
</li>
|
||||
<!-- <li>
|
||||
<a class="menu-element" href="/blog"
|
||||
><i>
|
||||
<FontAwesomeIcon icon={addressCardDefinition} />
|
||||
</i><span>{menu.blog[currentLanguage]}</span></a
|
||||
>
|
||||
</li> -->
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
@import '../../app.scss';
|
||||
.header {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
padding-top: 10px;
|
||||
height: 10%;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
button {
|
||||
height: 80px;
|
||||
width: 80px;
|
||||
border: none;
|
||||
font-size: 40px;
|
||||
background: none;
|
||||
}
|
||||
}
|
||||
|
||||
.menu-container {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 80%;
|
||||
margin: auto;
|
||||
}
|
||||
ul {
|
||||
list-style-type: none;
|
||||
overflow: hidden;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
margin: auto;
|
||||
}
|
||||
a {
|
||||
padding-left: 10px;
|
||||
display: flex;
|
||||
justify-content: start;
|
||||
align-items: center;
|
||||
background-color: $basecolor2;
|
||||
font-size: larger;
|
||||
height: 60px;
|
||||
i {
|
||||
margin-right: 10%;
|
||||
}
|
||||
}
|
||||
li {
|
||||
border-left: 1px solid;
|
||||
border-right: 1px solid;
|
||||
border-bottom: 1px solid;
|
||||
}
|
||||
li:first-of-type {
|
||||
border-top: 1px solid;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
background-color: $default-active-color;
|
||||
outline: solid 1px;
|
||||
}
|
||||
.wrapper {
|
||||
height: 0px;
|
||||
}
|
||||
</style>
|
||||
37
src/lib/elements/Skills.svelte
Normal file
37
src/lib/elements/Skills.svelte
Normal file
@@ -0,0 +1,37 @@
|
||||
<script lang="ts"></script>
|
||||
|
||||
<div>
|
||||
<div class="round_base">
|
||||
<div class="inside"><p>HTML</p></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
p {
|
||||
font-weight: 600;
|
||||
}
|
||||
.round_base {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
outline: 0.1px solid black;
|
||||
background-image: linear-gradient(to right, red 5px 5px, black 5px 5px, red 1px);
|
||||
// background-size: 1px 20px;
|
||||
// background-repeat: no-repeat;
|
||||
}
|
||||
.inside {
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
// background-color:$basecolor2;
|
||||
border-radius: 50%;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
outline: 0.1px solid black;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
||||
63
src/lib/elements/Training.svelte
Normal file
63
src/lib/elements/Training.svelte
Normal file
@@ -0,0 +1,63 @@
|
||||
<script lang="ts">
|
||||
import MarkdownIt from 'markdown-it';
|
||||
import data from '../model/training.json';
|
||||
import type { Job } from '../model/job';
|
||||
import type { CurrentLanguage } from '$lib/types';
|
||||
|
||||
const md = new MarkdownIt({
|
||||
html: true,
|
||||
xhtmlOut: true,
|
||||
typographer: true
|
||||
});
|
||||
export let currentLanguage: CurrentLanguage = 'it';
|
||||
const training: Job[] = data as Job[];
|
||||
</script>
|
||||
|
||||
<div>
|
||||
{#each training as school}
|
||||
<div class="element">
|
||||
<img src={school.images[0]} alt="school logo" />
|
||||
<div>
|
||||
<h3>{school.title[currentLanguage]}</h3>
|
||||
<p>{school.content[currentLanguage]}</p>
|
||||
<p>{school.year.start} - {school.year.end}</p>
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
@import '../../app.scss';
|
||||
.element {
|
||||
border-radius: $default-border-radius;
|
||||
background-color: $basecolor2;
|
||||
padding: 45px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
align-content: center;
|
||||
margin-top: 30px;
|
||||
img {
|
||||
max-width: 100%;
|
||||
max-height: 150px;
|
||||
object-fit: scale-down;
|
||||
}
|
||||
div {
|
||||
width: 80%;
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: $min-tablet) {
|
||||
.element {
|
||||
flex-direction: row;
|
||||
div {
|
||||
width: 50%;
|
||||
margin-right: 0;
|
||||
}
|
||||
img {
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user