changes, global search (clients, cleintCases)

This commit is contained in:
Simon Pocrnjič
2024-11-19 12:49:16 +01:00
parent c45751c1e2
commit 3ae70bf340
37 changed files with 1888 additions and 229 deletions
+135
View File
@@ -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>
+89 -3
View File
@@ -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 -->
+3 -3
View File
@@ -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">
-2
View File
@@ -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>
+19
View File
@@ -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>
+66
View File
@@ -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
View File
@@ -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';