changes, global search (clients, cleintCases)
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
@import '/node_modules/floating-vue/dist/style.css';
|
||||
@import '/node_modules/vue-search-input/dist/styles.css';
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
<script setup>
|
||||
import { FwbListGroup, FwbListGroupItem } from 'flowbite-vue';
|
||||
import { computed, onMounted, ref, useTemplateRef, watch } from 'vue';
|
||||
import draggable from 'vuedraggable';
|
||||
|
||||
|
||||
const props = defineProps({
|
||||
list1: Array,
|
||||
list2: Array
|
||||
});
|
||||
|
||||
const item1 = {
|
||||
id: 1,
|
||||
name: 'Item 1'
|
||||
}
|
||||
|
||||
const item2 = {
|
||||
id: 2,
|
||||
name: 'Item 2'
|
||||
}
|
||||
|
||||
const item3 = {
|
||||
id: 3,
|
||||
name: 'Item 3'
|
||||
}
|
||||
|
||||
const isDragging = ref(false);
|
||||
|
||||
let containerOne = ref([item1, item2])
|
||||
let containerTwo = ref([item3])
|
||||
|
||||
const dragOptions = computed(() => {
|
||||
return {
|
||||
animation: 200,
|
||||
group: "actions",
|
||||
disabled: false,
|
||||
ghostClass: "ghost"
|
||||
}
|
||||
});
|
||||
|
||||
const removeAt = (idx, targeContainer) => {
|
||||
targeContainer.splice(idx, 1);
|
||||
};
|
||||
|
||||
watch(
|
||||
() => containerOne.value,
|
||||
(value) => {
|
||||
console.log(value)
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<div class="grid grid-cols-4 gap-4">
|
||||
<draggable
|
||||
class="list-group"
|
||||
:list="containerOne"
|
||||
item-key="id"
|
||||
:component-data="{
|
||||
tag: 'ul',
|
||||
type: 'transition-group',
|
||||
name: !isDragging ? 'flip-list' : null
|
||||
}"
|
||||
v-bind="dragOptions"
|
||||
@start="isDragging = true"
|
||||
@end="isDragging = false"
|
||||
group="actions"
|
||||
>
|
||||
<template #item="{element, index}">
|
||||
<fwb-list-group-item class="flex justify-between">
|
||||
<span class="text">{{ element.name }} </span>
|
||||
|
||||
<i class=" cursor-pointer" @click="removeAt(index, containerOne)"><svg class="w-6 h-6 text-gray-800 dark:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
|
||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18 17.94 6M18 18 6.06 6"/>
|
||||
</svg></i>
|
||||
</fwb-list-group-item>
|
||||
</template>
|
||||
</draggable>
|
||||
<draggable
|
||||
class="list-group"
|
||||
:list="containerTwo"
|
||||
:component-data="{
|
||||
tag: 'ul',
|
||||
type: 'transition-group',
|
||||
name: !isDragging ? 'flip-list' : null
|
||||
}"
|
||||
item-key="id"
|
||||
v-bind="dragOptions"
|
||||
@start="isDragging = true"
|
||||
@end="isDragging = false"
|
||||
group="actions"
|
||||
>
|
||||
<template #item="{element, index}">
|
||||
<fwb-list-group-item class="flex justify-between">
|
||||
<span class="text">{{ element.name }} </span>
|
||||
|
||||
<i class="cursor-pointer" @click="removeAt(index, containerOne)"><svg class="w-6 h-6 text-gray-800 dark:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
|
||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18 17.94 6M18 18 6.06 6"/>
|
||||
</svg></i>
|
||||
</fwb-list-group-item>
|
||||
</template>
|
||||
</draggable>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="css">
|
||||
.button {
|
||||
margin-top: 35px;
|
||||
}
|
||||
|
||||
.flip-list-move {
|
||||
transition: transform 0.5s;
|
||||
}
|
||||
|
||||
.no-move {
|
||||
transition: transform 0s;
|
||||
}
|
||||
|
||||
.ghost {
|
||||
opacity: 0.5;
|
||||
background: #c8ebfb;
|
||||
}
|
||||
|
||||
.list-group {
|
||||
min-height: 20px;
|
||||
}
|
||||
|
||||
.list-group-item {
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
.list-group-item i {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,79 @@
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
|
||||
const item1 = {
|
||||
id: 1,
|
||||
text: 'Item 1'
|
||||
};
|
||||
const item2 = {
|
||||
id: 2,
|
||||
text: 'Item 2'
|
||||
};
|
||||
|
||||
let containerOne = ref([item1, item2])
|
||||
let containerTwo = ref([])
|
||||
|
||||
const handleDragStart = (event, container, itemData) => {
|
||||
event.dataTransfer.setData('application/json', JSON.stringify(itemData));
|
||||
|
||||
};
|
||||
|
||||
const handleDrop = (event, targetContainer) => {
|
||||
const itemData = JSON.parse(event.dataTransfer.getData('application/json'));
|
||||
if (targetContainer === containerOne.value) {
|
||||
containerTwo.value = containerTwo.value.filter(i => i.id !== itemData.id);
|
||||
} else if (targetContainer === containerTwo.value) {
|
||||
containerOne.value = containerOne.value.filter(i => i.id !== itemData.id);
|
||||
}
|
||||
targetContainer.push(itemData);
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="drag-drop-container">
|
||||
<div class="container-one"
|
||||
v-on:dragover.prevent
|
||||
v-on:drop="handleDrop($event, containerOne)">
|
||||
<div class="item"
|
||||
v-for="item in containerOne"
|
||||
:key="item.id"
|
||||
draggable="true"
|
||||
v-on:dragstart="handleDragStart($event, containerOne, item)">
|
||||
{{ item.text }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container-two"
|
||||
v-on:dragover.prevent
|
||||
v-on:drop="handleDrop($event, containerTwo)">
|
||||
<div class="item"
|
||||
v-for="item in containerTwo"
|
||||
:key="item.id"
|
||||
draggable="true"
|
||||
v-on:dragstart="handleDragStart($event, containerTwo, item)">
|
||||
{{ item.text }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.drag-drop-container {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.container-one, .container-two {
|
||||
border: 1px solid #1a1a1a;
|
||||
width: 600px;
|
||||
height: 800px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.item {
|
||||
padding: 10px;
|
||||
background-color: black;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
width: 90%;
|
||||
}
|
||||
</style>
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup>
|
||||
import { computed, ref } from 'vue';
|
||||
import { computed, onMounted, ref, watch } from 'vue';
|
||||
import { Head, Link, router, usePage } from '@inertiajs/vue3';
|
||||
import ApplicationMark from '@/Components/ApplicationMark.vue';
|
||||
import Banner from '@/Components/Banner.vue';
|
||||
@@ -8,16 +8,66 @@ import DropdownLink from '@/Components/DropdownLink.vue';
|
||||
import NavLink from '@/Components/NavLink.vue';
|
||||
import ResponsiveNavLink from '@/Components/ResponsiveNavLink.vue';
|
||||
import Breadcrumbs from '@/Components/Breadcrumbs.vue';
|
||||
import axios from 'axios';
|
||||
import { debounce } from 'lodash';
|
||||
import { FwbButton, FwbInput, FwbListGroup, FwbListGroupItem } from 'flowbite-vue';
|
||||
import { AdjustmentIcon, SearchIcon } from '@/Utilities/Icons';
|
||||
|
||||
const props = defineProps({
|
||||
title: String,
|
||||
});
|
||||
|
||||
const showingNavigationDropdown = ref(false);
|
||||
const querySearchDiv = ref(null);
|
||||
|
||||
const querySearch = ref('');
|
||||
|
||||
const querySearchList = ref(true);
|
||||
const querySearchResult = ref([]);
|
||||
|
||||
const logout = () => {
|
||||
router.post(route('logout'));
|
||||
};
|
||||
|
||||
const setRoute = (index) => {
|
||||
return route('client.show', index);
|
||||
}
|
||||
|
||||
const onSearchFocus = () => {
|
||||
if(querySearch.value.length > 0) {
|
||||
querySearchList.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
const onSearchBlue = () => {
|
||||
setTimeout(() => querySearchList.value = true, 100)
|
||||
}
|
||||
|
||||
watch(querySearch, debounce((value) => {
|
||||
axios.get(
|
||||
route('search'),
|
||||
{
|
||||
params: {
|
||||
query: value,
|
||||
limit: 5,
|
||||
tag: ''
|
||||
}
|
||||
}
|
||||
)
|
||||
.then(function(res) {
|
||||
querySearchResult.value = res.data
|
||||
querySearchList.value = false;
|
||||
console.log(res);
|
||||
})
|
||||
.catch(function(error){
|
||||
console.log(error)
|
||||
})
|
||||
.finally(function(){
|
||||
|
||||
});
|
||||
}, 300));
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -65,6 +115,42 @@ const logout = () => {
|
||||
|
||||
<div class="hidden sm:flex sm:items-center sm:ms-6">
|
||||
<!-- Settings Dropdown -->
|
||||
<div>
|
||||
<fwb-input
|
||||
v-model="querySearch"
|
||||
placeholder="Iskalnik..."
|
||||
size="md"
|
||||
@focus="onSearchFocus"
|
||||
@blur="onSearchBlue"
|
||||
>
|
||||
<template #prefix>
|
||||
<SearchIcon />
|
||||
</template>
|
||||
|
||||
</fwb-input>
|
||||
<fwb-list-group ref="querySearchDiv" class="absolute" :hidden="querySearchList">
|
||||
<fwb-list-group-item>
|
||||
<div>
|
||||
<p>Naročniki:</p>
|
||||
<fwb-list-group>
|
||||
<fwb-list-group-item hover v-for="client in querySearchResult.clients">
|
||||
<a :href="route('client.show', {uuid: client.uuid})">{{ client.person.full_name }}</a>
|
||||
</fwb-list-group-item>
|
||||
</fwb-list-group>
|
||||
</div>
|
||||
</fwb-list-group-item>
|
||||
<fwb-list-group-item>
|
||||
<div>
|
||||
<p>Primeri:</p>
|
||||
<fwb-list-group>
|
||||
<fwb-list-group-item hover v-for="clientCase in querySearchResult.client_cases">
|
||||
<a :href="route('clientCase.show', {uuid: clientCase.uuid})">{{ clientCase.person.full_name }}</a>
|
||||
</fwb-list-group-item>
|
||||
</fwb-list-group>
|
||||
</div>
|
||||
</fwb-list-group-item>
|
||||
</fwb-list-group>
|
||||
</div>
|
||||
<div class="ms-3 relative">
|
||||
<Dropdown align="right" width="48">
|
||||
<template #trigger>
|
||||
@@ -154,7 +240,6 @@ const logout = () => {
|
||||
Nastavitve
|
||||
</ResponsiveNavLink>
|
||||
</div>
|
||||
|
||||
<!-- Responsive Settings Options -->
|
||||
<div class="pt-4 pb-1 border-t border-gray-200">
|
||||
<div class="flex items-center px-4">
|
||||
@@ -233,11 +318,12 @@ const logout = () => {
|
||||
</nav>
|
||||
|
||||
<!-- Page Heading -->
|
||||
<header v-if="$slots.header" class="bg-white shadow">
|
||||
<header v-if="$slots.header" class="bg-white shadow ">
|
||||
<div class="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
|
||||
<Breadcrumbs :breadcrumbs="$page.props.breadcrumbs"></Breadcrumbs>
|
||||
|
||||
</div>
|
||||
|
||||
</header>
|
||||
|
||||
<!-- Page Content -->
|
||||
|
||||
@@ -96,7 +96,7 @@ const closeDrawer = () => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pt-1">
|
||||
<!--div class="pt-1">
|
||||
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
|
||||
<div class="bg-white overflow-hidden shadow-xl sm:rounded-lg border-l-4 border-blue-400">
|
||||
<div class="mx-auto max-w-4x1 p-3">
|
||||
@@ -104,8 +104,8 @@ const closeDrawer = () => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pt-12">
|
||||
</div-->
|
||||
<div class="pt-6">
|
||||
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
|
||||
<div class="bg-white overflow-hidden shadow-xl sm:rounded-lg border-l-4 border-red-400">
|
||||
<div class="mx-auto max-w-4x1 p-3">
|
||||
|
||||
@@ -19,7 +19,6 @@ const activeTab = ref('actions')
|
||||
<div class="pt-12">
|
||||
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
|
||||
<div class="bg-white overflow-hidden shadow-xl sm:rounded-lg">
|
||||
|
||||
<fwb-tabs v-model="activeTab" variant="underline" >
|
||||
<fwb-tab name="actions" title="Actions">
|
||||
<ActionTable :actions="actions" />
|
||||
@@ -28,7 +27,6 @@ const activeTab = ref('actions')
|
||||
<DecisionTable :decisions="decisions" />
|
||||
</fwb-tab>
|
||||
</fwb-tabs>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,36 +1,36 @@
|
||||
<script setup>
|
||||
import BasicTable from '@/Components/BasicTable.vue';
|
||||
import { LinkOptions as C_LINK, TableColumn as C_TD, TableRow as C_TR} from '@/Shared/AppObjects';
|
||||
import { FwbTable, FwbTableBody, FwbTableHead, FwbTableHeadCell, FwbTableCell, FwbTableRow } from 'flowbite-vue';
|
||||
import { EditIcon, TrashBinIcon } from '@/Utilities/Icons';
|
||||
|
||||
const props = defineProps({
|
||||
actions: Array
|
||||
});
|
||||
|
||||
const header = [
|
||||
C_TD.make('#', 'header'),
|
||||
C_TD.make('Name', 'header'),
|
||||
C_TD.make('Color tag', 'header'),
|
||||
C_TD.make('Decisions', 'header')
|
||||
];
|
||||
|
||||
const createBody = (data) => {
|
||||
let content = [];
|
||||
|
||||
data.forEach((a) => {
|
||||
const cols = [
|
||||
C_TD.make(a.id, 'body'),
|
||||
C_TD.make(a.name, 'body'),
|
||||
C_TD.make(a.color_tag, 'body'),
|
||||
C_TD.make(a.decisions.length, 'body')
|
||||
];
|
||||
|
||||
content.push(C_TR.make(cols));
|
||||
});
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<BasicTable :header="header" :body="createBody(actions)" />
|
||||
<fwb-table>
|
||||
<fwb-table-head>
|
||||
<fwb-table-head-cell>#</fwb-table-head-cell>
|
||||
<fwb-table-head-cell>Name</fwb-table-head-cell>
|
||||
<fwb-table-head-cell>Color tag</fwb-table-head-cell>
|
||||
<fwb-table-head-cell>Decisions</fwb-table-head-cell>
|
||||
<fwb-table-head-cell>
|
||||
<span class="sr-only">Edit</span>
|
||||
</fwb-table-head-cell>
|
||||
</fwb-table-head>
|
||||
<fwb-table-body>
|
||||
<fwb-table-row v-for="act in actions" :key="act.id">
|
||||
<fwb-table-cell>{{ act.id }}</fwb-table-cell>
|
||||
<fwb-table-cell>{{ act.name }}</fwb-table-cell>
|
||||
<fwb-table-cell>{{ act.color_tag }}</fwb-table-cell>
|
||||
<fwb-table-cell>{{ act.decisions.length }}</fwb-table-cell>
|
||||
<fwb-table-cell>
|
||||
<button><EditIcon /></button>
|
||||
<button><TrashBinIcon /></button>
|
||||
</fwb-table-cell>
|
||||
</fwb-table-row>
|
||||
</fwb-table-body>
|
||||
</fwb-table>
|
||||
</template>
|
||||
@@ -0,0 +1,19 @@
|
||||
<script setup>
|
||||
import DragDropListEx from '@/Components/DragDropListEx.vue';
|
||||
import AppLayout from '@/Layouts/AppLayout.vue';
|
||||
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<AppLayout title="Testing">
|
||||
<div class="pt-12">
|
||||
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
|
||||
<div class="bg-white overflow-hidden shadow-xl sm:rounded-lg">
|
||||
<div class="grid grid-flow-col">
|
||||
<DragDropListEx />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</AppLayout>
|
||||
</template>
|
||||
@@ -0,0 +1,66 @@
|
||||
|
||||
import { ref } from "vue";
|
||||
|
||||
const Icon = {
|
||||
props: {
|
||||
css: {
|
||||
type: String,
|
||||
default: 'text-gray-800'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const AddressBookIcon = {
|
||||
__proto__: Icon,
|
||||
setup: () => {
|
||||
console.log(this.props)
|
||||
},
|
||||
template: `<svg class="w-6 h-6 dark:text-white" :class="css" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
|
||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 6H5m2 3H5m2 3H5m2 3H5m2 3H5m11-1a2 2 0 0 0-2-2h-2a2 2 0 0 0-2 2M7 3h11a1 1 0 0 1 1 1v16a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1Zm8 7a2 2 0 1 1-4 0 2 2 0 0 1 4 0Z"/>
|
||||
</svg>`
|
||||
};
|
||||
|
||||
const AlignCenterIcon = {
|
||||
__proto__: Icon,
|
||||
template: `<svg class="w-6 h-6 dark:text-white" :class="css" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
|
||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 6h8M6 10h12M8 14h8M6 18h12"/>
|
||||
</svg>`
|
||||
}
|
||||
|
||||
const EditIcon = {
|
||||
__proto__: Icon,
|
||||
template: `<svg class="w-6 h-6 dark:text-white" :class="css" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
|
||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m14.304 4.844 2.852 2.852M7 7H4a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h11a1 1 0 0 0 1-1v-4.5m2.409-9.91a2.017 2.017 0 0 1 0 2.853l-6.844 6.844L8 14l.713-3.565 6.844-6.844a2.015 2.015 0 0 1 2.852 0Z"/>
|
||||
</svg>`
|
||||
}
|
||||
|
||||
const TrashBinIcon = {
|
||||
__proto__: Icon,
|
||||
template: `<svg class="w-6 h-6 dark:text-white" :class="css" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path fill-rule="evenodd" d="M8.586 2.586A2 2 0 0 1 10 2h4a2 2 0 0 1 2 2v2h3a1 1 0 1 1 0 2v12a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V8a1 1 0 0 1 0-2h3V4a2 2 0 0 1 .586-1.414ZM10 6h4V4h-4v2Zm1 4a1 1 0 1 0-2 0v8a1 1 0 1 0 2 0v-8Zm4 0a1 1 0 1 0-2 0v8a1 1 0 1 0 2 0v-8Z" clip-rule="evenodd"/>
|
||||
</svg>`
|
||||
}
|
||||
|
||||
const SearchIcon = {
|
||||
__proto__: Icon,
|
||||
template: `<svg aria-hidden="true" class="w-5 h-5 text-gray-500 dark:text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" />
|
||||
</svg>`
|
||||
}
|
||||
|
||||
const AdjustmentIcon = {
|
||||
__proto__: Icon,
|
||||
template: `<svg class="w-6 h-6 text-gray-800 dark:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
|
||||
<path stroke="currentColor" stroke-linecap="round" stroke-width="2" d="M20 6H10m0 0a2 2 0 1 0-4 0m4 0a2 2 0 1 1-4 0m0 0H4m16 6h-2m0 0a2 2 0 1 0-4 0m4 0a2 2 0 1 1-4 0m0 0H4m16 6H10m0 0a2 2 0 1 0-4 0m4 0a2 2 0 1 1-4 0m0 0H4"/>
|
||||
</svg>
|
||||
`
|
||||
}
|
||||
|
||||
export {
|
||||
AddressBookIcon,
|
||||
AlignCenterIcon,
|
||||
EditIcon,
|
||||
TrashBinIcon,
|
||||
SearchIcon,
|
||||
AdjustmentIcon
|
||||
};
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import './bootstrap';
|
||||
import '../css/app.css';
|
||||
|
||||
import { createApp, h } from 'vue';
|
||||
import { createApp, h } from 'vue/dist/vue.esm-bundler.js';
|
||||
import { createInertiaApp } from '@inertiajs/vue3';
|
||||
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
|
||||
import { ZiggyVue } from '../../vendor/tightenco/ziggy';
|
||||
|
||||
Reference in New Issue
Block a user