feat: enhancing visuals
Some checks failed
Format / formatting (push) Successful in 5s
Build / build (push) Successful in 38s
CI / build (push) Failing after 8s
Format / formatting (pull_request) Successful in 5s

This commit is contained in:
ALAMI Adnane 2025-04-09 00:05:15 +02:00
parent 2dfee66958
commit 647812576e
3 changed files with 133 additions and 58 deletions

View File

@ -7,8 +7,8 @@ import ErrorWrapper from "@/views/errorWrapper.vue";
<Header />
<ErrorWrapper />
<RouterLink to="/">Home</RouterLink> |
<RouterLink to="/canvas">Canvas</RouterLink>
<!--<RouterLink to="/">Home</RouterLink> | -->
<!--<RouterLink to="/canvas">Canvas</RouterLink> -->
<RouterView />
</template>

View File

@ -35,9 +35,12 @@
</template>
</template>
</div>
<!---------------------------------------------------------------------------------------------------->
<template v-if="expanded">
<div class="canvas-exit-hint">
Cliquez n'importe pour quitter le canvas
</div>
</template>
</div>
</template>
@ -107,9 +110,9 @@ const mockFetch = async (projectId: number, title: number, date: string) => {
return new Promise<{ txt: string }[]>((resolve) => {
setTimeout(() => {
resolve([
{ txt: "Ceci est une description 1 pour tester the damn front, Why are u still reading dumbass this is just some nonsense sentence XD" },
{ txt: "Ceci est une description 1 pour tester the damn front, Bruh are u still here?" },
{ txt: "Ceci est une description 1 pour tester the damn front, .-. BRUH" }
{txt: "Ceci est une description 1 pour tester le front. Franchement, si tu es encore en train de lire, cest probablement que tu veux t'assurer que tout saffiche bien même avec un texte bien long. Allez, encore quelques mots inutiles pour bien remplir la ligne et tester les retours à la ligne. Bravo champion."},
{txt: "Deuxième description : elle est là pour taider à tester le comportement du composant avec du texte plus dense. Peut-être même avec quelques caractères spéciaux, tiens : éèàçù$#@! Et si on faisait semblant davoir du contenu sérieux ? Non, toujours pas."},
{txt: "Troisième description, probablement inutile mais bon, on continue pour la forme. À ce stade, tu testes sûrement si le champ de texte peut supporter un pavé sans exploser. Spoiler alert : si t'as tout bien codé, ça devrait aller. Sinon, bah... débogue. Courage."}
]);
}, 500); // Simule un délai réseau de 500ms
});
@ -118,7 +121,7 @@ const mockFetch = async (projectId: number, title: number, date: string) => {
// Utilisation du mock dans handleClick pour tester sans serveur
const handleClick = async () => {
if (!expanded.value) {
await fetchData(props.projectId, props.title, "NaN", IS_MOCK_MODE); // true pour activer le mock
await fetchData(props.projectId, props.title, "NaN", IS_MOCK_MODE);
} else if (!isEditing.value.includes(true)) {
// Réinitialiser les descriptions si aucune édition n'est en cours
currentDescriptions.value = [props.description];
@ -152,7 +155,6 @@ const saveEdit = async (index: number) => {
};
*/
// Utilisation de `mockSaveEdit` au lieu de `saveEdit` dans `handleClick` ou tout autre endroit
const saveEdit = async (index: number) => {
if (IS_MOCK_MODE) {
await mockSaveEdit(index);
@ -175,10 +177,9 @@ const saveEdit = async (index: number) => {
// Fonction de mock pour l'enregistrement
const mockSaveEdit = async (index: number) => {
try {
const id = index + 1; // À adapter selon l'ID réel des données
const id = index + 1;
console.log(`Mock save pour l'ID ${id} avec la description : ${editedDescriptions.value[index]}`);
// Simuler un délai d'enregistrement comme une requête réseau
await new Promise((resolve) => setTimeout(resolve, 500)); // Simulation de délai réseau
// Mettre à jour l'affichage local après la mise à jour réussie
@ -198,6 +199,9 @@ const cancelEdit = (index: number) => {
<style scoped>
@import "@/components/canvas/style-project.css";
#marque {
}
.cell {
display: flex;
flex-direction: column;
@ -221,7 +225,6 @@ const cancelEdit = (index: number) => {
.cell h3 {
font-size: 20px;
font-weight: 500;
/*margin-bottom: 10px;*/
}
.cell p {
@ -247,9 +250,9 @@ const cancelEdit = (index: number) => {
.description {
display: flex;
align-items: center; /* Centre verticalement */
justify-content: center; /* Centre horizontalement */
text-align: center; /* Centre le texte à l'intérieur */
align-items: center;
justify-content: center;
text-align: center;
width: 100%;
height: 100%;
font-size: 16px;
@ -344,4 +347,15 @@ const cancelEdit = (index: number) => {
background-color: #c82333;
}
.canvas-exit-hint {
font-size: 0.75rem;
color: #666;
position: fixed;
bottom: 10px;
left: 0;
width: 100%;
text-align: center;
z-index: 1000;
}
</style>

View File

@ -1,19 +1,19 @@
<template>
<header>
<img src="../icons/logo inpulse.png" alt="INPulse Logo">
<div class="header-buttons">
<div class="menu">
<header class="header">
<img src="../icons/logo inpulse.png" alt="INPulse Logo" class="logo" />
<div class="header-actions">
<div class="dropdown-wrapper">
<button class="contact-button" @click="toggleDropdown">Contact</button>
<div class="contact-dropdown" v-bind:class="{ 'dropdown-visible': isDropdownOpen }">
<button @click="contactAll">Contact All</button>
<div class="contact-dropdown" :class="{ 'dropdown-visible': isDropdownOpen }">
<button @click="contactAll">Contacter tous</button>
<button v-for="(email, index) in entrepreneurEmails" :key="index">
{{ email }}
</button>
</div>
<button class="return-button">
<RouterLink to="/">Return to list project</RouterLink>
</button>
</div>
<RouterLink to="/" class="return-button">Retour</RouterLink>
</div>
</header>
</template>
@ -23,76 +23,138 @@
import { ref, onMounted } from "vue";
import axios from "axios";
const IS_MOCK_MODE = true;
const props = defineProps<{
projectId: number;
}>();
type Entrepreneur = {
id: number;
name: string;
primaryMail: string;
};
const isDropdownOpen = ref(false);
const entrepreneurEmails = ref([]);
const toggleDropdown = () => {
isDropdownOpen.value = !isDropdownOpen.value;
console.log("Dropdown toggled:", isDropdownOpen.value); // for debug purposes
console.log("Dropdown toggled:", isDropdownOpen.value);
};
const fetchEntrepreneurs = async () => {
const fetchEntrepreneurs = async (projectId :number, useMock = IS_MOCK_MODE) => {
try {
const response = await axios.get("http://localhost:5000/entrepreneurs");
entrepreneurEmails.value = response.data.map((e: { email: string }) => e.email);
const responseData = useMock
? await mockFetchEntrepreneurs(projectId)
: (await axios.get(`http://localhost:5000/shared/projects/entrepreneurs/${projectId}`)).data;
if (responseData.length > 0) {
entrepreneurEmails.value = responseData.map((item) => item.primaryMail);
} else {
console.warn("Aucun entrepreneur trouvé.");
}
} catch (error) {
console.error("Erreur lors de la récupération des entrepreneurs:", error);
console.error("Erreur lors de la récupération des entrepreneurs :", error);
}
};
// Fonction de simulation de l'API
const mockFetchEntrepreneurs = async (projectId :number) => {
console.log(`Mock fetch pour projectId: ${projectId}`);
return new Promise((resolve) => {
setTimeout(() => {
resolve([
{
idUser: 1,
userSurname: "Doe",
userName: "John",
primaryMail: "john.doe@example.com",
secondaryMail: "johndoe@backup.com",
phoneNumber: "612345678",
school: "ENSEIRB",
course: "Info",
sneeStatus: false
},
{
idUser: 2,
userSurname: "Smith",
userName: "Jane",
primaryMail: "jane.smith@example.com",
secondaryMail: "janesmith@backup.com",
phoneNumber: "698765432",
school: "ENSEIRB",
course: "Info",
sneeStatus: true
}
]);
}, 500);
});
};
const contactAll = () => {
alert("Contacter tous les entrepreneurs : " + entrepreneurEmails.value.join(", "));
};
onMounted(fetchEntrepreneurs);
onMounted(() => fetchEntrepreneurs(props.projectId, IS_MOCK_MODE));
</script>
<style scoped>
@import "@/components/canvas/style-project.css";
header {
.header {
display: flex;
justify-content: space-between;
align-items: flex-start;
padding: 10px;
align-items: center;
padding: 15px 30px;
background-color: #f9f9f9;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.header-buttons {
.logo {
height: 50px;
}
.header-actions {
display: flex;
align-items: flex-start;
align-items: center;
gap: 20px;
position: relative;
}
.menu {
display: flex;
flex-direction: column;
gap: 10px;
}
.contact-button, .return-button {
background-color: #000;
.contact-button,
.return-button {
background-color: #009CDE;
color: white;
border: none;
padding: 10px;
padding: 10px 15px;
cursor: pointer;
font-size: 14px;
text-align: center;
border-radius: 5px;
text-decoration: none;
transition: background-color 0.2s ease;
}
.return-button a {
color: white;
text-decoration: none;
.return-button:hover,
.contact-button:hover {
background-color: #007bad;
}
.contact-dropdown {
display: none;
position: absolute;
background-color: white;
box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.2);
top: 100%;
left: 0;
background-color: #000;
color: white;
box-shadow: 0px 4px 8px rgba(255, 255, 255, 0.2);
border-radius: 8px;
padding: 10px;
margin-top: 5px;
z-index: 1000;
min-width: 200px;
display: none;
}
.contact-dropdown button {
@ -103,18 +165,17 @@ header {
border: none;
background: none;
cursor: pointer;
color: white;
}
.contact-dropdown button:hover {
background-color: #f0f0f0;
background-color: #009CDE;
}
.dropdown-visible {
.contact-dropdown.dropdown-visible {
display: block;
}
header img {
width: 100px;
height: auto;
}
</style>