394 lines
9.7 KiB
Vue
Executable File
394 lines
9.7 KiB
Vue
Executable File
<template>
|
|
<div :class="['cell', { expanded }]" @click="handleClick">
|
|
<h3 class="fs-5 fw-medium">{{ titleText }}</h3>
|
|
|
|
<div v-for="(desc, index) in currentDescriptions" :key="index" class="section-bloc">
|
|
|
|
<!-- ADMIN -------------------------------------------------------------------------------------------->
|
|
|
|
<template v-if="IS_ADMIN">
|
|
<div class="description">
|
|
<p class="m-0">{{ desc }}</p>
|
|
</div>
|
|
</template>
|
|
|
|
<!-- ENTREP ------------------------------------------------------------------------------------------->
|
|
|
|
<template v-if="!IS_ADMIN">
|
|
<!-- Mode affichage -->
|
|
<template v-if="!isEditing[index]">
|
|
<div class="description">
|
|
<p class="m-0">{{ desc }}</p>
|
|
</div>
|
|
<div class="button-container">
|
|
<button v-if="expanded" class="edit-button" @click.stop="startEditing(index)">Éditer</button>
|
|
</div>
|
|
</template>
|
|
|
|
<!-- Mode édition -->
|
|
<template v-else>
|
|
<textarea v-model="editedDescriptions[index]" class="edit-input"></textarea>
|
|
<div class="button-container">
|
|
<button class="save-button" @click.stop="saveEdit(index)">Enregistrer</button>
|
|
<button class="cancel-button" @click.stop="cancelEdit(index)">Annuler</button>
|
|
</div>
|
|
</template>
|
|
</template>
|
|
</div>
|
|
<!---------------------------------------------------------------------------------------------------->
|
|
<template v-if="expanded">
|
|
<div class="canvas-exit-hint">
|
|
Cliquez n'importe où pour quitter le canvas
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, defineProps, onMounted } from "vue";
|
|
import axios from "axios";
|
|
import { axiosInstance } from "@/services/api.ts";
|
|
|
|
const IS_MOCK_MODE = true;
|
|
const IS_ADMIN = false;
|
|
|
|
const props = defineProps<{
|
|
projectId: number;
|
|
title: number;
|
|
titleText: string;
|
|
description: string;
|
|
}>();
|
|
|
|
const expanded = ref(false);
|
|
const currentDescriptions = ref<string[]>([]);
|
|
currentDescriptions.value[0] = props.description;
|
|
const editedDescriptions = ref<string[]>([]);
|
|
const isEditing = ref<boolean[]>([]);
|
|
|
|
onMounted(() => {
|
|
fetchData(props.projectId, props.title, "NaN", IS_MOCK_MODE);
|
|
});
|
|
|
|
|
|
/* FOR LOCAL DATABASE
|
|
const fetchData = async () => {
|
|
try {
|
|
const response = await axios.get("http://localhost:5000/data"); // Met à jour l'URL
|
|
if (response.data.length > 0) {
|
|
currentDescription.value = response.data[0].canva_data;
|
|
editedDescription.value = response.data[0].canva_data;
|
|
} else {
|
|
console.warn("Aucune donnée reçue.");
|
|
}
|
|
} catch (error) {
|
|
console.error("Erreur lors de la récupération des données :", error);
|
|
}
|
|
};
|
|
*/
|
|
|
|
// Fonction fetchData avec possibilité d'utiliser le mock
|
|
/* FOR FETCHING WITH AXIOS DIRECTLY
|
|
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];
|
|
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);
|
|
}
|
|
};
|
|
*/
|
|
|
|
// 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 axiosInstance.get<{ txt: string }[]>(
|
|
`/shared/projects/lcsection/${projectId}/${title}/${date}`
|
|
)).data;
|
|
|
|
if (responseData.length > 0) {
|
|
currentDescriptions.value = responseData.map((item) => item.txt);
|
|
editedDescriptions.value = [...currentDescriptions.value];
|
|
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);
|
|
}
|
|
};
|
|
|
|
// 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 le front."},
|
|
{txt: "Deuxième description."},
|
|
{txt: "Troisième description."}
|
|
]);
|
|
}, 500); // Simule un délai réseau de 500ms
|
|
});
|
|
};
|
|
|
|
// Utilisation du mock dans handleClick pour tester sans serveur
|
|
const handleClick = async () => {
|
|
if (!expanded.value) {
|
|
await fetchData(props.projectId, props.title, "NaN", IS_MOCK_MODE);
|
|
} 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.includes(true)) {
|
|
expanded.value = !expanded.value;
|
|
}
|
|
};
|
|
|
|
|
|
const startEditing = (index: number) => {
|
|
isEditing.value[index] = true;
|
|
};
|
|
|
|
/*
|
|
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);
|
|
}
|
|
};
|
|
*/
|
|
|
|
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);
|
|
}
|
|
}
|
|
};
|
|
|
|
// Fonction de mock pour l'enregistrement
|
|
const mockSaveEdit = async (index: number) => {
|
|
try {
|
|
const id = index + 1;
|
|
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
|
|
|
|
// 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 = (index: number) => {
|
|
editedDescriptions.value[index] = currentDescriptions.value[index];
|
|
isEditing.value[index] = false;
|
|
};
|
|
</script>
|
|
|
|
<style scoped>
|
|
@import "@/components/canvas/style-project.css";
|
|
|
|
|
|
.cell {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
text-align: center;
|
|
transition: all 0.3s ease;
|
|
cursor: pointer;
|
|
box-shadow: 0 4px 5px rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
|
|
.expanded-content {
|
|
justify-content: flex-start !important;
|
|
}
|
|
|
|
.cell:not(.expanded):hover {
|
|
transform: scale(1.05);
|
|
box-shadow: 0 8px 9px rgba(0, 0, 0, 0.2);
|
|
}
|
|
|
|
.cell h3 {
|
|
font-size: 15px;
|
|
font-weight: 500;
|
|
font-family: 'Arial', sans-serif;
|
|
}
|
|
|
|
.p {
|
|
font-size: 10px;
|
|
color: #666;
|
|
font-family: 'Arial', sans-serif;
|
|
}
|
|
|
|
.expanded {
|
|
padding-top: 10%;
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
background: white;
|
|
z-index: 10;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: flex-start;
|
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
|
|
}
|
|
|
|
|
|
.description {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
text-align: center;
|
|
width: 100%;
|
|
height: 100%;
|
|
font-size: 16px;
|
|
margin-top: 10px;
|
|
margin-left: 2%;
|
|
margin-right: 4%;
|
|
}
|
|
|
|
.description + .p {
|
|
align-items: center;
|
|
justify-content: center;
|
|
text-align: center;
|
|
}
|
|
|
|
|
|
|
|
.edit-input {
|
|
width: 100%;
|
|
height: 100%;
|
|
padding: 10px;
|
|
border: 1px solid #ccc;
|
|
border-radius: 5px;
|
|
margin-top: 10px;
|
|
box-sizing: border-box;
|
|
margin-left: 2%;
|
|
}
|
|
|
|
|
|
.button-container {
|
|
display: block;
|
|
margin-top: 20px;
|
|
justify-content: center;
|
|
align-items: center;
|
|
gap: 10px;
|
|
padding-right: 1%;
|
|
}
|
|
|
|
|
|
.section-bloc ,.editing-section-bloc {
|
|
width: 100%;
|
|
justify-content: center;
|
|
align-items: center;
|
|
display: flex;
|
|
margin-right: 10%;
|
|
margin: 10px;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.edit-button {
|
|
width: 100px;
|
|
height: 40px;
|
|
border: none;
|
|
border-radius: 5px;
|
|
cursor: pointer;
|
|
transition: background 0.3s ease;
|
|
font-size: 12px;
|
|
margin-right: 20px;
|
|
}
|
|
|
|
.save-button, .cancel-button {
|
|
width: 100px;
|
|
height: 40px;
|
|
border: none;
|
|
border-radius: 5px;
|
|
cursor: pointer;
|
|
transition: background 0.3s ease;
|
|
font-size: 12px;
|
|
margin-bottom: 5px;
|
|
}
|
|
|
|
.edit-button {
|
|
background-color: #007bff;
|
|
color: white;
|
|
}
|
|
|
|
.save-button {
|
|
background-color: #28a745;
|
|
color: white;
|
|
}
|
|
|
|
.cancel-button {
|
|
background-color: #dc3545;
|
|
color: white;
|
|
}
|
|
|
|
.edit-button:hover {
|
|
background-color: #0056b3;
|
|
}
|
|
|
|
.save-button:hover {
|
|
background-color: #218838;
|
|
}
|
|
|
|
.cancel-button:hover {
|
|
background-color: #c82333;
|
|
}
|
|
|
|
.canvas-exit-hint {
|
|
font-size: 0.75rem;
|
|
color: #666;
|
|
position: fixed;
|
|
bottom: 10px;
|
|
left: 0;
|
|
width: 100%;
|
|
text-align: center;
|
|
z-index: 1000;
|
|
}
|
|
|
|
</style> |