Changes in Document Creation, Calendar, Notifications, Settings
This commit is contained in:
@@ -4,12 +4,12 @@ import type { Notification } from '~/types'
|
||||
|
||||
const { isNotificationsSlideoverOpen } = useDashboard()
|
||||
|
||||
const { data: notifications } = await useFetch<Notification[]>('/api/notifications')
|
||||
//const { data: notifications } = await useFetch<Notification[]>('/api/notifications')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UDashboardSlideover v-model="isNotificationsSlideoverOpen" title="Notifications">
|
||||
<NuxtLink v-for="notification in notifications" :key="notification.id" :to="`/inbox?id=${notification.id}`" class="p-3 rounded-md hover:bg-gray-50 dark:hover:bg-gray-800/50 cursor-pointer flex items-center gap-3 relative">
|
||||
<!-- <NuxtLink v-for="notification in notifications" :key="notification.id" :to="`/inbox?id=${notification.id}`" class="p-3 rounded-md hover:bg-gray-50 dark:hover:bg-gray-800/50 cursor-pointer flex items-center gap-3 relative">
|
||||
<UChip color="red" :show="!!notification.unread" inset>
|
||||
<UAvatar v-bind="notification.sender.avatar" :alt="notification.sender.name" size="md" />
|
||||
</UChip>
|
||||
@@ -24,6 +24,6 @@ const { data: notifications } = await useFetch<Notification[]>('/api/notificatio
|
||||
{{ notification.body }}
|
||||
</p>
|
||||
</div>
|
||||
</NuxtLink>
|
||||
</NuxtLink>-->
|
||||
</UDashboardSlideover>
|
||||
</template>
|
||||
|
||||
@@ -12,7 +12,7 @@ const _useDashboard = () => {
|
||||
'g-u': () => router.push('/users'),
|
||||
'g-s': () => router.push('/settings'),
|
||||
'?': () => isHelpSlideoverOpen.value = true,
|
||||
n: () => isNotificationsSlideoverOpen.value = true
|
||||
n: () => isNotificationsSlideoverOpen.value = !isNotificationsSlideoverOpen.value
|
||||
})
|
||||
|
||||
watch(() => route.fullPath, () => {
|
||||
|
||||
@@ -593,9 +593,9 @@ export const useCreatePdf = async (invoiceData,backgroundSourceBuffer) => {
|
||||
|
||||
invoiceData.rows.forEach((row,index) => {
|
||||
|
||||
if(row.mode === 'free' || row.mode === 'normal'){
|
||||
if(row.mode !== 'pagebreak'){
|
||||
|
||||
pages[pageCounter - 1].drawText(row.pos, {
|
||||
pages[pageCounter - 1].drawText(String(row.pos), {
|
||||
...getCoordinatesForPDFLib(21,rowHeight, page1),
|
||||
size:10,
|
||||
color:rgb(0,0,0),
|
||||
@@ -667,7 +667,13 @@ export const useCreatePdf = async (invoiceData,backgroundSourceBuffer) => {
|
||||
})
|
||||
}
|
||||
|
||||
rowHeight += 14
|
||||
if(row.description) {
|
||||
rowHeight += 24
|
||||
} else {
|
||||
rowHeight += 14
|
||||
}
|
||||
|
||||
|
||||
pageIndex += 1
|
||||
|
||||
|
||||
|
||||
@@ -320,6 +320,18 @@ let links = [
|
||||
to: "/plants",
|
||||
icon: "i-heroicons-clipboard-document"
|
||||
},
|
||||
{
|
||||
label: "Einstellungen",
|
||||
defaultOpen: false,
|
||||
icon: "i-heroicons-cog-8-tooth",
|
||||
children: [
|
||||
{
|
||||
label: "Nummernkreise",
|
||||
to: "/settings/numberRanges",
|
||||
icon: "i-heroicons-clipboard-document-list"
|
||||
}
|
||||
]
|
||||
},
|
||||
]
|
||||
|
||||
const actions = [
|
||||
|
||||
@@ -13,6 +13,7 @@ definePageMeta({
|
||||
|
||||
//Config
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const mode = ref(route.params.mode || "grid")
|
||||
const supabase = useSupabaseClient()
|
||||
const dataStore = useDataStore()
|
||||
@@ -102,7 +103,10 @@ const calendarOptionsGrid = reactive({
|
||||
|
||||
newEventData.value.start = info.startStr
|
||||
newEventData.value.end = info.endStr
|
||||
showNewEventModal.value = true
|
||||
//showNewEventModal.value = true
|
||||
|
||||
router.push(`/calendar/edit/?start=${info.startStr}&end=${info.endStr}&source=grid`)
|
||||
|
||||
},
|
||||
eventClick: function (info){
|
||||
selectedEvent.value = info.event
|
||||
@@ -138,7 +142,9 @@ const calendarOptionsTimeline = reactive({
|
||||
newEventData.value.end = info.endStr
|
||||
console.log(newEventData.value)
|
||||
convertResourceIds()
|
||||
showNewEventModal.value = true
|
||||
//showNewEventModal.value = true
|
||||
|
||||
router.push(`/calendar/edit/?start=${info.startStr}&end=${info.endStr}&resources=${JSON.stringify([info.resource.id])}&source=timeline`)
|
||||
},
|
||||
eventClick: function (info){
|
||||
selectedEvent.value = info.event
|
||||
|
||||
118
spaces/pages/calendar/edit/[[id]].vue
Normal file
118
spaces/pages/calendar/edit/[[id]].vue
Normal file
@@ -0,0 +1,118 @@
|
||||
<script setup>
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const dataStore = useDataStore()
|
||||
|
||||
|
||||
const itemInfo = ref({
|
||||
resources: []
|
||||
})
|
||||
|
||||
|
||||
const setupPage = () => {
|
||||
if(route.query.start) itemInfo.value.start = route.query.start.replace(" ", "+")
|
||||
if(route.query.end) itemInfo.value.end = route.query.end.replace(" ", "+")
|
||||
if(route.query.resources) itemInfo.value.resources = JSON.parse(route.query.resources)
|
||||
if(route.query.project) itemInfo.value.project = route.query.project
|
||||
}
|
||||
|
||||
setupPage()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UDashboardNavbar title="Neuen Termin erstellen">
|
||||
<template #right>
|
||||
<UButton
|
||||
color="rose"
|
||||
@click="router.push(`/calendar/${route.query.source}`)"
|
||||
>
|
||||
Abbrechen
|
||||
</UButton>
|
||||
|
||||
<UButton
|
||||
@click="dataStore.createNewItem('events',itemInfo)"
|
||||
>
|
||||
Erstellen
|
||||
</UButton>
|
||||
</template>
|
||||
</UDashboardNavbar>
|
||||
<!-- <UDashboardToolbar>
|
||||
|
||||
</UDashboardToolbar>-->
|
||||
|
||||
<UForm class="p-5">
|
||||
<UFormGroup
|
||||
label="Resource:"
|
||||
>
|
||||
<USelectMenu
|
||||
v-model="itemInfo.resources"
|
||||
:options="dataStore.getResources"
|
||||
option-attribute="title"
|
||||
value-attribute="id"
|
||||
multiple
|
||||
@change=""
|
||||
>
|
||||
<template #label>
|
||||
<span v-if="itemInfo.resources.length == 0">Keine Ressourcen ausgewählt</span>
|
||||
<span v-else >{{ itemInfo.resources.length }} ausgewählt</span>
|
||||
</template>
|
||||
</USelectMenu>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Titel:"
|
||||
>
|
||||
<UInput
|
||||
v-model="itemInfo.title"
|
||||
/>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Projekt:"
|
||||
>
|
||||
<USelectMenu
|
||||
v-model="itemInfo.project"
|
||||
:options="dataStore.projects"
|
||||
option-attribute="name"
|
||||
value-attribute="id"
|
||||
searchable
|
||||
searchable-placeholder="Suche..."
|
||||
:search-attributes="['name']"
|
||||
>
|
||||
<template #label>
|
||||
{{dataStore.getProjectById(itemInfo.project) ? dataStore.getProjectById(itemInfo.project).name : "Kein Projekt ausgewählt"}}
|
||||
</template>
|
||||
|
||||
</USelectMenu>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Typ:"
|
||||
>
|
||||
<USelectMenu
|
||||
v-model="itemInfo.type"
|
||||
:options="dataStore.getEventTypes"
|
||||
option-attribute="label"
|
||||
value-attribute="label"
|
||||
>
|
||||
|
||||
</USelectMenu>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Start:"
|
||||
>
|
||||
<UInput
|
||||
v-model="itemInfo.start"
|
||||
/>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Ende:"
|
||||
>
|
||||
<UInput
|
||||
v-model="itemInfo.end"
|
||||
/>
|
||||
</UFormGroup>
|
||||
</UForm>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -61,6 +61,9 @@ const tabItems = computed(() => {
|
||||
const setupPage = () => {
|
||||
if(route.params) {
|
||||
if(route.params.id) itemInfo.value = dataStore.getCreatedDocumentById(Number(route.params.id))
|
||||
|
||||
if(!itemInfo.value.deliveryDateType) itemInfo.value.deliveryDateType = "Lieferdatum"
|
||||
|
||||
}
|
||||
|
||||
if(route.query) {
|
||||
@@ -165,6 +168,18 @@ const addPosition = (mode) => {
|
||||
|
||||
}
|
||||
|
||||
const editRowDescription = (row) => {
|
||||
rowToEdit.value = row.description
|
||||
showEditRowDescription.value = true
|
||||
|
||||
}
|
||||
const showEditRowDescription = ref(false)
|
||||
const rowToEdit = ref("")
|
||||
const saveRowDescription = () => {
|
||||
|
||||
}
|
||||
|
||||
|
||||
const removePosition = (id) => {
|
||||
let rows = itemInfo.value.rows.filter(row => row.id !== id)
|
||||
/*rows = rows.sort((a,b) => a.pos - b.pos)
|
||||
@@ -185,7 +200,7 @@ const documentTotal = computed(() => {
|
||||
let totalGross = 0
|
||||
|
||||
itemInfo.value.rows.forEach(row => {
|
||||
if(row.mode === 'free' || row.mode === 'normal'){
|
||||
if(row.mode !== 'pagebreak'){
|
||||
console.log(row)
|
||||
let rowPrice = Number(Number(row.quantity) * Number(row.price) * (1 - Number(row.discountPercent) /100) ).toFixed(2)
|
||||
console.log(rowPrice)
|
||||
@@ -222,8 +237,9 @@ const getDocumentData = () => {
|
||||
|
||||
let unit = dataStore.units.find(i => i.id === row.unit)
|
||||
|
||||
if(row.mode === 'free' || row.mode === 'normal') {
|
||||
if(row.mode !== 'pagebreak') {
|
||||
if(row.mode === 'normal') row.text = dataStore.getProductById(row.product).name
|
||||
if(row.mode === 'service') row.text = dataStore.getServiceById(row.service).name
|
||||
|
||||
return {
|
||||
...row,
|
||||
@@ -323,6 +339,7 @@ const saveDocument = async () => {
|
||||
project: itemInfo.value.project,
|
||||
documentNumber: itemInfo.value.documentNumber,
|
||||
documentDate: itemInfo.value.documentDate,
|
||||
deliveryDateType: itemInfo.value.deliveryDateType,
|
||||
info: {
|
||||
|
||||
},
|
||||
@@ -595,22 +612,31 @@ setupPage()
|
||||
<UFormGroup
|
||||
label="Projekt:"
|
||||
>
|
||||
<USelectMenu
|
||||
:options="dataStore.projects"
|
||||
v-model="itemInfo.project"
|
||||
value-attribute="id"
|
||||
option-attribute="name"
|
||||
searchable
|
||||
searchable-placeholder="Suche..."
|
||||
:search-attributes="['name']"
|
||||
>
|
||||
<template #label>
|
||||
{{dataStore.getProjectById(itemInfo.project) ? dataStore.getProjectById(itemInfo.project).name : "Kein Projekt ausgewählt"}}
|
||||
</template>
|
||||
<template #option="{option: project}">
|
||||
{{dataStore.getCustomerById(project.customer).name}} - {{project.name}}
|
||||
</template>
|
||||
</USelectMenu>
|
||||
<InputGroup>
|
||||
<USelectMenu
|
||||
:options="dataStore.projects"
|
||||
v-model="itemInfo.project"
|
||||
value-attribute="id"
|
||||
option-attribute="name"
|
||||
searchable
|
||||
searchable-placeholder="Suche..."
|
||||
:search-attributes="['name']"
|
||||
class="w-full"
|
||||
>
|
||||
<template #label>
|
||||
{{dataStore.getProjectById(itemInfo.project) ? dataStore.getProjectById(itemInfo.project).name : "Kein Projekt ausgewählt"}}
|
||||
</template>
|
||||
<template #option="{option: project}">
|
||||
{{dataStore.getCustomerById(project.customer).name}} - {{project.name}}
|
||||
</template>
|
||||
</USelectMenu>
|
||||
<UButton
|
||||
variant="outline"
|
||||
v-if="itemInfo.project"
|
||||
icon="i-heroicons-arrow-right-end-on-rectangle"
|
||||
>Projekt</UButton>
|
||||
</InputGroup>
|
||||
|
||||
</UFormGroup>
|
||||
|
||||
</div>
|
||||
@@ -674,12 +700,13 @@ setupPage()
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Pos.</th>
|
||||
<th>Produkt / Leistung</th>
|
||||
<th>Name</th>
|
||||
<th>Menge</th>
|
||||
<th>Einheit</th>
|
||||
<th>Preis</th>
|
||||
<th>Steuer</th>
|
||||
<th>Rabatt</th>
|
||||
<th>Beschreibung</th>
|
||||
<th>Gesamt</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -704,7 +731,7 @@ setupPage()
|
||||
</td>
|
||||
<td
|
||||
v-if="row.mode === 'pagebreak'"
|
||||
colspan="8"
|
||||
colspan="9"
|
||||
>
|
||||
<UDivider/>
|
||||
</td>
|
||||
@@ -788,6 +815,7 @@ setupPage()
|
||||
</USelectMenu>
|
||||
</td>
|
||||
<td
|
||||
class="w-40"
|
||||
v-if="row.mode !== 'pagebreak'"
|
||||
>
|
||||
<UInput
|
||||
@@ -833,6 +861,37 @@ setupPage()
|
||||
</template>
|
||||
</UInput>
|
||||
</td>
|
||||
<td
|
||||
class="w-40"
|
||||
v-if="row.mode !== 'pagebreak'"
|
||||
>
|
||||
<UButton
|
||||
icon="i-heroicons-document-text"
|
||||
@click="showEditRowDescription = true"
|
||||
/>
|
||||
<UModal v-model="showEditRowDescription">
|
||||
<UCard>
|
||||
<template #header>
|
||||
Beschreibung bearbeiten
|
||||
</template>
|
||||
<UTextarea
|
||||
v-model="row.description"
|
||||
|
||||
>
|
||||
|
||||
</UTextarea>
|
||||
<template #footer>
|
||||
<UButton
|
||||
@click="showEditRowDescription = false"
|
||||
>
|
||||
Speichern
|
||||
</UButton>
|
||||
</template>
|
||||
</UCard>
|
||||
|
||||
|
||||
</UModal>
|
||||
</td>
|
||||
<td
|
||||
v-if="row.mode !== 'pagebreak'"
|
||||
>
|
||||
|
||||
@@ -18,24 +18,38 @@ setupPage()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UDashboardNavbar
|
||||
title="Erstelltes Dokument anzeigen"
|
||||
>
|
||||
|
||||
<InputGroup>
|
||||
<UButton
|
||||
@click="router.push(`/createDocument/edit/${itemInfo.id}`)"
|
||||
>
|
||||
Bearbeiten
|
||||
</UButton>
|
||||
</InputGroup>
|
||||
<DevOnly>
|
||||
{{itemInfo}}
|
||||
</DevOnly>
|
||||
</UDashboardNavbar>
|
||||
<UDashboardToolbar>
|
||||
<template #left>
|
||||
<UButton
|
||||
@click="router.push(`/createDocument/edit/${itemInfo.id}`)"
|
||||
>
|
||||
Bearbeiten
|
||||
</UButton>
|
||||
<UButton
|
||||
:to="dataStore.documents.find(i => i.createdDocument === itemInfo.id) ? dataStore.documents.find(i => i.createdDocument === itemInfo.id).url : ''"
|
||||
target="_blank"
|
||||
>In neuen Tab anzeigen</UButton>
|
||||
</template>
|
||||
</UDashboardToolbar>
|
||||
|
||||
|
||||
|
||||
<DocumentDisplay
|
||||
:document-data="dataStore.documents.find(i => i.createdDocument === itemInfo.id)"
|
||||
<object
|
||||
:data="dataStore.documents.find(i => i.createdDocument === itemInfo.id) ? dataStore.documents.find(i => i.createdDocument === itemInfo.id).url : ''"
|
||||
class="h-full"
|
||||
/>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- <DocumentDisplay
|
||||
:document-data="dataStore.documents.find(i => i.createdDocument === itemInfo.id)"
|
||||
/>-->
|
||||
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -187,10 +187,10 @@ setupPage()
|
||||
/>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Einkaufspreis:"
|
||||
label="Verkaufspreis:"
|
||||
>
|
||||
<UInput
|
||||
v-model="itemInfo.purchasePrice"
|
||||
v-model="itemInfo.sellingPrice"
|
||||
type="number"
|
||||
steps="0.01"
|
||||
>
|
||||
|
||||
@@ -339,6 +339,35 @@ setupPage()
|
||||
</UButton>
|
||||
</Toolbar>
|
||||
|
||||
<UTable
|
||||
:rows="dataStore.getCreatedDocumentsByProject(currentItem.id)"
|
||||
:columns="[
|
||||
{
|
||||
label: 'Typ',
|
||||
key: 'type'
|
||||
}, {
|
||||
label: 'Status',
|
||||
key: 'state'
|
||||
}, {
|
||||
label: 'Dokumentennummer',
|
||||
key: 'documentNumber'
|
||||
}, {
|
||||
label: 'Ansprechpartner',
|
||||
key: 'createdBy'
|
||||
}
|
||||
|
||||
]"
|
||||
@select="(row) => row.state === 'Entwurf' ? router.push(`/createDocument/edit/${row.id}`) : router.push(`/createDocument/show/${row.id}`)"
|
||||
>
|
||||
<template #type-data="{row}">
|
||||
<span v-if="row.type === 'invoices'">Rechnung</span>
|
||||
<span v-if="row.type === 'quotes'">Angebot</span>
|
||||
<span v-if="row.type === 'deliveryNotes'">Lieferschein</span>
|
||||
</template>
|
||||
<template #createdBy-data="{row}">
|
||||
{{dataStore.getProfileById(row.createdBy).fullName}}
|
||||
</template>
|
||||
</UTable>
|
||||
|
||||
<DocumentList :documents="dataStore.getDocumentsByProjectId(currentItem.id)"/>
|
||||
|
||||
|
||||
@@ -56,50 +56,41 @@ const updateNumberRange = async (range) => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UModal
|
||||
v-model="showAddModal"
|
||||
>
|
||||
|
||||
</UModal>
|
||||
|
||||
|
||||
<UAlert
|
||||
title="Änderungen an diesen Werten betreffen nur neu Erstellte Einträge."
|
||||
color="rose"
|
||||
variant="outline"
|
||||
icon="i-heroicons-exclamation-triangle"
|
||||
/>
|
||||
<UDashboardToolbar>
|
||||
<UAlert
|
||||
title="Änderungen an diesen Werten betreffen nur neu Erstellte Einträge."
|
||||
color="rose"
|
||||
variant="outline"
|
||||
icon="i-heroicons-exclamation-triangle"
|
||||
/>
|
||||
</UDashboardToolbar>
|
||||
|
||||
<UTable
|
||||
:rows="dataStore.numberRanges"
|
||||
:columns="columns"
|
||||
:rows="dataStore.numberRanges"
|
||||
:columns="columns"
|
||||
>
|
||||
<template #resourceType-data="{row}">
|
||||
{{resources[row.resourceType] ? resources[row.resourceType].label : ""}}
|
||||
</template>
|
||||
<template #prefix-data="{row}">
|
||||
<UInput
|
||||
v-model="row.prefix"
|
||||
@focusout="updateNumberRange(row)"
|
||||
v-model="row.prefix"
|
||||
@focusout="updateNumberRange(row)"
|
||||
/>
|
||||
</template>
|
||||
<template #suffix-data="{row}">
|
||||
<UInput
|
||||
v-model="row.suffix"
|
||||
@focusout="updateNumberRange(row)"
|
||||
v-model="row.suffix"
|
||||
@focusout="updateNumberRange(row)"
|
||||
/>
|
||||
</template>
|
||||
<template #nextNumber-data="{row}">
|
||||
<UInput
|
||||
v-model="row.nextNumber"
|
||||
@focusout="updateNumberRange(row)"
|
||||
v-model="row.nextNumber"
|
||||
@focusout="updateNumberRange(row)"
|
||||
/>
|
||||
</template>
|
||||
</UTable>
|
||||
<DevOnly>
|
||||
{{dataStore.numberRanges}}
|
||||
</DevOnly>
|
||||
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -98,6 +98,10 @@ export const useDataStore = defineStore('data', () => {
|
||||
labelSingle: "Leistung",
|
||||
redirect: true
|
||||
},
|
||||
events: {
|
||||
label: "Termine",
|
||||
labelSingle: "Termin"
|
||||
},
|
||||
}
|
||||
|
||||
const documentTypesForCreation = ref({
|
||||
@@ -461,7 +465,7 @@ export const useDataStore = defineStore('data', () => {
|
||||
} else if (data) {
|
||||
const returnPath = data.path
|
||||
|
||||
documentsToInsert.push({...formData, path: returnPath})
|
||||
documentsToInsert.push({...formData, path: returnPath, tenant: currentTenant.value})
|
||||
}
|
||||
|
||||
console.log(data)
|
||||
@@ -766,6 +770,10 @@ export const useDataStore = defineStore('data', () => {
|
||||
return texttemplates.value.filter(i => i.documentType === documentType)
|
||||
})
|
||||
|
||||
const getCreatedDocumentsByProject = computed(() => (project) => {
|
||||
return createddocuments.value.filter(i => i.project === project)
|
||||
})
|
||||
|
||||
const getStockByProductId = computed(() => (productId) => {
|
||||
let productMovements = movements.value.filter(movement => movement.productId === productId)
|
||||
|
||||
@@ -1127,6 +1135,7 @@ export const useDataStore = defineStore('data', () => {
|
||||
getMovementsBySpaceId,
|
||||
getMessagesByChatId,
|
||||
getTextTemplatesByDocumentType,
|
||||
getCreatedDocumentsByProject,
|
||||
getStockByProductId,
|
||||
getIncomingInvoicesByVehicleId,
|
||||
getEventTypes,
|
||||
|
||||
Reference in New Issue
Block a user