Initial commit

This commit is contained in:
2025-08-04 16:33:07 +03:30
commit f798e8e35c
9595 changed files with 1208683 additions and 0 deletions

View File

@@ -0,0 +1,237 @@
<script setup>
import {
animations,
remapNodes,
} from '@formkit/drag-and-drop'
import { dragAndDrop } from '@formkit/drag-and-drop/vue'
import { VForm } from 'vuetify/components/VForm'
import KanbanBoardEditDrawer from '@/views/apps/kanban/KanbanBoardEditDrawer.vue'
import KanbanItems from '@/views/apps/kanban/KanbanItems.vue'
const props = defineProps({
kanbanData: {
type: null,
required: true,
},
groupName: {
type: String,
required: false,
default: 'kanban',
},
})
const emit = defineEmits([
'addNewBoard',
'renameBoard',
'deleteBoard',
'addNewItem',
'editItem',
'deleteItem',
'updateItemsState',
'updateBoardState',
])
const kanbanWrapper = ref()
const localKanbanData = ref(props.kanbanData.boards)
const isKanbanBoardEditVisible = ref(false)
const isAddNewFormVisible = ref(false)
const refAddNewBoard = ref()
const boardTitle = ref('')
const editKanbanItem = ref()
// 👉 Add new board function that emit the name and id of new board
const addNewBoard = () => {
refAddNewBoard.value?.validate().then(valid => {
if (valid.valid) {
emit('addNewBoard', boardTitle.value)
isAddNewFormVisible.value = false
boardTitle.value = ''
}
})
}
const deleteBoard = boardId => {
emit('deleteBoard', boardId)
}
const renameBoard = boardName => {
emit('renameBoard', boardName)
}
const addNewItem = item => {
emit('addNewItem', item)
}
const editKanbanItemFn = item => {
if (item) {
editKanbanItem.value = item
isKanbanBoardEditVisible.value = true
}
}
const updateStateFn = kanbanState => {
emit('updateItemsState', kanbanState)
}
// 👉 initialize the drag and drop
dragAndDrop({
parent: kanbanWrapper,
values: localKanbanData,
dragHandle: '.drag-handler',
plugins: [animations()],
})
// assign the new kanban data to the local kanban data
watch(() => props, () => {
localKanbanData.value = props.kanbanData.boards
// 👉 remap the nodes when we rename the board: https://github.com/formkit/drag-and-drop/discussions/52#discussioncomment-8995203
remapNodes(kanbanWrapper.value)
}, { deep: true })
const emitUpdatedTaskFn = item => {
emit('editItem', item)
}
const deleteKanbanItemFn = item => {
emit('deleteItem', item)
}
// 👉 update boards data when it sort
watch(localKanbanData, () => {
const getIds = localKanbanData.value.map(board => board.id)
emit('updateBoardState', getIds)
}, { deep: true })
// 👉 validators for add new board
const validateBoardTitle = () => {
return props.kanbanData.boards.some(board => boardTitle.value && board.title.toLowerCase() === boardTitle.value.toLowerCase()) ? 'Board title already exists' : true
}
const hideAddNewForm = () => {
isAddNewFormVisible.value = false
refAddNewBoard.value?.reset()
}
// close add new item form when you loose focus from the form
onClickOutside(refAddNewBoard, hideAddNewForm)
</script>
<template>
<div class="kanban-main-wrapper d-flex gap-4 h-100">
<!-- 👉 kanban render -->
<div
ref="kanbanWrapper"
class="d-flex ga-6"
>
<template
v-for="kb in localKanbanData"
:key="kb.id"
>
<!-- 👉 kanban task render -->
<KanbanItems
:group-name="groupName"
:kanban-ids="kb.itemsIds"
:board-name="kb.title"
:board-id="kb.id"
:kanban-items="kanbanData.items"
:kanban-data="kanbanData"
@delete-board="deleteBoard"
@rename-board="renameBoard"
@add-new-item="addNewItem"
@edit-item="editKanbanItemFn"
@update-items-state="updateStateFn"
@delete-item="deleteKanbanItemFn"
/>
</template>
</div>
<!-- 👉 add new form -->
<div
class="add-new-form text-no-wrap"
style="inline-size: 10rem;"
>
<h6
class="text-lg font-weight-medium cursor-pointer"
@click="isAddNewFormVisible = !isAddNewFormVisible"
>
<VIcon
size="18"
icon="tabler-plus"
/> Add New
</h6>
<!-- 👉 Form -->
<VForm
v-if="isAddNewFormVisible"
ref="refAddNewBoard"
class="mt-4"
validate-on="submit"
@submit.prevent="addNewBoard"
>
<div class="mb-4">
<VTextField
v-model="boardTitle"
:rules="[requiredValidator, validateBoardTitle]"
autofocus
placeholder="Add Board Title"
@keydown.esc="hideAddNewForm"
/>
</div>
<div class="d-flex gap-3">
<VBtn
size="small"
type="submit"
>
Add
</VBtn>
<VBtn
size="small"
variant="tonal"
color="secondary"
type="reset"
@click="hideAddNewForm"
>
Cancel
</VBtn>
</div>
</VForm>
</div>
</div>
<!-- kanban edit drawer -->
<KanbanBoardEditDrawer
v-model:is-drawer-open="isKanbanBoardEditVisible"
:kanban-item="editKanbanItem"
@update:kanban-item="emitUpdatedTaskFn"
@delete-kanban-item="deleteKanbanItemFn"
/>
</template>
<style lang="scss">
@use "@styles/variables/_vuetify.scss" as vuetify;
.kanban-main-wrapper {
overflow: auto hidden;
margin-inline-start: -0.6rem;
min-block-size: calc(100vh - 10.5rem);
padding-inline-start: 0.6rem;
.kanban-board {
inline-size: 16.875rem;
min-inline-size: 16.875rem;
.kanban-board-drop-zone {
min-block-size: 100%;
}
}
.add-new-form {
.v-field__field {
border-radius: vuetify.$border-radius-root;
background-color: rgb(var(--v-theme-surface));
}
}
}
</style>