Changes to dev branch
This commit is contained in:
parent
f5530edcea
commit
70dc0b893f
18
package-lock.json
generated
18
package-lock.json
generated
|
|
@ -3627,9 +3627,9 @@
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/electron-to-chromium": {
|
"node_modules/electron-to-chromium": {
|
||||||
"version": "1.5.262",
|
"version": "1.5.263",
|
||||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.262.tgz",
|
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.263.tgz",
|
||||||
"integrity": "sha512-NlAsMteRHek05jRUxUR0a5jpjYq9ykk6+kO0yRaMi5moe7u0fVIOeQ3Y30A8dIiWFBNUoQGi1ljb1i5VtS9WQQ==",
|
"integrity": "sha512-DrqJ11Knd+lo+dv+lltvfMDLU27g14LMdH2b0O3Pio4uk0x+z7OR+JrmyacTPN2M8w3BrZ7/RTwG3R9B7irPlg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
|
|
@ -5056,9 +5056,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/reka-ui": {
|
"node_modules/reka-ui": {
|
||||||
"version": "2.6.0",
|
"version": "2.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/reka-ui/-/reka-ui-2.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/reka-ui/-/reka-ui-2.6.1.tgz",
|
||||||
"integrity": "sha512-NrGMKrABD97l890mFS3TNUzB0BLUfbL3hh0NjcJRIUSUljb288bx3Mzo31nOyUcdiiW0HqFGXJwyCBh9cWgb0w==",
|
"integrity": "sha512-XK7cJDQoNuGXfCNzBBo/81Yg/OgjPwvbabnlzXG2VsdSgNsT6iIkuPBPr+C0Shs+3bb0x0lbPvgQAhMSCKm5Ww==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@floating-ui/dom": "^1.6.13",
|
"@floating-ui/dom": "^1.6.13",
|
||||||
|
|
@ -5655,9 +5655,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite": {
|
"node_modules/vite": {
|
||||||
"version": "7.2.4",
|
"version": "7.2.6",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-7.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-7.2.6.tgz",
|
||||||
"integrity": "sha512-NL8jTlbo0Tn4dUEXEsUg8KeyG/Lkmc4Fnzb8JXN/Ykm9G4HNImjtABMJgkQoVjOBN/j2WAwDTRytdqJbZsah7w==",
|
"integrity": "sha512-tI2l/nFHC5rLh7+5+o7QjKjSR04ivXDF4jcgV0f/bTQ+OJiITy5S6gaynVsEM+7RqzufMnVbIon6Sr5x1SDYaQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
|
||||||
|
|
@ -187,74 +187,74 @@ @theme inline {
|
||||||
--color-sidebar-ring: var(--sidebar-ring);
|
--color-sidebar-ring: var(--sidebar-ring);
|
||||||
}
|
}
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--radius: 0.65rem;
|
--radius: 0.65rem;
|
||||||
--background: oklch(1 0 0);
|
--background: oklch(1 0 0);
|
||||||
--foreground: oklch(0.141 0.005 285.823);
|
--foreground: oklch(0.141 0.005 285.823);
|
||||||
--card: oklch(1 0 0);
|
--card: oklch(1 0 0);
|
||||||
--card-foreground: oklch(0.141 0.005 285.823);
|
--card-foreground: oklch(0.141 0.005 285.823);
|
||||||
--popover: oklch(1 0 0);
|
--popover: oklch(1 0 0);
|
||||||
--popover-foreground: oklch(0.141 0.005 285.823);
|
--popover-foreground: oklch(0.141 0.005 285.823);
|
||||||
--primary: oklch(0.648 0.2 131.684);
|
--primary: oklch(0.488 0.243 264.376);
|
||||||
--primary-foreground: oklch(0.986 0.031 120.757);
|
--primary-foreground: oklch(0.97 0.014 254.604);
|
||||||
--secondary: oklch(0.967 0.001 286.375);
|
--secondary: oklch(0.967 0.001 286.375);
|
||||||
--secondary-foreground: oklch(0.21 0.006 285.885);
|
--secondary-foreground: oklch(0.21 0.006 285.885);
|
||||||
--muted: oklch(0.967 0.001 286.375);
|
--muted: oklch(0.967 0.001 286.375);
|
||||||
--muted-foreground: oklch(0.552 0.016 285.938);
|
--muted-foreground: oklch(0.552 0.016 285.938);
|
||||||
--accent: oklch(0.967 0.001 286.375);
|
--accent: oklch(0.967 0.001 286.375);
|
||||||
--accent-foreground: oklch(0.21 0.006 285.885);
|
--accent-foreground: oklch(0.21 0.006 285.885);
|
||||||
--destructive: oklch(0.577 0.245 27.325);
|
--destructive: oklch(0.577 0.245 27.325);
|
||||||
--border: oklch(0.92 0.004 286.32);
|
--border: oklch(0.92 0.004 286.32);
|
||||||
--input: oklch(0.92 0.004 286.32);
|
--input: oklch(0.92 0.004 286.32);
|
||||||
--ring: oklch(0.841 0.238 128.85);
|
--ring: oklch(0.708 0 0);
|
||||||
--chart-1: oklch(0.871 0.15 154.449);
|
--chart-1: oklch(0.809 0.105 251.813);
|
||||||
--chart-2: oklch(0.723 0.219 149.579);
|
--chart-2: oklch(0.623 0.214 259.815);
|
||||||
--chart-3: oklch(0.627 0.194 149.214);
|
--chart-3: oklch(0.546 0.245 262.881);
|
||||||
--chart-4: oklch(0.527 0.154 150.069);
|
--chart-4: oklch(0.488 0.243 264.376);
|
||||||
--chart-5: oklch(0.448 0.119 151.328);
|
--chart-5: oklch(0.424 0.199 265.638);
|
||||||
--sidebar: oklch(0.985 0 0);
|
--sidebar: oklch(0.985 0 0);
|
||||||
--sidebar-foreground: oklch(0.141 0.005 285.823);
|
--sidebar-foreground: oklch(0.141 0.005 285.823);
|
||||||
--sidebar-primary: oklch(0.648 0.2 131.684);
|
--sidebar-primary: oklch(0.546 0.245 262.881);
|
||||||
--sidebar-primary-foreground: oklch(0.986 0.031 120.757);
|
--sidebar-primary-foreground: oklch(0.97 0.014 254.604);
|
||||||
--sidebar-accent: oklch(0.967 0.001 286.375);
|
--sidebar-accent: oklch(0.967 0.001 286.375);
|
||||||
--sidebar-accent-foreground: oklch(0.21 0.006 285.885);
|
--sidebar-accent-foreground: oklch(0.21 0.006 285.885);
|
||||||
--sidebar-border: oklch(0.92 0.004 286.32);
|
--sidebar-border: oklch(0.92 0.004 286.32);
|
||||||
--sidebar-ring: oklch(0.841 0.238 128.85);
|
--sidebar-ring: oklch(0.708 0 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark {
|
.dark {
|
||||||
--background: oklch(0.141 0.005 285.823);
|
--background: oklch(0.141 0.005 285.823);
|
||||||
--foreground: oklch(0.985 0 0);
|
--foreground: oklch(0.985 0 0);
|
||||||
--card: oklch(0.21 0.006 285.885);
|
--card: oklch(0.21 0.006 285.885);
|
||||||
--card-foreground: oklch(0.985 0 0);
|
--card-foreground: oklch(0.985 0 0);
|
||||||
--popover: oklch(0.21 0.006 285.885);
|
--popover: oklch(0.21 0.006 285.885);
|
||||||
--popover-foreground: oklch(0.985 0 0);
|
--popover-foreground: oklch(0.985 0 0);
|
||||||
--primary: oklch(0.648 0.2 131.684);
|
--primary: oklch(0.488 0.243 264.376);
|
||||||
--primary-foreground: oklch(0.986 0.031 120.757);
|
--primary-foreground: oklch(0.97 0.014 254.604);
|
||||||
--secondary: oklch(0.274 0.006 286.033);
|
--secondary: oklch(0.274 0.006 286.033);
|
||||||
--secondary-foreground: oklch(0.985 0 0);
|
--secondary-foreground: oklch(0.985 0 0);
|
||||||
--muted: oklch(0.274 0.006 286.033);
|
--muted: oklch(0.274 0.006 286.033);
|
||||||
--muted-foreground: oklch(0.705 0.015 286.067);
|
--muted-foreground: oklch(0.705 0.015 286.067);
|
||||||
--accent: oklch(0.274 0.006 286.033);
|
--accent: oklch(0.274 0.006 286.033);
|
||||||
--accent-foreground: oklch(0.985 0 0);
|
--accent-foreground: oklch(0.985 0 0);
|
||||||
--destructive: oklch(0.704 0.191 22.216);
|
--destructive: oklch(0.704 0.191 22.216);
|
||||||
--border: oklch(1 0 0 / 10%);
|
--border: oklch(1 0 0 / 10%);
|
||||||
--input: oklch(1 0 0 / 15%);
|
--input: oklch(1 0 0 / 15%);
|
||||||
--ring: oklch(0.405 0.101 131.063);
|
--ring: oklch(0.556 0 0);
|
||||||
--chart-1: oklch(0.871 0.15 154.449);
|
--chart-1: oklch(0.809 0.105 251.813);
|
||||||
--chart-2: oklch(0.723 0.219 149.579);
|
--chart-2: oklch(0.623 0.214 259.815);
|
||||||
--chart-3: oklch(0.627 0.194 149.214);
|
--chart-3: oklch(0.546 0.245 262.881);
|
||||||
--chart-4: oklch(0.527 0.154 150.069);
|
--chart-4: oklch(0.488 0.243 264.376);
|
||||||
--chart-5: oklch(0.448 0.119 151.328);
|
--chart-5: oklch(0.424 0.199 265.638);
|
||||||
--sidebar: oklch(0.21 0.006 285.885);
|
--sidebar: oklch(0.21 0.006 285.885);
|
||||||
--sidebar-foreground: oklch(0.985 0 0);
|
--sidebar-foreground: oklch(0.985 0 0);
|
||||||
--sidebar-primary: oklch(0.768 0.233 130.85);
|
--sidebar-primary: oklch(0.623 0.214 259.815);
|
||||||
--sidebar-primary-foreground: oklch(0.986 0.031 120.757);
|
--sidebar-primary-foreground: oklch(0.97 0.014 254.604);
|
||||||
--sidebar-accent: oklch(0.274 0.006 286.033);
|
--sidebar-accent: oklch(0.274 0.006 286.033);
|
||||||
--sidebar-accent-foreground: oklch(0.985 0 0);
|
--sidebar-accent-foreground: oklch(0.985 0 0);
|
||||||
--sidebar-border: oklch(1 0 0 / 10%);
|
--sidebar-border: oklch(1 0 0 / 10%);
|
||||||
--sidebar-ring: oklch(0.405 0.101 131.063);
|
--sidebar-ring: oklch(0.439 0 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
* {
|
* {
|
||||||
|
|
|
||||||
|
|
@ -6,40 +6,43 @@ import {
|
||||||
DialogFooter,
|
DialogFooter,
|
||||||
DialogHeader,
|
DialogHeader,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
} from '@/Components/ui/dialog';
|
} from "@/Components/ui/dialog";
|
||||||
import { Button } from '@/Components/ui/button';
|
import { Button } from "@/Components/ui/button";
|
||||||
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
|
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
|
||||||
import { faPlusCircle } from '@fortawesome/free-solid-svg-icons';
|
import { faPlusCircle } from "@fortawesome/free-solid-svg-icons";
|
||||||
import { computed, ref, watch, nextTick } from 'vue';
|
import { computed, ref, watch, nextTick } from "vue";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
show: { type: Boolean, default: false },
|
show: { type: Boolean, default: false },
|
||||||
title: { type: String, default: 'Ustvari novo' },
|
title: { type: String, default: "Ustvari novo" },
|
||||||
maxWidth: { type: String, default: '2xl' },
|
maxWidth: { type: String, default: "2xl" },
|
||||||
confirmText: { type: String, default: 'Ustvari' },
|
confirmText: { type: String, default: "Ustvari" },
|
||||||
cancelText: { type: String, default: 'Prekliči' },
|
cancelText: { type: String, default: "Prekliči" },
|
||||||
processing: { type: Boolean, default: false },
|
processing: { type: Boolean, default: false },
|
||||||
disabled: { type: Boolean, default: false },
|
disabled: { type: Boolean, default: false },
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits(['update:show', 'close', 'confirm']);
|
const emit = defineEmits(["update:show", "close", "confirm"]);
|
||||||
|
|
||||||
const open = ref(props.show);
|
const open = ref(props.show);
|
||||||
|
|
||||||
watch(() => props.show, (newVal) => {
|
watch(
|
||||||
open.value = newVal;
|
() => props.show,
|
||||||
if (newVal) {
|
(newVal) => {
|
||||||
// Emit custom event when dialog opens
|
open.value = newVal;
|
||||||
nextTick(() => {
|
if (newVal) {
|
||||||
window.dispatchEvent(new CustomEvent('dialog:open'));
|
// Emit custom event when dialog opens
|
||||||
});
|
nextTick(() => {
|
||||||
|
window.dispatchEvent(new CustomEvent("dialog:open"));
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
|
|
||||||
watch(open, (newVal) => {
|
watch(open, (newVal) => {
|
||||||
emit('update:show', newVal);
|
emit("update:show", newVal);
|
||||||
if (!newVal) {
|
if (!newVal) {
|
||||||
emit('close');
|
emit("close");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -48,19 +51,19 @@ const onClose = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const onConfirm = () => {
|
const onConfirm = () => {
|
||||||
emit('confirm');
|
emit("confirm");
|
||||||
};
|
};
|
||||||
|
|
||||||
const maxWidthClass = computed(() => {
|
const maxWidthClass = computed(() => {
|
||||||
const maxWidthMap = {
|
const maxWidthMap = {
|
||||||
sm: 'sm:max-w-sm',
|
sm: "sm:max-w-sm",
|
||||||
md: 'sm:max-w-md',
|
md: "sm:max-w-md",
|
||||||
lg: 'sm:max-w-lg',
|
lg: "sm:max-w-lg",
|
||||||
xl: 'sm:max-w-xl',
|
xl: "sm:max-w-xl",
|
||||||
'2xl': 'sm:max-w-2xl',
|
"2xl": "sm:max-w-2xl",
|
||||||
wide: 'sm:max-w-[1200px]',
|
wide: "sm:max-w-[1200px]",
|
||||||
};
|
};
|
||||||
return maxWidthMap[props.maxWidth] || 'sm:max-w-2xl';
|
return maxWidthMap[props.maxWidth] || "sm:max-w-2xl";
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
@ -70,7 +73,7 @@ const maxWidthClass = computed(() => {
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>
|
<DialogTitle>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<FontAwesomeIcon :icon="faPlusCircle" class="h-5 w-5 text-primary-600" />
|
<FontAwesomeIcon :icon="faPlusCircle" class="h-5 w-5 text-primary" />
|
||||||
<span>{{ title }}</span>
|
<span>{{ title }}</span>
|
||||||
</div>
|
</div>
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
|
|
@ -87,14 +90,10 @@ const maxWidthClass = computed(() => {
|
||||||
<Button variant="outline" @click="onClose" :disabled="processing">
|
<Button variant="outline" @click="onClose" :disabled="processing">
|
||||||
{{ cancelText }}
|
{{ cancelText }}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button @click="onConfirm" :disabled="processing || disabled">
|
||||||
@click="onConfirm"
|
|
||||||
:disabled="processing || disabled"
|
|
||||||
>
|
|
||||||
{{ confirmText }}
|
{{ confirmText }}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogFooter>
|
</DialogFooter>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,40 +6,43 @@ import {
|
||||||
DialogFooter,
|
DialogFooter,
|
||||||
DialogHeader,
|
DialogHeader,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
} from '@/Components/ui/dialog';
|
} from "@/Components/ui/dialog";
|
||||||
import { Button } from '@/Components/ui/button';
|
import { Button } from "@/Components/ui/button";
|
||||||
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
|
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
|
||||||
import { faPenToSquare } from '@fortawesome/free-solid-svg-icons';
|
import { faPenToSquare } from "@fortawesome/free-solid-svg-icons";
|
||||||
import { computed, ref, watch, nextTick } from 'vue';
|
import { computed, ref, watch, nextTick } from "vue";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
show: { type: Boolean, default: false },
|
show: { type: Boolean, default: false },
|
||||||
title: { type: String, default: 'Uredi' },
|
title: { type: String, default: "Uredi" },
|
||||||
maxWidth: { type: String, default: '2xl' },
|
maxWidth: { type: String, default: "2xl" },
|
||||||
confirmText: { type: String, default: 'Shrani' },
|
confirmText: { type: String, default: "Shrani" },
|
||||||
cancelText: { type: String, default: 'Prekliči' },
|
cancelText: { type: String, default: "Prekliči" },
|
||||||
processing: { type: Boolean, default: false },
|
processing: { type: Boolean, default: false },
|
||||||
disabled: { type: Boolean, default: false },
|
disabled: { type: Boolean, default: false },
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits(['update:show', 'close', 'confirm']);
|
const emit = defineEmits(["update:show", "close", "confirm"]);
|
||||||
|
|
||||||
const open = ref(props.show);
|
const open = ref(props.show);
|
||||||
|
|
||||||
watch(() => props.show, (newVal) => {
|
watch(
|
||||||
open.value = newVal;
|
() => props.show,
|
||||||
if (newVal) {
|
(newVal) => {
|
||||||
// Emit custom event when dialog opens
|
open.value = newVal;
|
||||||
nextTick(() => {
|
if (newVal) {
|
||||||
window.dispatchEvent(new CustomEvent('dialog:open'));
|
// Emit custom event when dialog opens
|
||||||
});
|
nextTick(() => {
|
||||||
|
window.dispatchEvent(new CustomEvent("dialog:open"));
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
|
|
||||||
watch(open, (newVal) => {
|
watch(open, (newVal) => {
|
||||||
emit('update:show', newVal);
|
emit("update:show", newVal);
|
||||||
if (!newVal) {
|
if (!newVal) {
|
||||||
emit('close');
|
emit("close");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -48,19 +51,19 @@ const onClose = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const onConfirm = () => {
|
const onConfirm = () => {
|
||||||
emit('confirm');
|
emit("confirm");
|
||||||
};
|
};
|
||||||
|
|
||||||
const maxWidthClass = computed(() => {
|
const maxWidthClass = computed(() => {
|
||||||
const maxWidthMap = {
|
const maxWidthMap = {
|
||||||
sm: 'sm:max-w-sm',
|
sm: "sm:max-w-sm",
|
||||||
md: 'sm:max-w-md',
|
md: "sm:max-w-md",
|
||||||
lg: 'sm:max-w-lg',
|
lg: "sm:max-w-lg",
|
||||||
xl: 'sm:max-w-xl',
|
xl: "sm:max-w-xl",
|
||||||
'2xl': 'sm:max-w-2xl',
|
"2xl": "sm:max-w-2xl",
|
||||||
wide: 'sm:max-w-[1200px]',
|
wide: "sm:max-w-[1200px]",
|
||||||
};
|
};
|
||||||
return maxWidthMap[props.maxWidth] || 'sm:max-w-2xl';
|
return maxWidthMap[props.maxWidth] || "sm:max-w-2xl";
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
@ -70,7 +73,7 @@ const maxWidthClass = computed(() => {
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>
|
<DialogTitle>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<FontAwesomeIcon :icon="faPenToSquare" class="h-5 w-5 text-primary-600" />
|
<FontAwesomeIcon :icon="faPenToSquare" class="h-5 w-5 text-primary" />
|
||||||
<span>{{ title }}</span>
|
<span>{{ title }}</span>
|
||||||
</div>
|
</div>
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
|
|
@ -87,14 +90,10 @@ const maxWidthClass = computed(() => {
|
||||||
<Button variant="outline" @click="onClose" :disabled="processing">
|
<Button variant="outline" @click="onClose" :disabled="processing">
|
||||||
{{ cancelText }}
|
{{ cancelText }}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button @click="onConfirm" :disabled="processing || disabled">
|
||||||
@click="onConfirm"
|
|
||||||
:disabled="processing || disabled"
|
|
||||||
>
|
|
||||||
{{ confirmText }}
|
{{ confirmText }}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogFooter>
|
</DialogFooter>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,9 @@ import DataTable from "@/Components/DataTable/DataTableNew2.vue";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
|
||||||
import { faFolderOpen } from "@fortawesome/free-solid-svg-icons";
|
import { faFolderOpen } from "@fortawesome/free-solid-svg-icons";
|
||||||
import Pagination from "@/Components/Pagination.vue";
|
import Pagination from "@/Components/Pagination.vue";
|
||||||
|
import AppCard from "@/Components/app/ui/card/AppCard.vue";
|
||||||
|
import { FolderOpenIcon } from "lucide-vue-next";
|
||||||
|
import CardTitle from "@/Components/ui/card/CardTitle.vue";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
client_cases: Object,
|
client_cases: Object,
|
||||||
|
|
@ -41,101 +44,106 @@ const fmtDateDMY = (v) => {
|
||||||
<template>
|
<template>
|
||||||
<AppLayout title="Client cases">
|
<AppLayout title="Client cases">
|
||||||
<template #header> </template>
|
<template #header> </template>
|
||||||
<div class="py-12">
|
<div class="py-6">
|
||||||
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
|
||||||
<div class="bg-white overflow-hidden shadow-xl sm:rounded-lg">
|
<AppCard
|
||||||
<div class="mx-auto max-w-4x1 py-3">
|
title=""
|
||||||
<div class="pb-3 px-3">
|
padding="none"
|
||||||
<SectionTitle>
|
class="p-0! gap-0"
|
||||||
<template #title>Primeri</template>
|
header-class="py-3! px-4 gap-0 text-muted-foreground"
|
||||||
</SectionTitle>
|
body-class=""
|
||||||
</div>
|
>
|
||||||
<DataTable
|
<template #header>
|
||||||
:columns="[
|
<div class="flex items-center gap-2">
|
||||||
{ key: 'nu', label: 'Št.', sortable: false },
|
<FolderOpenIcon size="18" />
|
||||||
{ key: 'case', label: 'Primer', sortable: false },
|
<CardTitle class="uppercase">Primeri</CardTitle>
|
||||||
{ key: 'client', label: 'Stranka', sortable: false },
|
|
||||||
{ key: 'tax', label: 'Davčna', sortable: false },
|
|
||||||
{ key: 'created_at', label: 'Ustvarjeno', sortable: false },
|
|
||||||
{
|
|
||||||
key: 'active_contracts',
|
|
||||||
label: 'Aktivne pogodbe',
|
|
||||||
sortable: false,
|
|
||||||
align: 'right',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'balance',
|
|
||||||
label: 'Skupaj stanje',
|
|
||||||
sortable: false,
|
|
||||||
align: 'right',
|
|
||||||
},
|
|
||||||
]"
|
|
||||||
:data="client_cases.data || []"
|
|
||||||
:page-size="client_cases.per_page"
|
|
||||||
:show-pagination="false"
|
|
||||||
:show-toolbar="true"
|
|
||||||
:hoverable="true"
|
|
||||||
row-key="uuid"
|
|
||||||
empty-text="Ni najdenih primerov."
|
|
||||||
>
|
|
||||||
<template #cell-nu="{ row }">
|
|
||||||
{{ row.person?.nu || "-" }}
|
|
||||||
</template>
|
|
||||||
<template #cell-case="{ row }">
|
|
||||||
<Link
|
|
||||||
:href="route('clientCase.show', { client_case: row.uuid })"
|
|
||||||
class="text-indigo-600 hover:underline"
|
|
||||||
>
|
|
||||||
{{ row.person?.full_name || "-" }}
|
|
||||||
</Link>
|
|
||||||
<button
|
|
||||||
v-if="!row.person"
|
|
||||||
@click.prevent="
|
|
||||||
router.post(
|
|
||||||
route('clientCase.emergencyPerson', { client_case: row.uuid })
|
|
||||||
)
|
|
||||||
"
|
|
||||||
class="ml-2 inline-flex items-center rounded bg-red-50 px-2 py-0.5 text-xs font-semibold text-red-600 hover:bg-red-100 border border-red-200"
|
|
||||||
title="Emergency: recreate missing person"
|
|
||||||
>
|
|
||||||
Add Person
|
|
||||||
</button>
|
|
||||||
</template>
|
|
||||||
<template #cell-client="{ row }">
|
|
||||||
{{ row.client?.person?.full_name || "-" }}
|
|
||||||
</template>
|
|
||||||
<template #cell-tax="{ row }">
|
|
||||||
{{ row.person?.tax_number || "-" }}
|
|
||||||
</template>
|
|
||||||
<template #cell-created_at="{ row }">
|
|
||||||
{{ fmtDateDMY(row.created_at) }}
|
|
||||||
</template>
|
|
||||||
<template #cell-active_contracts="{ row }">
|
|
||||||
<div class="text-right">{{ row.active_contracts_count ?? 0 }}</div>
|
|
||||||
</template>
|
|
||||||
<template #cell-balance="{ row }">
|
|
||||||
<div class="text-right">
|
|
||||||
{{ fmtCurrency(row.active_contracts_balance_sum) }}
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</DataTable>
|
|
||||||
<div class="border-t border-gray-200 p-4">
|
|
||||||
<Pagination
|
|
||||||
:links="client_cases.links"
|
|
||||||
:from="client_cases.from"
|
|
||||||
:to="client_cases.to"
|
|
||||||
:total="client_cases.total"
|
|
||||||
:per-page="client_cases.per_page || 20"
|
|
||||||
:last-page="client_cases.last_page"
|
|
||||||
:current-page="client_cases.current_page"
|
|
||||||
per-page-param="perPage"
|
|
||||||
page-param="clientCasesPage"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
</template>
|
||||||
|
<DataTable
|
||||||
|
:columns="[
|
||||||
|
{ key: 'nu', label: 'Št.', sortable: false },
|
||||||
|
{ key: 'case', label: 'Primer', sortable: false },
|
||||||
|
{ key: 'client', label: 'Stranka', sortable: false },
|
||||||
|
{ key: 'tax', label: 'Davčna', sortable: false },
|
||||||
|
{ key: 'created_at', label: 'Ustvarjeno', sortable: false },
|
||||||
|
{
|
||||||
|
key: 'active_contracts',
|
||||||
|
label: 'Aktivne pogodbe',
|
||||||
|
sortable: false,
|
||||||
|
align: 'right',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'balance',
|
||||||
|
label: 'Skupaj stanje',
|
||||||
|
sortable: false,
|
||||||
|
align: 'right',
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
:data="client_cases.data || []"
|
||||||
|
:page-size="client_cases.per_page"
|
||||||
|
:show-pagination="false"
|
||||||
|
:show-toolbar="true"
|
||||||
|
:hoverable="true"
|
||||||
|
row-key="uuid"
|
||||||
|
empty-text="Ni najdenih primerov."
|
||||||
|
>
|
||||||
|
<template #cell-nu="{ row }">
|
||||||
|
{{ row.person?.nu || "-" }}
|
||||||
|
</template>
|
||||||
|
<template #cell-case="{ row }">
|
||||||
|
<Link
|
||||||
|
:href="route('clientCase.show', { client_case: row.uuid })"
|
||||||
|
class="text-indigo-600 hover:underline"
|
||||||
|
>
|
||||||
|
{{ row.person?.full_name || "-" }}
|
||||||
|
</Link>
|
||||||
|
<button
|
||||||
|
v-if="!row.person"
|
||||||
|
@click.prevent="
|
||||||
|
router.post(
|
||||||
|
route('clientCase.emergencyPerson', { client_case: row.uuid })
|
||||||
|
)
|
||||||
|
"
|
||||||
|
class="ml-2 inline-flex items-center rounded bg-red-50 px-2 py-0.5 text-xs font-semibold text-red-600 hover:bg-red-100 border border-red-200"
|
||||||
|
title="Emergency: recreate missing person"
|
||||||
|
>
|
||||||
|
Add Person
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
<template #cell-client="{ row }">
|
||||||
|
{{ row.client?.person?.full_name || "-" }}
|
||||||
|
</template>
|
||||||
|
<template #cell-tax="{ row }">
|
||||||
|
{{ row.person?.tax_number || "-" }}
|
||||||
|
</template>
|
||||||
|
<template #cell-created_at="{ row }">
|
||||||
|
{{ fmtDateDMY(row.created_at) }}
|
||||||
|
</template>
|
||||||
|
<template #cell-active_contracts="{ row }">
|
||||||
|
<div class="text-right">{{ row.active_contracts_count ?? 0 }}</div>
|
||||||
|
</template>
|
||||||
|
<template #cell-balance="{ row }">
|
||||||
|
<div class="text-right">
|
||||||
|
{{ fmtCurrency(row.active_contracts_balance_sum) }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</DataTable>
|
||||||
|
<div class="border-t border-gray-200 p-4">
|
||||||
|
<Pagination
|
||||||
|
:links="client_cases.links"
|
||||||
|
:from="client_cases.from"
|
||||||
|
:to="client_cases.to"
|
||||||
|
:total="client_cases.total"
|
||||||
|
:per-page="client_cases.per_page || 20"
|
||||||
|
:last-page="client_cases.last_page"
|
||||||
|
:current-page="client_cases.current_page"
|
||||||
|
per-page-param="perPage"
|
||||||
|
page-param="clientCasesPage"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<!-- Pagination handled by DataTableServer -->
|
</AppCard>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<!-- Pagination handled by DataTableServer -->
|
||||||
</div>
|
</div>
|
||||||
</AppLayout>
|
</AppLayout>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,9 @@ import { useForm } from "vee-validate";
|
||||||
import { toTypedSchema } from "@vee-validate/zod";
|
import { toTypedSchema } from "@vee-validate/zod";
|
||||||
import * as z from "zod";
|
import * as z from "zod";
|
||||||
import ActionMessage from "@/Components/ActionMessage.vue";
|
import ActionMessage from "@/Components/ActionMessage.vue";
|
||||||
import { Mail, Plug2Icon, Plus } from "lucide-vue-next";
|
import { Mail, Plug2Icon, Plus, UsersRoundIcon } from "lucide-vue-next";
|
||||||
import { Separator } from "@/Components/ui/separator";
|
import { Separator } from "@/Components/ui/separator";
|
||||||
|
import AppCard from "@/Components/app/ui/card/AppCard.vue";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
clients: Object,
|
clients: Object,
|
||||||
|
|
@ -161,83 +162,91 @@ const fmtCurrency = (v) => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<AppLayout title="Client">
|
<AppLayout>
|
||||||
<template #header> </template>
|
<template #header> </template>
|
||||||
<div class="py-6">
|
<div class="py-6">
|
||||||
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
|
||||||
<Card class="p-0">
|
<AppCard
|
||||||
<CardHeader>
|
title=""
|
||||||
<CardTitle>Naročniki</CardTitle>
|
padding="none"
|
||||||
</CardHeader>
|
class="p-0! gap-0"
|
||||||
<CardContent class="p-0">
|
header-class="py-3! px-4 gap-0 text-muted-foreground"
|
||||||
<DataTable
|
body-class=""
|
||||||
:columns="[
|
>
|
||||||
{ key: 'nu', label: 'Št.', sortable: false },
|
<template #header>
|
||||||
{ key: 'name', label: 'Naročnik', sortable: false },
|
<div class="flex items-center gap-2">
|
||||||
{
|
<UsersRoundIcon size="18" />
|
||||||
key: 'cases',
|
<CardTitle class="uppercase">Naročniki</CardTitle>
|
||||||
label: 'Primeri z aktivnimi pogodbami',
|
</div>
|
||||||
sortable: false,
|
</template>
|
||||||
align: 'right',
|
|
||||||
},
|
<DataTable
|
||||||
{
|
:columns="[
|
||||||
key: 'balance',
|
{ key: 'nu', label: 'Št.', sortable: false },
|
||||||
label: 'Skupaj stanje',
|
{ key: 'name', label: 'Naročnik', sortable: false },
|
||||||
sortable: false,
|
{
|
||||||
align: 'right',
|
key: 'cases',
|
||||||
},
|
label: 'Primeri z aktivnimi pogodbami',
|
||||||
]"
|
sortable: false,
|
||||||
:data="clients.data || []"
|
align: 'right',
|
||||||
:show-pagination="false"
|
},
|
||||||
:show-toolbar="true"
|
{
|
||||||
:hoverable="true"
|
key: 'balance',
|
||||||
row-key="uuid"
|
label: 'Skupaj stanje',
|
||||||
:striped="true"
|
sortable: false,
|
||||||
empty-text="Ni najdenih naročnikov."
|
align: 'right',
|
||||||
>
|
},
|
||||||
<template #toolbar-actions>
|
]"
|
||||||
|
:data="clients.data || []"
|
||||||
|
:show-pagination="false"
|
||||||
|
:show-toolbar="true"
|
||||||
|
:hoverable="true"
|
||||||
|
row-key="uuid"
|
||||||
|
:striped="true"
|
||||||
|
empty-text="Ni najdenih naročnikov."
|
||||||
|
>
|
||||||
|
<template #toolbar-actions>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
v-if="hasPerm('client-edit')"
|
||||||
|
@click="openDrawerCreateClient"
|
||||||
|
>
|
||||||
|
<Plus class="w-4 h-4" /> Novi naročnik
|
||||||
|
</Button>
|
||||||
|
</template>
|
||||||
|
<template #cell-nu="{ row }">
|
||||||
|
{{ row.person?.nu || "-" }}
|
||||||
|
</template>
|
||||||
|
<template #cell-name="{ row }">
|
||||||
|
<Link
|
||||||
|
:href="route('client.show', { uuid: row.uuid })"
|
||||||
|
class="font-semibold hover:underline text-primary-700"
|
||||||
|
>
|
||||||
|
{{ row.person?.full_name || "-" }}
|
||||||
|
</Link>
|
||||||
|
<div v-if="!row.person" class="mt-1">
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="destructive"
|
||||||
v-if="hasPerm('client-edit')"
|
size="sm"
|
||||||
@click="openDrawerCreateClient"
|
@click.prevent="
|
||||||
|
router.post(route('client.emergencyPerson', { uuid: row.uuid }))
|
||||||
|
"
|
||||||
|
>Add Person</Button
|
||||||
>
|
>
|
||||||
<Plus class="w-4 h-4" /> Novi naročnik
|
</div>
|
||||||
</Button>
|
</template>
|
||||||
</template>
|
<template #cell-cases="{ row }">
|
||||||
<template #cell-nu="{ row }">
|
<div class="text-right">
|
||||||
{{ row.person?.nu || "-" }}
|
{{ row.cases_with_active_contracts_count ?? 0 }}
|
||||||
</template>
|
</div>
|
||||||
<template #cell-name="{ row }">
|
</template>
|
||||||
<Link
|
<template #cell-balance="{ row }">
|
||||||
:href="route('client.show', { uuid: row.uuid })"
|
<div class="text-right">
|
||||||
class="font-semibold hover:underline text-primary-700"
|
{{ fmtCurrency(row.active_contracts_balance_sum) }}
|
||||||
>
|
</div>
|
||||||
{{ row.person?.full_name || "-" }}
|
</template>
|
||||||
</Link>
|
</DataTable>
|
||||||
<div v-if="!row.person" class="mt-1">
|
</AppCard>
|
||||||
<Button
|
|
||||||
variant="destructive"
|
|
||||||
size="sm"
|
|
||||||
@click.prevent="
|
|
||||||
router.post(route('client.emergencyPerson', { uuid: row.uuid }))
|
|
||||||
"
|
|
||||||
>Add Person</Button
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<template #cell-cases="{ row }">
|
|
||||||
<div class="text-right">
|
|
||||||
{{ row.cases_with_active_contracts_count ?? 0 }}
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<template #cell-balance="{ row }">
|
|
||||||
<div class="text-right">
|
|
||||||
{{ fmtCurrency(row.active_contracts_balance_sum) }}
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</DataTable>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</AppLayout>
|
</AppLayout>
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import { Card } from "@/Components/ui/card";
|
||||||
import Badge from "@/Components/ui/badge/Badge.vue";
|
import Badge from "@/Components/ui/badge/Badge.vue";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { Input } from "@/Components/ui/input";
|
import { Input } from "@/Components/ui/input";
|
||||||
|
import { UsersRoundIcon } from "lucide-vue-next";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
client: Object,
|
client: Object,
|
||||||
|
|
@ -60,7 +61,7 @@ function applySearch() {
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<AppLayout title="Client">
|
<AppLayout title="Client">
|
||||||
<template #header></template>
|
<template #header> </template>
|
||||||
<div class="pt-6">
|
<div class="pt-6">
|
||||||
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
|
||||||
<Card class="border-l-4 border-blue-400 p-0!">
|
<Card class="border-l-4 border-blue-400 p-0!">
|
||||||
|
|
@ -93,7 +94,7 @@ function applySearch() {
|
||||||
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
|
||||||
<div class="bg-white overflow-hidden shadow-xl sm:rounded-lg">
|
<div class="bg-white overflow-hidden shadow-xl sm:rounded-lg">
|
||||||
<div class="mx-auto max-w-4x1">
|
<div class="mx-auto max-w-4x1">
|
||||||
<div class="px-3 py-4 flex flex-row items-center gap-3">
|
<div class="p-2 flex flex-row items-center gap-2">
|
||||||
<Link
|
<Link
|
||||||
:class="
|
:class="
|
||||||
cn(
|
cn(
|
||||||
|
|
|
||||||
|
|
@ -55,15 +55,15 @@ const formatBalance = (amount) => {
|
||||||
label="Skupno stanje"
|
label="Skupno stanje"
|
||||||
:value="formatBalance(kpis?.total_balance)"
|
:value="formatBalance(kpis?.total_balance)"
|
||||||
:icon="Banknote"
|
:icon="Banknote"
|
||||||
icon-bg="bg-chart-3/10"
|
icon-bg="bg-chart-2/10"
|
||||||
icon-color="text-chart-3"
|
icon-color="text-chart-2"
|
||||||
/>
|
/>
|
||||||
<SimpleKpiCard
|
<SimpleKpiCard
|
||||||
label="Aktivne obljube"
|
label="Aktivne obljube"
|
||||||
:value="kpis?.active_promises"
|
:value="kpis?.active_promises"
|
||||||
:icon="CalendarCheck"
|
:icon="CalendarCheck"
|
||||||
icon-bg="bg-chart-4/10"
|
icon-bg="bg-chart-2/10"
|
||||||
icon-color="text-chart-4"
|
icon-color="text-chart-2"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -71,28 +71,28 @@ const props = defineProps({
|
||||||
<!-- Stats grid -->
|
<!-- Stats grid -->
|
||||||
<ItemDescription>
|
<ItemDescription>
|
||||||
<div class="grid grid-cols-4 divide-x">
|
<div class="grid grid-cols-4 divide-x">
|
||||||
<div class="flex flex-row items-center justify-between p-2">
|
<div class="flex flex-row items-center justify-between p-3">
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<span class="text-muted-foreground text-xs">Skupaj</span>
|
<span class="text-muted-foreground text-xs">Skupaj</span>
|
||||||
<span class="text-xl font-bold">{{ p.today?.total ?? 0 }}</span>
|
<span class="text-xl font-bold">{{ p.today?.total ?? 0 }}</span>
|
||||||
</div>
|
</div>
|
||||||
<MessageSquare class="h-5 w-5 text-gray-500" />
|
<MessageSquare class="h-5 w-5 text-gray-500" />
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-row items-center justify-between p-2">
|
<div class="flex flex-row items-center justify-between p-3">
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<span class="text-muted-foreground text-xs">Poslano</span>
|
<span class="text-muted-foreground text-xs">Poslano</span>
|
||||||
<span class="text-xl font-bold">{{ p.today?.sent ?? 0 }}</span>
|
<span class="text-xl font-bold">{{ p.today?.sent ?? 0 }}</span>
|
||||||
</div>
|
</div>
|
||||||
<Send class="h-5 w-5 text-sky-600" />
|
<Send class="h-5 w-5 text-sky-600" />
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-row items-center justify-between p-2">
|
<div class="flex flex-row items-center justify-between p-3">
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<span class="text-muted-foreground text-xs">Delivered</span>
|
<span class="text-muted-foreground text-xs">Delivered</span>
|
||||||
<span class="text-xl font-bold">{{ p.today?.delivered ?? 0 }}</span>
|
<span class="text-xl font-bold">{{ p.today?.delivered ?? 0 }}</span>
|
||||||
</div>
|
</div>
|
||||||
<CheckCircle class="h-5 w-5 text-emerald-600" />
|
<CheckCircle class="h-5 w-5 text-emerald-600" />
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-row items-center justify-between p-2">
|
<div class="flex flex-row items-center justify-between p-3">
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<span class="text-muted-foreground text-xs">Failed</span>
|
<span class="text-muted-foreground text-xs">Failed</span>
|
||||||
<span class="text-xl font-bold">{{ p.today?.failed ?? 0 }}</span>
|
<span class="text-xl font-bold">{{ p.today?.failed ?? 0 }}</span>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user