Added Phases to Projects

This commit is contained in:
2024-02-05 20:48:15 +01:00
parent 22a3b8698c
commit 2fc45b3ea0
5 changed files with 190 additions and 38 deletions

View File

@@ -123,7 +123,8 @@ const renderText = (text) => {
</template> </template>
<div <div
v-if="historyItems.length > 0" v-if="historyItems.length > 0"
v-for="(item,index) in historyItems" v-for="(item,index) in historyItems.slice().reverse()
"
> >
<UDivider <UDivider
class="my-3" class="my-3"

View File

@@ -18,12 +18,13 @@ const id = ref(route.params.id ? route.params.id : null )
let currentItem = ref(null) let currentItem = ref(null)
const tabItems = [ const tabItems = [
/*{ {
key: "phases",
label: "Phasen"
},*/{
key: "information", key: "information",
label: "Informationen" label: "Informationen"
},
{
key: "phases",
label: "Phasen"
},{ },{
key: "tasks", key: "tasks",
label: "Aufgaben" label: "Aufgaben"
@@ -172,6 +173,52 @@ 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 phasesTemplateSelected = ref(dataStore.phasesTemplates[0].id)
const changeActivePhase = (phase) => {
currentItem.value.phases = currentItem.value.phases.map(p => {
if(p.active) delete p.active
if(p.label === phase.label) p.active = true
return p
})
savePhases()
}
const savePhases = () => {
dataStore.updateItem("projects", currentItem.value)
}
const loadPhases = async () => {
currentItem.value.phases = dataStore.phasesTemplates.find(i => i.id === phasesTemplateSelected.value).initialPhases
await dataStore.updateItem("projects", currentItem.value)
}
setupPage() setupPage()
</script> </script>
@@ -183,29 +230,69 @@ setupPage()
<UTabs :items="tabItems" class="w-full"> <UTabs :items="tabItems" class="w-full">
<template #item="{ item }"> <template #item="{ item }">
<!-- <div v-if="item.key === 'information'">
<div v-if="item.key === 'phases'" class="space-y-3"> <InputGroup>
<p>Hier wird aktuell noch gearbeitet</p> <UButton
&lt;!&ndash; <div id="phaseList"> @click="router.push(`/customers/show/${currentItem.customer}`)"
<a class="mb-3"
v-for="phase in []" >
@click="selectedPhase = phase" Zum Kunden
> </UButton>
<div <UButton
class="phaseContainer" @click="router.push(`/plants/show/${currentItem.plant}`)"
> class="mb-3"
<span>{{phase.name}} - {{phase.position}}</span> >
</div> Zum Objekt
</UButton>
</InputGroup>
<a class="plusIcon" @click="addPhase(phase)"> Kunde: {{dataStore.getCustomerById(currentItem.customer).name}}<br>
Objekt: {{currentItem.plant ? dataStore.getPlantById(currentItem.plant).name : ""}}<br>
Notizen:<br>
{{currentItem.notes}}
</div>
<div v-if="item.key === 'phases'" class="space-y-3">
<UFormGroup
label="Vorlage laden"
v-if="currentItem.phases.length === 0"
>
<InputGroup>
<USelectMenu
:options="dataStore.phasesTemplates"
option-attribute="name"
value-attribute="id"
v-model="phasesTemplateSelected"
class="flex-auto"
>
<UDivider icon="i-heroicons-plus-circle"/> </USelectMenu>
</a> <UButton
</a> @click="loadPhases"
</div>&ndash;&gt; >
Vorlage laden
</UButton>
</InputGroup>
</UFormGroup>
</div> <UAccordion
--> :items="currentItem.phases"
>
<template #item="{item}">
<InputGroup>
<UButton
v-if="!item.active"
@click="changeActivePhase(item)"
>
Phase aktivieren
</UButton>
<!-- <UButton>
+ Phase
</UButton>-->
</InputGroup>
</template>
</UAccordion>
</div>
<div v-if="item.key === 'tasks'" class="space-y-3"> <div v-if="item.key === 'tasks'" class="space-y-3">
<InputGroup> <InputGroup>
<UButton <UButton

View File

@@ -1,11 +1,16 @@
<template> <template>
<InputGroup> <InputGroup >
<UButton @click="router.push(`/projects/create/`)">+ Projekt</UButton> <UButton @click="router.push(`/projects/create/`)">+ Projekt</UButton>
<UInput <UInput
v-model="searchString" v-model="searchString"
placeholder="Suche..." placeholder="Suche..."
/> />
<UCheckbox
label="Abgeschlossene anzeigen"
v-model="showFinished"
/>
</InputGroup> </InputGroup>
@@ -16,6 +21,9 @@
:columns="itemColumns" :columns="itemColumns"
:empty-state="{ icon: 'i-heroicons-circle-stack-20-solid', label: 'Noch keine Einträge' }" :empty-state="{ icon: 'i-heroicons-circle-stack-20-solid', label: 'Noch keine Einträge' }"
> >
<template #phase-data="{row}">
{{getActivePhaseLabel(row)}}
</template>
<template #customer-data="{row}"> <template #customer-data="{row}">
{{dataStore.getCustomerById(row.customer) ? dataStore.getCustomerById(row.customer).name : ""}} {{dataStore.getCustomerById(row.customer) ? dataStore.getCustomerById(row.customer).name : ""}}
</template> </template>
@@ -35,6 +43,10 @@ const supabase = useSupabaseClient()
const router = useRouter() const router = useRouter()
const itemColumns = [ const itemColumns = [
{
key: "phase",
label: "Phase"
},
{ {
key: "measure", key: "measure",
label: "Gewerk" label: "Gewerk"
@@ -43,13 +55,13 @@ const itemColumns = [
label: "Name" label: "Name"
}, },
{ {
key: "notes", key: "customer",
label: "Notizen", label: "Kunde",
sortable: true sortable: true
}, },
{ {
key: "customer", key: "notes",
label: "Kunde", label: "Notizen",
sortable: true sortable: true
}, },
{ {
@@ -64,15 +76,49 @@ const selectItem = (item) => {
router.push(`/projects/show/${item.id} `) router.push(`/projects/show/${item.id} `)
} }
const getActivePhaseLabel = (item) => {
if(item.phases) {
if(item.phases.length > 0) {
let activePhase = item.phases.find(i => i.active)
if(activePhase) {
return activePhase.label
} else {
return ""
}
}
}
}
const searchString = ref('') const searchString = ref('')
const showFinished = ref(false)
const filteredRows = computed(() => { const filteredRows = computed(() => {
if(!searchString.value) { let items = dataStore.projects
return dataStore.projects
items = items.map(item => {
return {
...item,
phaseLabel: getActivePhaseLabel(item)
}
})
if(showFinished.value) {
items = items.filter(i => i.phaseLabel === "Abgeschlossen")
} else {
items = items.filter(i => i.phaseLabel !== "Abgeschlossen")
} }
return dataStore.projects.filter(product => { if(!searchString.value) {
return Object.values(product).some((value) => { return items
}
return items.filter(project => {
return Object.values(project).some((value) => {
return String(value).toLowerCase().includes(searchString.value.toLowerCase()) return String(value).toLowerCase().includes(searchString.value.toLowerCase())
}) })
}) })

View File

@@ -85,10 +85,20 @@ setupPage()
{{currentItem.name}} {{currentItem.name}}
</template> </template>
<InputGroup>
<UButton
v-if="currentItem.project"
@click="router.push(`/projects/show/${currentItem.project}`)"
class="mb-3"
>
Zum Projekt
</UButton>
</InputGroup>
Beschreibung:<br> Beschreibung:<br>
{{currentItem.description}}<br> {{currentItem.description}}<br>
Projekt: {{currentItem.project ? dataStore.getProjectById(currentItem.project).name : "Kein Projekt zugeordnet"}}

View File

@@ -156,6 +156,7 @@ export const useDataStore = defineStore('data', () => {
const messages = ref([]) const messages = ref([])
const createddocuments = ref([]) const createddocuments = ref([])
const workingtimes = ref([]) const workingtimes = ref([])
const phasesTemplates = ref([])
const rights = ref({ const rights = ref({
@@ -271,6 +272,7 @@ export const useDataStore = defineStore('data', () => {
await fetchMessages() await fetchMessages()
await fetchCreatedDocuments() await fetchCreatedDocuments()
await fetchWorkingTimes() await fetchWorkingTimes()
await fetchPhasesTemplates()
loaded.value = true loaded.value = true
} }
@@ -310,6 +312,7 @@ export const useDataStore = defineStore('data', () => {
messages.value = [] messages.value = []
createddocuments.value = [] createddocuments.value = []
workingtimes.value = [] workingtimes.value = []
phasesTemplates.value = []
} }
function hasRight (right) { function hasRight (right) {
@@ -333,7 +336,7 @@ export const useDataStore = defineStore('data', () => {
schema: 'public', schema: 'public',
}, },
(payload) => { (payload) => {
console.log(payload) //console.log(payload)
if(payload.eventType === 'INSERT') { if(payload.eventType === 'INSERT') {
const c = payload.table + '.value.push(' + JSON.stringify(payload.new) + ')' const c = payload.table + '.value.push(' + JSON.stringify(payload.new) + ')'
@@ -347,7 +350,7 @@ export const useDataStore = defineStore('data', () => {
.subscribe() .subscribe()
async function createNewItem (dataType,data){ async function createNewItem (dataType,data){
console.log(dataType) //console.log(dataType)
if(dataTypes[dataType].numberRangeHolder) { if(dataTypes[dataType].numberRangeHolder) {
const numberRange = useNumberRange(dataType) const numberRange = useNumberRange(dataType)
@@ -368,7 +371,7 @@ export const useDataStore = defineStore('data', () => {
if(supabaseError) { if(supabaseError) {
console.log(supabaseError) console.log(supabaseError)
} else if (supabaseData) { } else if (supabaseData) {
await eval( dataType + '.value.push(' + JSON.stringify(...supabaseData) + ')') //await eval( dataType + '.value.push(' + JSON.stringify(...supabaseData) + ')')
toast.add({title: `${dataTypes[dataType].labelSingle} hinzugefügt`}) toast.add({title: `${dataTypes[dataType].labelSingle} hinzugefügt`})
if(dataTypes[dataType].redirect) await router.push(`/${dataType}/show/${supabaseData[0].id}`) if(dataTypes[dataType].redirect) await router.push(`/${dataType}/show/${supabaseData[0].id}`)
return supabaseData return supabaseData
@@ -556,6 +559,10 @@ export const useDataStore = defineStore('data', () => {
workingtimes.value = (await supabase.from("workingtimes").select().eq('tenant', currentTenant.value).order('created_at', {ascending:true})).data workingtimes.value = (await supabase.from("workingtimes").select().eq('tenant', currentTenant.value).order('created_at', {ascending:true})).data
} }
async function fetchPhasesTemplates() {
phasesTemplates.value = (await supabase.from("phasesTemplates").select().eq('tenant', currentTenant.value).order('created_at', {ascending:true})).data
}
async function fetchDocuments () { async function fetchDocuments () {
let tempDocuments = (await supabase.from("documents").select().eq('tenant', currentTenant.value)).data let tempDocuments = (await supabase.from("documents").select().eq('tenant', currentTenant.value)).data
@@ -959,6 +966,7 @@ export const useDataStore = defineStore('data', () => {
messages, messages,
createddocuments, createddocuments,
workingtimes, workingtimes,
phasesTemplates,
documentTypesForCreation, documentTypesForCreation,
//Functions //Functions
createNewItem, createNewItem,