Add form section
This commit is contained in:
parent
c6705914e0
commit
2a4cf52465
33 changed files with 1031 additions and 311 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
<style lang="scss" scoped>
|
||||
|
||||
// --------------------------------------------------
|
||||
// FOOTER STYLE
|
||||
// STYLE
|
||||
// --------------------------------------------------
|
||||
|
||||
footer {
|
||||
|
|
|
@ -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>
|
57
components/ContactDecoration.vue
Normal file
57
components/ContactDecoration.vue
Normal 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
132
components/ContactForm.vue
Normal 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>
|
87
components/ContactHeader.vue
Normal file
87
components/ContactHeader.vue
Normal 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>
|
57
components/ContactSection.vue
Normal file
57
components/ContactSection.vue
Normal 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
53
components/HeroTitle.vue
Normal 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>
|
Loading…
Add table
Add a link
Reference in a new issue