Update-Current-User WIP

This commit is contained in:
Dominic Villemure
2024-06-29 22:44:49 -04:00
parent 81fe5abd7b
commit b07ca6f364
9 changed files with 168 additions and 134 deletions

View File

@@ -1,4 +1,5 @@
import UserTransactionsModel from "@/models/userTransactionsModel.js"; import UserTransactionsModel from "@/models/userTransactionsModel.js";
import SocialNetworksModel from "@/models/socialNetworksModel.js";
export default class MyUserModel export default class MyUserModel
{ {
@@ -6,6 +7,16 @@ export default class MyUserModel
firstName = ""; firstName = "";
lastName = ""; lastName = "";
userName = ""; userName = "";
occupation = "";
email = "";
phone = "";
birthDate = "";
country = "";
city = "";
address = "";
about = "";
description = "";
socialNetworks = new SocialNetworksModel();
totalBalance = ""; totalBalance = "";
userTransactions = []; userTransactions = [];

View File

@@ -0,0 +1,15 @@
export default class SocialNetworksModel
{
facebookUrl = "";
instagramUrl = "";
xUrl = "";
linkedInUrl = "";
tikTokUrl = "";
youtubeUrl = "";
redditUrl = "";
yourWebsiteUrl = "";
static createFromApiResult(apiResult){
return Object.assign(new SocialNetworksModel(), apiResult)
}
}

17
src/stores/user.js Normal file
View File

@@ -0,0 +1,17 @@
import { ref } from 'vue'
import { defineStore } from 'pinia'
import MyUserModel from "@/models/myUserModel.js";
export const useUserStore = defineStore('user', () => {
const user = ref(MyUserModel)
async function getCurrentUser(client) {
const myUser = await client.get("/api/GetMyUser");
return MyUserModel.createFromApiResult(myUser.data);
}
async function updateCurrentUser(client, myUserModel) {
await client.patch("/api/UpdateMyUser/profile", myUserModel)
}
return { user, getCurrentUser, updateCurrentUser }
})

View File

@@ -7,42 +7,42 @@
<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>
</div> </div>
<v-text-field v-model="firstName" label="Prénom" variant="outlined"></v-text-field> <v-text-field v-model="user.firstName" label="Prénom" variant="outlined"></v-text-field>
</div> </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">Nom</label> <label class="text-lg">Nom</label>
</div> </div>
<v-text-field v-model="lastName" label="Nom" variant="outlined"></v-text-field> <v-text-field v-model="user.lastName" label="Nom" variant="outlined"></v-text-field>
</div> </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">Occupation</label> <label class="text-lg">Occupation</label>
</div> </div>
<v-text-field v-model="occupation" label="Occupation" variant="outlined"></v-text-field> <v-text-field v-model="user.occupation" label="Occupation" variant="outlined"></v-text-field>
</div> </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">Courriel</label> <label class="text-lg">Courriel</label>
</div> </div>
<v-text-field v-model="email" label="Courriel" variant="outlined"></v-text-field> <v-text-field v-model="user.email" label="Courriel" variant="outlined"></v-text-field>
</div> </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">Téléphone</label> <label class="text-lg">Téléphone</label>
</div> </div>
<v-text-field v-model="phone" label="Téléphone" variant="outlined"></v-text-field> <v-text-field v-model="user.phone" label="Téléphone" variant="outlined"></v-text-field>
</div> </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">Date de naissance (JJ/MM/AAAA)</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="user.birthDate" label="Date de naissance" variant="outlined"
:rules="[dateRule]"></v-text-field> :rules="[dateRule]"></v-text-field>
</div> </div>
@@ -50,35 +50,35 @@
<div class="flex justify-between items-center mb-2"> <div class="flex justify-between items-center mb-2">
<label class="text-lg">Pays</label> <label class="text-lg">Pays</label>
</div> </div>
<v-text-field v-model="country" label="Pays" variant="outlined"></v-text-field> <v-text-field v-model="user.country" label="Pays" variant="outlined"></v-text-field>
</div> </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">Ville</label> <label class="text-lg">Ville</label>
</div> </div>
<v-text-field v-model="city" label="Ville" variant="outlined"></v-text-field> <v-text-field v-model="user.city" label="Ville" variant="outlined"></v-text-field>
</div> </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">Adresse</label> <label class="text-lg">Adresse</label>
</div> </div>
<v-text-field v-model="address" label="Adresse" variant="outlined"></v-text-field> <v-text-field v-model="user.address" label="Adresse" variant="outlined"></v-text-field>
</div> </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">Titre A propos</label> <label class="text-lg">Titre A propos</label>
</div> </div>
<v-text-field v-model="titre" label="Titre A propos" variant="outlined"></v-text-field> <v-text-field v-model="user.about" label="Titre A propos" variant="outlined"></v-text-field>
</div> </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">Description</label> <label class="text-lg">Description</label>
</div> </div>
<v-textarea v-model="description" label="Description" variant="outlined"></v-textarea> <v-textarea v-model="user.description" label="Description" variant="outlined"></v-textarea>
</div> </div>
</div> </div>
</div> </div>
@@ -86,19 +86,12 @@
</template> </template>
<script setup> <script setup>
import { ref } from 'vue'; import { ref, defineProps } from 'vue';
import MyUserModel from "@/models/myUserModel.js";
const firstName = ref(''); const props = defineProps({
const lastName = ref(''); user: { type: MyUserModel },
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 dateRule = value => {
const datePattern = /^(0[1-9]|[12][0-9]|3[01])\/(0[1-9]|1[0-2])\/(19|20)\d{2}$/; const datePattern = /^(0[1-9]|[12][0-9]|3[01])\/(0[1-9]|1[0-2])\/(19|20)\d{2}$/;

View File

@@ -101,11 +101,11 @@
</template> </template>
<script setup> <script setup>
import MyUserModel from "@/models/myUserModel.js";
import {useClient} from "@/plugins/api.js"; import {useClient} from "@/plugins/api.js";
import {ref, onMounted, onBeforeUnmount} from "vue"; import {ref, onMounted, onBeforeUnmount} from "vue";
import {eventBus} from '@/eventBus.js'; import {eventBus} from '@/eventBus.js';
import {useRouter} from 'vue-router'; import {useRouter} from 'vue-router';
import {useUserStore} from "@/stores/user.js";
const router = useRouter(); const router = useRouter();
const currentUserName = ref("Anonyme"); const currentUserName = ref("Anonyme");
@@ -113,6 +113,7 @@ const searchQuery = ref("");
const showSearch = ref(false); const showSearch = ref(false);
let currentUser = null; let currentUser = null;
const client = useClient(); const client = useClient();
const userStore = useUserStore();
const toggleSidebar = () => { const toggleSidebar = () => {
eventBus.value.toggleSidebar(); eventBus.value.toggleSidebar();
@@ -153,10 +154,8 @@ const logout = () => {
onMounted(async () => { onMounted(async () => {
try { try {
const myUser = await client.get("/api/GetMyUser"); currentUser = await userStore.getCurrentUser(client);
const currentUserModel = MyUserModel.createFromApiResult(myUser.data); currentUserName.value = currentUser.userName;
currentUser = currentUserModel;
currentUserName.value = currentUserModel.userName;
} catch (error) { } catch (error) {
console.log("User not logged"); console.log("User not logged");
} }

View File

@@ -2,13 +2,13 @@
<div class="px-2"> <div class="px-2">
<div class="flex flex-col max-w-2xl mx-auto rounded-3xl shadow-2xl mt-2 mb-16"> <div class="flex flex-col max-w-2xl mx-auto rounded-3xl shadow-2xl mt-2 mb-16">
<H1 class="text-center text-4xl bg-fuchsia-900 p-3 rounded-t-3xl border-b-4 border-b-gray-200 font-sans text-white"> <h1 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
</H1> </h1>
<ProfileBanner></ProfileBanner> <ProfileBanner :user="currentUser"></ProfileBanner>
<Aboutyou></Aboutyou> <Aboutyou :user="currentUser"></Aboutyou>
<SocialLinks></SocialLinks> <SocialLinks :social-networks="currentUser.socialNetworks"></SocialLinks>
<div class="sticky inset-x-0 bottom-0 flex justify-center px-4 pb-4"> <div class="sticky inset-x-0 bottom-0 flex justify-center px-4 pb-4">
<div class="flex space-x-2"> <div class="flex space-x-2">
@@ -28,6 +28,23 @@ 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"; import ProfileBanner from "@/views/main/ProfileBanner.vue";
import DonationPopup from "@/views/main/DonationPopup.vue"; import DonationPopup from "@/views/main/DonationPopup.vue";
import {onBeforeMount, ref} from "vue";
import {useClient} from "@/plugins/api.js";
import {useUserStore} from "@/stores/user.js";
import MyUserModel from "@/models/myUserModel.js";
const client = useClient();
const userStore = useUserStore();
const currentUser = ref(MyUserModel)
onBeforeMount(async () => {
try {
currentUser.value = await userStore.getCurrentUser(client);
} catch(error) {
console.log("User not logged")
}
})
</script> </script>

View File

@@ -67,105 +67,82 @@
</div> </div>
</template> </template>
<script> <script setup>
import {ref} from 'vue'; import { ref, defineProps } from 'vue';
import MyUserModel from "@/models/myUserModel.js";
export default { const props = defineProps({
props: { initialTopColor: { type: String, default: '#6B0065' },
initialTopColor: {type: String, default: '#6B0065'}, initialBottomColor: { type: String, default: '#A30E79' },
initialBottomColor: {type: String, default: '#A30E79'}, initialAccentColor: { type: String, default: '#282286' },
initialAccentColor: {type: String, default: '#282286'}, initialAccent2Color: { type: String, default: '#A526B6' },
initialAccent2Color: {type: String, default: '#A526B6'}, initialBannerImageUrl: { type: String, default: '/images/usersmedia/HutopyProfile/banners/banner01.png' },
initialBannerImageUrl: {type: String, default: '/images/usersmedia/HutopyProfile/banners/banner01.png'}, initialProfilePictureUrl: { type: String, default: '/images/usersmedia/HutopyProfile/profilepictures/profileHutopyProfile01.png' },
initialProfilePictureUrl: { user: { type: MyUserModel },
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 topColor = ref(props.initialTopColor);
const profilePictureUrl = ref(props.initialProfilePictureUrl); const bottomColor = ref(props.initialBottomColor);
const accentColor = ref(props.initialAccentColor);
const accent2Color = ref(props.initialAccent2Color);
const bannerImage = ref(null); const bannerImageUrl = ref(props.initialBannerImageUrl);
const profilePicture = ref(null); const profilePictureUrl = ref(props.initialProfilePictureUrl);
const showColorPicker = ref(false); const bannerImage = ref(null);
const selectedColor = ref('#F4F4F4'); const profilePicture = ref(null);
const colorTarget = ref('');
const onBannerFileChange = (event) => { const showColorPicker = ref(false);
const file = event.target.files[0]; const selectedColor = ref('#F4F4F4');
if (file) { const colorTarget = ref('');
const reader = new FileReader();
reader.onload = (e) => {
bannerImageUrl.value = e.target.result;
};
reader.readAsDataURL(file);
}
};
const onProfileFileChange = (event) => { const onBannerFileChange = (event) => {
const file = event.target.files[0]; const file = event.target.files[0];
if (file) { if (file) {
const reader = new FileReader(); const reader = new FileReader();
reader.onload = (e) => { reader.onload = (e) => {
profilePictureUrl.value = e.target.result; bannerImageUrl.value = e.target.result;
}; };
reader.readAsDataURL(file); reader.readAsDataURL(file);
} }
}; };
const openColorPicker = (target) => { const onProfileFileChange = (event) => {
colorTarget.value = target; const file = event.target.files[0];
showColorPicker.value = true; if (file) {
}; const reader = new FileReader();
reader.onload = (e) => {
profilePictureUrl.value = e.target.result;
};
reader.readAsDataURL(file);
}
};
const applyColor = () => { const openColorPicker = (target) => {
if (colorTarget.value === 'top') { colorTarget.value = target;
topColor.value = selectedColor.value; showColorPicker.value = true;
} 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) => { const applyColor = () => {
// Simple function to determine if the text should be white or black based on the background color if (colorTarget.value === 'top') {
const color = bgColor.replace('#', ''); topColor.value = selectedColor.value;
const r = parseInt(color.substr(0, 2), 16); } else if (colorTarget.value === 'bottom') {
const g = parseInt(color.substr(2, 2), 16); bottomColor.value = selectedColor.value;
const b = parseInt(color.substr(4, 2), 16); } else if (colorTarget.value === 'accent') {
const brightness = (r * 299 + g * 587 + b * 114) / 1000; accentColor.value = selectedColor.value;
return brightness > 155 ? '#000' : '#fff'; } else if (colorTarget.value === 'accent2') {
}; accent2Color.value = selectedColor.value;
}
showColorPicker.value = false;
};
return { const getTextColor = (bgColor) => {
topColor, // Simple function to determine if the text should be white or black based on the background color
bottomColor, const color = bgColor.replace('#', '');
accentColor, const r = parseInt(color.substr(0, 2), 16);
accent2Color, const g = parseInt(color.substr(2, 2), 16);
bannerImageUrl, const b = parseInt(color.substr(4, 2), 16);
profilePictureUrl, const brightness = (r * 299 + g * 587 + b * 114) / 1000;
bannerImage, return brightness > 155 ? '#000' : '#fff';
profilePicture,
showColorPicker,
selectedColor,
colorTarget,
onBannerFileChange,
onProfileFileChange,
openColorPicker,
applyColor,
getTextColor,
};
},
}; };
</script> </script>

View File

@@ -22,15 +22,20 @@
</template> </template>
<script setup> <script setup>
import { ref } from 'vue'; import {defineProps, ref} from 'vue';
import SocialNetworksModel from "@/models/socialNetworksModel.js";
const props = defineProps({
socialNetworks: { type: SocialNetworksModel },
});
const socialNetworks = ref([ const socialNetworks = ref([
{ label: 'Instagram', field: 'instagram', value: '' }, { label: 'Instagram', field: 'instagram', value: props.socialNetworks.instagramUrl },
{ label: 'TikTok', field: 'tiktok', value: '' }, { label: 'TikTok', field: 'tiktok', value: props.socialNetworks.tikTokUrl },
{ label: 'Facebook', field: 'facebook', value: '' }, { label: 'Facebook', field: 'facebook', value: props.socialNetworks.facebookUrl },
{ label: 'X', field: 'X', value: '' }, { label: 'X', field: 'X', value: props.socialNetworks.xUrl },
{ label: 'LinkedIn', field: 'linkedin', value: '' }, { label: 'LinkedIn', field: 'linkedin', value: props.socialNetworks.linkedInUrl },
{ label: 'Site Web', field: 'website', value: '' } { label: 'Site Web', field: 'website', value: props.socialNetworks.yourWebsiteUrl }
]); ]);
const iconUrl = ref(''); const iconUrl = ref('');

View File

@@ -27,7 +27,9 @@
import { onBeforeMount, ref } from 'vue'; import { onBeforeMount, ref } from 'vue';
import {useClient} from "@/plugins/api.js"; import {useClient} from "@/plugins/api.js";
import MyUserModel from "@/models/myUserModel.js"; import MyUserModel from "@/models/myUserModel.js";
import {useUserStore} from "@/stores/user.js";
const client = useClient(); const client = useClient();
const userStore = useUserStore();
const total = ref(false); const total = ref(false);
const drawer = ref(false); const drawer = ref(false);
@@ -36,10 +38,8 @@ let currentUser = null;
onBeforeMount(async () => { onBeforeMount(async () => {
try { try {
const myUser = await client.get("/api/GetMyUser"); currentUser = await userStore.getCurrentUser(client);
const currentUserModel = MyUserModel.createFromApiResult(myUser.data); currentUserName.value = currentUser.firstName + " " + currentUser.lastName
currentUser = currentUserModel;
currentUserName.value = currentUserModel.firstName + " " + currentUserModel.lastName
} catch(error) { } catch(error) {
console.log("User not logged") console.log("User not logged")