mirror of
https://github.com/LJ5O/website.git
synced 2026-08-11 14:44:46 +02:00
Compare commits
1 Commits
37684863b8
...
contact
| Author | SHA1 | Date | |
|---|---|---|---|
|
dd31944bc5
|
@@ -94,5 +94,30 @@
|
|||||||
"desc": "When working with AI, creating a high-quality dataset for training is vital. Many operations and transformations need to be executed, which require a solid understanding of data management. Some infrasctructures also come with databases containing valuable information, that should be extracted and analysed to extract the best from it."
|
"desc": "When working with AI, creating a high-quality dataset for training is vital. Many operations and transformations need to be executed, which require a solid understanding of data management. Some infrasctructures also come with databases containing valuable information, that should be extracted and analysed to extract the best from it."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"contact": {
|
||||||
|
"title": "Send me a message !",
|
||||||
|
"subtitle": "Thanks for your interest ! If you wish to contact me, the easiest way is by Email.",
|
||||||
|
"captcha":{
|
||||||
|
"title": "Sorry, but could you check that you're an human ?",
|
||||||
|
"desc": "Some bots are exploring the web to collect email adresses and send spam. In order to avoid this, please fill the following :",
|
||||||
|
"question": "If we add {x} and {y} minus {z}, what would the result be ?",
|
||||||
|
"submit": "Submit",
|
||||||
|
"false": "Sorry, this doesn't seems right !"
|
||||||
|
},
|
||||||
|
"emails": {
|
||||||
|
"work" :{
|
||||||
|
"title": "Work",
|
||||||
|
"desc": "If your message is about a job opportunity, a company or some professional matter, please use {email}"
|
||||||
|
},
|
||||||
|
"school" :{
|
||||||
|
"title": "Academics and research",
|
||||||
|
"desc": "{email} is the best suited to talk about universities and research."
|
||||||
|
},
|
||||||
|
"others" :{
|
||||||
|
"title": "Other cases",
|
||||||
|
"desc": "In case the two previous emails don't suit your needs, you can also use {email}. This address is considered to be a general purposes one."
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
98
src/components/contact/emails.vue
Normal file
98
src/components/contact/emails.vue
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
<template>
|
||||||
|
<div v-if="isHuman">
|
||||||
|
<h2>{{ $t("contact.emails.work.title") }}</h2>
|
||||||
|
<p>{{ $t("contact.emails.work.desc", {email:mail1}) }}</p>
|
||||||
|
<h2>{{ $t("contact.emails.school.title") }}</h2>
|
||||||
|
<p>{{ $t("contact.emails.school.desc", {email:mail2}) }}</p>
|
||||||
|
<h2>{{ $t("contact.emails.others.title") }}</h2>
|
||||||
|
<p>{{ $t("contact.emails.others.desc", {email:mail3}) }}</p>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<h2>{{ $t("contact.captcha.title") }}</h2>
|
||||||
|
<p>{{ $t("contact.captcha.desc") }}</p>
|
||||||
|
<p v-if="isFalse">{{ $t("contact.captcha.false") }}</p>
|
||||||
|
<label for="captcha">{{ $t("contact.captcha.question", {x:x, y:y, z:z}) }}</label>
|
||||||
|
<input type="number" id="captcha" v-model="captchaValue"/>
|
||||||
|
<button class="button" @click="captchaSubmit">{{ $t("contact.captcha.submit") }}</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { onBeforeMount, ref } from 'vue';
|
||||||
|
|
||||||
|
const validationChar = "&"; // Used to check that provided number is valid
|
||||||
|
const x = 7;
|
||||||
|
const y =20;
|
||||||
|
const z = 1;
|
||||||
|
|
||||||
|
let mail1 = ref("");
|
||||||
|
let mail2 = ref("");
|
||||||
|
let mail3 = ref("");
|
||||||
|
|
||||||
|
let captchaValue = ref(0);
|
||||||
|
let isHuman = ref(false);
|
||||||
|
let isFalse = ref(false);
|
||||||
|
|
||||||
|
onBeforeMount(()=>{
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
const captchaSubmit = ()=>{
|
||||||
|
if(ceasarEncryption(validationChar, captchaValue.value) == "@"){
|
||||||
|
//OK
|
||||||
|
isFalse.value = false;
|
||||||
|
isHuman;value = true;
|
||||||
|
readEmails();
|
||||||
|
}else{
|
||||||
|
isFalse.value = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const readEmails = ()=>{
|
||||||
|
for(let i=0; i<encryptedEmails.length; i++){
|
||||||
|
const letter = ceasarEncryption(encryptedEmails[i], 26);
|
||||||
|
if(letter == "*") continue;
|
||||||
|
if(i%3==0){
|
||||||
|
//mail1.value= mail1.value+letter;
|
||||||
|
}else if(i%3==1){
|
||||||
|
//mail2.value = mail2.value+letter;
|
||||||
|
}else{
|
||||||
|
//mail3.value = mail3.value+letter;
|
||||||
|
}
|
||||||
|
if(i%3==1)console.log(letter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ceasarEncryption = (input, gap)=>{
|
||||||
|
return String.fromCharCode(input.charCodeAt(0) + gap);
|
||||||
|
}
|
||||||
|
const encodeEmails = (emails, key)=>{
|
||||||
|
let output = "";
|
||||||
|
let i=0;
|
||||||
|
let j=0;
|
||||||
|
let letterIndex=0;
|
||||||
|
while(true){
|
||||||
|
const mail = emails[i%emails.length];
|
||||||
|
let end = true;
|
||||||
|
|
||||||
|
if(j<mail.length){
|
||||||
|
//still letters to add
|
||||||
|
output+=ceasarEncryption(mail[j], key);
|
||||||
|
end=false;
|
||||||
|
}else{
|
||||||
|
output+=ceasarEncryption('*', key);
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
if(end)break;
|
||||||
|
if(i%emails.length == emails.length-1)j++; // Looped through all emails, next letter
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
label{
|
||||||
|
color: #EAEAEA;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -2,14 +2,16 @@
|
|||||||
<div class="intersection_div">
|
<div class="intersection_div">
|
||||||
<div class="intersection_content test">
|
<div class="intersection_content test">
|
||||||
<h2 class="test">{{ props.text }}</h2>
|
<h2 class="test">{{ props.text }}</h2>
|
||||||
<a :href="props.buttonLink"><div class="button intersection_button_div test">
|
<RouterLink :to="buttonLink"><div class="button intersection_button_div test">
|
||||||
<p>{{buttonText}}</p>
|
<p>{{buttonText}}</p>
|
||||||
</div></a>
|
</div></RouterLink>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import { RouterLink } from 'vue-router';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
text:{
|
text:{
|
||||||
type: String,
|
type: String,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { createRouter, createWebHistory } from 'vue-router'
|
|||||||
import HomeView from '../views/HomeView.vue'
|
import HomeView from '../views/HomeView.vue'
|
||||||
import BaseArticle from '@/views/BaseArticle.vue'
|
import BaseArticle from '@/views/BaseArticle.vue'
|
||||||
import SkillsView from '@/views/SkillsView.vue'
|
import SkillsView from '@/views/SkillsView.vue'
|
||||||
|
import ContactView from '@/views/ContactView.vue'
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(import.meta.env.BASE_URL),
|
history: createWebHistory(import.meta.env.BASE_URL),
|
||||||
@@ -21,6 +22,11 @@ const router = createRouter({
|
|||||||
name: 'skills',
|
name: 'skills',
|
||||||
component: SkillsView
|
component: SkillsView
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/contact',
|
||||||
|
name: 'contact',
|
||||||
|
component: ContactView
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/about',
|
path: '/about',
|
||||||
name: 'about',
|
name: 'about',
|
||||||
|
|||||||
36
src/views/ContactView.vue
Normal file
36
src/views/ContactView.vue
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
<template>
|
||||||
|
<Header/>
|
||||||
|
<div id="contact_content">
|
||||||
|
<h1>{{ $t("contact.title") }}</h1>
|
||||||
|
<p>{{ $t("contact.subtitle") }}</p>
|
||||||
|
<!--<img :src="ContactSvg"/>-->
|
||||||
|
<emails/>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import Header from '@/components/header.vue';
|
||||||
|
import emails from '@/components/contact/emails.vue';
|
||||||
|
|
||||||
|
import ContactSvg from '@/assets/svg/contact.svg';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
#contact_content{
|
||||||
|
width: 80%;
|
||||||
|
margin: auto;
|
||||||
|
margin-top: 20px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
/*justify-content: center;*/
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
#contact_content img{
|
||||||
|
width: 100%;
|
||||||
|
max-width: 600px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
<welcome/>
|
<welcome/>
|
||||||
|
|
||||||
<intersection :text="i18n.t('home.contactMe')" :button-text="i18n.t('home.contactButton')" button-link="#"/>
|
<intersection :text="i18n.t('home.contactMe')" :button-text="i18n.t('home.contactButton')" button-link="contact"/>
|
||||||
|
|
||||||
<presentation/>
|
<presentation/>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user