front_foundation #9

Closed
mohamed_maoulainine wants to merge 181 commits from front_foundation into main
3 changed files with 163 additions and 112 deletions
Showing only changes of commit 4b6d501adc - Show all commits

View File

@ -1,43 +1,45 @@
<template> <template>
<div class="project" @click="goToLink"> <div class="project">
<div class="project-header"> <div class="project-header">
<h2>{{ projectName }}</h2> <h2 @click="goToLink">{{ projectName }}</h2>
<div class="header-actions"> <div class="header-actions">
<div class="dropdown-wrapper"> <div class="dropdown-wrapper">
<button class="contact-button" @click="toggleDropdown"> <!-- Empêche la propagation du clic vers le parent -->
Contact <button class="contact-button" @click.stop="toggleDropdown">
</button> Contact
<div </button>
class="contact-dropdown"
:class="{ 'dropdown-visible': isDropdownOpen }" <div class="dropdown-menu" v-if="isDropdownOpen">
> <button @click.stop="contactAll">Contacter tous</button>
<button @click="contactAll">Contacter tous</button> <button
<button v-for="(email, index) in entrepreneurEmails"
v-for="(email, index) in entrepreneurEmails" :key="index"
:key="index" @click.stop="contactSingle(email)"
@click="contactSingle(email)" >
> {{ email }}
{{ email }} </button>
</button> </div>
</div>
</div>
</div>
</div>
<div class="project-body">
<ul>
<li v-for="(name, index) in listName" :key="index">
{{ name }}
</li>
</ul>
</div> </div>
</div>
</div> </div>
<!-- Toute cette partie est cliquable -->
<div class="project-body" @click="goToLink">
<ul>
<li v-for="(name, index) in listName" :key="index">
{{ name }}
</li>
</ul>
</div>
</div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { defineProps } from "vue"; import { defineProps, ref, onMounted, onBeforeUnmount } from "vue";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
import { ref, onMounted } from "vue";
import axios from "axios"; import axios from "axios";
adnane marked this conversation as resolved Outdated
Outdated
Review

It would be better to use an ENV variable

It would be better to use an ENV variable
const IS_MOCK_MODE = true; const IS_MOCK_MODE = true;
const props = defineProps<{ const props = defineProps<{
@ -49,32 +51,36 @@ const props = defineProps<{
const router = useRouter(); const router = useRouter();
const isDropdownOpen = ref(false);
const entrepreneurEmails = ref<string[]>([]);
// Pour fermer le dropdown si on clique ailleurs
const handleClickOutside = (event: MouseEvent) => {
const dropdown = document.querySelector(".dropdown-wrapper");
if (dropdown && !dropdown.contains(event.target as Node)) {
isDropdownOpen.value = false;
}
};
onMounted(() => {
fetchEntrepreneurs(props.projectId, IS_MOCK_MODE);
document.addEventListener("click", handleClickOutside);
});
onBeforeUnmount(() => {
document.removeEventListener("click", handleClickOutside);
});
const toggleDropdown = () => {
isDropdownOpen.value = !isDropdownOpen.value;
};
const goToLink = () => { const goToLink = () => {
if (props.projectLink) { if (props.projectLink) {
router.push(props.projectLink); router.push(props.projectLink);
} }
}; };
type Entrepreneur = {
idUser: number;
userSurname: string;
userName: string;
primaryMail: string;
secondaryMail: string;
phoneNumber: string;
school: string;
course: string;
sneeStatus: boolean;
};
const isDropdownOpen = ref(false);
const entrepreneurEmails = ref<string[]>([]);
const toggleDropdown = () => {
isDropdownOpen.value = !isDropdownOpen.value;
console.log("Dropdown toggled:", isDropdownOpen.value);
};
const fetchEntrepreneurs = async ( const fetchEntrepreneurs = async (
projectId: number, projectId: number,
useMock = IS_MOCK_MODE useMock = IS_MOCK_MODE
@ -88,26 +94,28 @@ const fetchEntrepreneurs = async (
) )
).data; ).data;
if (responseData.length > 0) { entrepreneurEmails.value = responseData.map(
entrepreneurEmails.value = responseData.map( (item: Entrepreneur) => item.primaryMail
(item: Entrepreneur) => item.primaryMail
);
} else {
console.warn("Aucun entrepreneur trouvé.");
}
} catch (error) {
console.error(
"Erreur lors de la récupération des entrepreneurs :",
error
); );
} catch (error) {
console.error("Erreur lors de la récupération des entrepreneurs :", error);
} }
}; };
// Fonction de simulation de l'API type Entrepreneur = {
const mockFetchEntrepreneurs = async (projectId: number) => { idUser: number;
console.log(`Mock fetch pour projectId: ${projectId}`); userSurname: string;
userName: string;
primaryMail: string;
secondaryMail: string;
phoneNumber: string;
school: string;
course: string;
sneeStatus: boolean;
};
return new Promise((resolve) => { const mockFetchEntrepreneurs = async (projectId: number) => {
return new Promise<Entrepreneur[]>((resolve) => {
adnane marked this conversation as resolved Outdated
Outdated
Review

I don't love the fact that the mock tests are in the code here, it should be better to have a server. It's not a big probleme though

I don't love the fact that the mock tests are in the code here, it should be better to have a server. It's not a big probleme though
setTimeout(() => { setTimeout(() => {
resolve([ resolve([
{ {
@ -139,30 +147,18 @@ const mockFetchEntrepreneurs = async (projectId: number) => {
const contactAll = () => { const contactAll = () => {
const allEmails = entrepreneurEmails.value.join(", "); const allEmails = entrepreneurEmails.value.join(", ");
navigator.clipboard navigator.clipboard.writeText(allEmails).then(() => {
.writeText(allEmails) alert("Tous les emails copiés dans le presse-papiers !");
.then(() => { window.open("https://partage.bordeaux-inp.fr/", "_blank");
alert("Tous les emails copiés dans le presse-papiers !"); });
adnane marked this conversation as resolved Outdated
Outdated
Review

I personally hate that, can't we use an error mesage in green ?

I personally hate that, can't we use an error mesage in green ?

ok

ok
window.open("https://partage.bordeaux-inp.fr/", "_blank");
})
.catch((err) => {
console.error("Erreur lors de la copie :", err);
});
}; };
const contactSingle = (email: string) => { const contactSingle = (email: string) => {
navigator.clipboard navigator.clipboard.writeText(email).then(() => {
.writeText(email) alert(`Adresse copiée : ${email}`);
.then(() => { window.open("https://partage.bordeaux-inp.fr/", "_blank");
alert(`Adresse copiée : ${email}`); });
window.open("https://partage.bordeaux-inp.fr/", "_blank");
})
.catch((err) => {
console.error("Erreur lors de la copie :", err);
});
}; };
onMounted(() => fetchEntrepreneurs(props.projectId, IS_MOCK_MODE));
</script> </script>
<style scoped> <style scoped>
@ -246,4 +242,37 @@ button {
button:hover { button:hover {
background-color: #0056b3; background-color: #0056b3;
} }
.dropdown-wrapper {
position: relative;
}
.dropdown-menu {
position: absolute;
top: 100%; /* juste en dessous du bouton */
right: 0;
background-color: white;
border: 1px solid #ccc;
padding: 0.5rem;
z-index: 1000;
display: flex;
flex-direction: column;
gap: 0.5rem;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
border-radius: 0.25rem;
min-width: 150px;
}
.dropdown-menu button {
text-align: left;
padding: 0.3rem 0.5rem;
background: none;
border: none;
cursor: pointer;
transition: background-color 0.2s;
}
.dropdown-menu button:hover {
background-color: #f0f0f0;
}
</style> </style>

View File

@ -1,36 +1,38 @@
<template> <template>
adnane marked this conversation as resolved
Review

Doesn't this header overlap with the main app canvas ?

Doesn't this header overlap with the main app canvas ?
<header class="header"> <header class="header">
<img src="../icons/logo inpulse.png" alt="INPulse Logo" class="logo" /> <img src="../icons/logo inpulse.png" alt="INPulse Logo" class="logo" />
<div class="header-actions"> <div class="header-actions">
<div class="dropdown-wrapper"> <div class="dropdown-wrapper" ref="dropdownRef">
<button class="contact-button" @click="toggleDropdown"> <button class="contact-button" @click.stop="toggleDropdown">
Contact Contact
</button> </button>
<div <div
class="contact-dropdown" class="contact-dropdown"
:class="{ 'dropdown-visible': isDropdownOpen }" :class="{ 'dropdown-visible': isDropdownOpen }"
> >
<button @click="contactAll">Contacter tous</button> <button @click="contactAll">Contacter tous</button>
<button <button
v-for="(email, index) in entrepreneurEmails" v-for="(email, index) in entrepreneurEmails"
:key="index" :key="index"
@click="contactSingle(email)" @click="contactSingle(email)"
> >
{{ email }} {{ email }}
</button> </button>
</div>
</div>
<RouterLink to="/" class="return-button">Retour</RouterLink>
</div> </div>
</header> </div>
<RouterLink to="/" class="return-button">Retour</RouterLink>
</div>
</header>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted } from "vue"; import { ref, onMounted, onBeforeUnmount } from "vue";
adnane marked this conversation as resolved Outdated
Outdated
Review

I won't talk again about axios

I won't talk again about axios
import axios from "axios"; import axios from "axios";
const IS_MOCK_MODE = true; const IS_MOCK_MODE = true;
const dropdownRef = ref<HTMLElement | null>(null); // ref pour le dropdown
const props = defineProps<{ const props = defineProps<{
projectId: number; projectId: number;
@ -153,7 +155,27 @@ const copyToClipboard = (email: string) => {
}; };
*/ */
onMounted(() => fetchEntrepreneurs(props.projectId, IS_MOCK_MODE)); // Cacher le menu si on clique en dehors
const handleClickOutside = (event: MouseEvent) => {
if (
isDropdownOpen.value &&
dropdownRef.value &&
!dropdownRef.value.contains(event.target as Node)
) {
isDropdownOpen.value = false;
}
};
onMounted(() => {
fetchEntrepreneurs(props.projectId, IS_MOCK_MODE);
document.addEventListener("click", handleClickOutside);
});
onBeforeUnmount(() => {
document.removeEventListener("click", handleClickOutside);
});
</script> </script>
<style scoped> <style scoped>