Introduced New Projecttypes and Phase Display
This commit is contained in:
@@ -1,8 +1,6 @@
|
||||
<script setup>
|
||||
import dayjs from "dayjs";
|
||||
import HistoryDisplay from "~/components/HistoryDisplay.vue";
|
||||
import DocumentUpload from "~/components/DocumentUpload.vue";
|
||||
import DocumentList from "~/components/DocumentList.vue";
|
||||
|
||||
|
||||
definePageMeta({
|
||||
middleware: "auth"
|
||||
@@ -97,17 +95,18 @@ const itemInfo = ref({
|
||||
const oldItemInfo = ref({})
|
||||
const tags = dataStore.getDocumentTags
|
||||
const phasesTemplates = ref([])
|
||||
const phasesTemplateSelected = ref(null)
|
||||
|
||||
const plants = ref([])
|
||||
const contracts = ref([])
|
||||
|
||||
const projecttypes = ref([])
|
||||
const disableCustomerSelection =ref(false)
|
||||
|
||||
|
||||
//Functions
|
||||
const setupPage = async() => {
|
||||
plants.value = await useSupabaseSelect("plants")
|
||||
contracts.value = await useSupabaseSelect("contracts")
|
||||
projecttypes.value = await useSupabaseSelect("projecttypes", "*", "id")
|
||||
|
||||
if(mode.value === "show" ){
|
||||
itemInfo.value = await useSupabaseSelectSingle("projects",route.params.id,"*, customer(*), plant(*)")
|
||||
@@ -127,12 +126,10 @@ const setupPage = async() => {
|
||||
}
|
||||
if(itemInfo.value) oldItemInfo.value = JSON.parse(JSON.stringify(itemInfo.value))
|
||||
|
||||
phasesTemplates.value = await useSupabaseSelect("phasesTemplates","*","created_at")
|
||||
if(phasesTemplates.value.length > 0) {
|
||||
phasesTemplateSelected.value = phasesTemplates.value[0].id
|
||||
if(!oldItemInfo.value.projecttype) {
|
||||
itemInfo.value.projecttype = projecttypes.value[0].id
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
setupPage()
|
||||
@@ -155,53 +152,65 @@ const projectHours = () => {
|
||||
}
|
||||
|
||||
|
||||
/*const phasesTemplate = ref([{
|
||||
label: 'Erstkontakt',
|
||||
icon: 'i-heroicons-clipboard-document',
|
||||
active: true
|
||||
}, {
|
||||
label: 'Überprüfung Vor Ort',
|
||||
icon: 'i-heroicons-magnifying-glass'
|
||||
}, {
|
||||
label: 'Angebotserstellung',
|
||||
icon: 'i-heroicons-document-text'
|
||||
}, {
|
||||
label: 'Auftragsvergabe',
|
||||
icon: 'i-heroicons-document-check'
|
||||
}, {
|
||||
label: 'Umsetzung',
|
||||
icon: 'i-heroicons-wrench-screwdriver'
|
||||
},{
|
||||
label: 'Rechnungsstellung',
|
||||
icon: 'i-heroicons-document-text'
|
||||
}, {
|
||||
label: 'Abgeschlossen',
|
||||
icon: 'i-heroicons-check'
|
||||
}])*/
|
||||
const changeActivePhase = async (phase) => {
|
||||
itemInfo.value = await useSupabaseSelectSingle("projects",route.params.id,'*')
|
||||
|
||||
itemInfo.value.phases = itemInfo.value.phases.map(p => {
|
||||
if(p.active) delete p.active
|
||||
const createProject = async () => {
|
||||
let initialPhases = projecttypes.value.find(i => i.id === itemInfo.value.projecttype).initialPhases
|
||||
await dataStore.createNewItem('projects',{...itemInfo.value, phases: initialPhases })
|
||||
}
|
||||
|
||||
const changeActivePhase = async (key) => {
|
||||
console.log(key)
|
||||
let item = await useSupabaseSelectSingle("projects",itemInfo.value.id,'*')
|
||||
|
||||
item.phases = item.phases.map(p => {
|
||||
if(p.active) p.active = false
|
||||
|
||||
if(p.key === key) {
|
||||
p.active = true
|
||||
p.activated_at = dayjs().format()
|
||||
p.activated_by = dataStore.activeProfile.id
|
||||
}
|
||||
|
||||
if(p.label === phase.label) p.active = true
|
||||
|
||||
return p
|
||||
})
|
||||
|
||||
await savePhases()
|
||||
console.log(item.phases)
|
||||
|
||||
await dataStore.updateItem("projects", item)
|
||||
setupPage()
|
||||
}
|
||||
|
||||
const savePhases = () => {
|
||||
dataStore.updateItem("projects", itemInfo.value)
|
||||
|
||||
const renderedPhases = computed(() => {
|
||||
|
||||
if(itemInfo.value.phases) {
|
||||
return itemInfo.value.phases.map((phase,index,array) => {
|
||||
|
||||
let isAvailable = false
|
||||
|
||||
if(phase.active) {
|
||||
isAvailable = true
|
||||
} else if(index > 0 && array[index-1].active ){
|
||||
isAvailable = true
|
||||
} else if(index > 1 && array[index-1].optional && array[index-2].active){
|
||||
isAvailable = true
|
||||
} else if(array.findIndex(i => i.active) > index) {
|
||||
isAvailable = true
|
||||
}
|
||||
|
||||
const loadPhases = async () => {
|
||||
itemInfo.value.phases = dataStore.phasesTemplates.find(i => i.id === phasesTemplateSelected.value).initialPhases
|
||||
await dataStore.updateItem("projects", {...itemInfo.value, customer: itemInfo.value.customer ? itemInfo.value.customer.id : null, plant: itemInfo.value.plant ? itemInfo.value.plant.id : null})
|
||||
}
|
||||
|
||||
return {
|
||||
...phase,
|
||||
label: phase.optional ? `${phase.label}(optional)`: phase.label,
|
||||
disabled: !isAvailable,
|
||||
defaultOpen: phase.active ? true : false
|
||||
}
|
||||
})
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
@@ -231,7 +240,7 @@ const loadPhases = async () => {
|
||||
</UButton>
|
||||
<UButton
|
||||
v-else-if="mode === 'create'"
|
||||
@click="dataStore.createNewItem('projects',itemInfo)"
|
||||
@click="createProject"
|
||||
>
|
||||
Erstellen
|
||||
</UButton>
|
||||
@@ -294,37 +303,15 @@ const loadPhases = async () => {
|
||||
</div>
|
||||
<div v-if="item.key === 'phases'" class="space-y-3">
|
||||
<UCard class="mt-5">
|
||||
<UFormGroup
|
||||
label="Vorlage laden"
|
||||
v-if="itemInfo.phases.length === 0"
|
||||
>
|
||||
<InputGroup>
|
||||
<USelectMenu
|
||||
:options="phasesTemplates"
|
||||
option-attribute="name"
|
||||
value-attribute="id"
|
||||
v-model="phasesTemplateSelected"
|
||||
class="flex-auto"
|
||||
>
|
||||
|
||||
</USelectMenu>
|
||||
<UButton
|
||||
@click="loadPhases"
|
||||
>
|
||||
Vorlage laden
|
||||
</UButton>
|
||||
</InputGroup>
|
||||
|
||||
</UFormGroup>
|
||||
|
||||
<UAccordion
|
||||
:items="itemInfo.phases"
|
||||
:items="renderedPhases"
|
||||
>
|
||||
<template #default="{item,index,open}">
|
||||
<UButton
|
||||
variant="ghost"
|
||||
:color="item.active ? 'primary' : 'white'"
|
||||
class="mb-1"
|
||||
:disabled="true"
|
||||
>
|
||||
<template #leading>
|
||||
<div class="w-6 h-6 flex items-center justify-center -my-1">
|
||||
@@ -344,15 +331,35 @@ const loadPhases = async () => {
|
||||
|
||||
</UButton>
|
||||
</template>
|
||||
<template #item="{item}">
|
||||
<template #item="{item, index}">
|
||||
<UCard class="mx-5">
|
||||
<template #header>
|
||||
<span class="text-black">{{item.label}}</span>
|
||||
</template>
|
||||
<InputGroup>
|
||||
<UButton
|
||||
v-if="!item.active"
|
||||
@click="changeActivePhase(item)"
|
||||
v-if="!item.activated_at && index !== 0 "
|
||||
@click="changeActivePhase(item.key)"
|
||||
>
|
||||
Phase aktivieren
|
||||
</UButton>
|
||||
<UButton
|
||||
v-if="item.active"
|
||||
v-for="button in item.quickactions"
|
||||
@click="router.push(`${button.link}&customer=${itemInfo.customer.id}&project=${itemInfo.id}`)"
|
||||
>
|
||||
{{button.label}}
|
||||
</UButton>
|
||||
</InputGroup>
|
||||
|
||||
<div>
|
||||
<p v-if="item.activated_at" class="text-black">Aktiviert am: {{dayjs(item.activated_at).format("DD.MM.YY HH:mm")}} Uhr</p>
|
||||
<p v-if="item.activated_by" class="text-black">Aktiviert durch: {{dataStore.getProfileById(item.activated_by).fullName}}</p>
|
||||
<p v-if="item.description" class="text-black">Beschreibung: {{item.description}}</p>
|
||||
</div>
|
||||
</UCard>
|
||||
|
||||
|
||||
</template>
|
||||
</UAccordion>
|
||||
</UCard>
|
||||
@@ -490,23 +497,7 @@ const loadPhases = async () => {
|
||||
</UCard>
|
||||
</div>
|
||||
<div v-else-if="item.key === 'material'" class="space-y-3">
|
||||
<UCard class="mt-5">
|
||||
Auf das Projekt gebuchte Artikel:
|
||||
|
||||
<!-- <UTable
|
||||
:rows="dataStore.getStocksByProjectId(itemInfo.id)"
|
||||
:columns="[{key:'productId',label:'Artikel'},{key:'stock',label:'Anzahl'}]"
|
||||
@select="(i) => router.push(`/products/show/${i.productId}`)"
|
||||
>
|
||||
<template #productId-data="{row}">
|
||||
{{dataStore.getProductById(row.productId).name}}
|
||||
</template>
|
||||
<template #stock-data="{row}">
|
||||
{{dataStore.getProductById(row.productId)}}
|
||||
{{row.stock}} {{dataStore.units.find(i => i.id === dataStore.getProductById(row.productId).unit).short}}
|
||||
</template>
|
||||
</UTable>-->
|
||||
</UCard>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
@@ -532,6 +523,43 @@ const loadPhases = async () => {
|
||||
/>
|
||||
</UFormGroup>
|
||||
|
||||
<UFormGroup
|
||||
label="Objekt:"
|
||||
>
|
||||
<USelectMenu
|
||||
v-model="itemInfo.plant"
|
||||
:options="itemInfo.customer ? plants.filter(i => i.customer === itemInfo.customer) : plants"
|
||||
option-attribute="name"
|
||||
value-attribute="id"
|
||||
searchable
|
||||
:search-attributes="['name']"
|
||||
@change="itemInfo.customer = plants.find(i => i.id === itemInfo.plant).customer,
|
||||
disableCustomerSelection = true"
|
||||
>
|
||||
<template #label>
|
||||
{{plants.find(i => i.id === itemInfo.plant) ? plants.find(i => i.id === itemInfo.plant).name : "Objekt auswählen"}}
|
||||
</template>
|
||||
</USelectMenu>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Vertrag:"
|
||||
>
|
||||
<USelectMenu
|
||||
v-model="itemInfo.contract"
|
||||
:options="itemInfo.customer ? contracts.filter(i => i.customer === itemInfo.customer) : contracts"
|
||||
option-attribute="name"
|
||||
value-attribute="id"
|
||||
searchable
|
||||
:search-attributes="['name']"
|
||||
@change="itemInfo.customer = contracts.find(i => i.id === itemInfo.contract).customer,
|
||||
disableCustomerSelection = true"
|
||||
>
|
||||
<template #label>
|
||||
{{contracts.find(i => i.id === itemInfo.contract) ? contracts.find(i => i.id === itemInfo.contract).name : "Vertrag auswählen"}}
|
||||
</template>
|
||||
</USelectMenu>
|
||||
</UFormGroup>
|
||||
|
||||
<UFormGroup
|
||||
label="Kundennummer:"
|
||||
>
|
||||
@@ -542,6 +570,7 @@ const loadPhases = async () => {
|
||||
value-attribute="id"
|
||||
searchable
|
||||
:search-attributes="['name']"
|
||||
:disabled="disableCustomerSelection"
|
||||
>
|
||||
<template #label>
|
||||
{{dataStore.getCustomerById(itemInfo.customer) ? dataStore.getCustomerById(itemInfo.customer).name : "Kunde auswählen"}}
|
||||
@@ -549,6 +578,21 @@ const loadPhases = async () => {
|
||||
</USelectMenu>
|
||||
</UFormGroup>
|
||||
|
||||
<UFormGroup
|
||||
label="Typ:"
|
||||
>
|
||||
<USelectMenu
|
||||
v-model="itemInfo.projecttype"
|
||||
:options="projecttypes"
|
||||
option-attribute="name"
|
||||
value-attribute="id"
|
||||
searchable
|
||||
:search-attributes="['label']"
|
||||
:disabled="oldItemInfo.projecttype"
|
||||
>
|
||||
</USelectMenu>
|
||||
</UFormGroup>
|
||||
|
||||
<UFormGroup
|
||||
label="Gewerk:"
|
||||
>
|
||||
@@ -564,38 +608,7 @@ const loadPhases = async () => {
|
||||
</USelectMenu>
|
||||
</UFormGroup>
|
||||
|
||||
<UFormGroup
|
||||
label="Objekt:"
|
||||
>
|
||||
<USelectMenu
|
||||
v-model="itemInfo.plant"
|
||||
:options="plants"
|
||||
option-attribute="name"
|
||||
value-attribute="id"
|
||||
searchable
|
||||
:search-attributes="['name']"
|
||||
>
|
||||
<template #label>
|
||||
{{plants.find(i => i.id === itemInfo.plant) ? plants.find(i => i.id === itemInfo.plant).name : "Objekt auswählen"}}
|
||||
</template>
|
||||
</USelectMenu>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Vertrag:"
|
||||
>
|
||||
<USelectMenu
|
||||
v-model="itemInfo.contract"
|
||||
:options="contracts"
|
||||
option-attribute="name"
|
||||
value-attribute="id"
|
||||
searchable
|
||||
:search-attributes="['name']"
|
||||
>
|
||||
<template #label>
|
||||
{{contracts.find(i => i.id === itemInfo.contract) ? contracts.find(i => i.id === itemInfo.contract).name : "Vertrag auswählen"}}
|
||||
</template>
|
||||
</USelectMenu>
|
||||
</UFormGroup>
|
||||
|
||||
<UFormGroup
|
||||
label="Beteiligte Benutzer:"
|
||||
>
|
||||
@@ -622,6 +635,7 @@ const loadPhases = async () => {
|
||||
/>
|
||||
</UFormGroup>
|
||||
</UForm>
|
||||
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -26,7 +26,20 @@
|
||||
<UCheckbox
|
||||
label="Abgeschlossene anzeigen"
|
||||
v-model="showFinished"
|
||||
class="mt-1"
|
||||
/>
|
||||
<USelectMenu
|
||||
class="ml-3 w-36"
|
||||
v-model="selectedTypes"
|
||||
:options="projecttypes"
|
||||
value-attribute="id"
|
||||
option-attribute="name"
|
||||
multiple
|
||||
>
|
||||
<template #label>
|
||||
Typen
|
||||
</template>
|
||||
</USelectMenu>
|
||||
</template>
|
||||
|
||||
<template #right>
|
||||
@@ -60,6 +73,9 @@
|
||||
<span class="text-primary-500 font-bold" v-if="row === filteredRows[selectedItem]">{{row.name}}</span>
|
||||
<span v-else>{{row.name}}</span>
|
||||
</template>
|
||||
<template #projecttype-data="{row}">
|
||||
{{row.projecttype.name}}
|
||||
</template>
|
||||
<template #phase-data="{row}">
|
||||
{{getActivePhaseLabel(row)}}
|
||||
</template>
|
||||
@@ -117,9 +133,13 @@ const router = useRouter()
|
||||
|
||||
const items = ref([])
|
||||
const selectedItem = ref(0)
|
||||
const projecttypes = ref([])
|
||||
const selectedTypes = ref([])
|
||||
|
||||
const setupPage = async () => {
|
||||
items.value = await useSupabaseSelect("projects","*, customer (name), plant(name)","projectNumber")
|
||||
items.value = await useSupabaseSelect("projects","*, customer (name), plant(name), projecttype(name, id)","projectNumber")
|
||||
projecttypes.value = await useSupabaseSelect("projecttypes","*")
|
||||
selectedTypes.value = projecttypes.value.map(i => i.id)
|
||||
}
|
||||
|
||||
setupPage()
|
||||
@@ -129,6 +149,10 @@ const templateColumns = [
|
||||
key: "projectNumber",
|
||||
label: "Projektnummer"
|
||||
},
|
||||
{
|
||||
key: "projecttype",
|
||||
label: "Typ"
|
||||
},
|
||||
{
|
||||
key: "phase",
|
||||
label: "Phase"
|
||||
@@ -198,10 +222,11 @@ const filteredRows = computed(() => {
|
||||
temp = temp.filter(i => i.phaseLabel !== "Abgeschlossen")
|
||||
}
|
||||
|
||||
temp = temp.filter(i => selectedTypes.value.includes(i.projecttype.id))
|
||||
|
||||
if(!searchString.value) {
|
||||
return temp
|
||||
}
|
||||
|
||||
return useSearch(searchString.value, temp)
|
||||
})
|
||||
</script>
|
||||
292
pages/projecttypes/[mode]/[[id]].vue
Normal file
292
pages/projecttypes/[mode]/[[id]].vue
Normal file
@@ -0,0 +1,292 @@
|
||||
<script setup>
|
||||
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
definePageMeta({
|
||||
middleware: "auth"
|
||||
})
|
||||
|
||||
defineShortcuts({
|
||||
'backspace': () => {
|
||||
router.push("/projecttypes")
|
||||
},
|
||||
'arrowleft': () => {
|
||||
if(openTab.value > 0){
|
||||
openTab.value -= 1
|
||||
}
|
||||
},
|
||||
'arrowright': () => {
|
||||
if(openTab.value < 3) {
|
||||
openTab.value += 1
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
const openTab = ref(0)
|
||||
const dataStore = useDataStore()
|
||||
const supabase = useSupabaseClient()
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const toast = useToast()
|
||||
|
||||
const mode = ref(route.params.mode || "show")
|
||||
const itemInfo = ref({
|
||||
name: "",
|
||||
initialPhases: []
|
||||
})
|
||||
const oldItemInfo = ref({})
|
||||
|
||||
const openQuickActionModal = ref(false)
|
||||
const selectedKeyForQuickAction = ref("")
|
||||
|
||||
const setupPage = async() => {
|
||||
|
||||
if(mode.value === "show" ){
|
||||
itemInfo.value = await useSupabaseSelectSingle("projecttypes",route.params.id,"*")
|
||||
} else if (mode.value === "edit") {
|
||||
itemInfo.value = await useSupabaseSelectSingle("projecttypes",route.params.id,"*")
|
||||
}
|
||||
|
||||
if(mode.value === "create") {
|
||||
let query = route.query
|
||||
|
||||
|
||||
}
|
||||
if(itemInfo.value) oldItemInfo.value = JSON.parse(JSON.stringify(itemInfo.value))
|
||||
|
||||
setKeys()
|
||||
}
|
||||
|
||||
setupPage()
|
||||
|
||||
const setKeys = () => {
|
||||
itemInfo.value.initialPhases = itemInfo.value.initialPhases.map(i => {
|
||||
return {
|
||||
...i,
|
||||
key: uuidv4(),
|
||||
quickactions: i.quickactions || []
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UDashboardNavbar :title="itemInfo ? itemInfo.name : (mode === 'create' ? 'Projekt erstellen' : 'Projekt bearbeiten')">
|
||||
<template #left>
|
||||
<UButton
|
||||
icon="i-heroicons-chevron-left"
|
||||
variant="outline"
|
||||
@click="router.push(`/projecttypes`)"
|
||||
>
|
||||
Projekttypen
|
||||
</UButton>
|
||||
</template>
|
||||
<template #center>
|
||||
<h1
|
||||
v-if="itemInfo"
|
||||
class="text-xl font-medium"
|
||||
>{{itemInfo.name ? `Projekttyp: ${itemInfo.name}` : (mode === 'create' ? 'Projekttyp erstellen' : 'Projekttyp bearbeiten')}}</h1>
|
||||
</template>
|
||||
<template #right>
|
||||
<UButton
|
||||
v-if="mode === 'edit'"
|
||||
@click="dataStore.updateItem('projecttypes',itemInfo,oldItemInfo)"
|
||||
>
|
||||
Speichern
|
||||
</UButton>
|
||||
<UButton
|
||||
v-else-if="mode === 'create'"
|
||||
@click="dataStore.createNewItem('projecttyes', itemInfo)"
|
||||
>
|
||||
Erstellen
|
||||
</UButton>
|
||||
<UButton
|
||||
@click="router.push(itemInfo.id ? `/projecttypes/show/${itemInfo.id}` : `/projecttypes`)"
|
||||
color="red"
|
||||
class="ml-2"
|
||||
v-if="mode === 'edit' || mode === 'create'"
|
||||
>
|
||||
Abbrechen
|
||||
</UButton>
|
||||
<UButton
|
||||
v-if="mode === 'show'"
|
||||
@click="router.push(`/projecttypes/edit/${itemInfo.id}`)"
|
||||
>
|
||||
Bearbeiten
|
||||
</UButton>
|
||||
</template>
|
||||
</UDashboardNavbar>
|
||||
<UDashboardPanelContent>
|
||||
<UTabs
|
||||
:items="[{label: 'Informationen'}]"
|
||||
v-if="itemInfo.id && mode == 'show'"
|
||||
v-model="openTab"
|
||||
>
|
||||
<template #item="{ item }">
|
||||
<div v-if="item.label === 'Informationen'" class="flex flex-row">
|
||||
<div class="w-1/2 mr-3">
|
||||
<UCard class="mt-5">
|
||||
{{itemInfo}}
|
||||
</UCard>
|
||||
</div>
|
||||
<div class="w-1/2">
|
||||
<UCard class="mt-5">
|
||||
<HistoryDisplay
|
||||
type="project"
|
||||
v-if="itemInfo"
|
||||
:element-id="itemInfo.id"
|
||||
render-headline
|
||||
/>
|
||||
</UCard>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</UTabs>
|
||||
|
||||
<UForm v-else-if="mode === 'edit' || mode === 'create'">
|
||||
<UAlert
|
||||
color="rose"
|
||||
variant="outline"
|
||||
class="mb-5"
|
||||
description="Achtung Änderungen an diesem Projekttypen betreffen nur Projekte die damit neu erstellt werden. Bestehende Projekte bleiben unverändert."
|
||||
/>
|
||||
|
||||
<UFormGroup
|
||||
label="Name:"
|
||||
>
|
||||
<UInput
|
||||
v-model="itemInfo.name"
|
||||
/>
|
||||
</UFormGroup>
|
||||
|
||||
<UDivider class="mt-5">
|
||||
Initiale Phasen
|
||||
</UDivider>
|
||||
<UButton
|
||||
class="mt-3"
|
||||
@click="itemInfo.initialPhases.push({label: '', icon: ''}),
|
||||
setKeys"
|
||||
>
|
||||
+ Phase
|
||||
</UButton>
|
||||
|
||||
<table class="mt-3">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Name</th>
|
||||
<th>Icon</th>
|
||||
<th>Optional</th>
|
||||
<th>Beschreibung</th>
|
||||
<th>Schnellaktionen</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<draggable
|
||||
v-model="itemInfo.initialPhases"
|
||||
handle=".handle"
|
||||
tag="tbody"
|
||||
itemKey="pos"
|
||||
@end="setKeys"
|
||||
>
|
||||
|
||||
<template #item="{element: phase}">
|
||||
<tr>
|
||||
<td>
|
||||
<UIcon
|
||||
class="handle"
|
||||
name="i-mdi-menu"
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<UInput
|
||||
class="my-2 ml-2"
|
||||
v-model="phase.label"
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<UInput
|
||||
class="my-2 ml-2"
|
||||
v-model="phase.icon"
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<UCheckbox
|
||||
class="my-2 ml-2"
|
||||
v-model="phase.optional"
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<UInput
|
||||
class="my-2 ml-2"
|
||||
v-model="phase.description"
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<UButton
|
||||
class="my-2 ml-2"
|
||||
variant="outline"
|
||||
@click="openQuickActionModal = true,
|
||||
selectedKeyForQuickAction = phase.key"
|
||||
>+ Schnellaktion</UButton>
|
||||
<UButton
|
||||
@click="phase.quickactions = phase.quickactions.filter(i => i.label !== button.label)"
|
||||
v-for="button in phase.quickactions"
|
||||
class="ml-1"
|
||||
>
|
||||
{{ button.label }}
|
||||
</UButton>
|
||||
|
||||
<UModal v-model="openQuickActionModal">
|
||||
<UCard>
|
||||
<div class="flex items-center justify-between">
|
||||
<h3 class="text-base font-semibold leading-6 text-gray-900 dark:text-white">
|
||||
Schnellaktion hinzufügen
|
||||
</h3>
|
||||
<UButton color="gray" variant="ghost" icon="i-heroicons-x-mark-20-solid" class="-my-1" @click="openQuickActionModal = false" />
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
<UButton
|
||||
class="my-1"
|
||||
@click="itemInfo.initialPhases[itemInfo.initialPhases.findIndex(i=> i.key === selectedKeyForQuickAction)].quickactions.push({label:'+ Angebot',link:'/createDocument/edit/?type=quotes'})">Angebot Erstellen</UButton>
|
||||
<UButton
|
||||
class="my-1"
|
||||
@click="itemInfo.initialPhases[itemInfo.initialPhases.findIndex(i=> i.key === selectedKeyForQuickAction)].quickactions.push({label:'+ Lieferschein',link:'/createDocument/edit/?type=deliveryNotes'})">Lieferschein Erstellen</UButton>
|
||||
<UButton
|
||||
class="my-1"
|
||||
@click="itemInfo.initialPhases[itemInfo.initialPhases.findIndex(i=> i.key === selectedKeyForQuickAction)].quickactions.push({label:'+ Rechnung',link:'/createDocument/edit/?type=invoices'})">Rechnung Erstellen</UButton>
|
||||
<UButton
|
||||
class="my-1"
|
||||
@click="itemInfo.initialPhases[itemInfo.initialPhases.findIndex(i=> i.key === selectedKeyForQuickAction)].quickactions.push({label:'+ Aufgabe',link:'/tasks/create'})">Aufgabe Erstellen</UButton>
|
||||
<UButton
|
||||
class="my-1"
|
||||
@click="itemInfo.initialPhases[itemInfo.initialPhases.findIndex(i=> i.key === selectedKeyForQuickAction)].quickactions.push({label:'+ Termin',link:'/events/edit'})">Termin Erstellen</UButton>
|
||||
|
||||
</div>
|
||||
|
||||
</UCard>
|
||||
</UModal>
|
||||
</td>
|
||||
<td>
|
||||
<UButton
|
||||
class="my-2 ml-2"
|
||||
variant="outline"
|
||||
color="rose"
|
||||
@click="itemInfo.initialPhases = itemInfo.initialPhases.filter(i => i !== phase)"
|
||||
>X</UButton>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
</draggable>
|
||||
</table>
|
||||
|
||||
</UForm>
|
||||
</UDashboardPanelContent>
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
108
pages/projecttypes/index.vue
Normal file
108
pages/projecttypes/index.vue
Normal file
@@ -0,0 +1,108 @@
|
||||
<script setup>
|
||||
definePageMeta({
|
||||
middleware: "auth"
|
||||
})
|
||||
|
||||
defineShortcuts({
|
||||
'/': () => {
|
||||
//console.log(searchinput)
|
||||
//searchinput.value.focus()
|
||||
document.getElementById("searchinput").focus()
|
||||
},
|
||||
'+': () => {
|
||||
router.push("/projects/create")
|
||||
},
|
||||
'Enter': {
|
||||
usingInput: true,
|
||||
handler: () => {
|
||||
router.push(`/projecttypes/show/${filteredRows.value[selectedItem.value].id}`)
|
||||
}
|
||||
},
|
||||
'arrowdown': () => {
|
||||
if(selectedItem.value < filteredRows.value.length - 1) {
|
||||
selectedItem.value += 1
|
||||
} else {
|
||||
selectedItem.value = 0
|
||||
}
|
||||
},
|
||||
'arrowup': () => {
|
||||
if(selectedItem.value === 0) {
|
||||
selectedItem.value = filteredRows.value.length - 1
|
||||
} else {
|
||||
selectedItem.value -= 1
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
|
||||
const items = ref([])
|
||||
const selectedItem = ref(0)
|
||||
|
||||
|
||||
const setup = async () => {
|
||||
items.value = await useSupabaseSelect("projecttypes","*")
|
||||
}
|
||||
|
||||
setup()
|
||||
|
||||
const templateColumns = [
|
||||
{
|
||||
key: "name",
|
||||
label: "Name"
|
||||
},
|
||||
|
||||
]
|
||||
const selectedColumns = ref(templateColumns)
|
||||
const columns = computed(() => templateColumns.filter((column) => selectedColumns.value.includes(column)))
|
||||
|
||||
const searchString = ref("")
|
||||
|
||||
const filteredRows = computed(() => {
|
||||
return useListFilter(searchString.value, items.value)
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UDashboardNavbar title="Projekttypen" :badge="filteredRows.length">
|
||||
<template #right>
|
||||
<UInput
|
||||
id="searchinput"
|
||||
v-model="searchString"
|
||||
icon="i-heroicons-funnel"
|
||||
autocomplete="off"
|
||||
placeholder="Suche..."
|
||||
class="hidden lg:block"
|
||||
@keydown.esc="$event.target.blur()"
|
||||
>
|
||||
<template #trailing>
|
||||
<UKbd value="/" />
|
||||
</template>
|
||||
</UInput>
|
||||
|
||||
<UButton @click="router.push(`/projecttypes/create`)">+ Projekttyp</UButton>
|
||||
</template>
|
||||
</UDashboardNavbar>
|
||||
|
||||
<UTable
|
||||
:rows="filteredRows"
|
||||
:columns="columns"
|
||||
class="w-full"
|
||||
:ui="{ divide: 'divide-gray-200 dark:divide-gray-800' }"
|
||||
@select="(i) => router.push(`/projecttypes/show/${i.id}`) "
|
||||
:empty-state="{ icon: 'i-heroicons-circle-stack-20-solid', label: 'Keine Projekttypen anzuzeigen' }"
|
||||
>
|
||||
<template #name-data="{row}">
|
||||
<span class="text-primary-500 font-bold" v-if="row === filteredRows[selectedItem]">{{row.name}}</span>
|
||||
<span v-else>{{row.name}}</span>
|
||||
</template>
|
||||
|
||||
</UTable>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -155,6 +155,12 @@ export const useDataStore = defineStore('data', () => {
|
||||
labelSingle: "Fahrt",
|
||||
redirect: true,
|
||||
historyItemHolder: "trackingtrip",
|
||||
},
|
||||
projecttypes: {
|
||||
label: "Projekttypen",
|
||||
labelSingle: "Projekttyp",
|
||||
redirect: true,
|
||||
historyItemHolder: "projecttype"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -687,6 +693,12 @@ export const useDataStore = defineStore('data', () => {
|
||||
name = "Wöchentliche Arbeitszeit"
|
||||
} else if(key === "licensePlate") {
|
||||
name = "Kennzeichen"
|
||||
}else if(key === "towingCapacity") {
|
||||
name = "Anhängelast"
|
||||
}else if(key === "color") {
|
||||
name = "Farbe"
|
||||
}else if(key === "powerInKW") {
|
||||
name = "Leistung"
|
||||
} else if(key === "driver") {
|
||||
name = "Fahrer"
|
||||
if(prop.data.o) oldVal = profiles.value.find(i => i.id === prop.data.o).fullName
|
||||
@@ -1193,6 +1205,10 @@ export const useDataStore = defineStore('data', () => {
|
||||
return documents.value.filter(item => item.project === projectId && !item.tags.includes("Archiviert"))
|
||||
})
|
||||
|
||||
const getDocumentsByProfileId = computed(() => (profileId) => {
|
||||
return documents.value.filter(item => item.profile === profileId && !item.tags.includes("Archiviert"))
|
||||
})
|
||||
|
||||
const getDocumentsByPlantId = computed(() => (itemId) => {
|
||||
return documents.value.filter(item => item.plant === itemId && !item.tags.includes("Archiviert"))
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user