fix: with prettier
Some checks failed
Format / formatting (push) Successful in 6s
Build / build (push) Successful in 42s
CI / build (push) Failing after 10s
Format / formatting (pull_request) Successful in 5s

This commit is contained in:
Mohamed Maoulainine Maoulainine 2025-04-21 19:01:15 +02:00
parent e20556ed0f
commit c60fb8945b
17 changed files with 1414 additions and 1286 deletions

View File

@ -1,16 +1,12 @@
<script setup lang="ts"> <script setup lang="ts">
import { /*RouterLink,*/ RouterView } from 'vue-router' import { /*RouterLink,*/ RouterView } from "vue-router";
import ErrorWrapper from "@/views/errorWrapper.vue"; import ErrorWrapper from "@/views/errorWrapper.vue";
</script> </script>
<template> <template>
<Header /> <Header />
<ErrorWrapper /> <ErrorWrapper />
<!--<RouterLink to="/">Home</RouterLink> | --> <!--<RouterLink to="/">Home</RouterLink> | -->
<!--<RouterLink to="/canvas">Canvas</RouterLink> --> <!--<RouterLink to="/canvas">Canvas</RouterLink> -->
<RouterView /> <RouterView />
</template> </template>

View File

@ -53,7 +53,6 @@
</script> </script>
<style scoped> <style scoped>
h2 { h2 {
font-size: 1.5rem; font-size: 1.5rem;
color: #333; color: #333;
@ -107,4 +106,3 @@
background-color: #45a049; background-color: #45a049;
} }
</style> </style>

View File

@ -17,7 +17,6 @@
</tr> </tr>
</tbody> </tbody>
</table> </table>
</div> </div>
</template> </template>
@ -25,19 +24,17 @@
import { defineProps } from "vue"; import { defineProps } from "vue";
interface rendezVous { interface rendezVous {
projectName: string, projectName: string;
date: string, date: string;
lieu: string, lieu: string;
} }
defineProps<{ defineProps<{
projectRDV: rendezVous[] projectRDV: rendezVous[];
}>(); }>();
</script> </script>
<style scoped> <style scoped>
h3 { h3 {
font-size: 1.5rem; font-size: 1.5rem;
color: #333; color: #333;
@ -53,7 +50,6 @@
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05); box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
} }
/* Table Styling */ /* Table Styling */
table { table {
width: 100%; width: 100%;
@ -71,7 +67,6 @@
color: #333; color: #333;
} }
/* Table Body Rows */ /* Table Body Rows */
tbody tr { tbody tr {
border-bottom: 1px solid #ddd; border-bottom: 1px solid #ddd;
@ -95,5 +90,4 @@
text-align: center; text-align: center;
width: 50px; /* Adjust width as needed */ width: 50px; /* Adjust width as needed */
} }
</style> </style>

View File

@ -13,7 +13,7 @@ type TokenPayload = {
}; };
}; };
const customRequest = ref(''); const customRequest = ref("");
onMounted(() => { onMounted(() => {
if (store.authenticated && store.user.token) { if (store.authenticated && store.user.token) {
@ -40,19 +40,24 @@ const callApiWithLoading = async (path: string) => {
loading.value = false; loading.value = false;
}; };
*/ */
</script> </script>
<template> <template>
<error-wrapper></error-wrapper> <error-wrapper></error-wrapper>
<div class="auth-container"> <div class="auth-container">
<div class="auth-card"> <div class="auth-card">
<h1>Bienvenue</h1> <h1>Bienvenue</h1>
<div class="status" :class="store.authenticated ? 'success' : 'error'"> <div
class="status"
:class="store.authenticated ? 'success' : 'error'"
>
<p> <p>
{{ store.authenticated ? '✅ Authenticated' : '❌ Not Authenticated' }} {{
store.authenticated
? "✅ Authenticated"
: "❌ Not Authenticated"
}}
</p> </p>
</div> </div>
@ -74,12 +79,17 @@ const callApiWithLoading = async (path: string) => {
<div class="api-calls"> <div class="api-calls">
<h2>Test API Calls</h2> <h2>Test API Calls</h2>
<button @click="callApi('random')">Call Entrepreneur API</button> <button @click="callApi('random')">
Call Entrepreneur API
</button>
<button @click="callApi('random2')">Call Admin API</button> <button @click="callApi('random2')">Call Admin API</button>
<button @click="callApi('unauth/dev')">Call Unauth API</button> <button @click="callApi('unauth/dev')">Call Unauth API</button>
<div class="custom-call"> <div class="custom-call">
<input v-model="customRequest" placeholder="Custom endpoint" /> <input
v-model="customRequest"
placeholder="Custom endpoint"
/>
<button @click="callApi(customRequest)">Call</button> <button @click="callApi(customRequest)">Call</button>
</div> </div>
</div> </div>
@ -193,6 +203,4 @@ h1 {
background-color: #ffe2e2; background-color: #ffe2e2;
color: #c62828; color: #c62828;
} }
</style> </style>

View File

@ -11,11 +11,8 @@
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { defineProps } from "vue"; import { defineProps } from "vue";
import { postApi } from "@/services/api"; import { postApi } from "@/services/api";
@ -52,8 +49,6 @@ const acceptProject = () => sendDecision("true");
const refuseProject = () => sendDecision("false"); const refuseProject = () => sendDecision("false");
</script> </script>
<style scoped> <style scoped>
.project { .project {
background: linear-gradient(to right, #f8f9fb, #ffffff); background: linear-gradient(to right, #f8f9fb, #ffffff);
@ -109,11 +104,13 @@ button {
font-size: 0.9rem; font-size: 0.9rem;
font-weight: 500; font-weight: 500;
cursor: pointer; cursor: pointer;
transition: background-color 0.2s ease, transform 0.2s ease; transition:
background-color 0.2s ease,
transform 0.2s ease;
} }
#accept { #accept {
background-color: #4CAF50; background-color: #4caf50;
} }
#accept:hover { #accept:hover {
@ -129,5 +126,4 @@ button {
background-color: #c0392b; background-color: #c0392b;
transform: translateY(-2px); transform: translateY(-2px);
} }
</style> </style>

View File

@ -4,8 +4,13 @@
<h2>{{ projectName }}</h2> <h2>{{ projectName }}</h2>
<div class="header-actions"> <div class="header-actions">
<div class="dropdown-wrapper"> <div class="dropdown-wrapper">
<button class="contact-button" @click="toggleDropdown">Contact</button> <button class="contact-button" @click="toggleDropdown">
<div class="contact-dropdown" :class="{ 'dropdown-visible': isDropdownOpen }"> Contact
</button>
<div
class="contact-dropdown"
: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"
@ -17,21 +22,20 @@
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="project-body"> <div class="project-body">
<ul> <ul>
<li v-for="(name, index) in listName" :key="index">{{ name }}</li> <li v-for="(name, index) in listName" :key="index">
{{ name }}
</li>
</ul> </ul>
</div> </div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { defineProps } from "vue"; import { defineProps } from "vue";
import { useRouter } from 'vue-router' import { useRouter } from "vue-router";
import { ref, onMounted } from "vue"; import { ref, onMounted } from "vue";
import axios from "axios"; import axios from "axios";
const IS_MOCK_MODE = true; const IS_MOCK_MODE = true;
@ -49,7 +53,6 @@ const goToLink = () => {
if (props.projectLink) { if (props.projectLink) {
router.push(props.projectLink); router.push(props.projectLink);
} }
}; };
type Entrepreneur = { type Entrepreneur = {
@ -72,19 +75,31 @@ const toggleDropdown = () => {
console.log("Dropdown toggled:", isDropdownOpen.value); console.log("Dropdown toggled:", isDropdownOpen.value);
}; };
const fetchEntrepreneurs = async (projectId: number, useMock = IS_MOCK_MODE) => { const fetchEntrepreneurs = async (
projectId: number,
useMock = IS_MOCK_MODE
) => {
try { try {
const responseData: Entrepreneur[] = useMock const responseData: Entrepreneur[] = useMock
? await mockFetchEntrepreneurs(projectId) ? await mockFetchEntrepreneurs(projectId)
: (await axios.get(`http://localhost:5000/shared/projects/entrepreneurs/${projectId}`)).data; : (
await axios.get(
`http://localhost:5000/shared/projects/entrepreneurs/${projectId}`
)
).data;
if (responseData.length > 0) { if (responseData.length > 0) {
entrepreneurEmails.value = responseData.map((item: Entrepreneur) => item.primaryMail); entrepreneurEmails.value = responseData.map(
(item: Entrepreneur) => item.primaryMail
);
} else { } else {
console.warn("Aucun entrepreneur trouvé."); console.warn("Aucun entrepreneur trouvé.");
} }
} catch (error) { } 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
);
} }
}; };
@ -104,7 +119,7 @@ const mockFetchEntrepreneurs = async (projectId :number) => {
phoneNumber: "612345678", phoneNumber: "612345678",
school: "ENSEIRB", school: "ENSEIRB",
course: "Info", course: "Info",
sneeStatus: false sneeStatus: false,
}, },
{ {
idUser: 2, idUser: 2,
@ -115,8 +130,8 @@ const mockFetchEntrepreneurs = async (projectId :number) => {
phoneNumber: "698765432", phoneNumber: "698765432",
school: "ENSEIRB", school: "ENSEIRB",
course: "Info", course: "Info",
sneeStatus: true sneeStatus: true,
} },
]); ]);
}, 500); }, 500);
}); });
@ -124,23 +139,25 @@ const mockFetchEntrepreneurs = async (projectId :number) => {
const contactAll = () => { const contactAll = () => {
const allEmails = entrepreneurEmails.value.join(", "); const allEmails = entrepreneurEmails.value.join(", ");
navigator.clipboard.writeText(allEmails) navigator.clipboard
.writeText(allEmails)
.then(() => { .then(() => {
alert("Tous les emails copiés dans le presse-papiers !"); alert("Tous les emails copiés dans le presse-papiers !");
window.open("https://partage.bordeaux-inp.fr/", "_blank"); window.open("https://partage.bordeaux-inp.fr/", "_blank");
}) })
.catch(err => { .catch((err) => {
console.error("Erreur lors de la copie :", err); console.error("Erreur lors de la copie :", err);
}); });
}; };
const contactSingle = (email: string) => { const contactSingle = (email: string) => {
navigator.clipboard.writeText(email) navigator.clipboard
.writeText(email)
.then(() => { .then(() => {
alert(`Adresse copiée : ${email}`); alert(`Adresse copiée : ${email}`);
window.open("https://partage.bordeaux-inp.fr/", "_blank"); window.open("https://partage.bordeaux-inp.fr/", "_blank");
}) })
.catch(err => { .catch((err) => {
console.error("Erreur lors de la copie :", err); console.error("Erreur lors de la copie :", err);
}); });
}; };
@ -148,7 +165,6 @@ const contactSingle = (email: string) => {
onMounted(() => fetchEntrepreneurs(props.projectId, IS_MOCK_MODE)); onMounted(() => fetchEntrepreneurs(props.projectId, IS_MOCK_MODE));
</script> </script>
<style scoped> <style scoped>
.project { .project {
background: linear-gradient(to right, #f8f9fb, #ffffff); background: linear-gradient(to right, #f8f9fb, #ffffff);
@ -193,7 +209,9 @@ onMounted(() => fetchEntrepreneurs(props.projectId, IS_MOCK_MODE));
border-radius: 8px; border-radius: 8px;
font-size: 0.9rem; font-size: 0.9rem;
font-weight: 500; font-weight: 500;
transition: background-color 0.2s ease, transform 0.2s ease; transition:
background-color 0.2s ease,
transform 0.2s ease;
} }
.contact-btn:hover { .contact-btn:hover {
@ -217,7 +235,6 @@ onMounted(() => fetchEntrepreneurs(props.projectId, IS_MOCK_MODE));
line-height: 1.6; line-height: 1.6;
} }
button { button {
padding: 10px 15px; padding: 10px 15px;
background-color: #007bff; background-color: #007bff;
@ -229,5 +246,4 @@ onMounted(() => fetchEntrepreneurs(props.projectId, IS_MOCK_MODE));
button:hover { button:hover {
background-color: #0056b3; background-color: #0056b3;
} }
</style> </style>

View File

@ -2,8 +2,11 @@
<div :class="['cell', { expanded }]" @click="handleClick"> <div :class="['cell', { expanded }]" @click="handleClick">
<h3 class="fs-5 fw-medium">{{ titleText }}</h3> <h3 class="fs-5 fw-medium">{{ titleText }}</h3>
<div v-for="(desc, index) in currentDescriptions" :key="index" class="section-bloc"> <div
v-for="(desc, index) in currentDescriptions"
:key="index"
class="section-bloc"
>
<!-- ADMIN --------------------------------------------------------------------------------------------> <!-- ADMIN -------------------------------------------------------------------------------------------->
<template v-if="IS_ADMIN"> <template v-if="IS_ADMIN">
@ -21,16 +24,35 @@
<p class="m-0">{{ desc }}</p> <p class="m-0">{{ desc }}</p>
</div> </div>
<div class="button-container"> <div class="button-container">
<button v-if="expanded" class="edit-button" @click.stop="startEditing(index)">Éditer</button> <button
v-if="expanded"
class="edit-button"
@click.stop="startEditing(index)"
>
Éditer
</button>
</div> </div>
</template> </template>
<!-- Mode édition --> <!-- Mode édition -->
<template v-else> <template v-else>
<textarea v-model="editedDescriptions[index]" class="edit-input"></textarea> <textarea
v-model="editedDescriptions[index]"
class="edit-input"
></textarea>
<div class="button-container"> <div class="button-container">
<button class="save-button" @click.stop="saveEdit(index)">Enregistrer</button> <button
<button class="cancel-button" @click.stop="cancelEdit(index)">Annuler</button> class="save-button"
@click.stop="saveEdit(index)"
>
Enregistrer
</button>
<button
class="cancel-button"
@click.stop="cancelEdit(index)"
>
Annuler
</button>
</div> </div>
</template> </template>
</template> </template>
@ -71,7 +93,6 @@ onMounted(() => {
fetchData(props.projectId, props.title, "NaN", IS_MOCK_MODE); fetchData(props.projectId, props.title, "NaN", IS_MOCK_MODE);
}); });
/* FOR LOCAL DATABASE /* FOR LOCAL DATABASE
const fetchData = async () => { const fetchData = async () => {
try { try {
@ -111,13 +132,20 @@ const fetchData = async (projectId: number, title: number, date: string, useMock
*/ */
// Fonction fetchData avec possibilité d'utiliser le mock // Fonction fetchData avec possibilité d'utiliser le mock
const fetchData = async (projectId: number, title: number, date: string, useMock = false) => { const fetchData = async (
projectId: number,
title: number,
date: string,
useMock = false
) => {
try { try {
const responseData = useMock const responseData = useMock
? await mockFetch(projectId, title, date) ? await mockFetch(projectId, title, date)
: (await axiosInstance.get<{ txt: string }[]>( : (
await axiosInstance.get<{ txt: string }[]>(
`/shared/projects/lcsection/${projectId}/${title}/${date}` `/shared/projects/lcsection/${projectId}/${title}/${date}`
)).data; )
).data;
if (responseData.length > 0) { if (responseData.length > 0) {
currentDescriptions.value = responseData.map((item) => item.txt); currentDescriptions.value = responseData.map((item) => item.txt);
@ -133,14 +161,16 @@ const fetchData = async (projectId: number, title: number, date: string, useMock
// Fonction de simulation de l'API // Fonction de simulation de l'API
const mockFetch = async (projectId: number, title: number, date: string) => { const mockFetch = async (projectId: number, title: number, date: string) => {
console.log(`Mock fetch pour projectId: ${projectId}, title: ${title}, date: ${date}`); console.log(
`Mock fetch pour projectId: ${projectId}, title: ${title}, date: ${date}`
);
return new Promise<{ txt: string }[]>((resolve) => { return new Promise<{ txt: string }[]>((resolve) => {
setTimeout(() => { setTimeout(() => {
resolve([ resolve([
{ txt: "Ceci est une description 1 pour tester le front." }, { txt: "Ceci est une description 1 pour tester le front." },
{ txt: "Deuxième description." }, { txt: "Deuxième description." },
{txt: "Troisième description."} { txt: "Troisième description." },
]); ]);
}, 500); // Simule un délai réseau de 500ms }, 500); // Simule un délai réseau de 500ms
}); });
@ -161,7 +191,6 @@ const handleClick = async () => {
} }
}; };
const startEditing = (index: number) => { const startEditing = (index: number) => {
isEditing.value[index] = true; isEditing.value[index] = true;
}; };
@ -190,7 +219,7 @@ const saveEdit = async (index: number) => {
try { try {
const id = index + 1; const id = index + 1;
await axios.put(`http://localhost:5000/data/${id}`, { await axios.put(`http://localhost:5000/data/${id}`, {
canva_data: editedDescriptions.value[index] canva_data: editedDescriptions.value[index],
}); });
// Mettre à jour l'affichage local après la mise à jour réussie // Mettre à jour l'affichage local après la mise à jour réussie
@ -206,7 +235,9 @@ const saveEdit = async (index: number) => {
const mockSaveEdit = async (index: number) => { const mockSaveEdit = async (index: number) => {
try { try {
const id = index + 1; const id = index + 1;
console.log(`Mock save pour l'ID ${id} avec la description : ${editedDescriptions.value[index]}`); console.log(
`Mock save pour l'ID ${id} avec la description : ${editedDescriptions.value[index]}`
);
await new Promise((resolve) => setTimeout(resolve, 500)); // Simulation de délai réseau await new Promise((resolve) => setTimeout(resolve, 500)); // Simulation de délai réseau
@ -214,7 +245,10 @@ const mockSaveEdit = async (index: number) => {
currentDescriptions.value[index] = editedDescriptions.value[index]; currentDescriptions.value[index] = editedDescriptions.value[index];
isEditing.value[index] = false; isEditing.value[index] = false;
} catch (error) { } catch (error) {
console.error("Erreur lors de la mise à jour des données mockées :", error); console.error(
"Erreur lors de la mise à jour des données mockées :",
error
);
} }
}; };
@ -227,7 +261,6 @@ const cancelEdit = (index: number) => {
<style scoped> <style scoped>
@import "@/components/canvas/style-project.css"; @import "@/components/canvas/style-project.css";
.cell { .cell {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -239,7 +272,6 @@ const cancelEdit = (index: number) => {
box-shadow: 0 4px 5px rgba(0, 0, 0, 0.1); box-shadow: 0 4px 5px rgba(0, 0, 0, 0.1);
} }
.expanded-content { .expanded-content {
justify-content: flex-start !important; justify-content: flex-start !important;
} }
@ -252,13 +284,13 @@ const cancelEdit = (index: number) => {
.cell h3 { .cell h3 {
font-size: 15px; font-size: 15px;
font-weight: 500; font-weight: 500;
font-family: 'Arial', sans-serif; font-family: "Arial", sans-serif;
} }
.p { .p {
font-size: 10px; font-size: 10px;
color: #666; color: #666;
font-family: 'Arial', sans-serif; font-family: "Arial", sans-serif;
} }
.expanded { .expanded {
@ -276,7 +308,6 @@ const cancelEdit = (index: number) => {
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
} }
.description { .description {
display: flex; display: flex;
align-items: center; align-items: center;
@ -296,8 +327,6 @@ const cancelEdit = (index: number) => {
text-align: center; text-align: center;
} }
.edit-input { .edit-input {
width: 100%; width: 100%;
height: 100%; height: 100%;
@ -309,7 +338,6 @@ const cancelEdit = (index: number) => {
margin-left: 2%; margin-left: 2%;
} }
.button-container { .button-container {
display: block; display: block;
margin-top: 20px; margin-top: 20px;
@ -319,8 +347,8 @@ const cancelEdit = (index: number) => {
padding-right: 1%; padding-right: 1%;
} }
.section-bloc,
.section-bloc ,.editing-section-bloc { .editing-section-bloc {
width: 100%; width: 100%;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
@ -329,10 +357,6 @@ const cancelEdit = (index: number) => {
margin: 10px; margin: 10px;
} }
.edit-button { .edit-button {
width: 100px; width: 100px;
height: 40px; height: 40px;
@ -344,7 +368,8 @@ const cancelEdit = (index: number) => {
margin-right: 20px; margin-right: 20px;
} }
.save-button, .cancel-button { .save-button,
.cancel-button {
width: 100px; width: 100px;
height: 40px; height: 40px;
border: none; border: none;
@ -392,5 +417,4 @@ const cancelEdit = (index: number) => {
text-align: center; text-align: center;
z-index: 1000; z-index: 1000;
} }
</style> </style>

View File

@ -4,8 +4,13 @@
<div class="header-actions"> <div class="header-actions">
<div class="dropdown-wrapper"> <div class="dropdown-wrapper">
<button class="contact-button" @click="toggleDropdown">Contact</button> <button class="contact-button" @click="toggleDropdown">
<div class="contact-dropdown" :class="{ 'dropdown-visible': isDropdownOpen }"> Contact
</button>
<div
class="contact-dropdown"
: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"
@ -21,7 +26,6 @@
</header> </header>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted } from "vue"; import { ref, onMounted } from "vue";
import axios from "axios"; import axios from "axios";
@ -52,19 +56,31 @@ const toggleDropdown = () => {
console.log("Dropdown toggled:", isDropdownOpen.value); console.log("Dropdown toggled:", isDropdownOpen.value);
}; };
const fetchEntrepreneurs = async (projectId: number, useMock = IS_MOCK_MODE) => { const fetchEntrepreneurs = async (
projectId: number,
useMock = IS_MOCK_MODE
) => {
try { try {
const responseData: Entrepreneur[] = useMock const responseData: Entrepreneur[] = useMock
? await mockFetchEntrepreneurs(projectId) ? await mockFetchEntrepreneurs(projectId)
: (await axios.get(`http://localhost:5000/shared/projects/entrepreneurs/${projectId}`)).data; : (
await axios.get(
`http://localhost:5000/shared/projects/entrepreneurs/${projectId}`
)
).data;
if (responseData.length > 0) { if (responseData.length > 0) {
entrepreneurEmails.value = responseData.map((item: Entrepreneur) => item.primaryMail); entrepreneurEmails.value = responseData.map(
(item: Entrepreneur) => item.primaryMail
);
} else { } else {
console.warn("Aucun entrepreneur trouvé."); console.warn("Aucun entrepreneur trouvé.");
} }
} catch (error) { } 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
);
} }
}; };
@ -84,7 +100,7 @@ const mockFetchEntrepreneurs = async (projectId :number) => {
phoneNumber: "612345678", phoneNumber: "612345678",
school: "ENSEIRB", school: "ENSEIRB",
course: "Info", course: "Info",
sneeStatus: false sneeStatus: false,
}, },
{ {
idUser: 2, idUser: 2,
@ -95,8 +111,8 @@ const mockFetchEntrepreneurs = async (projectId :number) => {
phoneNumber: "698765432", phoneNumber: "698765432",
school: "ENSEIRB", school: "ENSEIRB",
course: "Info", course: "Info",
sneeStatus: true sneeStatus: true,
} },
]); ]);
}, 500); }, 500);
}); });
@ -104,23 +120,25 @@ const mockFetchEntrepreneurs = async (projectId :number) => {
const contactAll = () => { const contactAll = () => {
const allEmails = entrepreneurEmails.value.join(", "); const allEmails = entrepreneurEmails.value.join(", ");
navigator.clipboard.writeText(allEmails) navigator.clipboard
.writeText(allEmails)
.then(() => { .then(() => {
alert("Tous les emails copiés dans le presse-papiers !"); alert("Tous les emails copiés dans le presse-papiers !");
window.open("https://partage.bordeaux-inp.fr/", "_blank"); window.open("https://partage.bordeaux-inp.fr/", "_blank");
}) })
.catch(err => { .catch((err) => {
console.error("Erreur lors de la copie :", err); console.error("Erreur lors de la copie :", err);
}); });
}; };
const contactSingle = (email: string) => { const contactSingle = (email: string) => {
navigator.clipboard.writeText(email) navigator.clipboard
.writeText(email)
.then(() => { .then(() => {
alert(`Adresse copiée : ${email}`); alert(`Adresse copiée : ${email}`);
window.open("https://partage.bordeaux-inp.fr/", "_blank"); window.open("https://partage.bordeaux-inp.fr/", "_blank");
}) })
.catch(err => { .catch((err) => {
console.error("Erreur lors de la copie :", err); console.error("Erreur lors de la copie :", err);
}); });
}; };
@ -163,7 +181,7 @@ onMounted(() => fetchEntrepreneurs(props.projectId, IS_MOCK_MODE));
.contact-button, .contact-button,
.return-button { .return-button {
background-color: #009CDE; background-color: #009cde;
color: white; color: white;
border: none; border: none;
padding: 10px 15px; padding: 10px 15px;
@ -180,7 +198,6 @@ onMounted(() => fetchEntrepreneurs(props.projectId, IS_MOCK_MODE));
background-color: #007bad; background-color: #007bad;
} }
.contact-dropdown { .contact-dropdown {
position: absolute; position: absolute;
top: 100%; top: 100%;
@ -208,12 +225,10 @@ onMounted(() => fetchEntrepreneurs(props.projectId, IS_MOCK_MODE));
} }
.contact-dropdown button:hover { .contact-dropdown button:hover {
background-color: #009CDE; background-color: #009cde;
} }
.contact-dropdown.dropdown-visible { .contact-dropdown.dropdown-visible {
display: block; display: block;
} }
</style> </style>

View File

@ -8,7 +8,7 @@
:description="item.description" :description="item.description"
:project-id="item.projectId" :project-id="item.projectId"
:class="['canvas-item', item.class, 'card', 'shadow', 'p-3']" :class="['canvas-item', item.class, 'card', 'shadow', 'p-3']"
:is-admin= props.isAdmin :is-admin="props.isAdmin"
/> />
</div> </div>
</template> </template>
@ -22,31 +22,89 @@ const props = defineProps<{
}>(); }>();
const items = ref([ const items = ref([
{ projectId: 1, title: 1, title_text: "1. Problème", description: "3 problèmes essentiels à résoudre pour le client", class: "Probleme" }, {
{ projectId: 1, title: 2, title_text: "2. Segments", description: "Les segments de clientèle visés", class: "Segments" }, projectId: 1,
{ projectId: 1, title: 3, title_text: "3. Valeur", description: "La proposition de valeur", class: "Valeur" }, title: 1,
{ projectId: 1, title: 4, title_text: "4. Solution", description: "Les solutions proposées", class: "Solution" }, title_text: "1. Problème",
{ projectId: 1, title: 5, title_text: "5. Avantage", description: "Les avantages concurrentiels", class: "Avantage" }, description: "3 problèmes essentiels à résoudre pour le client",
{ projectId: 1, title: 6, title_text: "6. Canaux", description: "Les canaux de distribution", class: "Canaux" }, class: "Probleme",
{ projectId: 1, title: 7, title_text: "7. Indicateurs", description: "Les indicateurs clés de performance", class: "Indicateurs" }, },
{ projectId: 1, title: 8, title_text: "8. Coûts", description: "Les coûts associés", class: "Couts" }, {
{ projectId: 1, title: 9, title_text: "9. Revenus", description: "Les sources de revenus", class: "Revenus" } projectId: 1,
title: 2,
title_text: "2. Segments",
description: "Les segments de clientèle visés",
class: "Segments",
},
{
projectId: 1,
title: 3,
title_text: "3. Valeur",
description: "La proposition de valeur",
class: "Valeur",
},
{
projectId: 1,
title: 4,
title_text: "4. Solution",
description: "Les solutions proposées",
class: "Solution",
},
{
projectId: 1,
title: 5,
title_text: "5. Avantage",
description: "Les avantages concurrentiels",
class: "Avantage",
},
{
projectId: 1,
title: 6,
title_text: "6. Canaux",
description: "Les canaux de distribution",
class: "Canaux",
},
{
projectId: 1,
title: 7,
title_text: "7. Indicateurs",
description: "Les indicateurs clés de performance",
class: "Indicateurs",
},
{
projectId: 1,
title: 8,
title_text: "8. Coûts",
description: "Les coûts associés",
class: "Couts",
},
{
projectId: 1,
title: 9,
title_text: "9. Revenus",
description: "Les sources de revenus",
class: "Revenus",
},
]); ]);
onMounted(() => { onMounted(() => {
const bootstrapCss = document.createElement('link') const bootstrapCss = document.createElement("link");
bootstrapCss.rel = 'stylesheet' bootstrapCss.rel = "stylesheet";
bootstrapCss.href = 'https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css' bootstrapCss.href =
bootstrapCss.integrity = 'sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+Fpc+NC' "https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css";
bootstrapCss.crossOrigin = 'anonymous' bootstrapCss.integrity =
document.head.appendChild(bootstrapCss) "sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+Fpc+NC";
bootstrapCss.crossOrigin = "anonymous";
document.head.appendChild(bootstrapCss);
const bootstrapJs = document.createElement('script') const bootstrapJs = document.createElement("script");
bootstrapJs.src = 'https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js' bootstrapJs.src =
bootstrapJs.integrity = 'sha384-mQ93S0EhrF4Z1nM+fTflmYf0DyzsY5j7F5H3WlClDD6H3WUJh6kxBkF3GDW8n1j6' "https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js";
bootstrapJs.crossOrigin = 'anonymous' bootstrapJs.integrity =
document.body.appendChild(bootstrapJs) "sha384-mQ93S0EhrF4Z1nM+fTflmYf0DyzsY5j7F5H3WlClDD6H3WUJh6kxBkF3GDW8n1j6";
}) bootstrapJs.crossOrigin = "anonymous";
document.body.appendChild(bootstrapJs);
});
</script> </script>
<style scoped> <style scoped>
@ -64,15 +122,42 @@ onMounted(() => {
overflow: auto; overflow: auto;
} }
.Probleme { grid-column: 1 / 3; grid-row: 1 / 5; } .Probleme {
.Segments { grid-column: 9 / 11; grid-row: 1 / 5; } grid-column: 1 / 3;
.Valeur { grid-column: 5 / 7; grid-row: 1 / 5; } grid-row: 1 / 5;
.Solution { grid-column: 3 / 5; grid-row: 1 / 3; } }
.Avantage { grid-column: 7 / 9; grid-row: 1 / 3; } .Segments {
.Canaux { grid-column: 7 / 9; grid-row: 3 / 5; } grid-column: 9 / 11;
.Indicateurs { grid-column: 3 / 5; grid-row: 3 / 5; } grid-row: 1 / 5;
.Couts { grid-column: 1 / 6; grid-row: 5 / 7; } }
.Revenus { grid-column: 6 / 11; grid-row: 5 / 7; } .Valeur {
grid-column: 5 / 7;
grid-row: 1 / 5;
}
.Solution {
grid-column: 3 / 5;
grid-row: 1 / 3;
}
.Avantage {
grid-column: 7 / 9;
grid-row: 1 / 3;
}
.Canaux {
grid-column: 7 / 9;
grid-row: 3 / 5;
}
.Indicateurs {
grid-column: 3 / 5;
grid-row: 3 / 5;
}
.Couts {
grid-column: 1 / 6;
grid-row: 5 / 7;
}
.Revenus {
grid-column: 6 / 11;
grid-row: 5 / 7;
}
.canvas-item { .canvas-item {
/*background-color: white;*/ /*background-color: white;*/

View File

@ -39,7 +39,6 @@ body {
font-size: 14px; font-size: 14px;
} }
body { body {
font-family: Arial, sans-serif; font-family: Arial, sans-serif;
margin: 0; margin: 0;
@ -94,7 +93,8 @@ body {
position: relative; position: relative;
} }
.contact-button, .return { .contact-button,
.return {
padding: 10px 15px; padding: 10px 15px;
border: none; border: none;
border-radius: 4px; border-radius: 4px;
@ -103,7 +103,8 @@ body {
cursor: pointer; cursor: pointer;
} }
.contact-button:hover, .return:hover { .contact-button:hover,
.return:hover {
background-color: #1976d2; background-color: #1976d2;
} }
@ -150,7 +151,6 @@ body {
gap: 15px; gap: 15px;
} }
a { a {
color: white; color: white;
} }

View File

@ -26,8 +26,7 @@ keycloakService.CallInit(() => {
console.error(e); console.error(e);
createApp(App).mount("#app"); createApp(App).mount("#app");
} }
});
})
// this shit made by me so i can run the canva vue app // this shit made by me so i can run the canva vue app
//createApp(App).use(router).mount('#app'); //createApp(App).use(router).mount('#app');
@ -71,7 +70,4 @@ app.use(VueKeyCloak,{
} ); } );
*/ */
export { store }; export { store };

View File

@ -4,43 +4,43 @@ const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL), history: createWebHistory(import.meta.env.BASE_URL),
routes: [ routes: [
{ {
path: '/test', path: "/test",
name: 'test', name: "test",
// route level code-splitting // route level code-splitting
// this generates a separate chunk (About.[hash].js) for this route // this generates a separate chunk (About.[hash].js) for this route
// which is lazy-loaded when the route is visited. // which is lazy-loaded when the route is visited.
component: () => import('../views/testComponent.vue'), component: () => import("../views/testComponent.vue"),
}, },
{ {
path: '/login', path: "/login",
name: 'login', name: "login",
component: () => import('../components/LoginComponent.vue'), component: () => import("../components/LoginComponent.vue"),
}, },
{ {
path: '/', path: "/",
name: 'Admin-main', name: "Admin-main",
component: () => import('../views/AdminMain.vue'), component: () => import("../views/AdminMain.vue"),
}, },
// route pour les canvas (made by adnane), in fact the two vue apps are separated for now // route pour les canvas (made by adnane), in fact the two vue apps are separated for now
{ {
path: '/canvas', path: "/canvas",
name: 'canvas', name: "canvas",
component: () => import('../views/CanvasView.vue'), component: () => import("../views/CanvasView.vue"),
}, },
{ {
path: '/signup', path: "/signup",
name: 'signup', name: "signup",
component: () => import('../views/EntrepSignUp.vue'), component: () => import("../views/EntrepSignUp.vue"),
}, },
{ {
path: '/JorCproject', path: "/JorCproject",
name: 'JorCproject', name: "JorCproject",
component: () => import('../views/JoinOrCreatProjectForEntrep.vue'), component: () => import("../views/JoinOrCreatProjectForEntrep.vue"),
}, },
], ],
}) });
export default router; export default router;

View File

@ -88,5 +88,4 @@ function deleteApi(
.catch(onErrorHandler ?? defaultApiErrorHandler); .catch(onErrorHandler ?? defaultApiErrorHandler);
} }
export { axiosInstance, callApi, postApi, deleteApi }; export { axiosInstance, callApi, postApi, deleteApi };

View File

@ -29,7 +29,6 @@
<Agenda :project-r-d-v="rendezVous" /> <Agenda :project-r-d-v="rendezVous" />
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@ -89,7 +88,6 @@ import AddProjectForm from "@/components/AddProjectForm.vue";
onMounted(fetchProjects); onMounted(fetchProjects);
*/ */
const projects = ref([ const projects = ref([
{ {
name: "Projet Alpha", name: "Projet Alpha",
@ -103,21 +101,18 @@ const projects = ref([
}, },
]); ]);
const pendingProjects = ref([ const pendingProjects = ref([
{ name: "l'eau", creationDate: "26-02-2024" }, { name: "l'eau", creationDate: "26-02-2024" },
{ name: "l'air", creationDate: "09-03-2023" }, { name: "l'air", creationDate: "09-03-2023" },
]) ]);
const rendezVous = ref([ const rendezVous = ref([
{ projectName: "Projet Alpha", date: "2025-03-10", lieu: "P106" }, { projectName: "Projet Alpha", date: "2025-03-10", lieu: "P106" },
{ projectName: "Projet Beta", date: "2025-04-15", lieu: "Td10" }, { projectName: "Projet Beta", date: "2025-04-15", lieu: "Td10" },
]); ]);
</script> </script>
<style scoped> <style scoped>
#container { #container {
display: grid; display: grid;
grid-template-columns: 3fr 1fr; grid-template-columns: 3fr 1fr;
@ -162,6 +157,4 @@ button:hover {
#main > * + * { #main > * + * {
margin-top: 2rem; margin-top: 2rem;
} }
</style> </style>

View File

@ -8,24 +8,32 @@
<h1 class="page-title">PAGE CANVAS</h1> <h1 class="page-title">PAGE CANVAS</h1>
<p class="canvas-help-text"> <p class="canvas-help-text">
Cliquez sur un champ du tableau pour afficher son contenu en détail ci-dessous. Cliquez sur un champ du tableau pour afficher son contenu en détail
ci-dessous.
</p> </p>
<LeanCanvas :is-admin=isAdmin /> <LeanCanvas :is-admin="isAdmin" />
<div class="info-box"> <div class="info-box">
<p> <p>
Responsable : <strong>{{ admin.userName }} {{ admin.userSurname }}</strong><br /> Responsable :
Contact : <a href="mailto:{{ admin.primaryMail }}">{{ admin.primaryMail }}</a> | <strong>{{ admin.userName }} {{ admin.userSurname }}</strong
<a href="tel:{{ admin.phoneNumber }}">{{ admin.phoneNumber }}</a> ><br />
Contact :
<a href="mailto:{{ admin.primaryMail }}">{{
admin.primaryMail
}}</a>
|
<a href="tel:{{ admin.phoneNumber }}">{{
admin.phoneNumber
}}</a>
</p> </p>
</div> </div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import HeaderCanvas from "../components/canvas/HeaderCanvas.vue"; import HeaderCanvas from "../components/canvas/HeaderCanvas.vue";
import LeanCanvas from '../components/canvas/LeanCanvas.vue'; import LeanCanvas from "../components/canvas/LeanCanvas.vue";
import { ref, onMounted /*, defineProps*/ } from "vue"; import { ref, onMounted /*, defineProps*/ } from "vue";
import { axiosInstance } from "@/services/api.ts"; import { axiosInstance } from "@/services/api.ts";
@ -41,7 +49,7 @@ const props = defineProps<{
is_admin = token.includes("MyINPulse-admin") is_admin = token.includes("MyINPulse-admin")
*/ */
const isAdmin = 0 const isAdmin = 0;
// Variables pour les informations de l'administrateur // Variables pour les informations de l'administrateur
const admin = ref({ const admin = ref({
@ -50,7 +58,7 @@ const admin = ref({
userName: "", userName: "",
primaryMail: "", primaryMail: "",
secondaryMail: "", secondaryMail: "",
phoneNumber: "" phoneNumber: "",
}); });
const mockAdminData = { const mockAdminData = {
@ -59,22 +67,29 @@ const mockAdminData = {
userName: "Adnane", userName: "Adnane",
primaryMail: "mock.admin@example.com", primaryMail: "mock.admin@example.com",
secondaryMail: "admin.backup@example.com", secondaryMail: "admin.backup@example.com",
phoneNumber: "0600000000" phoneNumber: "0600000000",
}; };
// Fonction pour récupérer les données de l'administrateur // Fonction pour récupérer les données de l'administrateur
const fetchAdminData = async (projectId: number, useMock = IS_MOCK_MODE) => { const fetchAdminData = async (projectId: number, useMock = IS_MOCK_MODE) => {
try { try {
if (useMock) { if (useMock) {
console.log("Utilisation des données mockées pour l'administrateur"); console.log(
"Utilisation des données mockées pour l'administrateur"
);
admin.value = mockAdminData; admin.value = mockAdminData;
return; return;
} }
const response = await axiosInstance.get(`/shared/projects/admin/${projectId}`); const response = await axiosInstance.get(
`/shared/projects/admin/${projectId}`
);
admin.value = response.data; admin.value = response.data;
} catch (error) { } catch (error) {
console.error("Erreur lors de la récupération des données de l'administrateur :", error); console.error(
"Erreur lors de la récupération des données de l'administrateur :",
error
);
} }
}; };

View File

@ -4,12 +4,7 @@
<div class="form-group"> <div class="form-group">
<label for="name">Nom du projet</label> <label for="name">Nom du projet</label>
<input <input id="name" v-model="form.name" type="text" required />
id="name"
v-model="form.name"
type="text"
required
/>
</div> </div>
<h3>Entrepreneur</h3> <h3>Entrepreneur</h3>
@ -94,17 +89,17 @@
import { postApi } from "@/services/api"; import { postApi } from "@/services/api";
const form = ref({ const form = ref({
name: '', name: "",
founder: { founder: {
userSurname: '', userSurname: "",
userName: '', userName: "",
primaryMail: '', primaryMail: "",
secondaryMail: '', secondaryMail: "",
phoneNumber: '', phoneNumber: "",
school: '', school: "",
course: '', course: "",
sneeStatus: false sneeStatus: false,
} },
}); });
function submitForm() { function submitForm() {
@ -113,10 +108,10 @@
</script> </script>
<style scoped> <style scoped>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap'); @import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap");
.add-project-form { .add-project-form {
font-family: 'Inter', sans-serif; font-family: "Inter", sans-serif;
max-width: 600px; max-width: 600px;
margin: 0 auto; margin: 0 auto;
padding: 20px; padding: 20px;
@ -184,7 +179,7 @@
input[type="text"]:focus, input[type="text"]:focus,
input[type="email"]:focus, input[type="email"]:focus,
input[type="tel"]:focus { input[type="tel"]:focus {
border-color: #4CAF50; border-color: #4caf50;
outline: none; outline: none;
} }
</style> </style>

View File

@ -15,13 +15,11 @@ import ErrorModal from "@/components/errorModal.vue";
</template> </template>
<style scoped> <style scoped>
.error-wrapper { .error-wrapper {
position: absolute; position: absolute;
left: 70%; left: 70%;
/*background-color: blue;*/ /*background-color: blue;*/
height: 100%; height: 100%;
width: 30%; width: 30%;
} }
</style> </style>