-Added Profile.vue and his components - select color and upload pictures UI
This commit is contained in:
@@ -1,13 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="py-8" ref="container">
|
<div class="py-8" ref="container">
|
||||||
<div class="text-center text-2xl mb-4">À propos de vous</div>
|
<div class="text-center text-2xl py-4 border-t-4">À propos de vous</div>
|
||||||
<div class="px-5 relative">
|
<div class="px-5 relative">
|
||||||
<div class="flex flex-col space-y-4">
|
<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>
|
||||||
<div class="flex justify-between items-center mb-2">
|
<div class="flex justify-between items-center mb-2">
|
||||||
<label class="text-lg">Prénom</label>
|
<label class="text-lg">Prénom</label>
|
||||||
@@ -45,7 +40,7 @@
|
|||||||
|
|
||||||
<div>
|
<div>
|
||||||
<div class="flex justify-between items-center mb-2">
|
<div class="flex justify-between items-center mb-2">
|
||||||
<label class="text-lg">Date de naissance</label>
|
<label class="text-lg">Date de naissance (JJ/MM/AAAA)</label>
|
||||||
</div>
|
</div>
|
||||||
<v-text-field v-model="birthDate" label="Date de naissance" variant="outlined"
|
<v-text-field v-model="birthDate" label="Date de naissance" variant="outlined"
|
||||||
:rules="[dateRule]"></v-text-field>
|
:rules="[dateRule]"></v-text-field>
|
||||||
@@ -86,12 +81,6 @@
|
|||||||
<v-textarea v-model="description" label="Description" variant="outlined"></v-textarea>
|
<v-textarea v-model="description" label="Description" variant="outlined"></v-textarea>
|
||||||
</div>
|
</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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -132,10 +121,6 @@ const saveAll = () => {
|
|||||||
titre: titre.value,
|
titre: titre.value,
|
||||||
description: description.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>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -151,10 +151,6 @@ const handleClickOutside = (event) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const navigateToWallet = () => {
|
|
||||||
router.push('/wallet');
|
|
||||||
};
|
|
||||||
|
|
||||||
const navigateToMessages = () => {
|
const navigateToMessages = () => {
|
||||||
router.push('/messages');
|
router.push('/messages');
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,125 +1,37 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col max-w-4xl mx-auto rounded-3xl shadow-2xl mt-16 mb-16 custom-bg">
|
<div class="px-2">
|
||||||
|
<div class="flex flex-col max-w-2xl mx-auto rounded-3xl shadow-2xl mt-2 mb-16">
|
||||||
<!-- Titre -->
|
<!-- Titre -->
|
||||||
<div class="text-center md:text-6xl text-2xl p-10 bg-white rounded-t-3xl border-b-4 border-b-gray-200">
|
<div
|
||||||
|
class="text-center text-4xl bg-fuchsia-900 p-3 rounded-t-3xl border-b-4 border-b-gray-200 font-sans text-white">
|
||||||
Personnaliser votre profil
|
Personnaliser votre profil
|
||||||
</div>
|
</div>
|
||||||
|
<ProfileBanner></ProfileBanner>
|
||||||
<!-- 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>
|
|
||||||
</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>
|
<Aboutyou></Aboutyou>
|
||||||
|
|
||||||
<!-- Social Links -->
|
|
||||||
<div>
|
|
||||||
<SocialLinks></SocialLinks>
|
<SocialLinks></SocialLinks>
|
||||||
|
|
||||||
|
<div class="sticky inset-x-0 bottom-0 flex justify-center px-4 pb-4">
|
||||||
|
<div class="flex space-x-2">
|
||||||
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script async setup>
|
<script async setup>
|
||||||
import MyUserModel from "@/models/myUserModel.js";
|
|
||||||
import {useClient} from "@/plugins/api.js";
|
|
||||||
import {onBeforeMount, ref} from 'vue';
|
|
||||||
import Aboutyou from "@/views/main/Aboutyou.vue";
|
import Aboutyou from "@/views/main/Aboutyou.vue";
|
||||||
import SocialLinks from "@/views/main/SocialLinks.vue";
|
import SocialLinks from "@/views/main/SocialLinks.vue";
|
||||||
|
import ProfileBanner from "@/views/main/ProfileBanner.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 bannerImage = ref(null);
|
|
||||||
const profilePicture = ref(null);
|
|
||||||
|
|
||||||
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");
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error fetching user data:', error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const changeTopColor = () => {
|
|
||||||
// Logic to change top color
|
|
||||||
};
|
|
||||||
|
|
||||||
const changeBottomColor = () => {
|
|
||||||
// Logic to change bottom color
|
|
||||||
};
|
|
||||||
|
|
||||||
onBeforeMount(fetchUserData);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.save-btn {
|
.save-btn {
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-preview {
|
|
||||||
max-width: 250px;
|
|
||||||
max-height: 250px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.custom-bg {
|
|
||||||
background-color: #F4F4F4;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
171
src/views/main/ProfileBanner.vue
Normal file
171
src/views/main/ProfileBanner.vue
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<div class="px-5 py-2 bg-fuchsia-800 text-white" :style="{ backgroundColor: accent2Color }" >
|
||||||
|
<div class="flex justify-center text-2xl">Photo de couverture</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div :style="{ backgroundColor: topColor }" class="flex h-4"></div>
|
||||||
|
<img :src="bannerImageUrl" alt="Banner Image" class="w-full object-cover">
|
||||||
|
<div :style="{ backgroundColor: bottomColor }" class="h-4">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="space-x-4 flex justify-center py-2">
|
||||||
|
<v-btn @click="openColorPicker('top')"
|
||||||
|
:style="{ backgroundColor: topColor, color: getTextColor(topColor) }">Haut
|
||||||
|
</v-btn>
|
||||||
|
<v-btn @click="openColorPicker('bottom')"
|
||||||
|
:style="{ backgroundColor: bottomColor, color: getTextColor(bottomColor) }">Bas
|
||||||
|
</v-btn>
|
||||||
|
<v-btn @click="openColorPicker('accent')"
|
||||||
|
:style="{ backgroundColor: accentColor, color: getTextColor(accentColor) }">Accent1
|
||||||
|
</v-btn>
|
||||||
|
<v-btn @click="openColorPicker('accent2')"
|
||||||
|
:style="{ backgroundColor: accent2Color, color: getTextColor(accent2Color) }">Menu
|
||||||
|
</v-btn>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="px-3 py-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="border-t-4 items-center px-5 py-4">
|
||||||
|
<div class="flex justify-center text-2xl ">Photo de profil</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-center py-4">
|
||||||
|
<img :src="profilePictureUrl"
|
||||||
|
:style="{ borderColor: accentColor, borderWidth: '3px', borderStyle: 'solid' }"
|
||||||
|
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>
|
||||||
|
|
||||||
|
<!-- Color Picker Dialog -->
|
||||||
|
<v-dialog v-model="showColorPicker" max-width="400px" class="d-flex justify-center align-center">
|
||||||
|
<v-card>
|
||||||
|
<v-card-title class="justify-center text-center">Choisir une couleur</v-card-title>
|
||||||
|
<v-card-text class="d-flex justify-center">
|
||||||
|
<v-color-picker v-model="selectedColor"></v-color-picker>
|
||||||
|
</v-card-text>
|
||||||
|
<v-card-actions class="justify-center">
|
||||||
|
<v-spacer></v-spacer>
|
||||||
|
<v-btn color="primary" @click="applyColor">OK</v-btn>
|
||||||
|
</v-card-actions>
|
||||||
|
</v-card>
|
||||||
|
</v-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {ref} from 'vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
initialTopColor: {type: String, default: '#6B0065'},
|
||||||
|
initialBottomColor: {type: String, default: '#A30E79'},
|
||||||
|
initialAccentColor: {type: String, default: '#282286'},
|
||||||
|
initialAccent2Color: {type: String, default: '#A526B6'},
|
||||||
|
initialBannerImageUrl: {type: String, default: '/images/usersmedia/HutopyProfile/banners/banner01.png'},
|
||||||
|
initialProfilePictureUrl: {
|
||||||
|
type: String,
|
||||||
|
default: '/images/usersmedia/HutopyProfile/profilepictures/profileHutopyProfile01.png'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
setup(props) {
|
||||||
|
const topColor = ref(props.initialTopColor);
|
||||||
|
const bottomColor = ref(props.initialBottomColor);
|
||||||
|
const accentColor = ref(props.initialAccentColor);
|
||||||
|
const accent2Color = ref(props.initialAccent2Color);
|
||||||
|
|
||||||
|
const bannerImageUrl = ref(props.initialBannerImageUrl);
|
||||||
|
const profilePictureUrl = ref(props.initialProfilePictureUrl);
|
||||||
|
|
||||||
|
const bannerImage = ref(null);
|
||||||
|
const profilePicture = ref(null);
|
||||||
|
|
||||||
|
const showColorPicker = ref(false);
|
||||||
|
const selectedColor = ref('#F4F4F4');
|
||||||
|
const colorTarget = ref('');
|
||||||
|
|
||||||
|
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 openColorPicker = (target) => {
|
||||||
|
colorTarget.value = target;
|
||||||
|
showColorPicker.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const applyColor = () => {
|
||||||
|
if (colorTarget.value === 'top') {
|
||||||
|
topColor.value = selectedColor.value;
|
||||||
|
} else if (colorTarget.value === 'bottom') {
|
||||||
|
bottomColor.value = selectedColor.value;
|
||||||
|
} else if (colorTarget.value === 'accent') {
|
||||||
|
accentColor.value = selectedColor.value;
|
||||||
|
} else if (colorTarget.value === 'accent2') {
|
||||||
|
accent2Color.value = selectedColor.value; // Appliquer la nouvelle couleur
|
||||||
|
}
|
||||||
|
showColorPicker.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getTextColor = (bgColor) => {
|
||||||
|
// Simple function to determine if the text should be white or black based on the background color
|
||||||
|
const color = bgColor.replace('#', '');
|
||||||
|
const r = parseInt(color.substr(0, 2), 16);
|
||||||
|
const g = parseInt(color.substr(2, 2), 16);
|
||||||
|
const b = parseInt(color.substr(4, 2), 16);
|
||||||
|
const brightness = (r * 299 + g * 587 + b * 114) / 1000;
|
||||||
|
return brightness > 155 ? '#000' : '#fff';
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
topColor,
|
||||||
|
bottomColor,
|
||||||
|
accentColor,
|
||||||
|
accent2Color,
|
||||||
|
bannerImageUrl,
|
||||||
|
profilePictureUrl,
|
||||||
|
bannerImage,
|
||||||
|
profilePicture,
|
||||||
|
showColorPicker,
|
||||||
|
selectedColor,
|
||||||
|
colorTarget,
|
||||||
|
onBannerFileChange,
|
||||||
|
onProfileFileChange,
|
||||||
|
openColorPicker,
|
||||||
|
applyColor,
|
||||||
|
getTextColor,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="py-8" ref="container">
|
<div ref="container">
|
||||||
<div class="text-center text-2xl mb-4">Liens des réseaux sociaux et de votre site</div>
|
<div class="text-center text-2xl py-4 border-t-4">Liens des réseaux sociaux et de votre site</div>
|
||||||
<div class="px-5 py-4 flex flex-col space-y-4">
|
<div class="px-5 py-2 flex flex-col space-y-4">
|
||||||
<div v-for="network in socialNetworks" :key="network.field">
|
<div v-for="network in socialNetworks" :key="network.field">
|
||||||
<div class="flex justify-between items-center mb-2">
|
<div class="flex justify-between items-center mb-2">
|
||||||
<label class="text-lg">{{ network.label }}</label>
|
<label class="text-lg">{{ network.label }}</label>
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col space-y-4">
|
<div class="flex flex-col space-y-4">
|
||||||
<div class="flex items-center mb-2">
|
<div class="flex items-center mb-2">
|
||||||
<label class="text-lg mr-4">Icon</label>
|
<label class="text-lg mr-4">Icône pour votre site web *svg</label>
|
||||||
<v-file-input v-model="iconFile" label="Téléverser une icône" @change="onFileChange"></v-file-input>
|
<v-file-input v-model="iconFile" label="Téléverser une icône" @change="onFileChange"></v-file-input>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="iconUrl" class="flex justify-center">
|
<div v-if="iconUrl" class="flex justify-center">
|
||||||
@@ -18,12 +18,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</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>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -65,9 +59,6 @@ const saveAll = () => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.save-btn {
|
|
||||||
z-index: 10;
|
|
||||||
}
|
|
||||||
.icon-preview {
|
.icon-preview {
|
||||||
max-width: 250px;
|
max-width: 250px;
|
||||||
max-height: 250px;
|
max-height: 250px;
|
||||||
|
|||||||
Reference in New Issue
Block a user