Profile updated
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
<img class="rounded-2xl mr-8" src="/images/hutopymedia/loginpage/loginhutopy.png" alt="hutopy login">
|
||||
</div>
|
||||
<!-- Connexion-objects -->
|
||||
<div class="lg:w-4/12 md:w-6/12 sm:w-6/12 xs:w-6/12 bg-white shadow-lg rounded-lg p-8">
|
||||
<div class="lg:w-4/12 md:w-6/12 sm:w-6/12 xs:w-6/12 rounded-lg p-8">
|
||||
<h1 class="text-center text-2xl font-bold mb-6">Connexion</h1>
|
||||
<div class="mb-4">
|
||||
<!-- TODO: Fix input box overflowing when screen it too small -->
|
||||
|
||||
146
src/views/main/Aboutyou.vue
Normal file
146
src/views/main/Aboutyou.vue
Normal file
@@ -0,0 +1,146 @@
|
||||
<template>
|
||||
<div class="py-8" ref="container">
|
||||
<div class="text-center text-2xl mb-4">À propos de vous</div>
|
||||
<div class="px-5 relative">
|
||||
<div class="flex flex-col space-y-4">
|
||||
<!-- Vos champs de formulaire ici -->
|
||||
<div>
|
||||
<label class="flex justify-center text-lg">Nom d'utilisateur</label>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="flex justify-between items-center mb-2">
|
||||
<label class="text-lg">Prénom</label>
|
||||
</div>
|
||||
<v-text-field v-model="firstName" label="Prénom" variant="outlined"></v-text-field>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="flex justify-between items-center mb-2">
|
||||
<label class="text-lg">Nom</label>
|
||||
</div>
|
||||
<v-text-field v-model="lastName" label="Nom" variant="outlined"></v-text-field>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="flex justify-between items-center mb-2">
|
||||
<label class="text-lg">Occupation</label>
|
||||
</div>
|
||||
<v-text-field v-model="occupation" label="Occupation" variant="outlined"></v-text-field>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="flex justify-between items-center mb-2">
|
||||
<label class="text-lg">Courriel</label>
|
||||
</div>
|
||||
<v-text-field v-model="email" label="Courriel" variant="outlined"></v-text-field>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="flex justify-between items-center mb-2">
|
||||
<label class="text-lg">Téléphone</label>
|
||||
</div>
|
||||
<v-text-field v-model="phone" label="Téléphone" variant="outlined"></v-text-field>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="flex justify-between items-center mb-2">
|
||||
<label class="text-lg">Date de naissance</label>
|
||||
</div>
|
||||
<v-text-field v-model="birthDate" label="Date de naissance" variant="outlined"
|
||||
:rules="[dateRule]"></v-text-field>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="flex justify-between items-center mb-2">
|
||||
<label class="text-lg">Pays</label>
|
||||
</div>
|
||||
<v-text-field v-model="country" label="Pays" variant="outlined"></v-text-field>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="flex justify-between items-center mb-2">
|
||||
<label class="text-lg">Ville</label>
|
||||
</div>
|
||||
<v-text-field v-model="city" label="Ville" variant="outlined"></v-text-field>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="flex justify-between items-center mb-2">
|
||||
<label class="text-lg">Adresse</label>
|
||||
</div>
|
||||
<v-text-field v-model="address" label="Adresse" variant="outlined"></v-text-field>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="flex justify-between items-center mb-2">
|
||||
<label class="text-lg">Titre A propos</label>
|
||||
</div>
|
||||
<v-text-field v-model="titre" label="Titre A propos" variant="outlined"></v-text-field>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="flex justify-between items-center mb-2">
|
||||
<label class="text-lg">Description</label>
|
||||
</div>
|
||||
<v-textarea v-model="description" label="Description" variant="outlined"></v-textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-end space-x-2 px-4">
|
||||
<v-btn class="save-btn" @click="saveAll">Enregistrer</v-btn>
|
||||
<router-link :to="`/${currentUserName}`">
|
||||
<v-btn class="save-btn">Retour</v-btn>
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script async setup>
|
||||
import {ref, onMounted, onUnmounted} from 'vue';
|
||||
|
||||
const username = ref('');
|
||||
const firstName = ref('');
|
||||
const lastName = ref('');
|
||||
const occupation = ref('');
|
||||
const email = ref('');
|
||||
const phone = ref('');
|
||||
const birthDate = ref('');
|
||||
const country = ref('');
|
||||
const city = ref('');
|
||||
const address = ref('');
|
||||
const titre = ref('');
|
||||
const description = ref('');
|
||||
|
||||
const dateRule = value => {
|
||||
const datePattern = /^(0[1-9]|[12][0-9]|3[01])\/(0[1-9]|1[0-2])\/(19|20)\d{2}$/;
|
||||
return datePattern.test(value) || 'Format de date invalide (JJ/MM/AAAA)';
|
||||
};
|
||||
|
||||
const saveAll = () => {
|
||||
const formData = {
|
||||
username: username.value,
|
||||
firstName: firstName.value,
|
||||
lastName: lastName.value,
|
||||
occupation: occupation.value,
|
||||
email: email.value,
|
||||
phone: phone.value,
|
||||
birthDate: birthDate.value,
|
||||
country: country.value,
|
||||
city: city.value,
|
||||
address: address.value,
|
||||
titre: titre.value,
|
||||
description: description.value,
|
||||
};
|
||||
|
||||
// Envoyer les données
|
||||
console.log('Envoi des données : ', formData);
|
||||
// Vous pouvez utiliser une requête HTTP pour envoyer les données à votre serveur ici.
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.save-btn {
|
||||
z-index: 10;
|
||||
}
|
||||
</style>
|
||||
@@ -51,37 +51,55 @@
|
||||
<div class="text-center">
|
||||
<v-menu open-on-hover>
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn variant="plain" v-bind="props" class=" d-flex align-center text-capital-none">
|
||||
|
||||
<span class="normal-case max-w-xs hidden md:block">
|
||||
{{ currentUserName }}
|
||||
</span>
|
||||
<v-btn variant="plain" v-bind="props" class=" d-flex align-center text-capital-none">
|
||||
<span class="normal-case max-w-xs hidden md:block">
|
||||
{{ currentUserName }}
|
||||
</span>
|
||||
<img src="/images/usersmedia/anonyme/profilepictures/profileAnonymeSquare.png" alt="Profile Image"
|
||||
class="ml-2 rounded-full" style="width: 32px; height: 32px;">
|
||||
</v-btn>
|
||||
</template>
|
||||
|
||||
<v-list class="mt-2">
|
||||
<v-list-item>
|
||||
<v-list-item-title>
|
||||
<router-link to="/profile">
|
||||
Mon profil
|
||||
</router-link>
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item>
|
||||
<v-list-item-title>
|
||||
<router-link to="/wallet">
|
||||
Mon wallet
|
||||
</router-link>
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item @click="navigateToMessages">
|
||||
<v-list-item-title>Messages</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item @click="logout">
|
||||
<v-list-item-title>Déconnexion</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list min-width="200px" class=" align-center mt-3 left-3">
|
||||
<div v-if="!currentUser">
|
||||
<v-list-item class="nav-button">
|
||||
<v-list-item-title>
|
||||
<router-link to="/login">
|
||||
Connexion
|
||||
</router-link>
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
</div>
|
||||
|
||||
<div v-if="currentUser">
|
||||
<v-list-item class="nav-button">
|
||||
<v-list-item-title>
|
||||
<router-link :to="`/${currentUserName}`">
|
||||
{{ currentUserName }}
|
||||
</router-link>
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item class="nav-button">
|
||||
<v-list-item-title>
|
||||
<router-link to="/profile">
|
||||
Mon profil
|
||||
</router-link>
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item class="nav-button">
|
||||
<v-list-item-title>
|
||||
<router-link to="/wallet">
|
||||
Mon wallet
|
||||
</router-link>
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item class="nav-button" @click="navigateToMessages">
|
||||
<v-list-item-title>Messages</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item class="nav-button" @click="logout">
|
||||
<v-list-item-title>Déconnexion</v-list-item-title>
|
||||
</v-list-item>
|
||||
</div>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</div>
|
||||
@@ -93,13 +111,13 @@
|
||||
|
||||
<script setup>
|
||||
import MyUserModel from "@/models/myUserModel.js";
|
||||
import { useClient } from "@/plugins/api.js";
|
||||
import { ref, onMounted, onBeforeUnmount } from "vue";
|
||||
import { eventBus } from '@/eventBus.js';
|
||||
import { useRouter } from 'vue-router';
|
||||
import {useClient} from "@/plugins/api.js";
|
||||
import {ref, onMounted, onBeforeUnmount} from "vue";
|
||||
import {eventBus} from '@/eventBus.js';
|
||||
import {useRouter} from 'vue-router';
|
||||
|
||||
const router = useRouter();
|
||||
const currentUserName = ref("INVITÉ");
|
||||
const currentUserName = ref("Anonyme");
|
||||
const searchQuery = ref("");
|
||||
const showSearch = ref(false);
|
||||
let currentUser = null;
|
||||
@@ -118,7 +136,7 @@ const onSearch = () => {
|
||||
if (words.length === 1) {
|
||||
router.push(`/@${words[0]}`);
|
||||
} else {
|
||||
router.push({ name: "browse", query: { q: query } });
|
||||
router.push({name: "browse", query: {q: query}});
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -151,7 +169,7 @@ onMounted(async () => {
|
||||
const myUser = await client.get("/api/GetMyUser");
|
||||
const currentUserModel = MyUserModel.createFromApiResult(myUser.data);
|
||||
currentUser = currentUserModel;
|
||||
currentUserName.value = currentUserModel.firstName + " " + currentUserModel.lastName;
|
||||
currentUserName.value = currentUserModel.userName;
|
||||
} catch (error) {
|
||||
console.log("User not logged");
|
||||
}
|
||||
@@ -168,4 +186,8 @@ onBeforeUnmount(() => {
|
||||
.search-container {
|
||||
position: relative;
|
||||
}
|
||||
.nav-button:hover {
|
||||
@apply bg-[#903175] text-gray-200;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -1,92 +1,125 @@
|
||||
<template>
|
||||
<div class="bg-purple-800 h-24 -mt-12 -mb-6"></div>
|
||||
<div class="flex justify-center">
|
||||
<div class="w-full">
|
||||
<img :src="bannerImageUrl" class="max-h-96 object-cover shadow-md profile-banner">
|
||||
<div class="flex flex-col max-w-4xl mx-auto rounded-3xl shadow-2xl mt-16 mb-16 custom-bg">
|
||||
<!-- Titre -->
|
||||
<div class="text-center md:text-6xl text-2xl p-10 bg-white rounded-t-3xl border-b-4 border-b-gray-200">
|
||||
Personnaliser votre profil
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-purple-800 h-24 flex items-center">
|
||||
<div class="w-full text-right pr-12">
|
||||
<button class="bg-white text-purple-800 p-2 rounded-full shadow-md hover:bg-purple-600 hover:text-white transition-colors duration-300 ease-in-out mr-3">
|
||||
<i class="mdi mdi-pencil"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="max-w-4xl -mt-24 mx-auto flex justify-center items-center">
|
||||
<div class="w-full">
|
||||
<div class="bg-white rounded-3xl shadow-md p-6">
|
||||
<div class="flex justify-center mb-5">
|
||||
<div class="relative">
|
||||
<img :src="profilePictureUrl" class="w-32 h-32 rounded-full shadow-lg border-4 border-white transition-transform duration-500 ease-in-out hover:scale-110">
|
||||
<button class="absolute bottom-0 right-0 bg-white text-purple-800 p-2 rounded-full shadow-md hover:bg-purple-600 hover:text-white transition-colors duration-300 ease-in-out -mt-4">
|
||||
<i class="mdi mdi-pencil"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="text-center mb-3 text-3xl font-semibold">{{ userName }}</p>
|
||||
<p class="text-center mb-12 text-lg">{{ firstName }} {{ lastName }}</p>
|
||||
|
||||
<form>
|
||||
<div class="mb-4">
|
||||
<input type="text" v-model="firstName" placeholder="Prénom" :readonly="!isEditing" class="input input-bordered w-full">
|
||||
<!-- Banner -->
|
||||
<div class="py-5" >
|
||||
<div class="flex justify-between items-center px-5 py-5">
|
||||
<div>Photo de couverture</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="bg-fuchsia-900 h-10"></div>
|
||||
<img :src="bannerImageUrl" alt="Banner Image">
|
||||
<div class="bg-fuchsia-900 h-14 flex justify-center items-center">
|
||||
<div class="space-x-4">
|
||||
<v-btn @click="changeTopColor">Couleur Haut</v-btn>
|
||||
<v-btn @click="changeBottomColor">Couleur Bas</v-btn>
|
||||
<v-btn @click="changeBottomColor">Couleur d'accent</v-btn>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<input type="text" v-model="lastName" placeholder="Nom" :readonly="!isEditing" class="input input-bordered w-full">
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<input type="text" v-model="titre" placeholder="Titre" :readonly="!isEditing" class="input input-bordered w-full">
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<input type="text" v-model="description" placeholder="Description" :readonly="!isEditing" class="input input-bordered w-full">
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="text-right">
|
||||
<!-- <router-link :to="{ name: 'creatorfolio' }">-->
|
||||
<button class="bg-gray-500 text-white px-4 py-2 rounded-lg shadow-md hover:bg-gray-700 transition-colors duration-300 ease-in-out mr-5">Retour</button>
|
||||
<!-- </router-link>-->
|
||||
<button @click="toggleEdit" class="bg-purple-800 text-white px-4 py-2 rounded-lg shadow-md hover:bg-purple-600 transition-colors duration-300 ease-in-out">{{ isEditing ? 'Sauvegarder' : 'Éditer' }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="px-3">
|
||||
<v-file-input v-model="bannerImage" label="Téléverser une nouvelle bannière"
|
||||
@change="onBannerFileChange"></v-file-input>
|
||||
</div>
|
||||
|
||||
<!-- Profile -->
|
||||
<div>
|
||||
<div class="flex justify-between items-center px-5 py-5">
|
||||
<div>Photo de profil</div>
|
||||
</div>
|
||||
<div class="flex justify-center pb-4">
|
||||
<img :src="profilePictureUrl" class="rounded-full max-w-48 max-w-48" alt="Profile Image">
|
||||
</div>
|
||||
<div class="px-3">
|
||||
<v-file-input v-model="profilePicture" label="Téléverser une nouvelle photo de profil"
|
||||
@change="onProfileFileChange"></v-file-input>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Informations -->
|
||||
<Aboutyou></Aboutyou>
|
||||
|
||||
<!-- Social Links -->
|
||||
<div>
|
||||
<SocialLinks></SocialLinks>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script async setup>
|
||||
import MyUserModel from "@/models/myUserModel.js";
|
||||
import { useClient } from "@/plugins/api.js";
|
||||
import { onBeforeMount, ref } from 'vue';
|
||||
import {useClient} from "@/plugins/api.js";
|
||||
import {onBeforeMount, ref} from 'vue';
|
||||
import Aboutyou from "@/views/main/Aboutyou.vue";
|
||||
import SocialLinks from "@/views/main/SocialLinks.vue";
|
||||
|
||||
const client = useClient();
|
||||
|
||||
const currentUserName = ref("Anonyme");
|
||||
const profilePictureUrl = ref('/images/usersmedia/guillaumeMousseau/profilepictures/profileGuillaumeMousseau01.png');
|
||||
const bannerImageUrl = ref('/images/usersmedia/guillaumeMousseau/banners/bannerGuillaumeMousseau01.png');
|
||||
|
||||
const firstName = ref('');
|
||||
const lastName = ref('');
|
||||
const userName = ref('');
|
||||
const titre = ref('');
|
||||
const description = ref('');
|
||||
const bannerImage = ref(null);
|
||||
const profilePicture = ref(null);
|
||||
|
||||
const isEditing = ref(false);
|
||||
const onBannerFileChange = (event) => {
|
||||
const file = event.target.files[0];
|
||||
if (file) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = (e) => {
|
||||
bannerImageUrl.value = e.target.result;
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
};
|
||||
|
||||
const onProfileFileChange = (event) => {
|
||||
const file = event.target.files[0];
|
||||
if (file) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = (e) => {
|
||||
profilePictureUrl.value = e.target.result;
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
};
|
||||
|
||||
const fetchUserData = async () => {
|
||||
try {
|
||||
const myUser = await client.get("/api/GetMyUser");
|
||||
const currentUserModel = MyUserModel.createFromApiResult(myUser.data);
|
||||
firstName.value = currentUserModel.firstName;
|
||||
lastName.value = currentUserModel.lastName;
|
||||
userName.value = currentUserModel.userName;
|
||||
// Assignez d'autres champs si nécessaire
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error fetching user data:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const toggleEdit = () => {
|
||||
isEditing.value = !isEditing.value;
|
||||
const changeTopColor = () => {
|
||||
// Logic to change top color
|
||||
};
|
||||
|
||||
const changeBottomColor = () => {
|
||||
// Logic to change bottom color
|
||||
};
|
||||
|
||||
onBeforeMount(fetchUserData);
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.save-btn {
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.icon-preview {
|
||||
max-width: 250px;
|
||||
max-height: 250px;
|
||||
}
|
||||
|
||||
.custom-bg {
|
||||
background-color: #F4F4F4;
|
||||
}
|
||||
</style>
|
||||
|
||||
75
src/views/main/SocialLinks.vue
Normal file
75
src/views/main/SocialLinks.vue
Normal file
@@ -0,0 +1,75 @@
|
||||
<template>
|
||||
<div class="py-8" ref="container">
|
||||
<div class="text-center text-2xl mb-4">Liens des réseaux sociaux et de votre site</div>
|
||||
<div class="px-5 py-4 flex flex-col space-y-4">
|
||||
<div v-for="network in socialNetworks" :key="network.field">
|
||||
<div class="flex justify-between items-center mb-2">
|
||||
<label class="text-lg">{{ network.label }}</label>
|
||||
</div>
|
||||
<v-text-field v-model="network.value" :label="network.label" variant="outlined"></v-text-field>
|
||||
</div>
|
||||
<div class="flex flex-col space-y-4">
|
||||
<div class="flex items-center mb-2">
|
||||
<label class="text-lg mr-4">Icon</label>
|
||||
<v-file-input v-model="iconFile" label="Téléverser une icône" @change="onFileChange"></v-file-input>
|
||||
</div>
|
||||
<div v-if="iconUrl" class="flex justify-center">
|
||||
<img :src="iconUrl" alt="Icon" class="icon-preview">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-end space-x-2 px-4">
|
||||
<v-btn class="save-btn" @click="saveAll">Enregistrer</v-btn>
|
||||
<router-link :to="`/${currentUserName}`">
|
||||
<v-btn class="save-btn">Retour</v-btn>
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script async setup>
|
||||
import { ref } from 'vue';
|
||||
|
||||
const socialNetworks = ref([
|
||||
{ label: 'Instagram', field: 'instagram', value: '' },
|
||||
{ label: 'TikTok', field: 'tiktok', value: '' },
|
||||
{ label: 'Facebook', field: 'facebook', value: '' },
|
||||
{ label: 'X', field: 'X', value: '' },
|
||||
{ label: 'LinkedIn', field: 'linkedin', value: '' },
|
||||
{ label: 'Site Web', field: 'website', value: '' }
|
||||
]);
|
||||
|
||||
const iconUrl = ref('');
|
||||
|
||||
const onFileChange = (event) => {
|
||||
const file = event.target.files[0];
|
||||
if (file) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = (e) => {
|
||||
iconUrl.value = e.target.result;
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
};
|
||||
|
||||
const saveAll = () => {
|
||||
const formData = socialNetworks.value.reduce((acc, network) => {
|
||||
acc[network.field] = network.value;
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
console.log('Form data:', formData);
|
||||
console.log('Icon URL:', iconUrl.value);
|
||||
// Logic to save all fields and the icon
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.save-btn {
|
||||
z-index: 10;
|
||||
}
|
||||
.icon-preview {
|
||||
max-width: 250px;
|
||||
max-height: 250px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user