Add form section

This commit is contained in:
Paul Nicoué 2023-01-20 18:08:51 +01:00
parent c6705914e0
commit 2a4cf52465
33 changed files with 1031 additions and 311 deletions

View file

@ -7,7 +7,7 @@
<div class="error__emoticon" aria-hidden="true">¯\(°_o)/¯</div>
<button class="error__button" @click="$emit('handleError')">
<span class="error__button-text">Retourner à la page d'accueil</span>
<svg class="error__button-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg">
<svg class="error__button-icon" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg">
<path d="M 2 8.7 L 12 1 L 22 8.7 L 22 20.8 C 22 22.016 21.006 23 19.778 23 L 4.222 23 C 2.995 23 2 22.016 2 20.8 L 2 8.7 Z"/>
<polyline points="8.667 23 8.667 12 15.333 12 15.333 23"/>
</svg>
@ -35,11 +35,11 @@
<style lang="scss" scoped>
// --------------------------------------------------
// ERROR STYLE
// STYLE
// --------------------------------------------------
main {
padding: 4rem 2rem;
padding: 2rem;
}
.error {
@ -67,6 +67,7 @@
&__emoticon {
opacity: 0;
margin: 0 2rem;
font-family: var(--title-font-family);
font-size: var(--h1-font-size);
font-weight: var(--medium-font-weight);
animation: fade-in-from-top 400ms ease-in-out 600ms forwards;
@ -87,41 +88,7 @@
.error {
&__button {
display: flex;
justify-content: center;
align-items: center;
&-text {
transform: translateX(calc((0.8rem + var(--small-icon-size)) / 2));
transition: transform 200ms ease-in-out;
}
&-icon {
display: inherit;
flex-shrink: 0;
opacity: 0;
width: var(--small-icon-size);
height: var(--small-icon-size);
margin: 0 0 0 0.8rem;
transform: translateX(calc((0.8rem + var(--small-icon-size)) / 2));
transition:
opacity 200ms ease-in-out,
transform 200ms ease-in-out;
}
&:hover,
&:focus,
&:active {
.error__button-text {
transform: translateX(0);
}
.error__button-icon {
opacity: 1;
transform: translateX(0);
}
}
@include button-with-icon;
}
}
}

View file

@ -52,7 +52,7 @@
<style lang="scss" scoped>
// --------------------------------------------------
// FOOTER STYLE
// STYLE
// --------------------------------------------------
footer {

View file

@ -1,24 +0,0 @@
<template>
<header>
<div class="header-bar">
</div>
</header>
</template>
<script setup>
</script>
<style lang="scss" scoped>
// --------------------------------------------------
// HEADER STYLE
// --------------------------------------------------
header {
width: 100%;
height: 0;
}
</style>

View file

@ -0,0 +1,57 @@
<template>
<div class="contact-decoration" aria-hidden="true">
<div class="contact-decoration__icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg">
<path d="M 3.2 3.2 L 20.8 3.2 C 22.01 3.2 23 4.19 23 5.4 L 23 18.6 C 23 19.81 22.01 20.8 20.8 20.8 L 3.2 20.8 C 1.99 20.8 1 19.81 1 18.6 L 1 5.4 C 1 4.19 1.99 3.2 3.2 3.2 Z"/>
<polyline points="23 5.4 12 13.1 1 5.4"/>
</svg>
</div>
<div class="contact-decoration__separator"></div>
</div>
</template>
<script setup>
</script>
<style lang="scss" scoped>
// --------------------------------------------------
// LAYOUT & STYLE
// --------------------------------------------------
.contact-decoration {
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
height: 100%;
margin: 0 -1rem;
&__icon {
width: calc(var(--regular-icon-size) + 1rem);
height: calc(var(--regular-icon-size) + 1rem);
display: flex;
justify-content: center;
align-items: center;
background-color: var(--primary-color);
border: 1px solid var(--accent-color);
border-radius: 50%;
svg {
stroke: var(--secondary-color);
width: var(--regular-icon-size);
height: var(--regular-icon-size);
}
}
&__separator {
width: 1px;
height: 0;
background-color: var(--accent-color);
animation: expand-height 600ms ease-in-out 600ms forwards;
}
}
</style>

132
components/ContactForm.vue Normal file
View file

@ -0,0 +1,132 @@
<template>
<form class="contact-form">
<div class="contact-form__name">
<label for="name">Nom</label>
<input type="text" id="name" name="name" required />
</div>
<div class="contact-form__email">
<label for="email">Adresse e-mail</label>
<input type="email" id="email" name="email" required />
</div>
<div class="contact-form__subject">
<label for="subject">Sujet</label>
<input type="text" id="subject" name="subject" required />
</div>
<div class="contact-form__message">
<label for="message">Message</label>
<textarea id="message" name="message" required></textarea>
</div>
<button class="contact-form__button" @click.prevent="sendEmail()">
<span class="contact-form__button-text">Envoyer</span>
<svg class="contact-form__button-icon" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg">
<line x1="23" y1="1" x2="10.9" y2="13.1"/>
<polygon points="23 1 15.3 23 10.9 13.1 1 8.7 23 1"/>
</svg>
</button>
</form>
</template>
<script setup>
// --------------------------------------------------
// DATA
// --------------------------------------------------
// const contactName = ref('');
// const contactEmailAddress = ref('');
// const contactSubject = ref('');
// const contactMessage = ref('');
const contactName = 'Saint Victeur';
const contactEmailAddress = 'saint.victeur@email.com';
const contactSubject = 'Test - API Mailjet';
const contactMessage = `Saint Victeur vous bénit !`;
// --------------------------------------------------
// LOGIC
// --------------------------------------------------
const sendEmail = async () => {
try {
$fetch('/api/mailjet', {
method: 'post',
body: {
name: contactName,
emailAddress: contactEmailAddress,
subject: contactSubject,
message: contactMessage
}
});
console.log('Success!');
} catch(err) {
console.log('Failure!');
}
}
</script>
<style lang="scss" scoped>
// --------------------------------------------------
// LAYOUT & STYLE
// --------------------------------------------------
.contact-form {
width: var(--text-width);
display: grid;
grid:
'name name' auto
'email email' auto
'subject subject' auto
'message message' auto
'button .' auto
/ 1fr 1fr;
place-content: start;
place-items: start;
gap: 2rem;
&__name {
grid-area: name;
}
&__email {
grid-area: email;
}
&__subject {
grid-area: subject;
}
&__message {
grid-area: message;
}
&__name,
&__email,
&__subject,
&__message {
position: relative;
width: 100%;
}
&__button {
grid-area: button;
@include button-with-icon;
}
@media screen and (min-width: $tablet-media-query) {
grid:
'name .' auto
'email .' auto
'subject subject' auto
'message message' auto
'button .' auto
/ 1fr 1fr;
}
}
</style>

View file

@ -0,0 +1,87 @@
<template>
<section class="contact-header">
<h2 class="contact-header__title">Contact</h2>
<p class="contact-header__text">Vous avez un projet web à réaliser ? Contactez-moi à l'adresse e-mail <a href="mailto:contact@paulnicoue.com" target="_blank">contact@paulnicoue.com</a> ou via le formulaire ci-après. Vous pouvez également me retrouver sur les plateformes <a href="https://www.malt.fr/profile/paulnicoue" target="_blank">Malt</a> (mise en relation des entreprises et travailleurs indépendants) et <a href="https://gitlab.com/paulnicoue" target="_blank">GitLab</a> (hébergement et gestion de code source).</p>
<div class="contact-header__links" aria-hidden="true">
<a tabindex="-1" href="https://www.malt.fr/profile/paulnicoue" target="_blank" title="Consulter le profil Malt de Paul Nicoué">
<svg viewBox="0 0 24 24" fill="url(#icon-gradient)" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="icon-gradient" gradientUnits="userSpaceOnUse" x1="12" y1="0" x2="12" y2="24" gradientTransform="matrix(0.707651, 0.706562, -1, 1, 15.508194, -8.478749)">
<stop offset="0" style="stop-color: rgb(163, 243, 176);"/>
<stop offset="1" style="stop-color: rgb(114, 192, 128);"/>
</linearGradient>
</defs>
<path d="M 20.542 3.464 C 18.726 1.654 16.793 2.827 15.581 4.034 L 4.14 15.475 C 2.927 16.687 1.659 18.531 3.57 20.436 C 5.475 22.341 7.313 21.073 8.525 19.86 L 19.967 8.419 C 21.179 7.212 22.352 5.274 20.542 3.464 Z M 9.609 2.994 L 12.034 5.419 L 14.497 2.95 C 14.665 2.782 14.832 2.626 15.006 2.48 C 14.749 1.179 14.006 0 12.028 0 C 10.05 0 9.307 1.184 9.056 2.486 C 9.24 2.648 9.425 2.81 9.609 2.994 Z M 14.497 20.989 L 12.034 18.525 L 9.609 20.944 C 9.425 21.128 9.246 21.302 9.061 21.458 C 9.341 22.788 10.123 24 12.028 24 C 13.939 24 14.726 22.777 15 21.447 C 14.832 21.302 14.665 21.156 14.497 20.989 Z M 8.581 8.866 L 3.911 8.866 C 2.196 8.866 0 9.408 0 11.966 C 0 13.883 1.223 14.665 2.559 14.939 C 2.715 14.76 8.581 8.866 8.581 8.866 Z M 21.514 8.994 C 21.369 9.162 15.486 15.073 15.486 15.073 L 20.089 15.073 C 21.804 15.073 24 14.665 24 11.966 C 24 9.994 22.821 9.251 21.514 8.994 Z M 10.112 7.335 L 10.944 6.503 L 8.525 4.078 C 7.313 2.866 5.475 1.598 3.564 3.508 C 2.168 4.905 2.48 6.268 3.218 7.369 C 3.447 7.352 10.112 7.335 10.112 7.335 Z M 13.95 16.603 L 13.112 17.441 L 15.581 19.905 C 16.793 21.117 18.726 22.291 20.536 20.48 C 21.888 19.128 21.581 17.704 20.832 16.57 C 20.592 16.587 13.95 16.603 13.95 16.603 Z"/>
</svg>
</a>
<a tabindex="-1" href="https://gitlab.com/paulnicoue" target="_blank" title="Consulter le profil GitLab de Paul Nicoué">
<svg viewBox="0 0 24 24" fill="url(#icon-gradient)" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="icon-gradient" gradientUnits="userSpaceOnUse" x1="12" y1="0" x2="12" y2="24" gradientTransform="matrix(0.705192, 0.709016, -1, 1, 15.5377, -8.508194)">
<stop offset="0" style="stop-color: rgb(163, 243, 176);"/>
<stop offset="1" style="stop-color: rgb(114, 192, 128);"/>
</linearGradient>
</defs>
<path d="M 23.601 9.5 L 23.568 9.411 L 20.301 0.558 C 20.235 0.385 20.117 0.237 19.965 0.137 C 19.653 -0.063 19.254 -0.041 18.965 0.193 C 18.826 0.311 18.724 0.471 18.675 0.65 L 16.47 7.658 L 7.539 7.658 L 5.333 0.65 C 5.285 0.47 5.183 0.309 5.043 0.192 C 4.754 -0.042 4.355 -0.064 4.043 0.136 C 3.891 0.237 3.774 0.384 3.707 0.557 L 0.434 9.406 L 0.402 9.495 C -0.564 12.116 0.256 15.085 2.414 16.775 L 2.425 16.784 L 2.455 16.806 L 7.431 20.676 L 9.893 22.611 L 11.392 23.787 C 11.753 24.071 12.252 24.071 12.612 23.787 L 14.112 22.611 L 16.573 20.676 L 21.58 16.783 L 21.592 16.773 C 23.745 15.082 24.563 12.119 23.601 9.5 Z"/>
</svg>
</a>
</div>
</section>
</template>
<script setup>
</script>
<style lang="scss" scoped>
// --------------------------------------------------
// LAYOUT & STYLE
// --------------------------------------------------
.contact-header {
width: var(--text-width);
display: grid;
place-content: start;
place-items: start;
gap: 2rem;
&__links {
display: flex;
justify-content: center;
align-items: center;
a {
width: var(--regular-icon-size);
height: var(--regular-icon-size);
display: flex;
justify-content: center;
align-items: center;
+ a {
margin: 0 0 0 2rem;
}
svg {
width: 100%;
height: 100%;
transition:
fill 200ms ease-in-out,
transform 200ms ease-in-out;
}
&:hover,
&:focus,
&:active {
svg {
fill: var(--accent-color-light);
transform: scale(1.1) rotate(22.5deg);
}
}
}
}
}
</style>

View file

@ -0,0 +1,57 @@
<template>
<section class="contact">
<ContactDecoration class="contact__decoration" />
<ContactHeader class="contact__header" />
<ContactForm class="contact__form" />
</section>
</template>
<script setup>
</script>
<style lang="scss" scoped>
// --------------------------------------------------
// LAYOUT & STYLE
// --------------------------------------------------
.contact {
width: var(--content-width);
display: grid;
grid:
'decoration header' auto
'decoration form' auto
/ auto 1fr;
place-content: start stretch;
place-items: start stretch;
row-gap: 4rem;
column-gap: 2rem;
&__decoration {
grid-area: decoration;
}
&__header {
grid-area: header;
}
&__form {
grid-area: form;
}
@media screen and (min-width: $tablet-media-query) {
column-gap: 4rem;
}
@media screen and (min-width: $desktop-media-query) {
grid:
'decoration header form' auto
/ auto 1fr 2fr;
column-gap: 6rem;
}
}
</style>

53
components/HeroTitle.vue Normal file
View file

@ -0,0 +1,53 @@
<template>
<div class="hero-title">
<h1 class="hero-title__name">Paul Nicoué</h1>
<div class="hero-title__separator" aria-hidden="true"></div>
<h2 class="hero-title__job">Intégrateur web & développeur full stack</h2>
</div>
</template>
<script setup>
</script>
<style lang="scss" scoped>
// --------------------------------------------------
// STYLE
// --------------------------------------------------
.hero-title {
min-width: 50vw;
height: 100vh;
height: 100svh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
&__name {
opacity: 0;
margin: 0 2rem;
animation: fade-in-from-bottom 400ms ease-in-out 600ms forwards;
}
&__separator {
width: 0;
height: 1px;
margin: 0.5rem auto;
background-color: var(--accent-color);
animation: expand-width 400ms ease-in-out 200ms forwards;
}
&__job {
opacity: 0;
font-size: var(--h2-font-size);
font-weight: var(--light-font-weight);
margin: 0 2rem;
animation: fade-in-from-top 400ms ease-in-out 600ms forwards;
}
}
</style>