Merge branch 'front_foundation' of https://gitea.piair.dev/piair/MyINPulse into front_foundation

This commit is contained in:
Mohamed Maoulainine Maoulainine 2025-03-24 12:43:04 +01:00
commit 7e0851bfef
3 changed files with 221 additions and 52 deletions

View File

@ -1,10 +1,63 @@
{
"entrepreneurs": [
{ "id": 1, "name": "Alice", "email": "alice@example.com" },
{ "id": 2, "name": "Bob", "email": "bob@example.com" },
{ "id": 3, "name": "Charlie", "email": "charlie@example.com" }
{ "id": 1, "name": "Alice", "email": "alice@example.com" },
{ "id": 2, "name": "Bob", "email": "bob@example.com" },
{ "id": 3, "name": "Charlie", "email": "charlie@example.com" }
],
"data": [
{ "canva_data": "this is a fake data to test api" }
{
"projectId": 1,
"title": 1,
"title_text": "1. Problème",
"description": "3 problèmes essentiels à résoudre pour le client"
},
{
"projectId": 1,
"title": 2,
"title_text": "2. Segments",
"description": "Les segments de clientèle visés"
},
{
"projectId": 1,
"title": 3,
"title_text": "3. Valeur",
"description": "La proposition de valeur"
},
{
"projectId": 1,
"title": 4,
"title_text": "4. Solution",
"description": "Les solutions proposées"
},
{
"projectId": 1,
"title": 5,
"title_text": "5. Avantage",
"description": "Les avantages concurrentiels"
},
{
"projectId": 1,
"title": 6,
"title_text": "6. Canaux",
"description": "Les canaux de distribution"
},
{
"projectId": 1,
"title": 7,
"title_text": "7. Indicateurs",
"description": "Les indicateurs clés de performance"
},
{
"projectId": 1,
"title": 8,
"title_text": "8. Coûts",
"description": "Les coûts associés"
},
{
"projectId": 1,
"title": 9,
"title_text": "9. Revenus",
"description": "Les sources de revenus"
}
]
}

View File

@ -1,21 +1,28 @@
<template>
<div :class="['cell', { expanded }]" @click="handleClick">
<h3>{{ title }}</h3>
<h3>{{ title_text }}</h3>
<!-- Mode affichage -->
<template v-if="!isEditing">
<p>{{ currentDescription }}</p>
<button v-if="expanded" @click.stop="startEditing" class="edit-button">Éditer</button>
</template>
<div v-for="(desc, index) in currentDescriptions" :key="index">
<!-- Mode affichage -->
<template v-if="!isEditing[index]">
<div class="description">
<p>{{ desc }}</p>
</div>
<div class="button-container">
<button v-if="expanded" @click.stop="startEditing(index)" class="edit-button">Éditer</button>
</div>
</template>
<!-- Mode édition -->
<template v-else>
<textarea v-model="editedDescriptions[index]" class="edit-input"></textarea>
<div class="button-container">
<button @click.stop="saveEdit(index)" class="save-button">Enregistrer</button>
<button @click.stop="cancelEdit(index)" class="cancel-button">Annuler</button>
</div>
</template>
</div>
<!-- Mode édition -->
<template v-else>
<textarea v-model="editedDescription" class="edit-input"></textarea>
<div class="button-container">
<button @click.stop="saveEdit" class="save-button">Enregistrer</button>
<button @click.stop="cancelEdit" class="cancel-button">Annuler</button>
</div>
</template>
</div>
</template>
@ -23,16 +30,22 @@
import { ref, defineProps } from "vue";
import axios from "axios";
const props = defineProps<{
title: string;
const IS_MOCK_MODE = true;
const props = defineProps<{
projectId: number;
title: number;
title_text: string;
description: string;
}>();
const expanded = ref(false);
const isEditing = ref(false);
const currentDescription = ref(props.description);
const editedDescription = ref(props.description);
const currentDescriptions = ref<string[]>([]);
const editedDescriptions = ref<string[]>([]);
const isEditing = ref<boolean[]>([]);
/*
const fetchData = async () => {
try {
const response = await axios.get("http://localhost:5000/data"); // Met à jour l'URL
@ -46,32 +59,121 @@ const fetchData = async () => {
console.error("Erreur lors de la récupération des données :", error);
}
};
*/
// Fonction de simulation de l'API
const mockFetch = async (projectId: number, title: number, date: string) => {
console.log(`Mock fetch pour projectId: ${projectId}, title: ${title}, date: ${date}`);
return new Promise<{ txt: string }[]>((resolve) => {
setTimeout(() => {
resolve([
{ txt: "Ceci est une description 1 pour tester the damn front, Why are u still reading dumbass this is just some nonsense sentence XD" },
{ txt: "Ceci est une description 1 pour tester the damn front, Bruh are u still here?" },
{ txt: "Ceci est une description 1 pour tester the damn front, .-. BRUH" }
]);
}, 500); // Simule un délai réseau de 500ms
});
};
// Fonction fetchData avec possibilité d'utiliser le mock
const fetchData = async (projectId: number, title: number, date: string, useMock = false) => {
try {
const responseData = useMock
? await mockFetch(projectId, title, date)
: (await axios.get<{ txt: string }[]>(
`http://localhost:5000/shared/projects/lcsection/${projectId}/${title}/${date}`
)).data;
if (responseData.length > 0) {
currentDescriptions.value = responseData.map((item) => item.txt);
editedDescriptions.value = [...currentDescriptions.value]; // Copie initiale
isEditing.value = Array(responseData.length).fill(false);
} else {
console.warn("Aucune donnée reçue.");
}
} catch (error) {
console.error("Erreur lors de la récupération des données :", error);
}
};
// Utilisation du mock dans handleClick pour tester sans serveur
const handleClick = async () => {
if (!expanded.value) {
await fetchData();
} else if (!isEditing.value) {
currentDescription.value = props.description;
editedDescription.value = props.description;
await fetchData(props.projectId, props.title, "NaN", IS_MOCK_MODE); // true pour activer le mock
} else if (!isEditing.value.includes(true)) {
// Réinitialiser les descriptions si aucune édition n'est en cours
currentDescriptions.value = [props.description];
editedDescriptions.value = [props.description];
}
if (!isEditing.value) {
if (!isEditing.value.includes(true)) {
expanded.value = !expanded.value;
}
};
const startEditing = () => {
isEditing.value = true;
const startEditing = (index: number) => {
isEditing.value[index] = true;
};
const saveEdit = () => {
currentDescription.value = editedDescription.value;
isEditing.value = false;
/*
const saveEdit = async (index: number) => {
try {
const id = index + 1; // À adapter selon l'ID réel des données
await axios.put(`http://localhost:5000/data/${id}`, {
canva_data: editedDescriptions.value[index]
});
// Mettre à jour l'affichage local après la mise à jour réussie
currentDescriptions.value[index] = editedDescriptions.value[index];
isEditing.value[index] = false;
} catch (error) {
console.error("Erreur lors de la mise à jour des données :", error);
}
};
*/
// Fonction de mock pour l'enregistrement
const mockSaveEdit = async (index: number) => {
try {
const id = index + 1; // À adapter selon l'ID réel des données
console.log(`Mock save pour l'ID ${id} avec la description : ${editedDescriptions.value[index]}`);
// Simuler un délai d'enregistrement comme une requête réseau
await new Promise((resolve) => setTimeout(resolve, 500)); // Simulation de délai réseau
// Mettre à jour l'affichage local après la mise à jour réussie
currentDescriptions.value[index] = editedDescriptions.value[index];
isEditing.value[index] = false;
} catch (error) {
console.error("Erreur lors de la mise à jour des données mockées :", error);
}
};
const cancelEdit = () => {
editedDescription.value = currentDescription.value;
isEditing.value = false;
// Utilisation de `mockSaveEdit` au lieu de `saveEdit` dans `handleClick` ou tout autre endroit
const saveEdit = async (index: number) => {
if (IS_MOCK_MODE) {
await mockSaveEdit(index);
} else {
try {
const id = index + 1;
await axios.put(`http://localhost:5000/data/${id}`, {
canva_data: editedDescriptions.value[index]
});
// Mettre à jour l'affichage local après la mise à jour réussie
currentDescriptions.value[index] = editedDescriptions.value[index];
isEditing.value[index] = false;
} catch (error) {
console.error("Erreur lors de la mise à jour des données :", error);
}
}
};
const cancelEdit = (index: number) => {
editedDescriptions.value[index] = currentDescriptions.value[index];
isEditing.value[index] = false;
};
</script>
@ -109,6 +211,17 @@ const cancelEdit = () => {
color: #666;
}
.cell .description {
width: 800px;
height: 100px;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
padding: 10px;
}
.expanded {
position: fixed;
top: 0;
@ -124,21 +237,21 @@ const cancelEdit = () => {
}
.edit-input {
width: 80%;
width: 800px;
height: 100px;
font-size: 16px;
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
margin-top: 10px;
box-sizing: border-box;
}
.button-container {
position: absolute;
bottom: 20px;
right: 20px;
display: flex;
gap: 10px;
margin-top: 10px;
}
.edit-button, .save-button, .cancel-button {
@ -147,7 +260,8 @@ const cancelEdit = () => {
border-radius: 5px;
cursor: pointer;
transition: background 0.3s ease;
font-size: 16px;
font-size: 12px;
margin-right: 5px;
}
.edit-button {
@ -177,5 +291,4 @@ const cancelEdit = () => {
background-color: #c82333;
}
</style>
</style>

View File

@ -4,7 +4,9 @@
v-for="(item, index) in items"
:key="index"
:title="item.title"
:title_text="item.title_text"
:description="item.description"
:projectId="item.projectId"
:class="item.class"
/>
</div>
@ -15,16 +17,17 @@ import { ref } from "vue";
import CanvasItem from "@/components/canvas/CanvasItem.vue";
const items = ref([
{ title: "1. Problème", description: "3 problèmes essentiels à résoudre pour le client", class: "Probleme" },
{ title: "2. Segments", description: "Les segments de clientèle visés", class: "Segments" },
{ title: "3. Valeur", description: "La proposition de valeur", class: "Valeur" },
{ title: "4. Solution", description: "Les solutions proposées", class: "Solution" },
{ title: "5. Avantage", description: "Les avantages concurrentiels", class: "Avantage" },
{ title: "6. Canaux", description: "Les canaux de distribution", class: "Canaux" },
{ title: "7. Indicateurs", description: "Les indicateurs clés de performance", class: "Indicateurs" },
{ title: "8. Coûts", description: "Les coûts associés", class: "Couts" },
{ title: "9. Revenus", description: "Les sources de revenus", class: "Revenus" }
{ 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, 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" }
]);
</script>
<style scoped>