Last active
February 29, 2024 12:47
-
-
Save dansp89/1e9f5b9a8c30ee1cd3e4b7adca0d1be1 to your computer and use it in GitHub Desktop.
Componente VUE3 para criar Gestão de aulas, Módulos - Aulas,
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<el-button type="primary" @click="addModule">Adicionar Módulo</el-button> | |
<el-tree | |
:data="treeData" | |
draggable | |
default-expand-all | |
node-key="id" | |
:allow-drag="allowDrag" | |
:allow-drop="allowDrop" | |
@node-drag-start="handleDragStart" | |
@node-drag-enter="handleDragEnter" | |
@node-drag-leave="handleDragLeave" | |
@node-drag-over="handleDragOver" | |
@node-drag-end="handleDragEnd" | |
@node-drop="handleDrop" | |
> | |
<template #default="{ node, data }"> | |
<div | |
style=" | |
display: flex; | |
align-items: center; | |
justify-content: space-between; | |
" | |
> | |
<span>{{ node.label }}</span> | |
<!-- Mostrar botão de excluir para aulas --> | |
<el-button | |
v-if="data.type === 'lesson'" | |
:text="true" | |
icon="el-icon-delete" | |
@click.stop="deleteNode(data.id, data.type)" | |
> | |
x | |
</el-button> | |
<!-- Mostrar botão editar aulas --> | |
<el-button v-if="data.type === 'lesson'" :text="true" icon="el-icon-"> | |
Editar | |
</el-button> | |
<!-- Mostrar botão de excluir para módulos sem aulas --> | |
<el-button | |
v-if=" | |
data.type === 'module' && | |
(!data.children || data.children.length === 0) | |
" | |
:text="true" | |
icon="el-icon-delete" | |
@click.stop="deleteNode(data.id, data.type)" | |
> | |
X | |
</el-button> | |
<!-- Botão para adicionar aula, visível apenas para módulos --> | |
<el-button | |
v-if="data.type === 'module'" | |
:text="true" | |
icon="el-icon-plus" | |
@click.stop="addLesson(data.id)" | |
> | |
+ | |
</el-button> | |
</div> | |
</template> | |
</el-tree> | |
</template> | |
<script lang="ts" setup> | |
/** | |
* @source <https://element-plus.org/en-US/component/tree.html#draggable> | |
*/ | |
import { ref } from "vue"; | |
import type Node from "element-plus/es/components/tree/src/model/node"; | |
import type { DragEvents } from "element-plus/es/components/tree/src/model/useDragNode"; | |
import type { | |
AllowDropType, | |
NodeDropType | |
} from "element-plus/es/components/tree/src/tree.type"; | |
import { nanoid } from "nanoid"; | |
const treeData = ref([ | |
{ | |
id: "module-1", | |
label: "Módulo 1", | |
type: "module", | |
children: [ | |
{ | |
id: "lesson-1", | |
label: "Aula 1", | |
type: "lesson" | |
}, | |
{ | |
id: "lesson-2", | |
label: "Aula 2", | |
type: "lesson" | |
} | |
] | |
}, | |
{ | |
id: "module-2", | |
label: "Módulo 2", | |
type: "module", | |
children: [ | |
{ | |
id: "lesson-3", | |
label: "Aula 3", | |
type: "lesson" | |
}, | |
{ | |
id: "lesson-4", | |
label: "Aula 4", | |
type: "lesson" | |
} | |
] | |
} | |
]); | |
const allowDrop = (draggingNode: Node, dropNode: Node, type: AllowDropType) => { | |
// Ajuste para permitir que módulos sejam reordenados entre si. | |
if ( | |
draggingNode.data.type === "module" && | |
dropNode.data.type === "module" && | |
(type === "prev" || type === "next") | |
) { | |
return true; | |
} | |
// Permitir mover aulas apenas dentro de módulos ou entre módulos, mas não permitir que sejam pais (não podem ter filhos). | |
if (draggingNode.data.type === "lesson") { | |
// Permitir se o destino for um módulo e a aula está sendo movida para dentro dele (como filha). | |
if (dropNode.data.type === "module" && type === "inner") { | |
return true; | |
} | |
// Permitir mover aula para o mesmo nível dentro de outro módulo ou dentro do mesmo módulo (prev ou next, mas não dentro de outra aula). | |
if ( | |
dropNode.data.type === "lesson" && | |
(type === "prev" || type === "next") | |
) { | |
return true; | |
} | |
} | |
return false; // Não permite outros casos, incluindo aulas sendo pais. | |
}; | |
const allowDrag = (draggingNode: Node) => { | |
// Todos os nós podem ser arrastados, mas as restrições de onde podem ser soltos são definidas em allowDrop. | |
return true; | |
}; | |
const handleDragStart = (node: Node, ev: DragEvents) => { | |
console.log("drag start", node); | |
}; | |
const handleDragEnter = ( | |
draggingNode: Node, | |
dropNode: Node, | |
ev: DragEvents | |
) => { | |
console.log("tree drag enter:", dropNode.label); | |
}; | |
const handleDragLeave = ( | |
draggingNode: Node, | |
dropNode: Node, | |
ev: DragEvents | |
) => { | |
console.log("tree drag leave:", dropNode.label); | |
}; | |
const handleDragOver = (draggingNode: Node, dropNode: Node, ev: DragEvents) => { | |
console.log("tree drag over:", dropNode.label); | |
}; | |
const handleDragEnd = ( | |
draggingNode: Node, | |
dropNode: Node, | |
dropType: NodeDropType, | |
ev: DragEvents | |
) => { | |
console.log("tree drag end:", dropNode && dropNode.label, dropType); | |
}; | |
const handleDrop = ( | |
draggingNode: Node, | |
dropNode: Node, | |
dropType: NodeDropType, | |
ev: DragEvents | |
) => { | |
console.log("tree drop:", dropNode.label, dropType); | |
// Aqui você deve implementar a lógica para atualizar a estrutura de dados conforme a nova posição do nó arrastado. | |
}; | |
const deleteNode = (nodeId, nodeType) => { | |
// Função genérica para encontrar e excluir o nó | |
const findAndDelete = (nodes, id) => | |
nodes.filter((node) => { | |
if (node.id === id) { | |
return false; // Exclui o nó | |
} | |
if (node.children) { | |
node.children = findAndDelete(node.children, id); // Procura recursivamente | |
} | |
return true; | |
}); | |
if (nodeType === "module") { | |
// Excluir o módulo se não tiver aulas | |
treeData.value = findAndDelete(treeData.value, nodeId); | |
} else if (nodeType === "lesson") { | |
// Excluir a aula | |
treeData.value.forEach((module) => { | |
if (module.children) { | |
module.children = findAndDelete(module.children, nodeId); | |
} | |
}); | |
} | |
}; | |
const addModule = () => { | |
const newModule = { | |
id: nanoid(), // Gerar um ID único para o novo módulo | |
label: `Módulo ${treeData.value.length + 1}`, | |
type: "module", | |
children: [] | |
}; | |
treeData.value.push(newModule); | |
}; | |
const addLesson = (moduleId) => { | |
const newLesson = { | |
id: nanoid(), // Gerar um ID único para a nova aula | |
label: `Aula Nova`, | |
type: "lesson" | |
}; | |
const module = treeData.value.find((module) => module.id === moduleId); | |
if (module) { | |
if (!module.children) { | |
module.children = []; | |
} | |
module.children.push(newLesson); | |
} | |
}; | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment