Operation processes on invoices

This commit is contained in:
2026-02-13 00:11:51 +01:00
parent 882752472e
commit fd403f8520
44 changed files with 1635 additions and 42 deletions

View File

@@ -0,0 +1,146 @@
<template>
<teleport to="body">
<transition name="fade">
<div
v-if="show"
class="full-screen-modal-overlay"
@click.self="close"
>
<transition name="scale">
<div
v-if="show"
ref="modalRef"
class="full-screen-modal-content"
tabindex="-1"
>
<div class="full-screen-modal-body">
<slot />
<span @click="close" class="dashicons dashicons-dismiss full-screen-modal-close"></span>
</div>
</div>
</transition>
</div>
</transition>
</teleport>
</template>
<script setup>
import { ref, watch, onMounted, onUnmounted, nextTick } from 'vue'
const props = defineProps({
show: Boolean
})
const emit = defineEmits(['close'])
const modalRef = ref(null)
function close() {
emit('close')
}
// ESC-Key & Focus-Trap
function handleKeyDown(e) {
if (e.key === 'Escape') {
close()
}
if (e.key === 'Tab' && modalRef.value) {
const focusable = modalRef.value.querySelectorAll(
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
)
if (focusable.length === 0) return
const first = focusable[0]
const last = focusable[focusable.length - 1]
if (e.shiftKey && document.activeElement === first) {
e.preventDefault()
last.focus()
} else if (!e.shiftKey && document.activeElement === last) {
e.preventDefault()
first.focus()
}
}
}
// Body-Scroll sperren
watch(
() => props.show,
async (newVal) => {
if (newVal) {
document.body.style.overflow = 'hidden'
await nextTick()
modalRef.value?.focus()
} else {
document.body.style.overflow = ''
}
}
)
onMounted(() => {
window.addEventListener('keydown', handleKeyDown)
})
onUnmounted(() => {
window.removeEventListener('keydown', handleKeyDown)
document.body.style.overflow = ''
})
</script>
<style scoped>
.full-screen-modal-overlay {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 9999;
display: flex;
justify-content: center;
align-items: center;
}
.full-screen-modal-content {
background: white;
border-radius: 12px;
position: absolute;
top: 30px;
bottom: 30px;
left: 30px;
right: 30px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
outline: none;
display: flex;
flex-direction: column;
}
.full-screen-modal-body {
flex: 1;
overflow-y: auto;
padding: 20px;
position: relative;
}
.full-screen-modal-close {
position: absolute;
top: 15px;
right: 15px;
cursor: pointer;
font-size: 22px;
}
/* Animation */
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
.scale-enter-active,
.scale-leave-active {
transition: transform 0.25s ease, opacity 0.25s ease;
}
.scale-enter-from,
.scale-leave-to {
transform: scale(0.98);
opacity: 0;
}
</style>

View File

@@ -7,8 +7,17 @@ const props = defineProps({
name: { type: String, required: true },
})
if (SolidIcons[`fa${props.name.charAt(0).toUpperCase()}${props.name.slice(1)}`]) {
library.add(SolidIcons[`fa${props.name.charAt(0).toUpperCase()}${props.name.slice(1)}`])
function toPascalCase(str) {
return str
.split('-')
.map(part => part.charAt(0).toUpperCase() + part.slice(1))
.join('')
}
const iconName = `fa${toPascalCase(props.name)}`
if (SolidIcons[iconName]) {
library.add(SolidIcons[iconName])
}
</script>

View File

@@ -0,0 +1,46 @@
<script setup>
import { ref, onMounted } from "vue"
import { VuePDF, usePDF } from '@tato30/vue-pdf'
const props = defineProps({
url: String
})
const page = ref(1)
const { pdf, pages } = usePDF(props.url)
</script>
<template>
<div>
<div class="mareike-invoice-pdfview-controls">
<button @click="page = page > 1 ? page - 1 : page" class="button mareike-button page-switch-button">
Vorherige Seite
</button>
<span>{{ page }} / {{ pages }}</span>
<button @click="page = page < pages ? page + 1 : page" class="button mareike-button page-switch-button">
Nächste Seite
</button>
<VuePDF :pdf="pdf" :page="page" class="mareike_pdv_view" fitParent="true" cale="0.9" height="90"/>
</div>
</div>
</template>
<style scoped>
.page-switch-button {
padding: 8px 20px !important;
width: 200px !important;
margin: 0 10px !important;
}
.mareike-invoice-pdfview-controls {
position: relative;
top: -50px;
text-align: center;
}
</style>