Dev branch
This commit is contained in:
@@ -1,12 +1,21 @@
|
||||
<script setup>
|
||||
import ActionMessage from "@/Components/ActionMessage.vue";
|
||||
import BasicButton from "@/Components/buttons/BasicButton.vue";
|
||||
import DialogModal from "@/Components/DialogModal.vue";
|
||||
import InputLabel from "@/Components/InputLabel.vue";
|
||||
import DatePickerField from "@/Components/DatePickerField.vue";
|
||||
import CreateDialog from "@/Components/Dialogs/CreateDialog.vue";
|
||||
import DatePicker from "@/Components/DatePicker.vue";
|
||||
import CurrencyInput from "@/Components/CurrencyInput.vue";
|
||||
import { useForm, usePage } from "@inertiajs/vue3";
|
||||
import { FwbTextarea } from "flowbite-vue";
|
||||
import { useForm as useInertiaForm, usePage, router } from "@inertiajs/vue3";
|
||||
// Note: This form uses Inertia's useForm for API calls but shadcn-vue components for UI
|
||||
import { Textarea } from "@/Components/ui/textarea";
|
||||
import { Label } from "@/Components/ui/label";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/Components/ui/select";
|
||||
import { Checkbox } from "@/Components/ui/checkbox";
|
||||
import { ref, watch, computed } from "vue";
|
||||
|
||||
const props = defineProps({
|
||||
@@ -15,7 +24,6 @@ const props = defineProps({
|
||||
actions: { type: Array, default: () => [] },
|
||||
contractUuid: { type: String, default: null },
|
||||
phoneMode: { type: Boolean, default: false },
|
||||
// Prefer passing these from parent (e.g., phone view) to avoid reliance on global page props in teleports
|
||||
documents: { type: Array, default: null },
|
||||
contracts: { type: Array, default: null },
|
||||
});
|
||||
@@ -31,7 +39,8 @@ const decisions = ref(
|
||||
const emit = defineEmits(["close", "saved"]);
|
||||
const close = () => emit("close");
|
||||
|
||||
const form = useForm({
|
||||
// Using Inertia's useForm for API calls, but wrapping fields with shadcn-vue components
|
||||
const form = useInertiaForm({
|
||||
due_date: null,
|
||||
amount: null,
|
||||
note: "",
|
||||
@@ -123,7 +132,6 @@ const store = async () => {
|
||||
onSuccess: () => {
|
||||
close();
|
||||
form.reset("due_date", "amount", "note");
|
||||
// Notify parent to react (e.g., refresh, redirect in phone mode when no contracts left)
|
||||
emit("saved");
|
||||
},
|
||||
});
|
||||
@@ -180,11 +188,9 @@ const isToday = (val) => {
|
||||
if (val instanceof Date) {
|
||||
d = val;
|
||||
} else if (typeof val === "string") {
|
||||
// Normalize common MySQL timestamp 'YYYY-MM-DD HH:mm:ss' for Safari/iOS
|
||||
const s = val.includes("T") ? val : val.replace(" ", "T");
|
||||
d = new Date(s);
|
||||
if (isNaN(d.getTime())) {
|
||||
// Fallback: parse manually as local date
|
||||
const m = val.match(/^(\d{4})-(\d{2})-(\d{2})[ T](\d{2}):(\d{2})(?::(\d{2}))?/);
|
||||
if (m) {
|
||||
const [_, yy, mm, dd, hh, mi, ss] = m;
|
||||
@@ -243,7 +249,13 @@ const pageContracts = computed(() => {
|
||||
if (Array.isArray(props.contracts)) {
|
||||
return props.contracts;
|
||||
}
|
||||
if (props.contracts?.data) {
|
||||
return props.contracts.data;
|
||||
}
|
||||
const propsVal = page?.props?.value || {};
|
||||
if (propsVal.contracts?.data) {
|
||||
return propsVal.contracts.data;
|
||||
}
|
||||
return Array.isArray(propsVal.contracts) ? propsVal.contracts : [];
|
||||
});
|
||||
|
||||
@@ -273,143 +285,149 @@ watch(
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DialogModal :show="show" @close="close">
|
||||
<template #title>Dodaj aktivnost</template>
|
||||
<template #content>
|
||||
<form @submit.prevent="store">
|
||||
<div class="col-span-6 sm:col-span-4">
|
||||
<InputLabel for="activityAction" value="Akcija" />
|
||||
<select
|
||||
class="block w-full border-gray-300 focus:border-indigo-500 focus:ring-indigo-500 rounded-md shadow-sm"
|
||||
id="activityAction"
|
||||
ref="activityActionSelect"
|
||||
v-model="form.action_id"
|
||||
:disabled="!actions || !actions.length"
|
||||
>
|
||||
<option v-for="a in actions" :key="a.id" :value="a.id">{{ a.name }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-span-6 sm:col-span-4">
|
||||
<InputLabel for="activityDecision" value="Odločitev" />
|
||||
<select
|
||||
class="block w-full border-gray-300 focus:border-indigo-500 focus:ring-indigo-500 rounded-md shadow-sm"
|
||||
id="activityDecision"
|
||||
ref="activityDecisionSelect"
|
||||
v-model="form.decision_id"
|
||||
:disabled="!decisions || !decisions.length"
|
||||
>
|
||||
<option v-for="d in decisions" :key="d.id" :value="d.id">{{ d.name }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-span-6 sm:col-span-4">
|
||||
<FwbTextarea
|
||||
label="Opomba"
|
||||
id="activityNote"
|
||||
ref="activityNoteTextarea"
|
||||
v-model="form.note"
|
||||
class="block w-full border-gray-300 focus:border-indigo-500 focus:ring-indigo-500 rounded-md shadow-sm"
|
||||
/>
|
||||
</div>
|
||||
<DatePickerField
|
||||
id="activityDueDate"
|
||||
label="Datum zapadlosti"
|
||||
v-model="form.due_date"
|
||||
format="dd.MM.yyyy"
|
||||
:enable-time-picker="false"
|
||||
:auto-position="true"
|
||||
:teleport-target="'body'"
|
||||
:inline="false"
|
||||
:auto-apply="true"
|
||||
:fixed="false"
|
||||
:close-on-auto-apply="true"
|
||||
:close-on-scroll="true"
|
||||
/>
|
||||
<div class="col-span-6 sm:col-span-4">
|
||||
<InputLabel for="activityAmount" value="Znesek" />
|
||||
<CurrencyInput
|
||||
id="activityAmount"
|
||||
ref="activityAmountinput"
|
||||
v-model="form.amount"
|
||||
:precision="{ min: 0, max: 4 }"
|
||||
placeholder="0,00"
|
||||
/>
|
||||
</div>
|
||||
<div class="mt-2" v-if="showSendAutoMail()">
|
||||
<div class="flex items-center justify-between">
|
||||
<label class="flex items-center gap-2 text-sm">
|
||||
<input
|
||||
type="checkbox"
|
||||
v-model="form.send_auto_mail"
|
||||
:disabled="autoMailDisabled"
|
||||
class="rounded border-gray-300 text-indigo-600 shadow-sm focus:ring-indigo-500 disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
/>
|
||||
<span>Send auto email</span>
|
||||
</label>
|
||||
<CreateDialog
|
||||
:show="show"
|
||||
title="Dodaj aktivnost"
|
||||
confirm-text="Shrani"
|
||||
:processing="form.processing"
|
||||
@close="close"
|
||||
@confirm="store"
|
||||
>
|
||||
<form @submit.prevent="store">
|
||||
<div class="space-y-4">
|
||||
<div class="space-y-2">
|
||||
<Label>Akcija</Label>
|
||||
<Select v-model="form.action_id" :disabled="!actions || !actions.length">
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Izberi akcijo" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem v-for="a in actions" :key="a.id" :value="a.id">
|
||||
{{ a.name }}
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<p v-if="autoMailDisabled" class="mt-1 text-xs text-amber-600">
|
||||
{{ autoMailDisabledHint }}
|
||||
</p>
|
||||
|
||||
<div v-if="templateAllowsAttachments && form.contract_uuid" class="mt-3">
|
||||
<label class="inline-flex items-center gap-2">
|
||||
<input type="checkbox" v-model="form.attach_documents" />
|
||||
<span class="text-sm">Dodaj priponke iz izbrane pogodbe</span>
|
||||
</label>
|
||||
<div
|
||||
v-if="form.attach_documents"
|
||||
class="mt-2 border rounded p-2 max-h-48 overflow-auto"
|
||||
>
|
||||
<div class="text-xs text-gray-600 mb-2">
|
||||
Izberite dokumente, ki bodo poslani kot priponke:
|
||||
<div class="space-y-2">
|
||||
<Label>Odločitev</Label>
|
||||
<Select v-model="form.decision_id" :disabled="!decisions || !decisions.length">
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Izberi odločitev" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem v-for="d in decisions" :key="d.id" :value="d.id">
|
||||
{{ d.name }}
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<div class="space-y-2">
|
||||
<Label for="activityNote">Opomba</Label>
|
||||
<Textarea
|
||||
id="activityNote"
|
||||
v-model="form.note"
|
||||
class="block w-full"
|
||||
placeholder="Opomba"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="space-y-2">
|
||||
<Label for="activityDueDate">Datum zapadlosti</Label>
|
||||
<DatePicker
|
||||
id="activityDueDate"
|
||||
v-model="form.due_date"
|
||||
format="dd.MM.yyyy"
|
||||
:error="form.errors.due_date"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="space-y-2">
|
||||
<Label for="activityAmount">Znesek</Label>
|
||||
<CurrencyInput
|
||||
id="activityAmount"
|
||||
v-model="form.amount"
|
||||
:precision="{ min: 0, max: 4 }"
|
||||
placeholder="0,00"
|
||||
class="w-full"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div v-if="showSendAutoMail()" class="space-y-2">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center space-x-2">
|
||||
<Checkbox
|
||||
v-model="form.send_auto_mail"
|
||||
:disabled="autoMailDisabled"
|
||||
/>
|
||||
<Label class="cursor-pointer">Send auto email</Label>
|
||||
</div>
|
||||
<div class="space-y-1">
|
||||
<template v-for="c in pageContracts" :key="c.uuid || c.id">
|
||||
<div v-if="c.uuid === form.contract_uuid">
|
||||
<div class="font-medium text-sm text-gray-700 mb-1">
|
||||
Pogodba {{ c.reference }}
|
||||
</div>
|
||||
<div class="space-y-1">
|
||||
<div
|
||||
v-for="doc in availableContractDocs"
|
||||
:key="doc.uuid || doc.id"
|
||||
class="flex items-center gap-2 text-sm"
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
:value="doc.id"
|
||||
v-model="form.attachment_document_ids"
|
||||
/>
|
||||
<span>{{ doc.original_name || doc.name }}</span>
|
||||
<span class="text-xs text-gray-400"
|
||||
>({{ doc.extension?.toUpperCase() || "" }},
|
||||
{{ (doc.size / 1024 / 1024).toFixed(2) }} MB)</span
|
||||
</div>
|
||||
<p v-if="autoMailDisabled" class="text-xs text-amber-600">
|
||||
{{ autoMailDisabledHint }}
|
||||
</p>
|
||||
|
||||
<div v-if="templateAllowsAttachments && form.contract_uuid" class="mt-3">
|
||||
<label class="inline-flex items-center gap-2">
|
||||
<Checkbox v-model="form.attach_documents" />
|
||||
<span class="text-sm">Dodaj priponke iz izbrane pogodbe</span>
|
||||
</label>
|
||||
<div
|
||||
v-if="form.attach_documents"
|
||||
class="mt-2 border rounded p-2 max-h-48 overflow-auto"
|
||||
>
|
||||
<div class="text-xs text-gray-600 mb-2">
|
||||
Izberite dokumente, ki bodo poslani kot priponke:
|
||||
</div>
|
||||
<div class="space-y-1">
|
||||
<template v-for="c in pageContracts" :key="c.uuid || c.id">
|
||||
<div v-if="c.uuid === form.contract_uuid">
|
||||
<div class="font-medium text-sm text-gray-700 mb-1">
|
||||
Pogodba {{ c.reference }}
|
||||
</div>
|
||||
<div class="space-y-1">
|
||||
<div
|
||||
v-for="doc in availableContractDocs"
|
||||
:key="doc.uuid || doc.id"
|
||||
class="flex items-center gap-2 text-sm"
|
||||
>
|
||||
<Checkbox
|
||||
:checked="form.attachment_document_ids.includes(doc.id)"
|
||||
@update:checked="(checked) => {
|
||||
if (checked) {
|
||||
if (!form.attachment_document_ids.includes(doc.id)) {
|
||||
form.attachment_document_ids.push(doc.id);
|
||||
}
|
||||
} else {
|
||||
form.attachment_document_ids = form.attachment_document_ids.filter(id => id !== doc.id);
|
||||
}
|
||||
}"
|
||||
/>
|
||||
<span>{{ doc.original_name || doc.name }}</span>
|
||||
<span class="text-xs text-gray-400"
|
||||
>({{ doc.extension?.toUpperCase() || "" }},
|
||||
{{ (doc.size / 1024 / 1024).toFixed(2) }} MB)</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div
|
||||
v-if="availableContractDocs.length === 0"
|
||||
class="text-sm text-gray-500"
|
||||
>
|
||||
Ni dokumentov, povezanih s to pogodbo.
|
||||
</div>
|
||||
</template>
|
||||
<div
|
||||
v-if="availableContractDocs.length === 0"
|
||||
class="text-sm text-gray-500"
|
||||
>
|
||||
Ni dokumentov, povezanih s to pogodbo.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-end mt-4">
|
||||
<ActionMessage :on="form.recentlySuccessful" class="me-3">
|
||||
|
||||
<ActionMessage :on="form.recentlySuccessful" class="text-sm text-green-600">
|
||||
Shranjuje.
|
||||
</ActionMessage>
|
||||
<BasicButton
|
||||
:class="{ 'opacity-25': form.processing }"
|
||||
:disabled="form.processing"
|
||||
>
|
||||
Shrani
|
||||
</BasicButton>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
</DialogModal>
|
||||
</CreateDialog>
|
||||
</template>
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import { ref, computed } from "vue";
|
||||
import { Link, router } from "@inertiajs/vue3";
|
||||
import DataTable from "@/Components/DataTable/DataTable.vue";
|
||||
import Dropdown from "@/Components/Dropdown.vue";
|
||||
import ConfirmationModal from "@/Components/ConfirmationModal.vue";
|
||||
import SecondaryButton from "@/Components/SecondaryButton.vue";
|
||||
import DangerButton from "@/Components/DangerButton.vue";
|
||||
import DeleteDialog from "@/Components/Dialogs/DeleteDialog.vue";
|
||||
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
|
||||
import { library } from "@fortawesome/fontawesome-svg-core";
|
||||
import { faTrash, faEllipsisVertical, faCopy } from "@fortawesome/free-solid-svg-icons";
|
||||
@@ -17,6 +16,17 @@ const props = defineProps({
|
||||
edit: Boolean,
|
||||
});
|
||||
|
||||
const columns = computed(() => [
|
||||
{ key: "decision_dot", label: "", class: "w-[6%]" },
|
||||
{ key: "contract", label: "Pogodba", class: "w-[14%]" },
|
||||
{ key: "decision", label: "Odločitev", class: "w-[26%]" },
|
||||
{ key: "note", label: "Opomba", class: "w-[14%]" },
|
||||
{ key: "promise", label: "Obljuba", class: "w-[20%]" },
|
||||
{ key: "user", label: "Dodal", class: "w-[10%]" },
|
||||
]);
|
||||
|
||||
const rows = computed(() => props.activities?.data || []);
|
||||
|
||||
const fmtDate = (d) => {
|
||||
if (!d) return "";
|
||||
try {
|
||||
@@ -105,236 +115,212 @@ const copyToClipboard = async (text) => {
|
||||
<template>
|
||||
<div class="relative">
|
||||
<div class="activity-scroll-wrapper max-h-[32rem] overflow-y-auto overflow-x-auto">
|
||||
<table
|
||||
class="activity-basic-table min-w-full table-fixed text-left text-sm border-collapse"
|
||||
<DataTable
|
||||
:columns="columns"
|
||||
:rows="rows"
|
||||
:show-toolbar="true"
|
||||
:show-pagination="false"
|
||||
:show-search="false"
|
||||
:show-page-size="false"
|
||||
:hoverable="true"
|
||||
row-key="id"
|
||||
empty-text="Ni aktivnosti."
|
||||
class="border-0"
|
||||
>
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Pogodba</th>
|
||||
<th>Odločitev</th>
|
||||
<th>Opomba</th>
|
||||
<th>Obljuba</th>
|
||||
<th>Dodal</th>
|
||||
<th class="w-8" v-if="edit"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr
|
||||
v-for="row in activities.data"
|
||||
:key="row.id"
|
||||
class="border-b last:border-b-0"
|
||||
>
|
||||
<td class="py-2 decision-dot text-center">
|
||||
<span
|
||||
v-if="row.decision?.color_tag"
|
||||
class="inline-block h-4 w-4 rounded-full ring-1 ring-gray-300 dark:ring-gray-600"
|
||||
:style="{ backgroundColor: row.decision?.color_tag }"
|
||||
:title="row.decision?.color_tag"
|
||||
aria-hidden="true"
|
||||
></span>
|
||||
</td>
|
||||
<td class="py-2 pr-4 align-top">
|
||||
<template v-if="row.contract?.reference">
|
||||
{{ row.contract.reference }}
|
||||
</template>
|
||||
<template v-else>
|
||||
<span class="text-gray-400">—</span>
|
||||
</template>
|
||||
</td>
|
||||
<template #toolbar-add>
|
||||
<slot name="add" />
|
||||
</template>
|
||||
<template #cell-decision_dot="{ row }">
|
||||
<div class="flex justify-center">
|
||||
<span
|
||||
v-if="row.decision?.color_tag"
|
||||
class="inline-block h-4 w-4 rounded-full ring-1 ring-gray-300"
|
||||
:style="{ backgroundColor: row.decision?.color_tag }"
|
||||
:title="row.decision?.color_tag"
|
||||
aria-hidden="true"
|
||||
></span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<td class="py-2 pr-4 align-top">
|
||||
<div class="flex flex-col gap-1">
|
||||
<span
|
||||
v-if="row.action?.name"
|
||||
class="inline-block w-fit px-2 py-0.5 rounded text-[10px] font-medium bg-indigo-100 text-indigo-700 tracking-wide uppercase"
|
||||
>{{ row.action.name }}</span
|
||||
>
|
||||
<span class="text-gray-800">{{ row.decision?.name || "" }}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td class="py-2 pr-4 align-top">
|
||||
<div class="max-w-[280px] whitespace-pre-wrap break-words leading-snug">
|
||||
<template v-if="row.note && row.note.length <= 60">{{
|
||||
row.note
|
||||
}}</template>
|
||||
<template v-else-if="row.note">
|
||||
<span>{{ row.note.slice(0, 60) }}… </span>
|
||||
<Dropdown
|
||||
align="left"
|
||||
width="56"
|
||||
:content-classes="['p-2', 'bg-white', 'shadow', 'max-w-xs']"
|
||||
>
|
||||
<template #trigger>
|
||||
<button
|
||||
type="button"
|
||||
class="inline-flex items-center text-[11px] text-indigo-600 hover:underline focus:outline-none"
|
||||
>
|
||||
Več
|
||||
</button>
|
||||
</template>
|
||||
<template #content>
|
||||
<div class="relative" @click.stop>
|
||||
<div
|
||||
class="flex items-center justify-between p-1 border-b border-gray-200"
|
||||
>
|
||||
<span class="text-xs font-medium text-gray-600">Opomba</span>
|
||||
<button
|
||||
@click="copyToClipboard(row.note)"
|
||||
class="flex items-center gap-1 px-2 py-1 text-xs text-indigo-600 hover:text-indigo-800 hover:bg-indigo-50 rounded transition-colors"
|
||||
title="Kopiraj v odložišče"
|
||||
>
|
||||
<FontAwesomeIcon :icon="faCopy" class="text-xs" />
|
||||
<span>Kopiraj</span>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="max-h-60 overflow-auto text-[12px] whitespace-pre-wrap break-words p-2"
|
||||
>
|
||||
{{ row.note }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Dropdown>
|
||||
</template>
|
||||
<template v-else><span class="text-gray-400">—</span></template>
|
||||
</div>
|
||||
</td>
|
||||
<td class="py-2 pr-4 align-top">
|
||||
<div class="flex flex-col gap-1 text-[12px]">
|
||||
<div v-if="row.amount && Number(row.amount) !== 0" class="leading-tight">
|
||||
<span class="text-gray-500">Z:</span
|
||||
><span class="font-medium ml-1">{{ fmtCurrency(row.amount) }}</span>
|
||||
</div>
|
||||
<div v-if="row.due_date" class="leading-tight">
|
||||
<span class="text-gray-500">D:</span
|
||||
><span class="ml-1">{{ fmtDate(row.due_date) }}</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="!row.due_date && (!row.amount || Number(row.amount) === 0)"
|
||||
class="text-gray-400"
|
||||
>
|
||||
—
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="py-2 pr-4 align-top">
|
||||
<div class="text-gray-800 font-medium leading-tight">
|
||||
{{ row.user?.name || row.user_name || "" }}
|
||||
</div>
|
||||
<div v-if="row.created_at" class="mt-1">
|
||||
<span
|
||||
class="inline-block px-2 py-0.5 rounded text-[11px] bg-gray-100 text-gray-600 tracking-wide"
|
||||
>{{ fmtDateTime(row.created_at) }}</span
|
||||
>
|
||||
</div>
|
||||
</td>
|
||||
<td class="py-2 pl-2 pr-2 align-middle text-right" v-if="edit">
|
||||
<Dropdown align="right" width="30">
|
||||
<template #cell-contract="{ row }">
|
||||
<template v-if="row.contract?.reference">
|
||||
{{ row.contract.reference }}
|
||||
</template>
|
||||
<template v-else>
|
||||
<span class="text-gray-400">—</span>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<template #cell-decision="{ row }">
|
||||
<div class="flex flex-col gap-1">
|
||||
<span
|
||||
v-if="row.action?.name"
|
||||
class="inline-block w-fit px-2 py-0.5 rounded text-[10px] font-medium bg-indigo-100 text-indigo-700 tracking-wide uppercase"
|
||||
>
|
||||
{{ row.action.name }}
|
||||
</span>
|
||||
<span class="text-gray-800">{{ row.decision?.name || "" }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #cell-note="{ row }">
|
||||
<div class="max-w-[280px] whitespace-pre-wrap break-words leading-snug">
|
||||
<template v-if="row.note && row.note.length <= 60">
|
||||
{{ row.note }}
|
||||
</template>
|
||||
<template v-else-if="row.note">
|
||||
<span>{{ row.note.slice(0, 60) }}… </span>
|
||||
<Dropdown
|
||||
align="left"
|
||||
width="56"
|
||||
:content-classes="['p-2', 'bg-white', 'shadow', 'max-w-xs']"
|
||||
>
|
||||
<template #trigger>
|
||||
<button
|
||||
type="button"
|
||||
class="inline-flex items-center justify-center h-8 w-8 rounded-full hover:bg-gray-100 focus:outline-none"
|
||||
:title="'Actions'"
|
||||
class="inline-flex items-center text-[11px] text-indigo-600 hover:underline focus:outline-none"
|
||||
>
|
||||
<FontAwesomeIcon
|
||||
:icon="faEllipsisVertical"
|
||||
class="h-4 w-4 text-gray-700"
|
||||
/>
|
||||
Več
|
||||
</button>
|
||||
</template>
|
||||
<template #content>
|
||||
<button
|
||||
type="button"
|
||||
class="w-full flex items-center gap-2 px-3 py-2 text-sm hover:bg-red-50 text-red-600"
|
||||
@click.stop="openDelete(row)"
|
||||
>
|
||||
<FontAwesomeIcon :icon="['fas', 'trash']" class="text-[16px]" />
|
||||
<span>Izbriši</span>
|
||||
</button>
|
||||
<div class="relative" @click.stop>
|
||||
<div
|
||||
class="flex items-center justify-between p-1 border-b border-gray-200"
|
||||
>
|
||||
<span class="text-xs font-medium text-gray-600">Opomba</span>
|
||||
<button
|
||||
@click="copyToClipboard(row.note)"
|
||||
class="flex items-center gap-1 px-2 py-1 text-xs text-indigo-600 hover:text-indigo-800 hover:bg-indigo-50 rounded transition-colors"
|
||||
title="Kopiraj v odložišče"
|
||||
>
|
||||
<FontAwesomeIcon :icon="faCopy" class="w-3 h-3" />
|
||||
<span>Kopiraj</span>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="max-h-60 overflow-auto text-[12px] whitespace-pre-wrap break-words p-2"
|
||||
>
|
||||
{{ row.note }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Dropdown>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="!activities?.data || activities.data.length === 0">
|
||||
<td :colspan="6" class="py-4 text-gray-500">Ni aktivnosti.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span class="text-gray-400">—</span>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #cell-promise="{ row }">
|
||||
<div class="flex flex-col gap-1 text-[12px]">
|
||||
<div v-if="row.amount && Number(row.amount) !== 0" class="leading-tight">
|
||||
<span class="text-gray-500">Z:</span>
|
||||
<span class="font-medium ml-1">{{ fmtCurrency(row.amount) }}</span>
|
||||
</div>
|
||||
<div v-if="row.due_date" class="leading-tight">
|
||||
<span class="text-gray-500">D:</span>
|
||||
<span class="ml-1">{{ fmtDate(row.due_date) }}</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="!row.due_date && (!row.amount || Number(row.amount) === 0)"
|
||||
class="text-gray-400"
|
||||
>
|
||||
—
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #cell-user="{ row }">
|
||||
<div class="text-gray-800 font-medium leading-tight">
|
||||
{{ row.user?.name || row.user_name || "" }}
|
||||
</div>
|
||||
<div v-if="row.created_at" class="mt-1">
|
||||
<span
|
||||
class="inline-block px-2 py-0.5 rounded text-[11px] bg-gray-100 text-gray-600 tracking-wide"
|
||||
>
|
||||
{{ fmtDateTime(row.created_at) }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #actions="{ row }" v-if="edit">
|
||||
<Dropdown align="right" width="30">
|
||||
<template #trigger>
|
||||
<button
|
||||
type="button"
|
||||
class="inline-flex items-center justify-center h-8 w-8 rounded-full hover:bg-gray-100 focus:outline-none"
|
||||
title="Actions"
|
||||
>
|
||||
<FontAwesomeIcon
|
||||
:icon="faEllipsisVertical"
|
||||
class="h-4 w-4 text-gray-700"
|
||||
/>
|
||||
</button>
|
||||
</template>
|
||||
<template #content>
|
||||
<button
|
||||
type="button"
|
||||
class="w-full flex items-center gap-2 px-3 py-2 text-sm hover:bg-red-50 text-red-600"
|
||||
@click.stop="openDelete(row)"
|
||||
>
|
||||
<FontAwesomeIcon :icon="['fas', 'trash']" class="w-4 h-4" />
|
||||
<span>Izbriši</span>
|
||||
</button>
|
||||
</template>
|
||||
</Dropdown>
|
||||
</template>
|
||||
</DataTable>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ConfirmationModal :show="confirmDelete" @close="cancelDelete">
|
||||
<template #title>Potrditev</template>
|
||||
<template #content
|
||||
>Ali ste prepričani, da želite izbrisati to aktivnost? Tega dejanja ni mogoče
|
||||
razveljaviti.</template
|
||||
>
|
||||
<template #footer>
|
||||
<SecondaryButton type="button" @click="cancelDelete">Prekliči</SecondaryButton>
|
||||
<DangerButton type="button" class="ml-2" @click="confirmDeleteAction"
|
||||
>Izbriši</DangerButton
|
||||
>
|
||||
</template>
|
||||
</ConfirmationModal>
|
||||
<DeleteDialog
|
||||
:show="confirmDelete"
|
||||
title="Izbriši aktivnost"
|
||||
message="Ali ste prepričani, da želite izbrisati to aktivnost?"
|
||||
confirm-text="Izbriši"
|
||||
@close="cancelDelete"
|
||||
@confirm="confirmDeleteAction"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.activity-scroll-wrapper {
|
||||
scrollbar-gutter: stable;
|
||||
}
|
||||
.activity-basic-table thead th {
|
||||
|
||||
/* Ensure sticky header works within scroll container */
|
||||
.activity-scroll-wrapper :deep(table) {
|
||||
border-collapse: separate;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
.activity-scroll-wrapper :deep([data-table-container]) {
|
||||
overflow: visible !important;
|
||||
}
|
||||
|
||||
.activity-scroll-wrapper :deep([data-table-container] > div) {
|
||||
overflow-x: visible !important;
|
||||
overflow-y: visible !important;
|
||||
}
|
||||
|
||||
.activity-scroll-wrapper :deep(table thead) {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 20;
|
||||
background: #ffffff;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
font-size: 12px;
|
||||
letter-spacing: 0.05em;
|
||||
color: #374151;
|
||||
padding: 0.5rem 1rem; /* unified horizontal padding */
|
||||
}
|
||||
|
||||
.activity-scroll-wrapper :deep(table thead tr) {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.activity-scroll-wrapper :deep(table thead th) {
|
||||
background-color: white !important;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 20;
|
||||
box-shadow: 0 1px 0 0 #e5e7eb;
|
||||
border-bottom: 1px solid #e5e7eb;
|
||||
}
|
||||
.activity-basic-table tbody td {
|
||||
vertical-align: top;
|
||||
padding: 0.625rem 1rem; /* match header horizontal padding */
|
||||
}
|
||||
/* Center the decision dot in its column */
|
||||
.activity-basic-table td.decision-dot {
|
||||
vertical-align: middle;
|
||||
}
|
||||
/* Ensure first column lines up exactly (no extra offset) */
|
||||
.activity-basic-table th:first-child,
|
||||
.activity-basic-table td:first-child {
|
||||
padding-left: 1rem;
|
||||
}
|
||||
.activity-basic-table tbody tr:hover {
|
||||
background: #f9fafb;
|
||||
}
|
||||
/* Column sizing hints (optional fine tuning) */
|
||||
.activity-basic-table th:nth-child(1),
|
||||
.activity-basic-table td:nth-child(1) {
|
||||
width: 6%;
|
||||
}
|
||||
.activity-basic-table th:nth-child(2),
|
||||
.activity-basic-table td:nth-child(2) {
|
||||
width: 14%;
|
||||
}
|
||||
.activity-basic-table th:nth-child(3),
|
||||
.activity-basic-table td:nth-child(3) {
|
||||
width: 26%;
|
||||
}
|
||||
.activity-basic-table th:nth-child(4),
|
||||
.activity-basic-table td:nth-child(4) {
|
||||
width: 14%;
|
||||
}
|
||||
.activity-basic-table th:nth-child(5),
|
||||
.activity-basic-table td:nth-child(5) {
|
||||
width: 20%;
|
||||
}
|
||||
.activity-basic-table th:nth-child(6),
|
||||
.activity-basic-table td:nth-child(6) {
|
||||
width: 10%;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<script setup>
|
||||
import DialogModal from '@/Components/DialogModal.vue'
|
||||
import InputLabel from '@/Components/InputLabel.vue'
|
||||
import TextInput from '@/Components/TextInput.vue'
|
||||
import CreateDialog from '@/Components/Dialogs/CreateDialog.vue'
|
||||
import PrimaryButton from '@/Components/PrimaryButton.vue'
|
||||
import SectionTitle from '@/Components/SectionTitle.vue'
|
||||
import { useForm } from '@inertiajs/vue3'
|
||||
import { Label } from "@/Components/ui/label";
|
||||
import { Input } from "@/Components/ui/input";
|
||||
import { Textarea } from "@/Components/ui/textarea";
|
||||
|
||||
const props = defineProps({
|
||||
show: { type: Boolean, default: false },
|
||||
@@ -36,35 +37,75 @@ const submit = () => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DialogModal :show="show" @close="close">
|
||||
<template #title>Dodaj premet</template>
|
||||
<template #content>
|
||||
<form @submit.prevent="submit">
|
||||
<CreateDialog
|
||||
:show="show"
|
||||
title="Dodaj premet"
|
||||
confirm-text="Shrani"
|
||||
:processing="form.processing"
|
||||
@close="close"
|
||||
@confirm="submit"
|
||||
>
|
||||
<form @submit.prevent="submit">
|
||||
<SectionTitle class="mt-2 border-b mb-4">
|
||||
<template #title>Premet</template>
|
||||
</SectionTitle>
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<InputLabel for="objRef" value="Referenca" />
|
||||
<TextInput id="objRef" v-model="form.reference" type="text" class="mt-1 block w-full" />
|
||||
|
||||
<div class="space-y-4">
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||
<div class="space-y-2">
|
||||
<Label for="objRef">Referenca</Label>
|
||||
<Input
|
||||
id="objRef"
|
||||
v-model="form.reference"
|
||||
type="text"
|
||||
placeholder="Referenca"
|
||||
/>
|
||||
<p v-if="form.errors.reference" class="text-sm text-red-600">
|
||||
{{ form.errors.reference }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="space-y-2">
|
||||
<Label for="objType">Tip</Label>
|
||||
<Input
|
||||
id="objType"
|
||||
v-model="form.type"
|
||||
type="text"
|
||||
placeholder="Tip"
|
||||
/>
|
||||
<p v-if="form.errors.type" class="text-sm text-red-600">
|
||||
{{ form.errors.type }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<InputLabel for="objType" value="Tip" />
|
||||
<TextInput id="objType" v-model="form.type" type="text" class="mt-1 block w-full" />
|
||||
|
||||
<div class="space-y-2">
|
||||
<Label for="objName">Naziv</Label>
|
||||
<Input
|
||||
id="objName"
|
||||
v-model="form.name"
|
||||
type="text"
|
||||
placeholder="Naziv"
|
||||
required
|
||||
/>
|
||||
<p v-if="form.errors.name" class="text-sm text-red-600">
|
||||
{{ form.errors.name }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-4">
|
||||
<InputLabel for="objName" value="Naziv" />
|
||||
<TextInput id="objName" v-model="form.name" type="text" class="mt-1 block w-full" required />
|
||||
</div>
|
||||
<div class="mt-4">
|
||||
<InputLabel for="objDesc" value="Opis" />
|
||||
<textarea id="objDesc" v-model="form.description" class="mt-1 block w-full border-gray-300 focus:border-indigo-500 focus:ring-indigo-500 rounded-md shadow-sm" rows="3" />
|
||||
</div>
|
||||
<div class="flex justify-end mt-6">
|
||||
<PrimaryButton :class="{ 'opacity-25': form.processing }" :disabled="form.processing">Shrani</PrimaryButton>
|
||||
|
||||
<div class="space-y-2">
|
||||
<Label for="objDesc">Opis</Label>
|
||||
<Textarea
|
||||
id="objDesc"
|
||||
v-model="form.description"
|
||||
rows="3"
|
||||
placeholder="Opis"
|
||||
/>
|
||||
<p v-if="form.errors.description" class="text-sm text-red-600">
|
||||
{{ form.errors.description }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
</DialogModal>
|
||||
</CreateDialog>
|
||||
</template>
|
||||
|
||||
@@ -92,7 +92,7 @@ const deleteObject = (o) => {
|
||||
:title="'Prekliči'"
|
||||
@click.stop="confirmingId = null"
|
||||
>
|
||||
<FontAwesomeIcon :icon="['fas', 'xmark']" class="text-[16px]" />
|
||||
<FontAwesomeIcon :icon="['fas', 'xmark']" class="w-4 h-4" />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
@@ -100,7 +100,7 @@ const deleteObject = (o) => {
|
||||
:title="'Potrdi brisanje'"
|
||||
@click.stop="deleteObject(o)"
|
||||
>
|
||||
<FontAwesomeIcon :icon="['fas', 'check']" class="text-[16px]" />
|
||||
<FontAwesomeIcon :icon="['fas', 'check']" class="w-4 h-4" />
|
||||
</button>
|
||||
</template>
|
||||
<template v-else>
|
||||
|
||||
@@ -1,15 +1,22 @@
|
||||
<script setup>
|
||||
import ActionMessage from "@/Components/ActionMessage.vue";
|
||||
import DialogModal from "@/Components/DialogModal.vue";
|
||||
import InputLabel from "@/Components/InputLabel.vue";
|
||||
import InputError from "@/Components/InputError.vue";
|
||||
import PrimaryButton from "@/Components/PrimaryButton.vue";
|
||||
import CreateDialog from "@/Components/Dialogs/CreateDialog.vue";
|
||||
import UpdateDialog from "@/Components/Dialogs/UpdateDialog.vue";
|
||||
import SectionTitle from "@/Components/SectionTitle.vue";
|
||||
import TextInput from "@/Components/TextInput.vue";
|
||||
import CurrencyInput from "@/Components/CurrencyInput.vue";
|
||||
import DatePickerField from "@/Components/DatePickerField.vue";
|
||||
import DatePicker from "@/Components/DatePicker.vue";
|
||||
import { useForm, router } from "@inertiajs/vue3";
|
||||
import { watch, nextTick, ref as vRef } from "vue";
|
||||
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_case: Object,
|
||||
@@ -20,8 +27,6 @@ const props = defineProps({
|
||||
contract: { type: Object, default: null },
|
||||
});
|
||||
|
||||
console.log(props.types);
|
||||
|
||||
const emit = defineEmits(["close"]);
|
||||
|
||||
const close = () => {
|
||||
@@ -155,11 +160,128 @@ const storeOrUpdate = () => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DialogModal :show="show" @close="close">
|
||||
<template #title>{{
|
||||
formContract.uuid ? "Uredi pogodbo" : "Dodaj pogodbo"
|
||||
}}</template>
|
||||
<template #content>
|
||||
<CreateDialog
|
||||
v-if="!formContract.uuid"
|
||||
:show="show"
|
||||
title="Dodaj pogodbo"
|
||||
confirm-text="Shrani"
|
||||
:processing="formContract.processing"
|
||||
@close="close"
|
||||
@confirm="storeOrUpdate"
|
||||
>
|
||||
<form @submit.prevent="storeOrUpdate">
|
||||
<div
|
||||
v-if="formContract.errors.reference"
|
||||
class="mb-4 rounded border border-red-200 bg-red-50 px-3 py-2 text-sm text-red-700"
|
||||
>
|
||||
{{ formContract.errors.reference }}
|
||||
</div>
|
||||
<SectionTitle class="mt-4 border-b mb-4">
|
||||
<template #title> Pogodba </template>
|
||||
</SectionTitle>
|
||||
|
||||
<div class="space-y-4">
|
||||
<div class="space-y-2">
|
||||
<Label for="contractRef">Referenca</Label>
|
||||
<Input
|
||||
id="contractRef"
|
||||
ref="contractRefInput"
|
||||
v-model="formContract.reference"
|
||||
type="text"
|
||||
:class="[
|
||||
formContract.errors.reference
|
||||
? 'border-red-500 focus:border-red-500 focus:ring-red-500'
|
||||
: '',
|
||||
]"
|
||||
autocomplete="contract-reference"
|
||||
/>
|
||||
<p v-if="formContract.errors.reference" class="text-sm text-red-600">
|
||||
{{ formContract.errors.reference }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="space-y-2">
|
||||
<Label for="contractStartDate">Datum pričetka</Label>
|
||||
<DatePicker
|
||||
id="contractStartDate"
|
||||
v-model="formContract.start_date"
|
||||
format="dd.MM.yyyy"
|
||||
:error="formContract.errors.start_date"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="space-y-2">
|
||||
<Label for="contractTypeSelect">Tip</Label>
|
||||
<Select v-model="formContract.type_id">
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Izberi tip" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem v-for="t in types" :key="t.id" :value="t.id">
|
||||
{{ t.name }}
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<div class="space-y-2">
|
||||
<Label for="contractDescription">Opis</Label>
|
||||
<Textarea
|
||||
id="contractDescription"
|
||||
v-model="formContract.description"
|
||||
rows="3"
|
||||
placeholder="Opis"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<SectionTitle class="mt-6 border-b mb-4">
|
||||
<template #title> Račun </template>
|
||||
</SectionTitle>
|
||||
|
||||
<div class="space-y-2">
|
||||
<Label for="accountTypeSelect">Tip računa</Label>
|
||||
<Select v-model="formContract.account_type_id">
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Izberi tip računa" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem :value="null">—</SelectItem>
|
||||
<SelectItem v-for="at in account_types" :key="at.id" :value="at.id">
|
||||
{{ at.name ?? "#" + at.id }}
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<p v-if="formContract.errors.account_type_id" class="text-sm text-red-600">
|
||||
{{ formContract.errors.account_type_id }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||
<div class="space-y-2">
|
||||
<Label for="initialAmount">Predani znesek</Label>
|
||||
<CurrencyInput id="initialAmount" v-model="formContract.initial_amount" />
|
||||
</div>
|
||||
<div class="space-y-2">
|
||||
<Label for="balanceAmount">Odprti znesek</Label>
|
||||
<CurrencyInput id="balanceAmount" v-model="formContract.balance_amount" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ActionMessage :on="formContract.recentlySuccessful" class="text-sm text-green-600">
|
||||
Shranjuje.
|
||||
</ActionMessage>
|
||||
</div>
|
||||
</form>
|
||||
</CreateDialog>
|
||||
<UpdateDialog
|
||||
v-else
|
||||
:show="show"
|
||||
title="Uredi pogodbo"
|
||||
confirm-text="Posodobi"
|
||||
:processing="formContract.processing"
|
||||
@close="close"
|
||||
@confirm="storeOrUpdate"
|
||||
>
|
||||
<form @submit.prevent="storeOrUpdate">
|
||||
<div
|
||||
v-if="formContract.errors.reference"
|
||||
@@ -170,90 +292,98 @@ const storeOrUpdate = () => {
|
||||
<SectionTitle class="mt-4 border-b mb-4">
|
||||
<template #title> Pogodba </template>
|
||||
</SectionTitle>
|
||||
<div class="col-span-6 sm:col-span-4">
|
||||
<InputLabel for="contractRef" value="Referenca" />
|
||||
<TextInput
|
||||
id="contractRef"
|
||||
ref="contractRefInput"
|
||||
v-model="formContract.reference"
|
||||
type="text"
|
||||
:class="[
|
||||
'mt-1 block w-full',
|
||||
formContract.errors.reference
|
||||
? 'border-red-500 focus:border-red-500 focus:ring-red-500'
|
||||
: '',
|
||||
]"
|
||||
autocomplete="contract-reference"
|
||||
/>
|
||||
<InputError :message="formContract.errors.reference" />
|
||||
</div>
|
||||
<DatePickerField
|
||||
id="contractStartDate"
|
||||
label="Datum pričetka"
|
||||
v-model="formContract.start_date"
|
||||
format="dd.MM.yyyy"
|
||||
:enable-time-picker="false"
|
||||
/>
|
||||
<div class="col-span-6 sm:col-span-4">
|
||||
<InputLabel for="contractTypeSelect" value="Tip" />
|
||||
<select
|
||||
class="block w-full border-gray-300 focus:border-indigo-500 focus:ring-indigo-500 rounded-md shadow-sm"
|
||||
id="contractTypeSelect"
|
||||
v-model="formContract.type_id"
|
||||
>
|
||||
<option v-for="t in types" :value="t.id">{{ t.name }}</option>
|
||||
<!-- ... -->
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-span-6 sm:col-span-4 mt-4">
|
||||
<InputLabel for="contractDescription" value="Opis" />
|
||||
<textarea
|
||||
id="contractDescription"
|
||||
v-model="formContract.description"
|
||||
class="mt-1 block w-full border-gray-300 focus:border-indigo-500 focus:ring-indigo-500 rounded-md shadow-sm"
|
||||
rows="3"
|
||||
/>
|
||||
</div>
|
||||
<SectionTitle class="mt-6 border-b mb-4">
|
||||
<template #title> Račun </template>
|
||||
</SectionTitle>
|
||||
<div class="col-span-6 sm:col-span-4">
|
||||
<InputLabel for="accountTypeSelect" value="Tip računa" />
|
||||
<select
|
||||
id="accountTypeSelect"
|
||||
v-model="formContract.account_type_id"
|
||||
class="block w-full border-gray-300 focus:border-indigo-500 focus:ring-indigo-500 rounded-md shadow-sm"
|
||||
>
|
||||
<option :value="null">—</option>
|
||||
<option v-for="at in account_types" :key="at.id" :value="at.id">
|
||||
{{ at.name ?? "#" + at.id }}
|
||||
</option>
|
||||
</select>
|
||||
<InputError :message="formContract.errors.account_type_id" />
|
||||
</div>
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<InputLabel for="initialAmount" value="Predani znesek" />
|
||||
<CurrencyInput id="initialAmount" v-model="formContract.initial_amount" />
|
||||
|
||||
<div class="space-y-4">
|
||||
<div class="space-y-2">
|
||||
<Label for="contractRef">Referenca</Label>
|
||||
<Input
|
||||
id="contractRef"
|
||||
ref="contractRefInput"
|
||||
v-model="formContract.reference"
|
||||
type="text"
|
||||
:class="[
|
||||
formContract.errors.reference
|
||||
? 'border-red-500 focus:border-red-500 focus:ring-red-500'
|
||||
: '',
|
||||
]"
|
||||
autocomplete="contract-reference"
|
||||
/>
|
||||
<p v-if="formContract.errors.reference" class="text-sm text-red-600">
|
||||
{{ formContract.errors.reference }}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<InputLabel for="balanceAmount" value="Odprti znesek" />
|
||||
<CurrencyInput id="balanceAmount" v-model="formContract.balance_amount" />
|
||||
|
||||
<div class="space-y-2">
|
||||
<Label for="contractStartDate">Datum pričetka</Label>
|
||||
<DatePicker
|
||||
id="contractStartDate"
|
||||
v-model="formContract.start_date"
|
||||
format="dd.MM.yyyy"
|
||||
:error="formContract.errors.start_date"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-end mt-4">
|
||||
<ActionMessage :on="formContract.recentlySuccessful" class="me-3">
|
||||
|
||||
<div class="space-y-2">
|
||||
<Label for="contractTypeSelect">Tip</Label>
|
||||
<Select v-model="formContract.type_id">
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Izberi tip" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem v-for="t in types" :key="t.id" :value="t.id">
|
||||
{{ t.name }}
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<div class="space-y-2">
|
||||
<Label for="contractDescription">Opis</Label>
|
||||
<Textarea
|
||||
id="contractDescription"
|
||||
v-model="formContract.description"
|
||||
rows="3"
|
||||
placeholder="Opis"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<SectionTitle class="mt-6 border-b mb-4">
|
||||
<template #title> Račun </template>
|
||||
</SectionTitle>
|
||||
|
||||
<div class="space-y-2">
|
||||
<Label for="accountTypeSelect">Tip računa</Label>
|
||||
<Select v-model="formContract.account_type_id">
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Izberi tip računa" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem :value="null">—</SelectItem>
|
||||
<SelectItem v-for="at in account_types" :key="at.id" :value="at.id">
|
||||
{{ at.name ?? "#" + at.id }}
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<p v-if="formContract.errors.account_type_id" class="text-sm text-red-600">
|
||||
{{ formContract.errors.account_type_id }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||
<div class="space-y-2">
|
||||
<Label for="initialAmount">Predani znesek</Label>
|
||||
<CurrencyInput id="initialAmount" v-model="formContract.initial_amount" />
|
||||
</div>
|
||||
<div class="space-y-2">
|
||||
<Label for="balanceAmount">Odprti znesek</Label>
|
||||
<CurrencyInput id="balanceAmount" v-model="formContract.balance_amount" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ActionMessage :on="formContract.recentlySuccessful" class="text-sm text-green-600">
|
||||
Shranjuje.
|
||||
</ActionMessage>
|
||||
|
||||
<PrimaryButton
|
||||
:class="{ 'opacity-25': formContract.processing }"
|
||||
:disabled="formContract.processing"
|
||||
>
|
||||
{{ formContract.uuid ? "Posodobi" : "Shrani" }}
|
||||
</PrimaryButton>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
</DialogModal>
|
||||
</UpdateDialog>
|
||||
</template>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,9 @@
|
||||
<script setup>
|
||||
import DialogModal from "@/Components/DialogModal.vue";
|
||||
import CreateDialog from "@/Components/Dialogs/CreateDialog.vue";
|
||||
import CurrencyInput from "@/Components/CurrencyInput.vue";
|
||||
import { Label } from "@/Components/ui/label";
|
||||
import { Input } from "@/Components/ui/input";
|
||||
import DatePicker from "@/Components/DatePicker.vue";
|
||||
|
||||
const props = defineProps({
|
||||
show: { type: Boolean, default: false },
|
||||
@@ -14,12 +17,17 @@ const onSubmit = () => emit("submit");
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DialogModal :show="show" @close="onClose">
|
||||
<template #title>Dodaj plačilo</template>
|
||||
<template #content>
|
||||
<div class="space-y-3">
|
||||
<div>
|
||||
<label class="block text-sm text-gray-700 mb-1">Znesek</label>
|
||||
<CreateDialog
|
||||
:show="show"
|
||||
title="Dodaj plačilo"
|
||||
confirm-text="Shrani"
|
||||
:processing="form.processing"
|
||||
@close="onClose"
|
||||
@confirm="onSubmit"
|
||||
>
|
||||
<div class="space-y-4">
|
||||
<div class="space-y-2">
|
||||
<Label for="paymentAmount">Znesek</Label>
|
||||
<CurrencyInput
|
||||
id="paymentAmount"
|
||||
v-model="form.amount"
|
||||
@@ -27,64 +35,48 @@ const onSubmit = () => emit("submit");
|
||||
placeholder="0,00"
|
||||
class="w-full"
|
||||
/>
|
||||
<div v-if="form.errors?.amount" class="text-sm text-red-600 mt-0.5">
|
||||
<p v-if="form.errors?.amount" class="text-sm text-red-600">
|
||||
{{ form.errors.amount }}
|
||||
</div>
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<div class="flex-1">
|
||||
<label class="block text-sm text-gray-700 mb-1">Valuta</label>
|
||||
<input
|
||||
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
<div class="space-y-2">
|
||||
<Label for="paymentCurrency">Valuta</Label>
|
||||
<Input
|
||||
id="paymentCurrency"
|
||||
type="text"
|
||||
v-model="form.currency"
|
||||
class="w-full rounded border-gray-300"
|
||||
maxlength="3"
|
||||
placeholder="EUR"
|
||||
/>
|
||||
<div v-if="form.errors?.currency" class="text-sm text-red-600 mt-0.5">
|
||||
<p v-if="form.errors?.currency" class="text-sm text-red-600">
|
||||
{{ form.errors.currency }}
|
||||
</div>
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<label class="block text-sm text-gray-700 mb-1">Datum</label>
|
||||
<input
|
||||
type="date"
|
||||
<div class="space-y-2">
|
||||
<Label for="paymentDate">Datum</Label>
|
||||
<DatePicker
|
||||
id="paymentDate"
|
||||
v-model="form.paid_at"
|
||||
class="w-full rounded border-gray-300"
|
||||
format="dd.MM.yyyy"
|
||||
:error="form.errors?.paid_at"
|
||||
/>
|
||||
<div v-if="form.errors?.paid_at" class="text-sm text-red-600 mt-0.5">
|
||||
{{ form.errors.paid_at }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm text-gray-700 mb-1">Sklic</label>
|
||||
<input
|
||||
|
||||
<div class="space-y-2">
|
||||
<Label for="paymentReference">Sklic</Label>
|
||||
<Input
|
||||
id="paymentReference"
|
||||
type="text"
|
||||
v-model="form.reference"
|
||||
class="w-full rounded border-gray-300"
|
||||
placeholder="Sklic"
|
||||
/>
|
||||
<div v-if="form.errors?.reference" class="text-sm text-red-600 mt-0.5">
|
||||
<p v-if="form.errors?.reference" class="text-sm text-red-600">
|
||||
{{ form.errors.reference }}
|
||||
</div>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template #footer>
|
||||
<button
|
||||
type="button"
|
||||
class="px-4 py-2 rounded bg-gray-200 hover:bg-gray-300"
|
||||
@click="onClose"
|
||||
>
|
||||
Prekliči
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="px-4 py-2 rounded bg-indigo-600 text-white hover:bg-indigo-700"
|
||||
:disabled="form.processing"
|
||||
@click="onSubmit"
|
||||
>
|
||||
Shrani
|
||||
</button>
|
||||
</template>
|
||||
</DialogModal>
|
||||
</CreateDialog>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user