Dev branch

This commit is contained in:
Simon Pocrnjič
2025-11-02 12:31:01 +01:00
parent 5f879c9436
commit 63e0958b66
241 changed files with 17686 additions and 7327 deletions
@@ -0,0 +1,111 @@
<script setup>
import { computed, ref, watch } from 'vue';
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from '@/Components/ui/dialog';
import { Button } from '@/Components/ui/button';
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
import { faCircleQuestion, faCheckCircle } from '@fortawesome/free-solid-svg-icons';
const props = defineProps({
show: { type: Boolean, default: false },
title: { type: String, default: 'Potrditev' },
message: { type: String, default: 'Ali ste prepričani?' },
confirmText: { type: String, default: 'Potrdi' },
cancelText: { type: String, default: 'Prekliči' },
processing: { type: Boolean, default: false },
maxWidth: { type: String, default: 'md' },
variant: {
type: String,
default: 'default', // 'default' or 'success'
validator: (v) => ['default', 'success'].includes(v)
},
});
const emit = defineEmits(['update:show', 'close', 'confirm']);
const open = ref(props.show);
watch(() => props.show, (newVal) => {
open.value = newVal;
});
watch(open, (newVal) => {
emit('update:show', newVal);
if (!newVal) {
emit('close');
}
});
const onClose = () => {
open.value = false;
};
const onConfirm = () => {
emit('confirm');
};
const icon = computed(() => props.variant === 'success' ? faCheckCircle : faCircleQuestion);
const iconColor = computed(() => props.variant === 'success' ? 'text-green-600' : 'text-primary-600');
const iconBg = computed(() => props.variant === 'success' ? 'bg-green-100' : 'bg-primary-100');
const maxWidthClass = computed(() => {
const maxWidthMap = {
sm: 'sm:max-w-sm',
md: 'sm:max-w-md',
lg: 'sm:max-w-lg',
xl: 'sm:max-w-xl',
'2xl': 'sm:max-w-2xl',
wide: 'sm:max-w-[1200px]',
};
return maxWidthMap[props.maxWidth] || 'sm:max-w-md';
});
</script>
<template>
<Dialog v-model:open="open">
<DialogContent :class="maxWidthClass">
<DialogHeader>
<DialogTitle>
<div class="flex items-center gap-2">
<FontAwesomeIcon :icon="icon" :class="['h-5 w-5', iconColor]" />
<span>{{ title }}</span>
</div>
</DialogTitle>
<DialogDescription>
<div class="flex items-start gap-4 pt-4">
<div class="flex-shrink-0">
<div :class="['flex items-center justify-center h-12 w-12 rounded-full', iconBg]">
<FontAwesomeIcon :icon="icon" :class="['h-6 w-6', iconColor]" />
</div>
</div>
<div class="flex-1">
<p class="text-sm text-gray-700">
{{ message }}
</p>
<slot />
</div>
</div>
</DialogDescription>
</DialogHeader>
<DialogFooter>
<Button variant="outline" @click="onClose" :disabled="processing">
{{ cancelText }}
</Button>
<Button
@click="onConfirm"
:disabled="processing"
>
{{ confirmText }}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</template>
@@ -0,0 +1,100 @@
<script setup>
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from '@/Components/ui/dialog';
import { Button } from '@/Components/ui/button';
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
import { faPlusCircle } from '@fortawesome/free-solid-svg-icons';
import { computed, ref, watch, nextTick } from 'vue';
const props = defineProps({
show: { type: Boolean, default: false },
title: { type: String, default: 'Ustvari novo' },
maxWidth: { type: String, default: '2xl' },
confirmText: { type: String, default: 'Ustvari' },
cancelText: { type: String, default: 'Prekliči' },
processing: { type: Boolean, default: false },
disabled: { type: Boolean, default: false },
});
const emit = defineEmits(['update:show', 'close', 'confirm']);
const open = ref(props.show);
watch(() => props.show, (newVal) => {
open.value = newVal;
if (newVal) {
// Emit custom event when dialog opens
nextTick(() => {
window.dispatchEvent(new CustomEvent('dialog:open'));
});
}
});
watch(open, (newVal) => {
emit('update:show', newVal);
if (!newVal) {
emit('close');
}
});
const onClose = () => {
open.value = false;
};
const onConfirm = () => {
emit('confirm');
};
const maxWidthClass = computed(() => {
const maxWidthMap = {
sm: 'sm:max-w-sm',
md: 'sm:max-w-md',
lg: 'sm:max-w-lg',
xl: 'sm:max-w-xl',
'2xl': 'sm:max-w-2xl',
wide: 'sm:max-w-[1200px]',
};
return maxWidthMap[props.maxWidth] || 'sm:max-w-2xl';
});
</script>
<template>
<Dialog v-model:open="open">
<DialogContent :class="maxWidthClass">
<DialogHeader>
<DialogTitle>
<div class="flex items-center gap-2">
<FontAwesomeIcon :icon="faPlusCircle" class="h-5 w-5 text-primary-600" />
<span>{{ title }}</span>
</div>
</DialogTitle>
<DialogDescription>
<slot name="description" />
</DialogDescription>
</DialogHeader>
<div class="py-4">
<slot />
</div>
<DialogFooter>
<Button variant="outline" @click="onClose" :disabled="processing">
{{ cancelText }}
</Button>
<Button
@click="onConfirm"
:disabled="processing || disabled"
>
{{ confirmText }}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</template>
@@ -0,0 +1,96 @@
<script setup>
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from '@/Components/ui/dialog';
import { Button } from '@/Components/ui/button';
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
import { faTrashCan, faTriangleExclamation } from '@fortawesome/free-solid-svg-icons';
import { ref, watch } from 'vue';
const props = defineProps({
show: { type: Boolean, default: false },
title: { type: String, default: 'Izbriši' },
message: { type: String, default: 'Ali ste prepričani, da želite izbrisati ta element?' },
confirmText: { type: String, default: 'Izbriši' },
cancelText: { type: String, default: 'Prekliči' },
processing: { type: Boolean, default: false },
itemName: { type: String, default: null }, // Optional name to show in confirmation
});
const emit = defineEmits(['update:show', 'close', 'confirm']);
const open = ref(props.show);
watch(() => props.show, (newVal) => {
open.value = newVal;
});
watch(open, (newVal) => {
emit('update:show', newVal);
if (!newVal) {
emit('close');
}
});
const onClose = () => {
open.value = false;
};
const onConfirm = () => {
emit('confirm');
};
</script>
<template>
<Dialog v-model:open="open">
<DialogContent class="sm:max-w-md">
<DialogHeader>
<DialogTitle>
<div class="flex items-center gap-2">
<FontAwesomeIcon :icon="faTrashCan" class="h-5 w-5 text-red-600" />
<span>{{ title }}</span>
</div>
</DialogTitle>
<DialogDescription>
<div class="flex items-start gap-4 pt-4">
<div class="flex-shrink-0">
<div class="flex items-center justify-center h-12 w-12 rounded-full bg-red-100">
<FontAwesomeIcon :icon="faTriangleExclamation" class="h-6 w-6 text-red-600" />
</div>
</div>
<div class="flex-1 space-y-2">
<p class="text-sm text-gray-700">
{{ message }}
</p>
<p v-if="itemName" class="text-sm font-medium text-gray-900">
{{ itemName }}
</p>
<p class="text-sm text-gray-500">
Ta dejanje ni mogoče razveljaviti.
</p>
</div>
</div>
</DialogDescription>
</DialogHeader>
<DialogFooter>
<Button variant="outline" @click="onClose" :disabled="processing">
{{ cancelText }}
</Button>
<Button
variant="destructive"
@click="onConfirm"
:disabled="processing"
>
{{ confirmText }}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</template>
@@ -0,0 +1,100 @@
<script setup>
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from '@/Components/ui/dialog';
import { Button } from '@/Components/ui/button';
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
import { faPenToSquare } from '@fortawesome/free-solid-svg-icons';
import { computed, ref, watch, nextTick } from 'vue';
const props = defineProps({
show: { type: Boolean, default: false },
title: { type: String, default: 'Uredi' },
maxWidth: { type: String, default: '2xl' },
confirmText: { type: String, default: 'Shrani' },
cancelText: { type: String, default: 'Prekliči' },
processing: { type: Boolean, default: false },
disabled: { type: Boolean, default: false },
});
const emit = defineEmits(['update:show', 'close', 'confirm']);
const open = ref(props.show);
watch(() => props.show, (newVal) => {
open.value = newVal;
if (newVal) {
// Emit custom event when dialog opens
nextTick(() => {
window.dispatchEvent(new CustomEvent('dialog:open'));
});
}
});
watch(open, (newVal) => {
emit('update:show', newVal);
if (!newVal) {
emit('close');
}
});
const onClose = () => {
open.value = false;
};
const onConfirm = () => {
emit('confirm');
};
const maxWidthClass = computed(() => {
const maxWidthMap = {
sm: 'sm:max-w-sm',
md: 'sm:max-w-md',
lg: 'sm:max-w-lg',
xl: 'sm:max-w-xl',
'2xl': 'sm:max-w-2xl',
wide: 'sm:max-w-[1200px]',
};
return maxWidthMap[props.maxWidth] || 'sm:max-w-2xl';
});
</script>
<template>
<Dialog v-model:open="open">
<DialogContent :class="maxWidthClass">
<DialogHeader>
<DialogTitle>
<div class="flex items-center gap-2">
<FontAwesomeIcon :icon="faPenToSquare" class="h-5 w-5 text-primary-600" />
<span>{{ title }}</span>
</div>
</DialogTitle>
<DialogDescription>
<slot name="description" />
</DialogDescription>
</DialogHeader>
<div class="py-4">
<slot />
</div>
<DialogFooter>
<Button variant="outline" @click="onClose" :disabled="processing">
{{ cancelText }}
</Button>
<Button
@click="onConfirm"
:disabled="processing || disabled"
>
{{ confirmText }}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</template>
@@ -0,0 +1,104 @@
<script setup>
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from '@/Components/ui/dialog';
import { Button } from '@/Components/ui/button';
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
import { faTriangleExclamation } from '@fortawesome/free-solid-svg-icons';
import { computed, ref, watch } from 'vue';
const props = defineProps({
show: { type: Boolean, default: false },
title: { type: String, default: 'Opozorilo' },
message: { type: String, default: 'Prosimo, bodite pozorni.' },
confirmText: { type: String, default: 'Razumem' },
cancelText: { type: String, default: 'Prekliči' },
processing: { type: Boolean, default: false },
maxWidth: { type: String, default: 'md' },
showCancel: { type: Boolean, default: true },
});
const emit = defineEmits(['update:show', 'close', 'confirm']);
const open = ref(props.show);
watch(() => props.show, (newVal) => {
open.value = newVal;
});
watch(open, (newVal) => {
emit('update:show', newVal);
if (!newVal) {
emit('close');
}
});
const onClose = () => {
open.value = false;
};
const onConfirm = () => {
emit('confirm');
};
const maxWidthClass = computed(() => {
const maxWidthMap = {
sm: 'sm:max-w-sm',
md: 'sm:max-w-md',
lg: 'sm:max-w-lg',
xl: 'sm:max-w-xl',
'2xl': 'sm:max-w-2xl',
wide: 'sm:max-w-[1200px]',
};
return maxWidthMap[props.maxWidth] || 'sm:max-w-md';
});
</script>
<template>
<Dialog v-model:open="open">
<DialogContent :class="maxWidthClass">
<DialogHeader>
<DialogTitle>
<div class="flex items-center gap-2">
<FontAwesomeIcon :icon="faTriangleExclamation" class="h-5 w-5 text-amber-600" />
<span>{{ title }}</span>
</div>
</DialogTitle>
<DialogDescription>
<div class="flex items-start gap-4 pt-4">
<div class="flex-shrink-0">
<div class="flex items-center justify-center h-12 w-12 rounded-full bg-amber-100">
<FontAwesomeIcon :icon="faTriangleExclamation" class="h-6 w-6 text-amber-600" />
</div>
</div>
<div class="flex-1">
<p class="text-sm text-gray-700">
{{ message }}
</p>
<slot />
</div>
</div>
</DialogDescription>
</DialogHeader>
<DialogFooter>
<Button v-if="showCancel" variant="outline" @click="onClose" :disabled="processing">
{{ cancelText }}
</Button>
<Button
@click="onConfirm"
:disabled="processing"
class="bg-amber-600 hover:bg-amber-700 focus:ring-amber-500"
>
{{ confirmText }}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</template>