Some Changes
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
const toast = useToast()
|
const toast = useToast()
|
||||||
const supabase = useSupabaseClient()
|
const supabase = useSupabaseClient()
|
||||||
|
const router = useRouter()
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
document: {
|
document: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@@ -14,7 +15,7 @@ const props = defineProps({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const {document, openShowModal:openShowModalProp } = props;
|
const {document, openShowModal:openShowModalProp } = props;
|
||||||
const {fetchDocuments, getDocumentTags} = useDataStore()
|
const {fetchDocuments, getDocumentTags, fetchVendorInvoices} = useDataStore()
|
||||||
const {projects, customers} = storeToRefs(useDataStore())
|
const {projects, customers} = storeToRefs(useDataStore())
|
||||||
const tags = getDocumentTags
|
const tags = getDocumentTags
|
||||||
const openShowModal = ref(false)
|
const openShowModal = ref(false)
|
||||||
@@ -26,7 +27,7 @@ const openDocument = async () => {
|
|||||||
openShowModal.value = true
|
openShowModal.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
const uploadFiles = async () => {
|
/*const uploadFiles = async () => {
|
||||||
const uploadSingleFile = async (file) => {
|
const uploadSingleFile = async (file) => {
|
||||||
|
|
||||||
const {data, error} = await supabase
|
const {data, error} = await supabase
|
||||||
@@ -76,7 +77,7 @@ const uploadFiles = async () => {
|
|||||||
uploadModalOpen.value = false;
|
uploadModalOpen.value = false;
|
||||||
uploadInProgress.value = false;
|
uploadInProgress.value = false;
|
||||||
fetchDocuments()
|
fetchDocuments()
|
||||||
}
|
}*/
|
||||||
|
|
||||||
|
|
||||||
const updateDocument = async () => {
|
const updateDocument = async () => {
|
||||||
@@ -101,7 +102,21 @@ const updateDocument = async () => {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const createVendorInvoice = async () => {
|
||||||
|
const {data,error} = await supabase
|
||||||
|
.from("vendorInvoices")
|
||||||
|
.insert([{
|
||||||
|
document: document.id,
|
||||||
|
}])
|
||||||
|
.select()
|
||||||
|
if(error) {
|
||||||
|
console.log(error)
|
||||||
|
} else if(data) {
|
||||||
|
fetchVendorInvoices()
|
||||||
|
await router.push("/vendorinvoices")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -125,53 +140,7 @@ const updateDocument = async () => {
|
|||||||
|
|
||||||
|
|
||||||
<!-- Slideovers -->
|
<!-- Slideovers -->
|
||||||
<USlideover
|
|
||||||
v-model="uploadModalOpen"
|
|
||||||
>
|
|
||||||
|
|
||||||
<UCard class="flex flex-col flex-1" :ui="{ body: { base: 'flex-1' }, ring: '', divide: 'divide-y divide-gray-100 dark:divide-gray-800' }">
|
|
||||||
<template #header>
|
|
||||||
Datei Hochladen
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<div class="h-full">
|
|
||||||
<UFormGroup
|
|
||||||
label="Datei:"
|
|
||||||
>
|
|
||||||
<UInput
|
|
||||||
type="file"
|
|
||||||
id="fileUploadInput"
|
|
||||||
multiple
|
|
||||||
/>
|
|
||||||
</UFormGroup>
|
|
||||||
|
|
||||||
<UFormGroup
|
|
||||||
label="Tags:"
|
|
||||||
class="mt-3"
|
|
||||||
>
|
|
||||||
<USelectMenu
|
|
||||||
multiple
|
|
||||||
searchable
|
|
||||||
searchable-placeholder="Suchen..."
|
|
||||||
:options="tags"
|
|
||||||
v-model="fileUploadFormData.tags"
|
|
||||||
/>
|
|
||||||
</UFormGroup>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<template #footer>
|
|
||||||
<UButton
|
|
||||||
v-if="!uploadInProgress"
|
|
||||||
class="mt-3"
|
|
||||||
@click="uploadFiles"
|
|
||||||
>Hochladen</UButton>
|
|
||||||
<UProgress
|
|
||||||
v-else
|
|
||||||
animation="carousel"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</UCard>
|
|
||||||
</USlideover>
|
|
||||||
<USlideover
|
<USlideover
|
||||||
v-model="openShowModal"
|
v-model="openShowModal"
|
||||||
fullscreen
|
fullscreen
|
||||||
@@ -241,7 +210,12 @@ const updateDocument = async () => {
|
|||||||
</USelectMenu>
|
</USelectMenu>
|
||||||
</UFormGroup>
|
</UFormGroup>
|
||||||
|
|
||||||
|
<UButton
|
||||||
|
v-if="document.tags.includes('Eingangsrechnung')"
|
||||||
|
@click="createVendorInvoice"
|
||||||
|
>
|
||||||
|
Eingangsrechnung erstellen
|
||||||
|
</UButton>
|
||||||
|
|
||||||
|
|
||||||
</UCard>
|
</UCard>
|
||||||
|
|||||||
219
spaces/pages/contracts/[mode]/[[id]].vue
Normal file
219
spaces/pages/contracts/[mode]/[[id]].vue
Normal file
@@ -0,0 +1,219 @@
|
|||||||
|
<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 {customers, contracts } = storeToRefs(useDataStore())
|
||||||
|
const {fetchCustomers, getCustomerById, getContractById, fetchContracts} = useDataStore()
|
||||||
|
|
||||||
|
let currentContract = null
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//Working
|
||||||
|
const mode = ref(route.params.mode || "show")
|
||||||
|
const itemInfo = ref({
|
||||||
|
name: "",
|
||||||
|
customer: 0,
|
||||||
|
active: true
|
||||||
|
})
|
||||||
|
|
||||||
|
//Functions
|
||||||
|
const setupPage = () => {
|
||||||
|
if(mode.value === "show" || mode.value === "edit"){
|
||||||
|
currentContract = getContractById(Number(useRoute().params.id))
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mode.value === "edit") itemInfo.value = currentContract
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const createItem = async () => {
|
||||||
|
const {data,error} = await supabase
|
||||||
|
.from("contracts")
|
||||||
|
.insert([itemInfo.value])
|
||||||
|
.select()
|
||||||
|
|
||||||
|
if(error) {
|
||||||
|
console.log(error)
|
||||||
|
} else {
|
||||||
|
mode.value = "show"
|
||||||
|
itemInfo.value = {
|
||||||
|
id: 0,
|
||||||
|
name: ""
|
||||||
|
}
|
||||||
|
toast.add({title: "Vertrag erfolgreich erstellt"})
|
||||||
|
await fetchContracts()
|
||||||
|
router.push(`/contracts/show/${data[0].id}`)
|
||||||
|
setupPage()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const editCustomer = async () => {
|
||||||
|
router.push(`/contracts/edit/${currentContract.id}`)
|
||||||
|
setupPage()
|
||||||
|
}
|
||||||
|
|
||||||
|
const cancelEditorCreate = () => {
|
||||||
|
mode.value = "show"
|
||||||
|
itemInfo.value = {
|
||||||
|
id: 0,
|
||||||
|
name: "",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateCustomer = async () => {
|
||||||
|
const {error} = await supabase
|
||||||
|
.from("contracts")
|
||||||
|
.update(itemInfo.value)
|
||||||
|
.eq('id',itemInfo.value.id)
|
||||||
|
console.log(error)
|
||||||
|
mode.value = "show"
|
||||||
|
itemInfo.value = {
|
||||||
|
id: 0,
|
||||||
|
name: "",
|
||||||
|
}
|
||||||
|
toast.add({title: "Vertrag erfolgreich gespeichert"})
|
||||||
|
fetchContracts()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
setupPage()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<UCard v-if="currentContract && mode == 'show'" >
|
||||||
|
<template #header>
|
||||||
|
<UBadge
|
||||||
|
v-if="currentContract.active"
|
||||||
|
>
|
||||||
|
Vertrag aktiv
|
||||||
|
</UBadge>
|
||||||
|
<UBadge
|
||||||
|
v-else
|
||||||
|
color="red"
|
||||||
|
>
|
||||||
|
Vertrag gesperrt
|
||||||
|
</UBadge>
|
||||||
|
{{currentContract.name}}
|
||||||
|
</template>
|
||||||
|
|
||||||
|
Kundennummer: {{currentContract.customer}} <br>
|
||||||
|
|
||||||
|
<UDivider
|
||||||
|
class="my-2"
|
||||||
|
/>
|
||||||
|
|
||||||
|
Beschreibung:<br>
|
||||||
|
{{currentContract.description}}<br>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<UButton
|
||||||
|
v-if="mode == 'show' && currentContract.id"
|
||||||
|
@click="editCustomer"
|
||||||
|
>
|
||||||
|
Bearbeiten
|
||||||
|
</UButton>
|
||||||
|
<UButton
|
||||||
|
color="red"
|
||||||
|
class="ml-2"
|
||||||
|
disabled
|
||||||
|
>
|
||||||
|
Archivieren
|
||||||
|
</UButton>
|
||||||
|
<!-- TODO: Vertrag archivieren -->
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</UCard>
|
||||||
|
<UCard v-else-if="mode == 'edit' || mode == 'create'" >
|
||||||
|
<template #header>
|
||||||
|
<UBadge>{{itemInfo.customerNumber}}</UBadge> {{itemInfo.name}}
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<UFormGroup
|
||||||
|
label="Name:"
|
||||||
|
>
|
||||||
|
<UInput
|
||||||
|
v-model="itemInfo.name"
|
||||||
|
/>
|
||||||
|
</UFormGroup>
|
||||||
|
|
||||||
|
<UFormGroup
|
||||||
|
label="Kunde:"
|
||||||
|
>
|
||||||
|
<USelectMenu
|
||||||
|
v-model="itemInfo.customer"
|
||||||
|
option-attribute="name"
|
||||||
|
value-attribute="id"
|
||||||
|
:options="customers"
|
||||||
|
searchable
|
||||||
|
:search-attributes="['name']"
|
||||||
|
>
|
||||||
|
<template #label>
|
||||||
|
{{customers.find(customer => customer.id === itemInfo.customer) ? customers.find(customer => customer.id === itemInfo.customer).name : itemInfo.customer}}
|
||||||
|
</template>
|
||||||
|
</USelectMenu>
|
||||||
|
</UFormGroup>
|
||||||
|
|
||||||
|
<UFormGroup
|
||||||
|
label="Vertrag aktiv:"
|
||||||
|
>
|
||||||
|
<UCheckbox
|
||||||
|
v-model="itemInfo.active"
|
||||||
|
/>
|
||||||
|
</UFormGroup>
|
||||||
|
<UFormGroup
|
||||||
|
label="Beschreibung:"
|
||||||
|
>
|
||||||
|
<UTextarea
|
||||||
|
v-model="itemInfo.description"
|
||||||
|
/>
|
||||||
|
</UFormGroup>
|
||||||
|
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<UButton
|
||||||
|
v-if="mode == 'edit'"
|
||||||
|
@click="updateCustomer"
|
||||||
|
>
|
||||||
|
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>
|
||||||
81
spaces/pages/contracts/index.vue
Normal file
81
spaces/pages/contracts/index.vue
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
<template>
|
||||||
|
<div id="main">
|
||||||
|
<!-- TODO: Kontakte erstellen und dem Kunden zuweisen -->
|
||||||
|
|
||||||
|
<div class="flex items-center gap-1">
|
||||||
|
<UButton @click="router.push(`/contracts/create/`)">+ Vertrag</UButton>
|
||||||
|
|
||||||
|
<UInput
|
||||||
|
v-model="searchString"
|
||||||
|
placeholder="Suche..."
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<UTable
|
||||||
|
:rows="filteredRows"
|
||||||
|
:columns="itemColumns"
|
||||||
|
@select="selectItem"
|
||||||
|
|
||||||
|
>
|
||||||
|
<template #customer-data="{row}">
|
||||||
|
{{customers.find(customer => customer.id === row.customer) ? customers.find(customer => customer.id === row.customer).name : row.customer }}
|
||||||
|
</template>
|
||||||
|
</UTable>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
|
||||||
|
definePageMeta({
|
||||||
|
middleware: "auth"
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const {contracts, customers } = storeToRefs(useDataStore())
|
||||||
|
const mode = ref("show")
|
||||||
|
|
||||||
|
const itemColumns = [
|
||||||
|
{
|
||||||
|
key: 'customer',
|
||||||
|
label: "Kundennr.:",
|
||||||
|
sortable: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "name",
|
||||||
|
label: "Name",
|
||||||
|
sortable: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "description",
|
||||||
|
label: "Beschreibung"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
const selectItem = (item) => {
|
||||||
|
router.push(`/contracts/show/${item.id} `)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const searchString = ref('')
|
||||||
|
|
||||||
|
const filteredRows = computed(() => {
|
||||||
|
if(!searchString.value) {
|
||||||
|
return contracts.value
|
||||||
|
}
|
||||||
|
|
||||||
|
return contracts.value.filter(item => {
|
||||||
|
return Object.values(item).some((value) => {
|
||||||
|
return String(value).toLowerCase().includes(searchString.value.toLowerCase())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -171,6 +171,7 @@ setupPage()
|
|||||||
<UButton
|
<UButton
|
||||||
v-if="mode == 'show' && currentItem.id"
|
v-if="mode == 'show' && currentItem.id"
|
||||||
@click="printSpaceLabel"
|
@click="printSpaceLabel"
|
||||||
|
class="ml-2"
|
||||||
>
|
>
|
||||||
Label Drucken
|
Label Drucken
|
||||||
</UButton>
|
</UButton>
|
||||||
|
|||||||
@@ -9,11 +9,11 @@
|
|||||||
<div
|
<div
|
||||||
class="previewDoc"
|
class="previewDoc"
|
||||||
>
|
>
|
||||||
<embed
|
<!-- <embed
|
||||||
:src="fileurl + '#toolbar=0&navpanes=0&scrollbar=0&statusbar=0&messages=0&scrollbar=0'"
|
:src="fileurl + '#toolbar=0&navpanes=0&scrollbar=0&statusbar=0&messages=0&scrollbar=0'"
|
||||||
width="40vw"
|
width="40vw"
|
||||||
height="50vh"
|
height="50vh"
|
||||||
>
|
>-->
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="inputData"
|
class="inputData"
|
||||||
@@ -98,7 +98,9 @@
|
|||||||
<UInput disabled/>
|
<UInput disabled/>
|
||||||
</UFormGroup>
|
</UFormGroup>
|
||||||
</div>-->
|
</div>-->
|
||||||
{{vendorInvoiceData}}
|
{{vendorInvoiceData}}<br>
|
||||||
|
{{currentVendorInvoice}}<br>
|
||||||
|
{{getDocumentById(78)}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -108,7 +110,7 @@ const supabase = useSupabaseClient()
|
|||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
|
||||||
const {vendors} = storeToRefs(useDataStore())
|
const {vendors} = storeToRefs(useDataStore())
|
||||||
|
const {getVendorInvoiceById, getDocumentById} = useDataStore()
|
||||||
|
|
||||||
|
|
||||||
const invoice = ref({
|
const invoice = ref({
|
||||||
@@ -126,12 +128,13 @@ const labelDueDate = computed(() => invoice.value.dueDate.toLocaleDateString('de
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
//const currentVendorInvoice = (await supabase.from('vendorInvoices').select().eq('id', route.params.id)).data
|
const currentVendorInvoice = ref(getVendorInvoiceById(Number(route.params.id)))
|
||||||
const document = (await supabase.from('documents').select().eq("id",18)).data[0]
|
console.log(currentVendorInvoice)
|
||||||
|
const currentDocument = getDocumentById(Number(currentVendorInvoice.document))
|
||||||
|
console.log(currentDocument)
|
||||||
|
//console.log(document)
|
||||||
|
|
||||||
console.log(document)
|
//let fileurl = (await supabase.storage.from('documents').createSignedUrl(document.path,60*60)).data.signedUrl
|
||||||
|
|
||||||
let fileurl = (await supabase.storage.from('documents').createSignedUrl(document.path,60*60)).data.signedUrl
|
|
||||||
|
|
||||||
|
|
||||||
let vendorInvoiceData = ref({
|
let vendorInvoiceData = ref({
|
||||||
|
|||||||
@@ -36,6 +36,16 @@ const {vendorInvoices } = storeToRefs(useDataStore())
|
|||||||
const mode = ref("show")
|
const mode = ref("show")
|
||||||
|
|
||||||
const itemColumns = [
|
const itemColumns = [
|
||||||
|
{
|
||||||
|
key: 'id',
|
||||||
|
label: "Id",
|
||||||
|
sortable: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'state',
|
||||||
|
label: "Status.",
|
||||||
|
sortable: true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'vendor',
|
key: 'vendor',
|
||||||
label: "Lieferantennr.",
|
label: "Lieferantennr.",
|
||||||
@@ -50,7 +60,7 @@ const itemColumns = [
|
|||||||
key: "date",
|
key: "date",
|
||||||
label: "Datum",
|
label: "Datum",
|
||||||
sortable: true
|
sortable: true
|
||||||
}
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ export const useDataStore = defineStore('data', {
|
|||||||
products: [] as any[],
|
products: [] as any[],
|
||||||
movements: [] as any[],
|
movements: [] as any[],
|
||||||
forms: [] as any[],
|
forms: [] as any[],
|
||||||
|
contracts: [] as any[],
|
||||||
jobs: [] as any[],
|
jobs: [] as any[],
|
||||||
formSubmits: [] as any[],
|
formSubmits: [] as any[],
|
||||||
contacts: [] as any[],
|
contacts: [] as any[],
|
||||||
@@ -52,6 +53,7 @@ export const useDataStore = defineStore('data', {
|
|||||||
|
|
||||||
|
|
||||||
await this.fetchCustomers()
|
await this.fetchCustomers()
|
||||||
|
await this.fetchContracts()
|
||||||
await this.fetchForms()
|
await this.fetchForms()
|
||||||
await this.fetchFormSubmits()
|
await this.fetchFormSubmits()
|
||||||
await this.fetchProducts()
|
await this.fetchProducts()
|
||||||
@@ -77,6 +79,10 @@ export const useDataStore = defineStore('data', {
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
this.events = (await supabase.from("events").select()).data
|
this.events = (await supabase.from("events").select()).data
|
||||||
},
|
},
|
||||||
|
async fetchContracts() {
|
||||||
|
// @ts-ignore
|
||||||
|
this.contracts = (await supabase.from("contracts").select()).data
|
||||||
|
},
|
||||||
async fetchCustomers() {
|
async fetchCustomers() {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
this.customers = (await supabase.from("customers").select().order('customerNumber', {ascending: true})).data
|
this.customers = (await supabase.from("customers").select().order('customerNumber', {ascending: true})).data
|
||||||
@@ -160,6 +166,8 @@ export const useDataStore = defineStore('data', {
|
|||||||
getProductById: (state) => (productId:number) => state.products.find(product => product.id === productId),
|
getProductById: (state) => (productId:number) => state.products.find(product => product.id === productId),
|
||||||
getVendorById: (state) => (itemId:number) => state.vendors.find(item => item.id === itemId),
|
getVendorById: (state) => (itemId:number) => state.vendors.find(item => item.id === itemId),
|
||||||
getVendorInvoiceById: (state) => (itemId:number) => state.vendorInvoices.find(item => item.id === itemId),
|
getVendorInvoiceById: (state) => (itemId:number) => state.vendorInvoices.find(item => item.id === itemId),
|
||||||
|
getContractById: (state) => (itemId:number) => state.contracts.find(item => item.id === itemId),
|
||||||
|
getDocumentById: (state) => (itemId:number) => state.documents.find(item => item.id === itemId),
|
||||||
getSpaceById: (state) => (itemId:number) => state.spaces.find(item => item.id === itemId),
|
getSpaceById: (state) => (itemId:number) => state.spaces.find(item => item.id === itemId),
|
||||||
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)
|
||||||
|
|||||||
Reference in New Issue
Block a user