Changes 0228092025 Laptop

This commit is contained in:
2025-09-28 14:51:02 +02:00
parent 765beb78b7
commit b40ee9dcde
36 changed files with 2099 additions and 65 deletions
@@ -1,9 +1,10 @@
<script setup>
import { FwbTable, FwbTableBody, FwbTableHead, FwbTableHeadCell, FwbTableCell, FwbTableRow, FwbDropdown } from 'flowbite-vue';
import { DottedMenu, EditIcon, TrashBinIcon } from '@/Utilities/Icons';
import { FwbTable, FwbTableBody, FwbTableHead, FwbTableHeadCell, FwbTableCell, FwbTableRow } from 'flowbite-vue';
import { EditIcon, TrashBinIcon } from '@/Utilities/Icons';
import DialogModal from '@/Components/DialogModal.vue';
import { onMounted, ref } from 'vue';
import { useForm } from '@inertiajs/vue3';
import ConfirmationModal from '@/Components/ConfirmationModal.vue';
import { computed, onMounted, ref, watch } from 'vue';
import { router, useForm } from '@inertiajs/vue3';
import InputLabel from '@/Components/InputLabel.vue';
import TextInput from '@/Components/TextInput.vue';
import Multiselect from 'vue-multiselect';
@@ -16,10 +17,13 @@ const props = defineProps({
segments: Array
});
const menuDropdown = ref();
const drawerEdit = ref(false);
const drawerCreate = ref(false);
const showDelete = ref(false);
const toDelete = ref(null);
const search = ref('');
const selectedSegment = ref(null);
const selectOptions = ref([]);
const segmentOptions = ref([]);
@@ -91,6 +95,15 @@ onMounted(() => {
});
const filtered = computed(() => {
const term = search.value?.toLowerCase() ?? '';
return (props.actions || []).filter(a => {
const matchesSearch = !term || a.name?.toLowerCase().includes(term) || a.color_tag?.toLowerCase().includes(term);
const matchesSegment = !selectedSegment.value || a.segment?.id === selectedSegment.value;
return matchesSearch && matchesSegment;
});
});
const update = () => {
form.put(route('settings.actions.update', { id: form.id }), {
onSuccess: () => {
@@ -107,11 +120,44 @@ const store = () => {
});
};
const confirmDelete = (action) => {
toDelete.value = action;
showDelete.value = true;
};
const cancelDelete = () => {
toDelete.value = null;
showDelete.value = false;
};
const destroyAction = () => {
if (!toDelete.value) return;
router.delete(route('settings.actions.destroy', { id: toDelete.value.id }), {
preserveScroll: true,
onFinish: () => cancelDelete(),
});
};
</script>
<template>
<div class="py-4 px-3">
<div class="p-4 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div class="flex gap-3 items-center w-full sm:w-auto">
<TextInput v-model="search" placeholder="Search actions..." class="w-full sm:w-64" />
<div class="w-64">
<Multiselect
v-model="selectedSegment"
:options="segmentOptions.map(o=>o.id)"
:multiple="false"
:searchable="true"
placeholder="Filter by segment"
:append-to-body="true"
:custom-label="(opt) => (segmentOptions.find(o=>o.id===opt)?.name || '')"
/>
</div>
</div>
<PrimaryButton @click="openCreateDrawer">+ Dodaj akcijo</PrimaryButton>
</div>
<fwb-table>
<fwb-table-head>
<fwb-table-head-cell>#</fwb-table-head-cell>
@@ -123,22 +169,25 @@ const store = () => {
</fwb-table-head-cell>
</fwb-table-head>
<fwb-table-body>
<fwb-table-row v-for="act in actions" :key="act.id">
<fwb-table-row v-for="act in filtered" :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>
<div class="flex items-center gap-2">
<span class="inline-block h-4 w-4 rounded" :style="{ backgroundColor: act.color_tag }"></span>
<span>{{ act.color_tag }}</span>
</div>
</fwb-table-cell>
<fwb-table-cell>{{ act.decisions.length }}</fwb-table-cell>
<fwb-table-cell>
<button class="px-2" @click="openEditDrawer(act)"><EditIcon size="md" css="text-gray-500" /></button>
<button class="px-2 disabled:opacity-40" :disabled="(act.activities_count ?? 0) > 0" @click="confirmDelete(act)"><TrashBinIcon size="md" css="text-red-500" /></button>
</fwb-table-cell>
</fwb-table-row>
</fwb-table-body>
</fwb-table>
<DialogModal
:show="drawerEdit"
@close="closeEditDrawer"
>
<DialogModal :show="drawerEdit" @close="closeEditDrawer">
<template #title>
<span>Spremeni akcijo</span>
</template>
@@ -215,10 +264,7 @@ const store = () => {
</template>
</DialogModal>
<DialogModal
:show="drawerCreate"
@close="closeCreateDrawer"
>
<DialogModal :show="drawerCreate" @close="closeCreateDrawer">
<template #title>
<span>Dodaj akcijo</span>
</template>
@@ -290,4 +336,17 @@ const store = () => {
</form>
</template>
</DialogModal>
<ConfirmationModal :show="showDelete" @close="cancelDelete">
<template #title>
Delete action
</template>
<template #content>
Are you sure you want to delete action "{{ toDelete?.name }}"? This cannot be undone.
</template>
<template #footer>
<button @click="cancelDelete" class="px-4 py-2 rounded bg-gray-200 hover:bg-gray-300 me-2">Cancel</button>
<PrimaryButton @click="destroyAction">Delete</PrimaryButton>
</template>
</ConfirmationModal>
</template>
@@ -1,9 +1,10 @@
<script setup>
import { FwbTable, FwbTableBody, FwbTableHead, FwbTableHeadCell, FwbTableCell, FwbTableRow } from 'flowbite-vue';
import { EditIcon } from '@/Utilities/Icons';
import { EditIcon, TrashBinIcon } from '@/Utilities/Icons';
import DialogModal from '@/Components/DialogModal.vue';
import { onMounted, ref } from 'vue';
import { useForm } from '@inertiajs/vue3';
import ConfirmationModal from '@/Components/ConfirmationModal.vue';
import { computed, onMounted, ref } from 'vue';
import { router, useForm } from '@inertiajs/vue3';
import InputLabel from '@/Components/InputLabel.vue';
import TextInput from '@/Components/TextInput.vue';
import Multiselect from 'vue-multiselect';
@@ -17,6 +18,10 @@ const props = defineProps({
const drawerEdit = ref(false);
const drawerCreate = ref(false);
const showDelete = ref(false);
const toDelete = ref(null);
const search = ref('');
const actionOptions = ref([]);
@@ -72,6 +77,13 @@ onMounted(() => {
});
});
const filtered = computed(() => {
const term = search.value?.toLowerCase() ?? '';
return (props.decisions || []).filter(d => {
return !term || d.name?.toLowerCase().includes(term) || d.color_tag?.toLowerCase().includes(term);
});
});
const update = () => {
form.put(route('settings.decisions.update', { id: form.id }), {
onSuccess: () => {
@@ -88,11 +100,31 @@ const store = () => {
});
};
const confirmDelete = (decision) => {
toDelete.value = decision;
showDelete.value = true;
};
const cancelDelete = () => {
toDelete.value = null;
showDelete.value = false;
};
const destroyDecision = () => {
if (!toDelete.value) return;
router.delete(route('settings.decisions.destroy', { id: toDelete.value.id }), {
preserveScroll: true,
onFinish: () => cancelDelete(),
});
};
</script>
<template>
<div class="py-4 px-3">
<div class="p-4 flex items-center justify-between gap-3">
<TextInput v-model="search" placeholder="Search decisions..." class="w-full sm:w-72" />
<PrimaryButton @click="openCreateDrawer">+ Dodaj odločitev</PrimaryButton>
</div>
<fwb-table>
<fwb-table-head>
<fwb-table-head-cell>#</fwb-table-head-cell>
@@ -104,22 +136,25 @@ const store = () => {
</fwb-table-head-cell>
</fwb-table-head>
<fwb-table-body>
<fwb-table-row v-for="d in decisions" :key="d.id">
<fwb-table-row v-for="d in filtered" :key="d.id">
<fwb-table-cell>{{ d.id }}</fwb-table-cell>
<fwb-table-cell>{{ d.name }}</fwb-table-cell>
<fwb-table-cell>{{ d.color_tag }}</fwb-table-cell>
<fwb-table-cell>
<div class="flex items-center gap-2">
<span class="inline-block h-4 w-4 rounded" :style="{ backgroundColor: d.color_tag }"></span>
<span>{{ d.color_tag }}</span>
</div>
</fwb-table-cell>
<fwb-table-cell>{{ d.actions.length }}</fwb-table-cell>
<fwb-table-cell>
<button class="px-2" @click="openEditDrawer(d)"><EditIcon size="md" css="text-gray-500" /></button>
<button class="px-2 disabled:opacity-40" :disabled="(d.activities_count ?? 0) > 0" @click="confirmDelete(d)"><TrashBinIcon size="md" css="text-red-500" /></button>
</fwb-table-cell>
</fwb-table-row>
</fwb-table-body>
</fwb-table>
<DialogModal
:show="drawerEdit"
@close="closeEditDrawer"
>
<DialogModal :show="drawerEdit" @close="closeEditDrawer">
<template #title>
<span>Spremeni odločitev</span>
</template>
@@ -177,10 +212,7 @@ const store = () => {
</template>
</DialogModal>
<DialogModal
:show="drawerCreate"
@close="closeCreateDrawer"
>
<DialogModal :show="drawerCreate" @close="closeCreateDrawer">
<template #title>
<span>Dodaj odločitev</span>
</template>
@@ -237,4 +269,17 @@ const store = () => {
</form>
</template>
</DialogModal>
<ConfirmationModal :show="showDelete" @close="cancelDelete">
<template #title>
Delete decision
</template>
<template #content>
Are you sure you want to delete decision "{{ toDelete?.name }}"? This cannot be undone.
</template>
<template #footer>
<button @click="cancelDelete" class="px-4 py-2 rounded bg-gray-200 hover:bg-gray-300 me-2">Cancel</button>
<PrimaryButton @click="destroyDecision">Delete</PrimaryButton>
</template>
</ConfirmationModal>
</template>