front_foundation #9
@ -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 />
|
||||||
piair
commented
same, I don't think it's really important to keep comments same, I don't think it's really important to keep comments
|
|||||||
<!--<RouterLink to="/">Home</RouterLink> | -->
|
<!--<RouterLink to="/">Home</RouterLink> | -->
|
||||||
<!--<RouterLink to="/canvas">Canvas</RouterLink> -->
|
<!--<RouterLink to="/canvas">Canvas</RouterLink> -->
|
||||||
<RouterView />
|
<RouterView />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
|
@ -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[];
|
||||||
Theo
commented
où est-ce que les RDV sont récupérés ? où est-ce que les RDV sont récupérés ?
|
|||||||
}>();
|
}>();
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
piair
commented
same comment as before, most of the style here is not for this part only, so it should not be here same comment as before, most of the style here is not for this part only, so it should not be here
|
|||||||
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>
|
@ -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) => {
|
|||||||
|
|
||||||
piair
commented
same, it should be hidden same, it should be hidden
|
|||||||
<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>
|
||||||
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
||||||
|
@ -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;*/
|
||||||
|
@ -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;
|
||||||
}
|
}
|
@ -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 };
|
||||||
|
@ -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",
|
||||||
adnane marked this conversation as resolved
piair
commented
Can we find a better name ? Can we find a better name ?
adnane
commented
ok ok
|
|||||||
name: 'JorCproject',
|
name: "JorCproject",
|
||||||
component: () => import('../views/JoinOrCreatProjectForEntrep.vue'),
|
component: () => import("../views/JoinOrCreatProjectForEntrep.vue"),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
});
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
@ -88,5 +88,4 @@ function deleteApi(
|
|||||||
.catch(onErrorHandler ?? defaultApiErrorHandler);
|
.catch(onErrorHandler ?? defaultApiErrorHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export { axiosInstance, callApi, postApi, deleteApi };
|
export { axiosInstance, callApi, postApi, deleteApi };
|
||||||
|
@ -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>
|
@ -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
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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");
|
||||||
adnane marked this conversation as resolved
piair
commented
this should be in a specific css file. this should be in a specific css file.
|
|||||||
|
|
||||||
.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>
|
@ -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;*/
|
||||||
piair
commented
why ? why ?
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
width: 30%;
|
width: 30%;
|
||||||
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user
I don't like the comments in the middle of the line, it would be better to delete this part.