front_foundation #9

Closed
mohamed_maoulainine wants to merge 181 commits from front_foundation into main
7 changed files with 187 additions and 32 deletions
Showing only changes of commit a0eeb6715e - Show all commits

View File

@ -2,10 +2,23 @@
<div class="project" @click="goToLink" >
<div class="project-header">
<h2 >{{ projectName }}</h2>
<div class="project-buttons">
<button class="contact-btn">Contact</button>
<div class="header-actions">
<div class="dropdown-wrapper">
<button class="contact-button" @click="toggleDropdown">Contact</button>
<div class="contact-dropdown" :class="{ 'dropdown-visible': isDropdownOpen }">
<button @click="contactAll">Contacter tous</button>
<button
v-for="(email, index) in entrepreneurEmails"
:key="index"
@click="contactSingle(email)"
>
{{ email }}
</button>
</div>
</div>
</div>
</div>
<div class="project-body">
<ul>
<li v-for="(name, index) in listName" :key="index">{{ name }}</li>
@ -19,12 +32,15 @@
<script setup lang="ts">
import { defineProps } from "vue";
import { useRouter } from 'vue-router'
import { ref, onMounted } from "vue";
import axios from "axios";
const IS_MOCK_MODE = true;
const props = defineProps<{
projectName: string;
listName: string[];
projectLink: string;
adnane marked this conversation as resolved Outdated
Outdated
Review

It would be better to use an ENV variable

It would be better to use an ENV variable
projectId: number;
}>();
const router = useRouter();
@ -35,6 +51,101 @@ const goToLink = () => {
}
};
type Entrepreneur = {
idUser: number;
userSurname: string;
userName: string;
primaryMail: string;
secondaryMail: string;
phoneNumber: string;
school: string;
course: string;
sneeStatus: boolean;
};
const isDropdownOpen = ref(false);
const entrepreneurEmails = ref<string[]>([]);
const toggleDropdown = () => {
isDropdownOpen.value = !isDropdownOpen.value;
console.log("Dropdown toggled:", isDropdownOpen.value);
};
const fetchEntrepreneurs = async (projectId: number, useMock = IS_MOCK_MODE) => {
try {
const responseData: Entrepreneur[] = useMock
? await mockFetchEntrepreneurs(projectId)
: (await axios.get(`http://localhost:5000/shared/projects/entrepreneurs/${projectId}`)).data;
if (responseData.length > 0) {
entrepreneurEmails.value = responseData.map((item: Entrepreneur) => item.primaryMail);
} else {
console.warn("Aucun entrepreneur trouvé.");
}
} catch (error) {
console.error("Erreur lors de la récupération des entrepreneurs :", error);
}
};
// Fonction de simulation de l'API
adnane marked this conversation as resolved Outdated
Outdated
Review

We should not use axios.get EVER, it does not send the authentication token.

We should not use axios.get EVER, it does not send the authentication token.
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
adnane marked this conversation as resolved Outdated
Outdated
Review

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

I don't love the fact that the mock tests are in the code here, it should be better to have a server. It's not a big probleme though
}
]);
}, 500);
});
};
const contactAll = () => {
const allEmails = entrepreneurEmails.value.join(", ");
navigator.clipboard.writeText(allEmails)
.then(() => {
alert("Tous les emails copiés dans le presse-papiers !");
window.open("https://partage.bordeaux-inp.fr/", "_blank");
})
.catch(err => {
console.error("Erreur lors de la copie :", err);
});
};
const contactSingle = (email: string) => {
navigator.clipboard.writeText(email)
.then(() => {
alert(`Adresse copiée : ${email}`);
window.open("https://partage.bordeaux-inp.fr/", "_blank");
})
.catch(err => {
console.error("Erreur lors de la copie :", err);
});
};
onMounted(() => fetchEntrepreneurs(props.projectId, IS_MOCK_MODE));
</script>
@ -79,19 +190,6 @@ const goToLink = () => {
transform: scale(1.05);
}
.contact-btn {
background-color: #007BFF;
color: #fff;
}
.contact-btn:hover {
background-color: #0056b3;
transform: scale(1.05);
}
.project-body {
margin-top: 15px;
}
@ -115,16 +213,65 @@ const goToLink = () => {
}
button {
padding: 10px 15px;
background-color: #007bff;
.header-actions {
display: flex;
align-items: center;
gap: 20px;
position: relative;
}
.contact-button,
.return-button {
background-color: #009CDE;
color: white;
border: none;
padding: 10px 15px;
cursor: pointer;
font-size: 14px;
border-radius: 5px;
text-decoration: none;
transition: background-color 0.2s ease;
font-family: Arial, sans-serif;
}
button:hover {
background-color: #0056b3;
adnane marked this conversation as resolved Outdated
Outdated
Review

generic style once again

generic style once again
.return-button:hover,
.contact-button:hover {
background-color: #007bad;
}
.contact-dropdown {
position: absolute;
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 {
display: block;
width: 100%;
padding: 5px;
text-align: left;
border: none;
background: none;
cursor: pointer;
color: white;
}
.contact-dropdown button:hover {
background-color: #009CDE;
}
.contact-dropdown.dropdown-visible {
display: block;
}
</style>

View File

@ -56,10 +56,10 @@ const props = defineProps<{
title: number;
titleText: string;
description: string;
is_admin: number;
isAdmin: number;
}>();
const IS_ADMIN = props.is_admin;
const IS_ADMIN = props.isAdmin;
const expanded = ref(false);
const currentDescriptions = ref<string[]>([]);

View File

@ -125,7 +125,7 @@ const contactSingle = (email: string) => {
});
};
/*
const copyToClipboard = (email: string) => {
navigator.clipboard.writeText(email).then(() => {
alert(`Adresse copiée : ${email}`);
@ -133,6 +133,7 @@ const copyToClipboard = (email: string) => {
console.error("Erreur lors de la copie :", err);
});
};
*/
onMounted(() => fetchEntrepreneurs(props.projectId, IS_MOCK_MODE));
</script>

View File

@ -4,11 +4,11 @@
v-for="(item, index) in items"
:key="index"
:title="item.title"
:titleText="item.title_text"
:title-text="item.title_text"
:description="item.description"
:project-id="item.projectId"
:class="['canvas-item', item.class, 'card', 'shadow', 'p-3']"
:is_admin=is_admin
:is-admin= props.isAdmin
/>
</div>
</template>
@ -18,7 +18,7 @@ import { ref, onMounted } from "vue";
import CanvasItem from "@/components/canvas/CanvasItem.vue";
const props = defineProps<{
is_admin: number;
isAdmin: number;
}>();
const items = ref([

View File

@ -34,6 +34,12 @@ const router = createRouter({
name: 'signup',
component: () => import('../views/EntrepSignUp.vue'),
},
{
path: '/JorCproject',
adnane marked this conversation as resolved
Review

Can we find a better name ?

Can we find a better name ?
Review

ok

ok
name: 'JorCproject',
component: () => import('../views/JoinOrCreatProjectForEntrep.vue'),
},
],
})

View File

@ -10,6 +10,7 @@
:project-name="project.name"
:list-name="project.members"
:project-link="project.link"
:project-id="0"
/>
<div id ="main">

View File

@ -10,7 +10,7 @@
<p class="canvas-help-text">
Cliquez sur un champ du tableau pour afficher son contenu en détail ci-dessous.
</p>
<LeanCanvas :is_admin=is_admin />
<LeanCanvas :is-admin=isAdmin />
<div class="info-box">
<p>
@ -26,7 +26,7 @@
import HeaderCanvas from "../components/canvas/HeaderCanvas.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";
const IS_MOCK_MODE = true;
@ -41,7 +41,7 @@ const props = defineProps<{
is_admin = token.includes("MyINPulse-admin")
*/
const is_admin = 0
const isAdmin = 0
// Variables pour les informations de l'administrateur
const admin = ref({