Juan Felipe Zapata Moreno a6abe2de40 Cambios al maquetador
2025-09-24 16:40:29 -06:00

201 lines
6.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup>
import { ref, computed, watch } from 'vue';
import GoogleIcon from '@Shared/GoogleIcon.vue';
const props = defineProps({
element: {
type: Object,
required: true
},
isEditing: {
type: Boolean,
default: false
}
});
const emit = defineEmits(['update', 'finish-editing']);
// Estructura simple: empezar con una celda
const tableData = ref([]);
// Watcher para sincronizar datos
watch(() => props.element.content, (newContent) => {
if (newContent && newContent.data && Array.isArray(newContent.data)) {
tableData.value = JSON.parse(JSON.stringify(newContent.data));
} else {
// Inicializar con una sola celda
tableData.value = [['']];
}
}, { immediate: true });
const rows = computed(() => tableData.value.length);
const cols = computed(() => tableData.value[0]?.length || 1);
// Agregar fila
const addRow = () => {
const newRow = new Array(cols.value).fill('');
tableData.value.push(newRow);
updateTable();
};
// Agregar columna
const addColumn = () => {
tableData.value.forEach(row => {
row.push('');
});
updateTable();
};
// Eliminar fila (no permitir si solo hay una)
const removeRow = (rowIndex) => {
if (tableData.value.length > 1) {
tableData.value.splice(rowIndex, 1);
updateTable();
}
};
// Eliminar columna (no permitir si solo hay una)
const removeColumn = (colIndex) => {
if (tableData.value[0]?.length > 1) {
tableData.value.forEach(row => {
row.splice(colIndex, 1);
});
updateTable();
}
};
// Actualizar celda
const updateCell = (rowIndex, colIndex, value) => {
if (tableData.value[rowIndex]) {
tableData.value[rowIndex][colIndex] = value;
updateTable();
}
};
// Actualizar tabla
const updateTable = () => {
const updatedContent = {
data: JSON.parse(JSON.stringify(tableData.value)),
rows: tableData.value.length,
cols: tableData.value[0]?.length || 1
};
// Calcular dimensiones dinámicas basadas en contenido
const cellWidth = 120;
const cellHeight = 35;
const newWidth = Math.max(120, updatedContent.cols * cellWidth);
const newHeight = Math.max(40, updatedContent.rows * cellHeight);
emit('update', {
id: props.element.id,
content: updatedContent,
width: newWidth,
height: newHeight
});
};
const finishEditing = () => {
emit('finish-editing');
};
</script>
<template>
<div class="w-full h-full bg-white rounded border border-gray-300 overflow-hidden">
<!-- Controles de tabla (solo cuando está editando) -->
<div
v-if="isEditing"
class="flex items-center gap-2 p-2 bg-gray-50 border-b"
>
<button
@click="addRow"
class="px-2 py-1 text-xs bg-green-500 hover:bg-green-600 text-white rounded flex items-center gap-1"
title="Agregar fila"
>
<GoogleIcon name="add" class="text-xs" />
+
</button>
<button
@click="addColumn"
class="px-2 py-1 text-xs bg-blue-500 hover:bg-blue-600 text-white rounded flex items-center gap-1"
title="Agregar columna"
>
<GoogleIcon name="add" class="text-xs" />
+
</button>
<div class="flex-1"></div>
<span class="text-xs text-gray-500">
{{ rows }}x{{ cols }}
</span>
<button
@click="finishEditing"
class="px-2 py-1 text-xs bg-gray-600 hover:bg-gray-700 text-white rounded"
>
Cerrar
</button>
</div>
<!-- Tabla -->
<div class="w-full h-full">
<table class="w-full h-full border-collapse text-sm">
<tbody>
<tr
v-for="(row, rowIndex) in tableData"
:key="`row-${rowIndex}`"
class="group"
:style="{ height: `${100/rows}%` }"
>
<td
v-for="(cell, colIndex) in row"
:key="`cell-${rowIndex}-${colIndex}`"
class="border border-gray-300 p-1 relative group/cell"
:style="{ width: `${100/cols}%` }"
>
<!-- Controles de celda (solo cuando está editando) -->
<div
v-if="isEditing && (rows > 1 || cols > 1)"
class="absolute -top-2 -right-2 opacity-0 group-hover/cell:opacity-100 transition-opacity z-10"
>
<!-- Eliminar fila -->
<button
v-if="rows > 1 && colIndex === 0"
@click="removeRow(rowIndex)"
class="w-4 h-4 bg-red-500 text-white rounded-full text-xs flex items-center justify-center mr-1"
title="Eliminar fila"
>
×
</button>
<!-- Eliminar columna -->
<button
v-if="cols > 1 && rowIndex === 0"
@click="removeColumn(colIndex)"
class="w-4 h-4 bg-red-500 text-white rounded-full text-xs flex items-center justify-center"
title="Eliminar columna"
>
×
</button>
</div>
<!-- Input de celda -->
<input
v-if="isEditing"
:value="cell"
@input="updateCell(rowIndex, colIndex, $event.target.value)"
class="w-full h-full bg-transparent outline-none text-center text-sm resize-none"
@click.stop
:placeholder="rowIndex === 0 && colIndex === 0 && !cell ? 'Escribe aquí...' : ''"
/>
<!-- Vista de solo lectura -->
<div v-else class="w-full h-full flex items-center justify-center text-center text-sm p-1">
{{ cell || (rowIndex === 0 && colIndex === 0 ? 'Tabla' : '') }}
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</template>