Added DayJS

Restructured Products
Some Changes in Documents
Some Changes with Logo
This commit is contained in:
2023-12-14 20:58:52 +01:00
parent 2dd31690e5
commit cd36514e1c
10 changed files with 426 additions and 248 deletions

View File

@@ -3,7 +3,7 @@
const user = useSupabaseUser() const user = useSupabaseUser()
console.log(user) //console.log(user.value)
const router = useRouter() const router = useRouter()
const route = useRoute() const route = useRoute()
const colorMode = useColorMode() const colorMode = useColorMode()
@@ -11,9 +11,14 @@ const supabase = useSupabaseClient()
const tenants = (await supabase.from("tenants").select()).data const tenants = (await supabase.from("tenants").select()).data
const {loaded, profiles} = storeToRefs(useDataStore()) const {loaded, profiles} = storeToRefs(useDataStore())
const {fetchData, getProfileById} = useDataStore() const {fetchData, getProfileById} = useDataStore()
const userProfile = user.value ? getProfileById(user.value.id) : {} const userProfile = (user.value ? getProfileById(user.value.id) : {})
//console.log(userProfile)
const viewport = useViewport()
watch(viewport.breakpoint, (newBreakpoint, oldBreakpoint) => {
console.log('Breakpoint updated:', oldBreakpoint, '->', newBreakpoint)
})
fetchData() fetchData()
@@ -110,26 +115,7 @@ generateLinks()
const userTenant = ref({}) const userTenant = ref({})
if(user) userTenant.value = tenants.find(tenant => tenant.id === user.value.app_metadata.tenant) if(user) userTenant.value = tenants.find(tenant => tenant.id === user.value.app_metadata.tenant)
const userDropdownItems = [
[
{
label: user.value ? user.value.email : "Profil",
},/*{
label: user ? userTenant.value.name : "",
}*/
],
[
{
label: "Logout",
click: () => {
router.push("/login")
}
}
]
]
useHead({ useHead({
@@ -182,8 +168,16 @@ const items = [
<UHeader :links="navLinks"> <UHeader :links="navLinks">
<template #logo> <template #logo>
<div id="logo"> <div id="logo">
<img v-if="colorMode.value === 'dark'" src="/spaces.svg"/> <img
<img v-else src="/spaces_hell.svg"/> v-if="colorMode.value === 'light'"
alt="Logo Hell"
src="/spaces_hell.svg"
/>
<img
v-else
src="/spaces_hell.svg"
alt="Logo Dunkel"
/>
</div> </div>
</template> </template>

View File

@@ -36,6 +36,7 @@
"@zip.js/zip.js": "^2.7.32", "@zip.js/zip.js": "^2.7.32",
"axios": "^1.6.2", "axios": "^1.6.2",
"buffer": "^6.0.3", "buffer": "^6.0.3",
"dayjs": "^1.11.10",
"jsprintmanager": "^6.0.3", "jsprintmanager": "^6.0.3",
"nuxt-editorjs": "^1.0.4", "nuxt-editorjs": "^1.0.4",
"nuxt-viewport": "^2.0.6", "nuxt-viewport": "^2.0.6",

View File

@@ -74,14 +74,14 @@
fullscreen fullscreen
> >
<UCard class="h-full"> <UCard class="h-full">
{{selectedDocument}} <embed
<!-- <embed
class="bigPreview mb-3" class="bigPreview mb-3"
:src="selectedDocument.url" :src="selectedDocument.url"
/>--> />
<UBadge <UBadge
v-for="tag in selectedDocument.tags" v-for="tag in selectedDocument.tags"
class="ml-2"
> >
{{tag}} {{tag}}
</UBadge> </UBadge>
@@ -98,6 +98,17 @@
/> />
</UFormGroup> </UFormGroup>
<UFormGroup
label="Tags ändern:"
>
<USelectMenu
:options="tags"
v-model="selectedDocument.tags"
@change="updateDocument"
multiple
/>
</UFormGroup>
@@ -169,8 +180,12 @@ definePageMeta({
}) })
const supabase = useSupabaseClient() const supabase = useSupabaseClient()
const user = useSupabaseUser() const user = useSupabaseUser()
const toast = useToast()
const {documents} = storeToRefs(useDataStore()) const {documents} = storeToRefs(useDataStore())
const {fetchDocuments} = useDataStore()
fetchDocuments()
const tabOpen = ref(0) const tabOpen = ref(0)
const uploadModalOpen = ref(false) const uploadModalOpen = ref(false)
@@ -183,7 +198,7 @@ const fileUploadFormData = ref({
const selectedDocuments = ref([]) const selectedDocuments = ref([])
let tags = ["Eingangsrechnung","Ausgangrechnung","Mahnung", "Dokument"] let tags = ["Eingangsrechnung","Ausgangrechnung","Mahnung", "Dokument", "E-Mail Anhang"]
const folders = [ const folders = [
{ {
label: "Eingang", label: "Eingang",
@@ -237,7 +252,29 @@ const uploadFile = async () => {
uploadModalOpen.value = false; uploadModalOpen.value = false;
} }
const updateDocument = async () => {
console.log(selectedDocument.value)
let objData = selectedDocument.value
delete objData.url
const {data,error} = await supabase
.from("documents")
.update(objData)
.eq('id',objData.id)
.select()
console.log(data)
if(error) {
console.log(error)
} else {
toast.add({title: "Dokument aktualisiert"})
selectedDocument.value = data[0]
showDocumentModal.value = false
fetchDocuments()
}
}
const changeFolder = async () => { const changeFolder = async () => {
console.log("Change Folder") console.log("Change Folder")

View File

@@ -1,6 +1,5 @@
<script setup> <script setup>
import FullCalendar from "@fullcalendar/vue3" import FullCalendar from "@fullcalendar/vue3"
import dayGridPlugin from '@fullcalendar/daygrid'
import resourceTimelinePlugin from '@fullcalendar/resource-timeline' import resourceTimelinePlugin from '@fullcalendar/resource-timeline'
import deLocale from '@fullcalendar/core/locales/de' import deLocale from '@fullcalendar/core/locales/de'
import interactionPlugin from '@fullcalendar/interaction' import interactionPlugin from '@fullcalendar/interaction'
@@ -50,7 +49,8 @@ const calendarOptionsList = reactive({
plugins: [listPlugin], plugins: [listPlugin],
initialView: "listWeek", initialView: "listWeek",
initialEvents: events, initialEvents: events,
nowIndicator: true nowIndicator: true,
height: "80vh"
}) })
const calendarOptionsTimeline = reactive({ const calendarOptionsTimeline = reactive({
@@ -171,4 +171,5 @@ const calendarOptionsTimeline = reactive({
</template> </template>
<style scoped> <style scoped>
</style> </style>

View File

@@ -1,209 +0,0 @@
<template>
<div id="main">
<div id="left">
<UButton @click="showCreateProduct = true" >+ Artikel</UButton>
<UModal v-model="showCreateProduct">
<UCard :ui="{ ring: '', divide: 'divide-y divide-gray-100 dark:divide-gray-800' }">
<template #header>
Artikel erstellen
</template>
<UFormGroup
label="Name:"
>
<UInput
v-model="createProductData.name"
/>
</UFormGroup>
<UFormGroup
label="Hersteller:"
>
<UInput
v-model="createProductData.manufacturer"
/>
</UFormGroup>
<UFormGroup
label="Einheit:"
>
<USelectMenu
v-model="createProductData.unit"
:options="units"
value-attribute="id"
option-attribute="name"
/>
</UFormGroup>
<template #footer>
<UButton @click="createProduct">Erstellen</UButton>
</template>
</UCard>
</UModal>
<div class="listContainer">
<a v-for="item in products" @click="selectItem(item)">
<UCard class="listItem">
<UBadge>{{item.id}}</UBadge> {{item.name}} - {{item.manufacturer}}
</UCard>
</a>
</div>
</div>
<div id="right">
<div v-if="false">
<img
v-if="selectedItem.image"
:src="'http://localhost:1337' + selectedItem.image.data.url"/>
{{selectedItem.image.data.url}}
</div>
<UCard v-if="selectedItem.id">
<template #header>
<UBadge>{{selectedItem.id}}</UBadge> {{selectedItem.name}}
</template>
<UBadge
v-for="tag in selectedItem.tags"
class="mr-2"
>
{{tag}}
</UBadge>
<UDivider class="my-3"/>
<div v-if="selectedItem">
Hersteller: {{selectedItem.manufacturer}}<br>
Einkaufspreis: {{selectedItem.purchasePriceNet}} <br>
Aufschlag: {{selectedItem.profitPercentage}} %<br>
Verkaufspreis: {{selectedItem.retailPriceNet}} <br>
</div>
<!--<UDivider class="my-3"/>
<p>Verlauf:</p>
<table>
<tr
v-for="item in history"
class="historyItem"
>
<td>
{{item.position}}
</td>
<td>
{{item.date}}
</td>
<td>
<UBadge>{{item.user}}</UBadge>
</td>
<td>
{{item.message}}
</td>
</tr>
</table>-->
<!-- <div
v-for="item in history"
class="historyItem"
>
<p>{{item.message}}</p>
<UBadge>{{item.user}}</UBadge>
</div>-->
</UCard> {{selectedItem}}
</div>
</div>
</template>
<script setup>
definePageMeta({
middleware: "auth"
})
const supabase = useSupabaseClient()
const {products,units} = storeToRefs(useDataStore())
const showCreateProduct = ref(false)
const createProductData = ref({})
let selectedItem = ref({})
const history = ref([
{
position: 0,
message: "Produkt erstellt",
date: "2023-11-20",
user: "flfeders"
}
])
const selectItem = (item) => {
selectedItem.value = item
console.log(item)
}
const createProduct = async () => {
//await create('products', createProductData.value)
const {data,error} = await supabase
.from("products")
.insert([createProductData.value])
.select()
console.log(error)
showCreateProduct.value = false
createProductData.value = {}
}
</script>
<style scoped>
#main {
display: flex;
flex-direction: row;
}
#left {
width: 25vw;
overflow: hidden;
}
#right {
width: 60vw;
padding-left: 3vw;
}
.listContainer {
height: 75vh;
overflow: auto;
margin-top: 3vh;
}
.historyItem >td {
border: 0.5px solid grey;
border-radius: 15px;
padding: 1em
}
/* Hide scrollbar for Chrome, Safari and Opera */
.listContainer::-webkit-scrollbar {
display: none;
}
/* Hide scrollbar for IE, Edge and Firefox */
.listContainer {
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
</style>

View File

@@ -0,0 +1,229 @@
<script setup>
definePageMeta({
middleware: "auth"
})
//
const supabase = useSupabaseClient()
const route = useRoute()
const router = useRouter()
const toast = useToast()
const id = ref(route.params.id ? route.params.id : null )
//Store
const {products, units, ownTenant } = storeToRefs(useDataStore())
const {fetchProducts, getProductById, getStockByProductId} = useDataStore()
let currentProduct = null
//Working
const mode = ref(route.params.mode || "show")
const itemInfo = ref({
unit: 1,
tags: []
})
//Functions
const setupPage = () => {
if(mode.value === "show" || mode.value === "edit"){
currentProduct = getProductById(Number(useRoute().params.id))
}
if(mode.value === "edit") itemInfo.value = currentProduct
}
const createItem = async () => {
const {data,error} = await supabase
.from("products")
.insert([itemInfo.value])
.select()
if(error) {
console.log(error)
} else {
mode.value = "show"
itemInfo.value = {
id: 0,
name: ""
}
toast.add({title: "Artikel erfolgreich erstellt"})
await fetchProducts()
router.push(`/products/show/${data[0].id}`)
setupPage()
}
}
const editItem = async () => {
router.push(`/products/edit/${currentProduct.id}`)
setupPage()
}
const cancelEditorCreate = () => {
mode.value = "show"
itemInfo.value = {
id: 0,
}
}
const updateItem = async () => {
const {error} = await supabase
.from("products")
.update(itemInfo.value)
.eq('id',itemInfo.value.id)
if(error) {
console.log(error)
} else {
mode.value = "show"
itemInfo.value = {
id: 0,
name: "",
}
toast.add({title: "Artikel erfolgreich gespeichert"})
fetchProducts()
}
}
setupPage()
</script>
<template>
<div>
<UCard v-if="currentProduct && mode == 'show'" >
<template #header>
{{currentProduct.name}}
</template>
<UBadge
v-for="tag in currentProduct.tags"
class="mr-2"
>
{{tag}}
</UBadge>
<UDivider
class="my-2"
/>
Bestand: {{getStockByProductId(currentProduct.id)}} {{units.find(unit => unit.id === currentProduct.unit) ? units.find(unit => unit.id === currentProduct.unit).name : ""}}
<UDivider
class="my-2"
/>
{{currentProduct}}
<template #footer>
<UButton
v-if="mode == 'show' && currentProduct.id"
@click="editItem"
>
Bearbeiten
</UButton>
<UButton
color="red"
class="ml-2"
disabled
>
Archivieren
</UButton>
<!-- TODO: Produkt archivieren -->
</template>
</UCard>
<UCard v-else-if="mode == 'edit' || mode == 'create'" >
<template #header>
{{itemInfo.name}}
</template>
<UFormGroup
label="Name:"
>
<UInput
v-model="itemInfo.name"
/>
</UFormGroup>
<UFormGroup
label="Hersteller:"
>
<UInput
v-model="itemInfo.manufacturer"
/>
</UFormGroup>
<UFormGroup
label="Einheit:"
>
<USelectMenu
v-model="itemInfo.unit"
:options="units"
option-attribute="name"
value-attribute="id"
>
<template #label>
{{units.find(unit => unit.id === itemInfo.unit) ? units.find(unit => unit.id === itemInfo.unit).name : itemInfo.unit }}
</template>
</USelectMenu>
</UFormGroup>
<UFormGroup
label="Tags:"
>
<USelectMenu
v-model="itemInfo.tags"
:options="ownTenant.tags.products"
multiple
/>
</UFormGroup>
<UFormGroup
label="EAN:"
>
<UInput
v-model="itemInfo.ean"
/>
</UFormGroup>
<template #footer>
<UButton
v-if="mode == 'edit'"
@click="updateItem"
>
Speichern
</UButton>
<UButton
v-else-if="mode == 'create'"
@click="createItem"
>
Erstellen
</UButton>
<UButton
@click="cancelEditorCreate"
color="red"
class="ml-2"
>
Abbrechen
</UButton>
</template>
</UCard>
</div>
</template>
<style scoped>
</style>

View File

@@ -0,0 +1,92 @@
<template>
<div>
<UButton @click="router.push(`/products/create/`)">+ Artikel</UButton>
<UInput
v-model="searchString"
placeholder="Suche..."
/>
<UTable
:rows="filteredRows"
:columns="itemColumns"
@select="selectItem"
>
<template #tags-data="{row}">
<UBadge
v-if="row.tags.length > 0"
v-for="tag in row.tags"
class="mr-2"
>
{{tag}}
</UBadge>
<span v-else>-</span>
</template>
<template #unit-data="{row}">
{{units.find(unit => unit.id === row.unit) ? units.find(unit => unit.id === row.unit).name : row.unit}}
</template>
</UTable>
</div>
</template>
<script setup>
definePageMeta({
middleware: "auth"
})
const supabase = useSupabaseClient()
const router = useRouter()
const {products,units} = storeToRefs(useDataStore())
const itemColumns = [
{
key: "id",
label: "Id"
},
{
key: "name",
label: "Name"
},
{
key: "manufacturer",
label: "Hersteller",
},
{
key: "unit",
label: "Einheit"
},
{
key: "tags",
label: "Tags"
}
]
const selectItem = (item) => {
console.log(item)
router.push(`/products/show/${item.id} `)
}
const searchString = ref('')
const filteredRows = computed(() => {
if(!searchString.value) {
return products.value
}
return products.value.filter(product => {
return Object.values(product).some((value) => {
return String(value).toLowerCase().includes(searchString.value.toLowerCase())
})
})
})
</script>
<style scoped>
</style>

View File

@@ -3,11 +3,13 @@ definePageMeta({
middleware: "auth" middleware: "auth"
}) })
import * as dayjs from 'dayjs'
const supabase = useSupabaseClient() const supabase = useSupabaseClient()
const route = useRoute() const route = useRoute()
const {getProjectById, getFormSubmitsWithLabelProp, getTimesByProjectId} = useDataStore() const {getProjectById, getFormSubmitsWithLabelProp, getTimesByProjectId} = useDataStore()
const {forms, formSubmits, times} = storeToRefs(useDataStore()) const {forms, formSubmits, times, profiles} = storeToRefs(useDataStore())
const currentProject = getProjectById(Number(route.params.id)) const currentProject = getProjectById(Number(route.params.id))
@@ -252,7 +254,19 @@ const phaseInfo = ref({
<UTable <UTable
:rows="getTimesByProjectId(currentProject.id)" :rows="getTimesByProjectId(currentProject.id)"
:columns="timeTableRows" :columns="timeTableRows"
/> >
<template #user-data="{row}">
{{profiles.find(profile => profile.id === row.user) ? profiles.find(profile => profile.id === row.user).firstName + " " + profiles.find(profile => profile.id === row.user).lastName : row.user }}
</template>
<template #start-data="{row}">
{{dayjs(row.start).format("DD.MM.YY HH:mm")}}
</template>
<template #end-data="{row}">
{{dayjs(row.end).format("DD.MM.YY HH:mm")}}
</template>
</UTable>
</div> </div>
<div v-else-if="item.key === 'material'" class="space-y-3"> <div v-else-if="item.key === 'material'" class="space-y-3">
<p>Hier wird aktuell noch gearbeitet</p> <p>Hier wird aktuell noch gearbeitet</p>

View File

@@ -49,7 +49,13 @@
:columns="projectColumns" :columns="projectColumns"
@select="selectProject" @select="selectProject"
/> >
<template #customer-data="{row}">
{{customers.find(customer => customer.id == row.customer ) ? customers.find(customer => customer.id == row.customer ).name : row.id}}
</template>
</UTable>

View File

@@ -38,20 +38,23 @@ export const useDataStore = defineStore('data', {
await this.fetchOwnTenant() await this.fetchOwnTenant()
await this.fetchProfiles() await this.fetchProfiles()
await this.fetchEvents() await this.fetchEvents()
await this.fetchCustomers()
await this.fetchTasks() await this.fetchTasks()
await this.fetchProjects()
await this.fetchTimes()
await this.fetchJobs()
this.loaded = true
await this.fetchCustomers()
await this.fetchForms() await this.fetchForms()
await this.fetchFormSubmits() await this.fetchFormSubmits()
await this.fetchProducts() await this.fetchProducts()
await this.fetchUnits() await this.fetchUnits()
await this.fetchProjects() //await this.fetchDocuments()
await this.fetchDocuments()
await this.fetchMovements() await this.fetchMovements()
await this.fetchTimes()
await this.fetchJobs()
await this.fetchSpaces() await this.fetchSpaces()
await this.fetchVehicles() await this.fetchVehicles()
this.loaded = true
}, },
async fetchOwnTenant() { async fetchOwnTenant() {
//TODO: Tenant ID Dynamisch machen //TODO: Tenant ID Dynamisch machen
@@ -84,7 +87,7 @@ export const useDataStore = defineStore('data', {
}, },
async fetchProducts() { async fetchProducts() {
// @ts-ignore // @ts-ignore
this.products = (await supabase.from("products").select()).data this.products = (await supabase.from("products").select().order('id',{ascending: true})).data
}, },
async fetchUnits() { async fetchUnits() {
// @ts-ignore // @ts-ignore
@@ -128,6 +131,16 @@ export const useDataStore = defineStore('data', {
getProfileById: (state) => (userUid:string) => state.profiles.find(profile => profile.id === userUid), getProfileById: (state) => (userUid:string) => state.profiles.find(profile => profile.id === userUid),
getOpenTasksCount: (state) => state.tasks.filter(task => task.categorie != "Erledigt").length, getOpenTasksCount: (state) => state.tasks.filter(task => task.categorie != "Erledigt").length,
movementsBySpace: (state) => (spaceId:number) => state.movements.filter(move => move.spaceId === spaceId), movementsBySpace: (state) => (spaceId:number) => state.movements.filter(move => move.spaceId === spaceId),
getStockByProductId: (state) => (productId:number) => {
let movements = state.movements.filter((movement:any) => movement.productId === productId)
let count = 0
movements.forEach(movement => count += movement.quantity)
return count
},
getProductById: (state) => (productId:number) => state.products.find(product => product.id === productId), getProductById: (state) => (productId:number) => state.products.find(product => product.id === productId),
getProjectById: (state) => (projectId:number) => { getProjectById: (state) => (projectId:number) => {
let project = state.projects.find(project => project.id === projectId) let project = state.projects.find(project => project.id === projectId)