diff --git a/app/Http/Controllers/FieldJobController.php b/app/Http/Controllers/FieldJobController.php index 92b79e5..51aa08c 100644 --- a/app/Http/Controllers/FieldJobController.php +++ b/app/Http/Controllers/FieldJobController.php @@ -62,7 +62,8 @@ public function index(Request $request) $unassignedClients = $unassignedContracts->get() ->pluck('clientCase.client') ->filter() - ->unique('id'); + ->unique('id') + ->values(); $assignedContracts = Contract::query() @@ -98,7 +99,8 @@ public function index(Request $request) $assignedClients = $assignedContracts->get() ->pluck('clientCase.client') ->filter() - ->unique('id'); + ->unique('id') + ->values(); $users = User::query()->orderBy('name')->get(['id', 'name']); diff --git a/config/jetstream.php b/config/jetstream.php index bff61fa..1fd04df 100644 --- a/config/jetstream.php +++ b/config/jetstream.php @@ -60,7 +60,7 @@ 'features' => [ // Features::termsAndPrivacyPolicy(), // Features::profilePhotos(), - Features::api(), + // Features::api(), // Features::teams(['invitations' => true]), Features::accountDeletion(), ], diff --git a/resources/js/Components/ConfirmsPassword.vue b/resources/js/Components/ConfirmsPassword.vue index 7b24493..e861e51 100644 --- a/resources/js/Components/ConfirmsPassword.vue +++ b/resources/js/Components/ConfirmsPassword.vue @@ -1,118 +1,118 @@ - - - - - - - - {{ title }} - - - - {{ content }} - - - - - - - - - - - Cancel - - - - {{ button }} - - - + + + + + + + {{ title }} + + + + {{ content }} + + + + + + + + + + Cancel + + + {{ button }} + + + + diff --git a/resources/js/Components/Layouts/NavMain.vue b/resources/js/Components/Layouts/NavMain.vue deleted file mode 100644 index e5261e3..0000000 --- a/resources/js/Components/Layouts/NavMain.vue +++ /dev/null @@ -1,70 +0,0 @@ - - - - - Platform - - - - - - - {{ item.title }} - - - - - - - - - {{ subItem.title }} - - - - - - - - - - diff --git a/resources/js/Components/PersonInfo/AddressCreateForm.vue b/resources/js/Components/PersonInfo/AddressCreateForm.vue index eb69b26..604e428 100644 --- a/resources/js/Components/PersonInfo/AddressCreateForm.vue +++ b/resources/js/Components/PersonInfo/AddressCreateForm.vue @@ -7,12 +7,7 @@ import { router } from "@inertiajs/vue3"; import CreateDialog from "../Dialogs/CreateDialog.vue"; import UpdateDialog from "../Dialogs/UpdateDialog.vue"; import SectionTitle from "../SectionTitle.vue"; -import { - FormControl, - FormItem, - FormLabel, - FormMessage, -} from "@/Components/ui/form"; +import { FormControl, FormItem, FormLabel, FormMessage } from "@/Components/ui/form"; import { Input } from "@/Components/ui/input"; import { Select, @@ -97,7 +92,7 @@ watch( country: a.country || "", post_code: a.post_code || a.postal_code || "", city: a.city || "", - type_id: a.type_id ?? (props.types?.[0]?.id ?? null), + type_id: a.type_id ?? props.types?.[0]?.id ?? null, description: a.description || "", }); return; @@ -108,52 +103,51 @@ watch( { immediate: true } ); -watch(() => props.show, (val) => { - if (val && props.edit && props.id) { - const a = props.person.addresses?.find((x) => x.id === props.id); - if (a) { - form.setValues({ - address: a.address || "", - country: a.country || "", - post_code: a.post_code || a.postal_code || "", - city: a.city || "", - type_id: a.type_id ?? (props.types?.[0]?.id ?? null), - description: a.description || "", - }); +watch( + () => props.show, + (val) => { + if (val && props.edit && props.id) { + const a = props.person.addresses?.find((x) => x.id === props.id); + if (a) { + form.setValues({ + address: a.address || "", + country: a.country || "", + post_code: a.post_code || a.postal_code || "", + city: a.city || "", + type_id: a.type_id ?? props.types?.[0]?.id ?? null, + description: a.description || "", + }); + } + } else if (val && !props.edit) { + resetForm(); } - } else if (val && !props.edit) { - resetForm(); } -}); +); const create = async () => { processing.value = true; const { values } = form; - router.post( - route("person.address.create", props.person), - values, - { - preserveScroll: true, - onSuccess: () => { - processing.value = false; - close(); - resetForm(); - }, - onError: (errors) => { - Object.keys(errors).forEach((field) => { - const errorMessages = Array.isArray(errors[field]) - ? errors[field] - : [errors[field]]; - form.setFieldError(field, errorMessages[0]); - }); - processing.value = false; - }, - onFinish: () => { - processing.value = false; - }, - } - ); + router.post(route("person.address.create", props.person), values, { + preserveScroll: true, + onSuccess: () => { + processing.value = false; + close(); + resetForm(); + }, + onError: (errors) => { + Object.keys(errors).forEach((field) => { + const errorMessages = Array.isArray(errors[field]) + ? errors[field] + : [errors[field]]; + form.setFieldError(field, errorMessages[0]); + }); + processing.value = false; + }, + onFinish: () => { + processing.value = false; + }, + }); }; const update = async () => { @@ -223,7 +217,12 @@ const onConfirm = () => { Naslov - + @@ -233,7 +232,12 @@ const onConfirm = () => { Država - + @@ -243,7 +247,12 @@ const onConfirm = () => { Poštna številka - + @@ -253,7 +262,22 @@ const onConfirm = () => { Mesto - + + + + + + + + + Opis + + diff --git a/resources/js/Components/PersonInfo/AddressUpdateForm.vue b/resources/js/Components/PersonInfo/AddressUpdateForm.vue index f63683d..71166b8 100644 --- a/resources/js/Components/PersonInfo/AddressUpdateForm.vue +++ b/resources/js/Components/PersonInfo/AddressUpdateForm.vue @@ -6,12 +6,7 @@ import * as z from "zod"; import { router } from "@inertiajs/vue3"; import UpdateDialog from "../Dialogs/UpdateDialog.vue"; import SectionTitle from "../SectionTitle.vue"; -import { - FormControl, - FormItem, - FormLabel, - FormMessage, -} from "@/Components/ui/form"; +import { FormControl, FormItem, FormLabel, FormMessage } from "@/Components/ui/form"; import { Input } from "@/Components/ui/input"; import { Select, @@ -85,7 +80,7 @@ const hydrate = () => { country: a.country || "", post_code: a.post_code || a.postal_code || "", city: a.city || "", - type_id: a.type_id ?? (props.types?.[0]?.id ?? null), + type_id: a.type_id ?? props.types?.[0]?.id ?? null, description: a.description || "", }); return; @@ -94,10 +89,17 @@ const hydrate = () => { resetForm(); }; -watch(() => props.id, () => hydrate(), { immediate: true }); -watch(() => props.show, (v) => { - if (v) hydrate(); -}); +watch( + () => props.id, + () => hydrate(), + { immediate: true } +); +watch( + () => props.show, + (v) => { + if (v) hydrate(); + } +); const update = async () => { processing.value = true; @@ -157,7 +159,12 @@ const onConfirm = () => { Naslov - + @@ -167,7 +174,12 @@ const onConfirm = () => { Država - + @@ -177,7 +189,12 @@ const onConfirm = () => { Poštna številka - + @@ -187,7 +204,22 @@ const onConfirm = () => { Mesto - + + + + + + + + + Opis + + diff --git a/resources/js/Components/PersonInfo/PersonInfoAddressesTab.vue b/resources/js/Components/PersonInfo/PersonInfoAddressesTab.vue index 20bada4..1d64af3 100644 --- a/resources/js/Components/PersonInfo/PersonInfoAddressesTab.vue +++ b/resources/js/Components/PersonInfo/PersonInfoAddressesTab.vue @@ -24,9 +24,9 @@ const handleDelete = (id, label) => emit("delete", id, label); - - - + + + @@ -61,13 +61,16 @@ const handleDelete = (id, label) => emit("delete", id, label); - + {{ address.post_code && address.city ? `${address.address}, ${address.post_code} ${address.city}` : address.address }} + + {{ address.description }} + emit("delete", id, label); - - - + + + emit("delete", id, label); - + {{ email?.value || email?.email || email?.address || "-" }} emit("sms", phone); - - - + + + @@ -79,9 +79,12 @@ const handleSms = (phone) => emit("sms", phone); - + {{ phone.nu }} + + {{ phone.description }} + { processing.value = true; const { values } = form; - router.post( - route("person.phone.create", props.person), - values, - { - preserveScroll: true, - onSuccess: () => { - close(); - resetForm(); - }, - onError: (errors) => { - Object.keys(errors).forEach((field) => { - const errorMessages = Array.isArray(errors[field]) - ? errors[field] - : [errors[field]]; - form.setFieldError(field, errorMessages[0]); - }); - processing.value = false; - }, - onFinish: () => { - processing.value = false; - }, - } - ); + router.post(route("person.phone.create", props.person), values, { + preserveScroll: true, + onSuccess: () => { + close(); + resetForm(); + }, + onError: (errors) => { + Object.keys(errors).forEach((field) => { + const errorMessages = Array.isArray(errors[field]) + ? errors[field] + : [errors[field]]; + form.setFieldError(field, errorMessages[0]); + }); + processing.value = false; + }, + onFinish: () => { + processing.value = false; + }, + }); }; const onSubmit = form.handleSubmit(() => { @@ -150,7 +141,12 @@ const onSubmit = form.handleSubmit(() => { Številka - + @@ -166,7 +162,11 @@ const onSubmit = form.handleSubmit(() => { - + {{ option.label }} @@ -204,7 +204,11 @@ const onSubmit = form.handleSubmit(() => { - + {{ option.label }} @@ -213,6 +217,16 @@ const onSubmit = form.handleSubmit(() => { + + + Opis + + + + + + + diff --git a/resources/js/Components/PersonInfo/PhoneUpdateForm.vue b/resources/js/Components/PersonInfo/PhoneUpdateForm.vue index c6c7a06..c30be34 100644 --- a/resources/js/Components/PersonInfo/PhoneUpdateForm.vue +++ b/resources/js/Components/PersonInfo/PhoneUpdateForm.vue @@ -6,12 +6,7 @@ import * as z from "zod"; import { router } from "@inertiajs/vue3"; import UpdateDialog from "../Dialogs/UpdateDialog.vue"; import SectionTitle from "../SectionTitle.vue"; -import { - FormControl, - FormItem, - FormLabel, - FormMessage, -} from "@/Components/ui/form"; +import { FormControl, FormItem, FormLabel, FormMessage } from "@/Components/ui/form"; import { Input } from "@/Components/ui/input"; import { Select, @@ -108,7 +103,7 @@ function hydrateFromProps() { form.setValues({ nu: p.nu || "", country_code: p.country_code ?? 386, - type_id: p.type_id ?? (props.types?.[0]?.id ?? null), + type_id: p.type_id ?? props.types?.[0]?.id ?? null, description: p.description || "", validated: !!p.validated, phone_type: p.phone_type ?? null, @@ -119,8 +114,17 @@ function hydrateFromProps() { resetForm(); } -watch(() => props.id, () => hydrateFromProps(), { immediate: true }); -watch(() => props.show, (val) => { if (val) hydrateFromProps(); }); +watch( + () => props.id, + () => hydrateFromProps(), + { immediate: true } +); +watch( + () => props.show, + (val) => { + if (val) hydrateFromProps(); + } +); const update = async () => { processing.value = true; @@ -175,7 +179,12 @@ const onSubmit = form.handleSubmit(() => { Številka - + @@ -191,7 +200,11 @@ const onSubmit = form.handleSubmit(() => { - + {{ option.label }} @@ -229,7 +242,11 @@ const onSubmit = form.handleSubmit(() => { - + {{ option.label }} @@ -238,6 +255,16 @@ const onSubmit = form.handleSubmit(() => { + + + Opis + + + + + + + diff --git a/resources/js/Components/ui/field/Field.vue b/resources/js/Components/ui/field/Field.vue new file mode 100644 index 0000000..f1eb945 --- /dev/null +++ b/resources/js/Components/ui/field/Field.vue @@ -0,0 +1,20 @@ + + + + + + + diff --git a/resources/js/Components/ui/field/FieldContent.vue b/resources/js/Components/ui/field/FieldContent.vue new file mode 100644 index 0000000..23af8c5 --- /dev/null +++ b/resources/js/Components/ui/field/FieldContent.vue @@ -0,0 +1,21 @@ + + + + + + + diff --git a/resources/js/Components/ui/field/FieldDescription.vue b/resources/js/Components/ui/field/FieldDescription.vue new file mode 100644 index 0000000..e10c129 --- /dev/null +++ b/resources/js/Components/ui/field/FieldDescription.vue @@ -0,0 +1,23 @@ + + + + + + + diff --git a/resources/js/Components/ui/field/FieldError.vue b/resources/js/Components/ui/field/FieldError.vue new file mode 100644 index 0000000..92b3b00 --- /dev/null +++ b/resources/js/Components/ui/field/FieldError.vue @@ -0,0 +1,43 @@ + + + + + + + + {{ content }} + + + + + {{ error?.message }} + + + + diff --git a/resources/js/Components/ui/field/FieldGroup.vue b/resources/js/Components/ui/field/FieldGroup.vue new file mode 100644 index 0000000..f471d40 --- /dev/null +++ b/resources/js/Components/ui/field/FieldGroup.vue @@ -0,0 +1,21 @@ + + + + + + + diff --git a/resources/js/Components/ui/field/FieldLabel.vue b/resources/js/Components/ui/field/FieldLabel.vue new file mode 100644 index 0000000..74f0469 --- /dev/null +++ b/resources/js/Components/ui/field/FieldLabel.vue @@ -0,0 +1,24 @@ + + + + + + + diff --git a/resources/js/Components/ui/field/FieldLegend.vue b/resources/js/Components/ui/field/FieldLegend.vue new file mode 100644 index 0000000..3ef8750 --- /dev/null +++ b/resources/js/Components/ui/field/FieldLegend.vue @@ -0,0 +1,25 @@ + + + + + + + diff --git a/resources/js/Components/ui/field/FieldSeparator.vue b/resources/js/Components/ui/field/FieldSeparator.vue new file mode 100644 index 0000000..064e0ff --- /dev/null +++ b/resources/js/Components/ui/field/FieldSeparator.vue @@ -0,0 +1,30 @@ + + + + + + + + + + diff --git a/resources/js/Components/ui/field/FieldSet.vue b/resources/js/Components/ui/field/FieldSet.vue new file mode 100644 index 0000000..f7d81d5 --- /dev/null +++ b/resources/js/Components/ui/field/FieldSet.vue @@ -0,0 +1,22 @@ + + + + + + + diff --git a/resources/js/Components/ui/field/FieldTitle.vue b/resources/js/Components/ui/field/FieldTitle.vue new file mode 100644 index 0000000..0ec8c8f --- /dev/null +++ b/resources/js/Components/ui/field/FieldTitle.vue @@ -0,0 +1,21 @@ + + + + + + + diff --git a/resources/js/Components/ui/field/index.js b/resources/js/Components/ui/field/index.js new file mode 100644 index 0000000..ed28078 --- /dev/null +++ b/resources/js/Components/ui/field/index.js @@ -0,0 +1,36 @@ +import { cva } from "class-variance-authority"; + +export const fieldVariants = cva( + "group/field flex w-full gap-3 data-[invalid=true]:text-destructive", + { + variants: { + orientation: { + vertical: ["flex-col [&>*]:w-full [&>.sr-only]:w-auto"], + horizontal: [ + "flex-row items-center", + "[&>[data-slot=field-label]]:flex-auto", + "has-[>[data-slot=field-content]]:items-start has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px", + ], + responsive: [ + "flex-col [&>*]:w-full [&>.sr-only]:w-auto @md/field-group:flex-row @md/field-group:items-center @md/field-group:[&>*]:w-auto", + "@md/field-group:[&>[data-slot=field-label]]:flex-auto", + "@md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px", + ], + }, + }, + defaultVariants: { + orientation: "vertical", + }, + }, +); + +export { default as Field } from "./Field.vue"; +export { default as FieldContent } from "./FieldContent.vue"; +export { default as FieldDescription } from "./FieldDescription.vue"; +export { default as FieldError } from "./FieldError.vue"; +export { default as FieldGroup } from "./FieldGroup.vue"; +export { default as FieldLabel } from "./FieldLabel.vue"; +export { default as FieldLegend } from "./FieldLegend.vue"; +export { default as FieldSeparator } from "./FieldSeparator.vue"; +export { default as FieldSet } from "./FieldSet.vue"; +export { default as FieldTitle } from "./FieldTitle.vue"; diff --git a/resources/js/Components/ui/select/SelectContent.vue b/resources/js/Components/ui/select/SelectContent.vue index f9cfbc8..2d54dd7 100644 --- a/resources/js/Components/ui/select/SelectContent.vue +++ b/resources/js/Components/ui/select/SelectContent.vue @@ -36,6 +36,7 @@ const props = defineProps({ reference: { type: null, required: false }, asChild: { type: Boolean, required: false }, as: { type: null, required: false }, + disableOutsidePointerEvents: { type: Boolean, required: false }, class: { type: null, required: false }, }); const emits = defineEmits([ diff --git a/resources/js/Layouts/Partials/GlobalSearch.vue b/resources/js/Layouts/Partials/GlobalSearch.vue index 6522c69..36229b4 100644 --- a/resources/js/Layouts/Partials/GlobalSearch.vue +++ b/resources/js/Layouts/Partials/GlobalSearch.vue @@ -1,8 +1,18 @@ - - - - - - (isOpen = v)"> + + + + + + + + + + + + + Začni tipkati za iskanje. + + Namig: uporabi Ctrl + + K + + + + + - - - - - - - - ESC - - - + Naročniki + {{ result.clients.length }} - - + - Začni tipkati za iskanje. - - Namig: uporabi - Ctrl - + - K - - - - - - Naročniki - {{ result.clients.length }} - - - - - C - {{ client.full_name }} - - - - - - - Primeri - {{ result.client_cases.length }} - - - - - - {{ clientcase.full_name }} - - - - {{ clientcase.contract_reference }} - - - - - - {{ seg.name || seg }} - - - - - {{ seg.name }} - - - - - - C - Ni rezultatov. - - + {{ client.full_name }} + + + + + + + + Primeri + {{ result.client_cases.length }} + + + + + + + {{ clientcase.full_name }} + + + Naročnik: {{ clientcase.client_full_name }} + + + + + {{ clientcase.contract_reference }} + + + + + + {{ seg.name || seg }} + + + + + + + {{ seg.name }} + + + + + + + + + + + Ni rezultatov. + - - + + - - diff --git a/resources/js/Pages/Cases/Partials/ContractMetaEditDialog.vue b/resources/js/Pages/Cases/Partials/ContractMetaEditDialog.vue new file mode 100644 index 0000000..d61581d --- /dev/null +++ b/resources/js/Pages/Cases/Partials/ContractMetaEditDialog.vue @@ -0,0 +1,229 @@ + + + + + + Uredi Meta podatke + + + Posodobi meta podatke za pogodbo {{ contract?.reference }} + + + + + + + + + + Naziv + + + + + + Tip + + + + + + Tekst + Številka + Datum + + + + + + Vrednost + + + + + + + + + + + + + + + Dodaj vnos + + + + + + + + Prekliči + + + {{ processing ? "Shranjujem..." : "Shrani" }} + + + + + diff --git a/resources/js/Pages/Cases/Partials/ContractTable.vue b/resources/js/Pages/Cases/Partials/ContractTable.vue index d9d1cc5..aaf862b 100644 --- a/resources/js/Pages/Cases/Partials/ContractTable.vue +++ b/resources/js/Pages/Cases/Partials/ContractTable.vue @@ -15,6 +15,7 @@ import CaseObjectCreateDialog from "./CaseObjectCreateDialog.vue"; import CaseObjectsDialog from "./CaseObjectsDialog.vue"; import PaymentDialog from "./PaymentDialog.vue"; import ViewPaymentsDialog from "./ViewPaymentsDialog.vue"; +import ContractMetaEditDialog from "./ContractMetaEditDialog.vue"; import CreateDialog from "@/Components/Dialogs/CreateDialog.vue"; import ConfirmationDialog from "@/Components/Dialogs/ConfirmationDialog.vue"; import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; @@ -33,6 +34,16 @@ import { } from "@fortawesome/free-solid-svg-icons"; import EmptyState from "@/Components/EmptyState.vue"; import { Button } from "@/Components/ui/button"; +import { Label } from "@/Components/ui/label"; +import { Input } from "@/Components/ui/input"; +import { Textarea } from "@/Components/ui/textarea"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/Components/ui/select"; const props = defineProps({ client: { type: Object, default: null }, @@ -433,6 +444,19 @@ const closePaymentsDialog = () => { selectedContract.value = null; }; +// Meta edit dialog +const showMetaEditDialog = ref(false); + +const openMetaEditDialog = (c) => { + selectedContract.value = c; + showMetaEditDialog.value = true; +}; + +const closeMetaEditDialog = () => { + showMetaEditDialog.value = false; + selectedContract.value = null; +}; + // Columns configuration const columns = computed(() => [ { key: "reference", label: "Ref.", sortable: false, align: "center" }, @@ -638,6 +662,19 @@ const availableSegmentsCount = computed(() => { Ni meta podatkov. + + + + Uredi meta podatke + + @@ -901,6 +938,13 @@ const availableSegmentsCount = computed(() => { :edit="edit" /> + + { @confirm="submitGenerate" > - - Predloga - - Izberi predlogo... - - {{ t.name }} (v{{ t.version }}) - - + + Predloga + + + + + + + {{ t.name }} (v{{ t.version }}) + + + @@ -932,14 +976,30 @@ const availableSegmentsCount = computed(() => { Prilagojene vrednosti - - + + {{ token.replace(/^custom\./, "") }} - - + + @@ -948,26 +1008,30 @@ const availableSegmentsCount = computed(() => { - Naslovi - - Naslov stranke - - Stranka - Oseba primera - + Naslovi + + Naslov stranke + + + + + + Stranka + Oseba primera + + - - Naslov osebe - - Oseba primera - Stranka - + + Naslov osebe + + + + + + Oseba primera + Stranka + + diff --git a/resources/js/Pages/Cases/Show.vue b/resources/js/Pages/Cases/Show.vue index b6fae60..40912a7 100644 --- a/resources/js/Pages/Cases/Show.vue +++ b/resources/js/Pages/Cases/Show.vue @@ -210,14 +210,6 @@ const closeDrawer = () => { drawerAddActivity.value = false; }; -const showClientDetails = () => { - clientDetails.value = false; -}; - -const hideClietnDetails = () => { - clientDetails.value = true; -}; - // Attach segment to case const showAttachSegment = ref(false); const openAttachSegment = () => { diff --git a/resources/js/Pages/Client/Contracts.vue b/resources/js/Pages/Client/Contracts.vue index d2185d3..9a20b21 100644 --- a/resources/js/Pages/Client/Contracts.vue +++ b/resources/js/Pages/Client/Contracts.vue @@ -24,18 +24,31 @@ import DateRangePicker from "@/Components/DateRangePicker.vue"; import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; import { ButtonGroup } from "@/Components/ui/button-group"; import AppPopover from "@/Components/app/ui/AppPopover.vue"; -import { Filter, LinkIcon, FileDown } from "lucide-vue-next"; +import { Filter, LinkIcon, FileDown, LayoutIcon } from "lucide-vue-next"; import { Card } from "@/Components/ui/card"; import { Badge } from "@/Components/ui/badge"; import { hasPermission } from "@/Services/permissions"; import InputLabel from "@/Components/InputLabel.vue"; import { cn } from "@/lib/utils"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuLabel, + DropdownMenuTrigger, +} from "@/Components/ui/dropdown-menu"; +import { toNumber } from "lodash"; +import { FormControl, FormField, FormFieldArray, FormLabel } from "@/Components/ui/form"; +import { Field, FieldLabel } from "@/Components/ui/field"; +import { toTypedSchema } from "@vee-validate/zod"; +import { z } from "zod"; +import FormChangeSegment from "./Partials/FormChangeSegment.vue"; const props = defineProps({ client: Object, contracts: Object, filters: Object, - segments: Object, + segments: Array, types: Object, }); @@ -59,10 +72,20 @@ const selectedSegments = ref( : [] ); const filterPopoverOpen = ref(false); +const selectedContracts = ref([]); +const changeSegmentDialogOpen = ref(false); +const contractTable = ref(null); const exportDialogOpen = ref(false); const exportScope = ref("current"); -const exportColumns = ref(["reference", "customer", "address", "start", "segment", "balance"]); +const exportColumns = ref([ + "reference", + "customer", + "address", + "start", + "segment", + "balance", +]); const exportError = ref(""); const isExporting = ref(false); @@ -85,6 +108,12 @@ const allColumnsSelected = computed( const exportDisabled = computed( () => exportColumns.value.length === 0 || isExporting.value ); +const segmentSelectItems = computed(() => + props.segments.map((val, i) => ({ + label: val.name, + value: val.id, + })) +); function applyDateFilter() { filterPopoverOpen.value = false; @@ -288,6 +317,24 @@ function extractFilenameFromHeaders(headers) { const asciiMatch = disposition.match(/filename="?([^";]+)"?/i); return asciiMatch?.[1] || null; } + +function handleSelectionChange(selectedKeys) { + selectedContracts.value = selectedKeys.map((val, i) => { + const num = toNumber(val); + + return props.contracts.data[num].uuid; + }); +} + +function openDialogChangeSegment() { + changeSegmentDialogOpen.value = true; +} + +function clearContractTableSelected() { + if (contractTable.value) { + contractTable.value.clearSelection(); + } +} @@ -357,6 +404,7 @@ function extractFilenameFromHeaders(headers) { - + Izvozi v Excel + + + + + {{ table.getSelectedRowModel().rows.length }} + + Akcija + + + + + + Spremeni segment + + + + + Odznači izbrane + @@ -519,7 +595,7 @@ function extractFilenameFromHeaders(headers) { - + @@ -626,5 +702,15 @@ function extractFilenameFromHeaders(headers) { + + + + diff --git a/resources/js/Pages/Client/Partials/FormChangeSegment.vue b/resources/js/Pages/Client/Partials/FormChangeSegment.vue new file mode 100644 index 0000000..b149125 --- /dev/null +++ b/resources/js/Pages/Client/Partials/FormChangeSegment.vue @@ -0,0 +1,155 @@ + + + + + + + Spremeni segment pogodbam + + + + + + + + + Segment + Izberi segment za preusmeritev + + + + + + + + + Auto + + {{ segment.label }} + + + + + + + + + + + { + close(); + resetForm(); + } + " + > + Prekliči + + + Potrdi + + + + + + + diff --git a/resources/js/Pages/FieldJob/Index.vue b/resources/js/Pages/FieldJob/Index.vue index b9ccf58..e5cb0c0 100644 --- a/resources/js/Pages/FieldJob/Index.vue +++ b/resources/js/Pages/FieldJob/Index.vue @@ -30,14 +30,15 @@ import AppPopover from "@/Components/app/ui/AppPopover.vue"; import InputLabel from "@/Components/InputLabel.vue"; import AppMultiSelect from "@/Components/app/ui/AppMultiSelect.vue"; import AppCard from "@/Components/app/ui/card/AppCard.vue"; +import { toNumber } from "lodash"; const props = defineProps({ setting: Object, unassignedContracts: Object, assignedContracts: Object, users: Array, - unassignedClients: Array, - assignedClients: Array, + unassignedClients: [Array, Object], + assignedClients: [Array, Object], filters: Object, }); @@ -54,6 +55,8 @@ const filterAssignedSelectedClient = ref( : [] ); +const unassignedContractTable = ref(null); + const form = useForm({ contract_uuid: null, assigned_user_id: null, @@ -107,6 +110,14 @@ function toggleContractSelection(uuid, checked) { console.log(selectedContractUuids.value); } +function handleContractSelection(selected) { + selectedContractUuids.value = selected.map((val, i) => { + const num = toNumber(val); + + return props.unassignedContracts.data[num].uuid; + }); +} + // Format helpers (Slovenian formatting) // Initialize search and filter from URL params @@ -296,6 +307,7 @@ function assignSelected() { bulkForm.contract_uuids = selectedContractUuids.value; bulkForm.post(route("fieldjobs.assign-bulk"), { onSuccess: () => { + unassignedContractTable.value.clearSelection(); selectedContractUuids.value = []; bulkForm.contract_uuids = []; }, @@ -304,7 +316,11 @@ function assignSelected() { function cancelAssignment(contract) { const payload = { contract_uuid: contract.uuid }; - form.transform(() => payload).post(route("fieldjobs.cancel")); + form + .transform(() => payload) + .post(route("fieldjobs.cancel"), { + preserveScroll: true, + }); } // Column definitions for DataTableNew2 @@ -437,6 +453,7 @@ const assignedRows = computed(() => - toggleContractSelection(row.uuid, checked) - " - /> - 0" class="space-y-4"> + - + { + + + + + No active sessions found. This feature requires session data to be configured in your Laravel application. + + + diff --git a/resources/js/Pages/Segments/Show.vue b/resources/js/Pages/Segments/Show.vue index fea317a..3250385 100644 --- a/resources/js/Pages/Segments/Show.vue +++ b/resources/js/Pages/Segments/Show.vue @@ -1,10 +1,11 @@
+
{{ address.post_code && address.city ? `${address.address}, ${address.post_code} ${address.city}` : address.address }}
+ {{ address.description }} +
{{ email?.value || email?.email || email?.address || "-" }}
emit("sms", phone); - - - + + + @@ -79,9 +79,12 @@ const handleSms = (phone) => emit("sms", phone); - + {{ phone.nu }} + + {{ phone.description }} + { processing.value = true; const { values } = form; - router.post( - route("person.phone.create", props.person), - values, - { - preserveScroll: true, - onSuccess: () => { - close(); - resetForm(); - }, - onError: (errors) => { - Object.keys(errors).forEach((field) => { - const errorMessages = Array.isArray(errors[field]) - ? errors[field] - : [errors[field]]; - form.setFieldError(field, errorMessages[0]); - }); - processing.value = false; - }, - onFinish: () => { - processing.value = false; - }, - } - ); + router.post(route("person.phone.create", props.person), values, { + preserveScroll: true, + onSuccess: () => { + close(); + resetForm(); + }, + onError: (errors) => { + Object.keys(errors).forEach((field) => { + const errorMessages = Array.isArray(errors[field]) + ? errors[field] + : [errors[field]]; + form.setFieldError(field, errorMessages[0]); + }); + processing.value = false; + }, + onFinish: () => { + processing.value = false; + }, + }); }; const onSubmit = form.handleSubmit(() => { @@ -150,7 +141,12 @@ const onSubmit = form.handleSubmit(() => { Številka - + @@ -166,7 +162,11 @@ const onSubmit = form.handleSubmit(() => { - + {{ option.label }} @@ -204,7 +204,11 @@ const onSubmit = form.handleSubmit(() => { - + {{ option.label }} @@ -213,6 +217,16 @@ const onSubmit = form.handleSubmit(() => { + + + Opis + + + + + + + diff --git a/resources/js/Components/PersonInfo/PhoneUpdateForm.vue b/resources/js/Components/PersonInfo/PhoneUpdateForm.vue index c6c7a06..c30be34 100644 --- a/resources/js/Components/PersonInfo/PhoneUpdateForm.vue +++ b/resources/js/Components/PersonInfo/PhoneUpdateForm.vue @@ -6,12 +6,7 @@ import * as z from "zod"; import { router } from "@inertiajs/vue3"; import UpdateDialog from "../Dialogs/UpdateDialog.vue"; import SectionTitle from "../SectionTitle.vue"; -import { - FormControl, - FormItem, - FormLabel, - FormMessage, -} from "@/Components/ui/form"; +import { FormControl, FormItem, FormLabel, FormMessage } from "@/Components/ui/form"; import { Input } from "@/Components/ui/input"; import { Select, @@ -108,7 +103,7 @@ function hydrateFromProps() { form.setValues({ nu: p.nu || "", country_code: p.country_code ?? 386, - type_id: p.type_id ?? (props.types?.[0]?.id ?? null), + type_id: p.type_id ?? props.types?.[0]?.id ?? null, description: p.description || "", validated: !!p.validated, phone_type: p.phone_type ?? null, @@ -119,8 +114,17 @@ function hydrateFromProps() { resetForm(); } -watch(() => props.id, () => hydrateFromProps(), { immediate: true }); -watch(() => props.show, (val) => { if (val) hydrateFromProps(); }); +watch( + () => props.id, + () => hydrateFromProps(), + { immediate: true } +); +watch( + () => props.show, + (val) => { + if (val) hydrateFromProps(); + } +); const update = async () => { processing.value = true; @@ -175,7 +179,12 @@ const onSubmit = form.handleSubmit(() => { Številka - + @@ -191,7 +200,11 @@ const onSubmit = form.handleSubmit(() => { - + {{ option.label }} @@ -229,7 +242,11 @@ const onSubmit = form.handleSubmit(() => { - + {{ option.label }} @@ -238,6 +255,16 @@ const onSubmit = form.handleSubmit(() => { + + + Opis + + + + + + + diff --git a/resources/js/Components/ui/field/Field.vue b/resources/js/Components/ui/field/Field.vue new file mode 100644 index 0000000..f1eb945 --- /dev/null +++ b/resources/js/Components/ui/field/Field.vue @@ -0,0 +1,20 @@ + + + + + + + diff --git a/resources/js/Components/ui/field/FieldContent.vue b/resources/js/Components/ui/field/FieldContent.vue new file mode 100644 index 0000000..23af8c5 --- /dev/null +++ b/resources/js/Components/ui/field/FieldContent.vue @@ -0,0 +1,21 @@ + + + + + + + diff --git a/resources/js/Components/ui/field/FieldDescription.vue b/resources/js/Components/ui/field/FieldDescription.vue new file mode 100644 index 0000000..e10c129 --- /dev/null +++ b/resources/js/Components/ui/field/FieldDescription.vue @@ -0,0 +1,23 @@ + + + + + + + diff --git a/resources/js/Components/ui/field/FieldError.vue b/resources/js/Components/ui/field/FieldError.vue new file mode 100644 index 0000000..92b3b00 --- /dev/null +++ b/resources/js/Components/ui/field/FieldError.vue @@ -0,0 +1,43 @@ + + + + + + + + {{ content }} + + + + + {{ error?.message }} + + + + diff --git a/resources/js/Components/ui/field/FieldGroup.vue b/resources/js/Components/ui/field/FieldGroup.vue new file mode 100644 index 0000000..f471d40 --- /dev/null +++ b/resources/js/Components/ui/field/FieldGroup.vue @@ -0,0 +1,21 @@ + + + + + + + diff --git a/resources/js/Components/ui/field/FieldLabel.vue b/resources/js/Components/ui/field/FieldLabel.vue new file mode 100644 index 0000000..74f0469 --- /dev/null +++ b/resources/js/Components/ui/field/FieldLabel.vue @@ -0,0 +1,24 @@ + + + + + + + diff --git a/resources/js/Components/ui/field/FieldLegend.vue b/resources/js/Components/ui/field/FieldLegend.vue new file mode 100644 index 0000000..3ef8750 --- /dev/null +++ b/resources/js/Components/ui/field/FieldLegend.vue @@ -0,0 +1,25 @@ + + + + + + + diff --git a/resources/js/Components/ui/field/FieldSeparator.vue b/resources/js/Components/ui/field/FieldSeparator.vue new file mode 100644 index 0000000..064e0ff --- /dev/null +++ b/resources/js/Components/ui/field/FieldSeparator.vue @@ -0,0 +1,30 @@ + + + + + + + + + + diff --git a/resources/js/Components/ui/field/FieldSet.vue b/resources/js/Components/ui/field/FieldSet.vue new file mode 100644 index 0000000..f7d81d5 --- /dev/null +++ b/resources/js/Components/ui/field/FieldSet.vue @@ -0,0 +1,22 @@ + + + + + + + diff --git a/resources/js/Components/ui/field/FieldTitle.vue b/resources/js/Components/ui/field/FieldTitle.vue new file mode 100644 index 0000000..0ec8c8f --- /dev/null +++ b/resources/js/Components/ui/field/FieldTitle.vue @@ -0,0 +1,21 @@ + + + + + + + diff --git a/resources/js/Components/ui/field/index.js b/resources/js/Components/ui/field/index.js new file mode 100644 index 0000000..ed28078 --- /dev/null +++ b/resources/js/Components/ui/field/index.js @@ -0,0 +1,36 @@ +import { cva } from "class-variance-authority"; + +export const fieldVariants = cva( + "group/field flex w-full gap-3 data-[invalid=true]:text-destructive", + { + variants: { + orientation: { + vertical: ["flex-col [&>*]:w-full [&>.sr-only]:w-auto"], + horizontal: [ + "flex-row items-center", + "[&>[data-slot=field-label]]:flex-auto", + "has-[>[data-slot=field-content]]:items-start has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px", + ], + responsive: [ + "flex-col [&>*]:w-full [&>.sr-only]:w-auto @md/field-group:flex-row @md/field-group:items-center @md/field-group:[&>*]:w-auto", + "@md/field-group:[&>[data-slot=field-label]]:flex-auto", + "@md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px", + ], + }, + }, + defaultVariants: { + orientation: "vertical", + }, + }, +); + +export { default as Field } from "./Field.vue"; +export { default as FieldContent } from "./FieldContent.vue"; +export { default as FieldDescription } from "./FieldDescription.vue"; +export { default as FieldError } from "./FieldError.vue"; +export { default as FieldGroup } from "./FieldGroup.vue"; +export { default as FieldLabel } from "./FieldLabel.vue"; +export { default as FieldLegend } from "./FieldLegend.vue"; +export { default as FieldSeparator } from "./FieldSeparator.vue"; +export { default as FieldSet } from "./FieldSet.vue"; +export { default as FieldTitle } from "./FieldTitle.vue"; diff --git a/resources/js/Components/ui/select/SelectContent.vue b/resources/js/Components/ui/select/SelectContent.vue index f9cfbc8..2d54dd7 100644 --- a/resources/js/Components/ui/select/SelectContent.vue +++ b/resources/js/Components/ui/select/SelectContent.vue @@ -36,6 +36,7 @@ const props = defineProps({ reference: { type: null, required: false }, asChild: { type: Boolean, required: false }, as: { type: null, required: false }, + disableOutsidePointerEvents: { type: Boolean, required: false }, class: { type: null, required: false }, }); const emits = defineEmits([ diff --git a/resources/js/Layouts/Partials/GlobalSearch.vue b/resources/js/Layouts/Partials/GlobalSearch.vue index 6522c69..36229b4 100644 --- a/resources/js/Layouts/Partials/GlobalSearch.vue +++ b/resources/js/Layouts/Partials/GlobalSearch.vue @@ -1,8 +1,18 @@ - - - - - - (isOpen = v)"> + + + + + + + + + + + + + Začni tipkati za iskanje. + + Namig: uporabi Ctrl + + K + + + + + - - - - - - - - ESC - - - + Naročniki + {{ result.clients.length }} - - + - Začni tipkati za iskanje. - - Namig: uporabi - Ctrl - + - K - - - - - - Naročniki - {{ result.clients.length }} - - - - - C - {{ client.full_name }} - - - - - - - Primeri - {{ result.client_cases.length }} - - - - - - {{ clientcase.full_name }} - - - - {{ clientcase.contract_reference }} - - - - - - {{ seg.name || seg }} - - - - - {{ seg.name }} - - - - - - C - Ni rezultatov. - - + {{ client.full_name }} + + + + + + + + Primeri + {{ result.client_cases.length }} + + + + + + + {{ clientcase.full_name }} + + + Naročnik: {{ clientcase.client_full_name }} + + + + + {{ clientcase.contract_reference }} + + + + + + {{ seg.name || seg }} + + + + + + + {{ seg.name }} + + + + + + + + + + + Ni rezultatov. + - - + + - - diff --git a/resources/js/Pages/Cases/Partials/ContractMetaEditDialog.vue b/resources/js/Pages/Cases/Partials/ContractMetaEditDialog.vue new file mode 100644 index 0000000..d61581d --- /dev/null +++ b/resources/js/Pages/Cases/Partials/ContractMetaEditDialog.vue @@ -0,0 +1,229 @@ + + + + + + Uredi Meta podatke + + + Posodobi meta podatke za pogodbo {{ contract?.reference }} + + + + + + + + + + Naziv + + + + + + Tip + + + + + + Tekst + Številka + Datum + + + + + + Vrednost + + + + + + + + + + + + + + + Dodaj vnos + + + + + + + + Prekliči + + + {{ processing ? "Shranjujem..." : "Shrani" }} + + + + + diff --git a/resources/js/Pages/Cases/Partials/ContractTable.vue b/resources/js/Pages/Cases/Partials/ContractTable.vue index d9d1cc5..aaf862b 100644 --- a/resources/js/Pages/Cases/Partials/ContractTable.vue +++ b/resources/js/Pages/Cases/Partials/ContractTable.vue @@ -15,6 +15,7 @@ import CaseObjectCreateDialog from "./CaseObjectCreateDialog.vue"; import CaseObjectsDialog from "./CaseObjectsDialog.vue"; import PaymentDialog from "./PaymentDialog.vue"; import ViewPaymentsDialog from "./ViewPaymentsDialog.vue"; +import ContractMetaEditDialog from "./ContractMetaEditDialog.vue"; import CreateDialog from "@/Components/Dialogs/CreateDialog.vue"; import ConfirmationDialog from "@/Components/Dialogs/ConfirmationDialog.vue"; import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; @@ -33,6 +34,16 @@ import { } from "@fortawesome/free-solid-svg-icons"; import EmptyState from "@/Components/EmptyState.vue"; import { Button } from "@/Components/ui/button"; +import { Label } from "@/Components/ui/label"; +import { Input } from "@/Components/ui/input"; +import { Textarea } from "@/Components/ui/textarea"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/Components/ui/select"; const props = defineProps({ client: { type: Object, default: null }, @@ -433,6 +444,19 @@ const closePaymentsDialog = () => { selectedContract.value = null; }; +// Meta edit dialog +const showMetaEditDialog = ref(false); + +const openMetaEditDialog = (c) => { + selectedContract.value = c; + showMetaEditDialog.value = true; +}; + +const closeMetaEditDialog = () => { + showMetaEditDialog.value = false; + selectedContract.value = null; +}; + // Columns configuration const columns = computed(() => [ { key: "reference", label: "Ref.", sortable: false, align: "center" }, @@ -638,6 +662,19 @@ const availableSegmentsCount = computed(() => { Ni meta podatkov. + + + + Uredi meta podatke + + @@ -901,6 +938,13 @@ const availableSegmentsCount = computed(() => { :edit="edit" /> + + { @confirm="submitGenerate" > - - Predloga - - Izberi predlogo... - - {{ t.name }} (v{{ t.version }}) - - + + Predloga + + + + + + + {{ t.name }} (v{{ t.version }}) + + + @@ -932,14 +976,30 @@ const availableSegmentsCount = computed(() => { Prilagojene vrednosti - - + + {{ token.replace(/^custom\./, "") }} - - + + @@ -948,26 +1008,30 @@ const availableSegmentsCount = computed(() => { - Naslovi - - Naslov stranke - - Stranka - Oseba primera - + Naslovi + + Naslov stranke + + + + + + Stranka + Oseba primera + + - - Naslov osebe - - Oseba primera - Stranka - + + Naslov osebe + + + + + + Oseba primera + Stranka + + diff --git a/resources/js/Pages/Cases/Show.vue b/resources/js/Pages/Cases/Show.vue index b6fae60..40912a7 100644 --- a/resources/js/Pages/Cases/Show.vue +++ b/resources/js/Pages/Cases/Show.vue @@ -210,14 +210,6 @@ const closeDrawer = () => { drawerAddActivity.value = false; }; -const showClientDetails = () => { - clientDetails.value = false; -}; - -const hideClietnDetails = () => { - clientDetails.value = true; -}; - // Attach segment to case const showAttachSegment = ref(false); const openAttachSegment = () => { diff --git a/resources/js/Pages/Client/Contracts.vue b/resources/js/Pages/Client/Contracts.vue index d2185d3..9a20b21 100644 --- a/resources/js/Pages/Client/Contracts.vue +++ b/resources/js/Pages/Client/Contracts.vue @@ -24,18 +24,31 @@ import DateRangePicker from "@/Components/DateRangePicker.vue"; import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; import { ButtonGroup } from "@/Components/ui/button-group"; import AppPopover from "@/Components/app/ui/AppPopover.vue"; -import { Filter, LinkIcon, FileDown } from "lucide-vue-next"; +import { Filter, LinkIcon, FileDown, LayoutIcon } from "lucide-vue-next"; import { Card } from "@/Components/ui/card"; import { Badge } from "@/Components/ui/badge"; import { hasPermission } from "@/Services/permissions"; import InputLabel from "@/Components/InputLabel.vue"; import { cn } from "@/lib/utils"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuLabel, + DropdownMenuTrigger, +} from "@/Components/ui/dropdown-menu"; +import { toNumber } from "lodash"; +import { FormControl, FormField, FormFieldArray, FormLabel } from "@/Components/ui/form"; +import { Field, FieldLabel } from "@/Components/ui/field"; +import { toTypedSchema } from "@vee-validate/zod"; +import { z } from "zod"; +import FormChangeSegment from "./Partials/FormChangeSegment.vue"; const props = defineProps({ client: Object, contracts: Object, filters: Object, - segments: Object, + segments: Array, types: Object, }); @@ -59,10 +72,20 @@ const selectedSegments = ref( : [] ); const filterPopoverOpen = ref(false); +const selectedContracts = ref([]); +const changeSegmentDialogOpen = ref(false); +const contractTable = ref(null); const exportDialogOpen = ref(false); const exportScope = ref("current"); -const exportColumns = ref(["reference", "customer", "address", "start", "segment", "balance"]); +const exportColumns = ref([ + "reference", + "customer", + "address", + "start", + "segment", + "balance", +]); const exportError = ref(""); const isExporting = ref(false); @@ -85,6 +108,12 @@ const allColumnsSelected = computed( const exportDisabled = computed( () => exportColumns.value.length === 0 || isExporting.value ); +const segmentSelectItems = computed(() => + props.segments.map((val, i) => ({ + label: val.name, + value: val.id, + })) +); function applyDateFilter() { filterPopoverOpen.value = false; @@ -288,6 +317,24 @@ function extractFilenameFromHeaders(headers) { const asciiMatch = disposition.match(/filename="?([^";]+)"?/i); return asciiMatch?.[1] || null; } + +function handleSelectionChange(selectedKeys) { + selectedContracts.value = selectedKeys.map((val, i) => { + const num = toNumber(val); + + return props.contracts.data[num].uuid; + }); +} + +function openDialogChangeSegment() { + changeSegmentDialogOpen.value = true; +} + +function clearContractTableSelected() { + if (contractTable.value) { + contractTable.value.clearSelection(); + } +} @@ -357,6 +404,7 @@ function extractFilenameFromHeaders(headers) { - + Izvozi v Excel + + + + + {{ table.getSelectedRowModel().rows.length }} + + Akcija + + + + + + Spremeni segment + + + + + Odznači izbrane + @@ -519,7 +595,7 @@ function extractFilenameFromHeaders(headers) { - + @@ -626,5 +702,15 @@ function extractFilenameFromHeaders(headers) { + + + + diff --git a/resources/js/Pages/Client/Partials/FormChangeSegment.vue b/resources/js/Pages/Client/Partials/FormChangeSegment.vue new file mode 100644 index 0000000..b149125 --- /dev/null +++ b/resources/js/Pages/Client/Partials/FormChangeSegment.vue @@ -0,0 +1,155 @@ + + + + + + + Spremeni segment pogodbam + + + + + + + + + Segment + Izberi segment za preusmeritev + + + + + + + + + Auto + + {{ segment.label }} + + + + + + + + + + + { + close(); + resetForm(); + } + " + > + Prekliči + + + Potrdi + + + + + + + diff --git a/resources/js/Pages/FieldJob/Index.vue b/resources/js/Pages/FieldJob/Index.vue index b9ccf58..e5cb0c0 100644 --- a/resources/js/Pages/FieldJob/Index.vue +++ b/resources/js/Pages/FieldJob/Index.vue @@ -30,14 +30,15 @@ import AppPopover from "@/Components/app/ui/AppPopover.vue"; import InputLabel from "@/Components/InputLabel.vue"; import AppMultiSelect from "@/Components/app/ui/AppMultiSelect.vue"; import AppCard from "@/Components/app/ui/card/AppCard.vue"; +import { toNumber } from "lodash"; const props = defineProps({ setting: Object, unassignedContracts: Object, assignedContracts: Object, users: Array, - unassignedClients: Array, - assignedClients: Array, + unassignedClients: [Array, Object], + assignedClients: [Array, Object], filters: Object, }); @@ -54,6 +55,8 @@ const filterAssignedSelectedClient = ref( : [] ); +const unassignedContractTable = ref(null); + const form = useForm({ contract_uuid: null, assigned_user_id: null, @@ -107,6 +110,14 @@ function toggleContractSelection(uuid, checked) { console.log(selectedContractUuids.value); } +function handleContractSelection(selected) { + selectedContractUuids.value = selected.map((val, i) => { + const num = toNumber(val); + + return props.unassignedContracts.data[num].uuid; + }); +} + // Format helpers (Slovenian formatting) // Initialize search and filter from URL params @@ -296,6 +307,7 @@ function assignSelected() { bulkForm.contract_uuids = selectedContractUuids.value; bulkForm.post(route("fieldjobs.assign-bulk"), { onSuccess: () => { + unassignedContractTable.value.clearSelection(); selectedContractUuids.value = []; bulkForm.contract_uuids = []; }, @@ -304,7 +316,11 @@ function assignSelected() { function cancelAssignment(contract) { const payload = { contract_uuid: contract.uuid }; - form.transform(() => payload).post(route("fieldjobs.cancel")); + form + .transform(() => payload) + .post(route("fieldjobs.cancel"), { + preserveScroll: true, + }); } // Column definitions for DataTableNew2 @@ -437,6 +453,7 @@ const assignedRows = computed(() => - toggleContractSelection(row.uuid, checked) - " - /> - 0" class="space-y-4"> + - + { + + + + + No active sessions found. This feature requires session data to be configured in your Laravel application. + + + diff --git a/resources/js/Pages/Segments/Show.vue b/resources/js/Pages/Segments/Show.vue index fea317a..3250385 100644 --- a/resources/js/Pages/Segments/Show.vue +++ b/resources/js/Pages/Segments/Show.vue @@ -1,10 +1,11 @@
{{ phone.nu }}
+ {{ phone.description }} +
+ +
Začni tipkati za iskanje.
+ Namig: uporabi Ctrl + + K +
- Namig: uporabi - Ctrl - + - K -
+ No active sessions found. This feature requires session data to be configured in your Laravel application. +