This commit is contained in:
2025-09-25 03:03:31 +05:00
commit ae480cf2f6
2768 changed files with 1485826 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
.grid {
display: grid;
}
.grid-col-3 {
grid-template-columns: 1fr 1fr 1fr;
}
.grid-col-gap-sm {
grid-column-gap: 6px;
}

View File

@@ -0,0 +1,9 @@
<template>
<PanelItem :index="index" :field="field" />
</template>
<script>
export default {
props: ['index', 'resource', 'resourceName', 'resourceId', 'field'],
}
</script>

View File

@@ -0,0 +1,231 @@
<template>
<DefaultField
:field="field"
:errors="errors"
:show-help-text="showHelpText"
:full-width-content="fullWidthContent"
>
<template #field>
<SearchInput
v-if="!currentlyIsReadonly"
:data-testid="`${field.attribute}-search-input`"
:error="hasError"
:value="selectedOption"
:data="options"
@input="performSearch"
@clear="clearSelection"
@selected="selectOption"
:clearable="field.nullable"
trackBy="value"
class="w-full"
>
<!-- The Selected Option Slot -->
<div v-if="selectedOption" class="flex items-center">
{{ selectedOption.label }}
</div>
<template #option="{ selected, option }">
<!-- Options List Slot -->
<div
class="flex items-center text-sm font-semibold leading-5"
:class="{ 'text-white': selected }"
>
{{ option.label }}
</div>
</template>
</SearchInput>
<div class="w-full grid grid-col-3 grid-col-gap-sm">
<div>
<label for="">Sany: </label>
<input
type="number"
v-model="form.quantity"
placeholder="Sany"
class="w-full form-control form-input form-input-bordered"
>
</div>
<div>
<label for="">Bahasy: </label>
<input
type="text"
v-model="form.price"
placeholder="Bahasy"
class="w-full form-control form-input form-input-bordered"
disabled
>
</div>
<div>
<label for="">Jemi: </label>
<input
type="text"
v-model="form.total"
placeholder="Jemi"
class="w-full form-control form-input form-input-bordered"
dusk="product-item-total"
disabled
>
</div>
</div>
</template>
</DefaultField>
</template>
<script>
import { DependentFormField, HandlesValidationErrors } from 'laravel-nova'
export default {
mixins: [DependentFormField, HandlesValidationErrors],
props: ['resourceName', 'resourceId', 'field'],
data: () => ({
options: [],
search: '',
selectedOption: null,
form: {
product_id: null,
quantity: 0,
price: 0,
total: 0,
}
}),
mounted() {
},
watch: {
'form.quantity'() {
this.updateProductTotal()
},
selectedOption() {
if (! this.selectedOption || ! this.selectedOption.value) {
return;
}
this.form.product_id = this.selectedOption.value.id;
this.form.price = this.selectedOption.value.cost_amount;
this.updateProductTotal()
}
},
methods: {
/*
* Set the initial, internal value for the field.
*/
setInitialValue() {
this.value = this.field.value || ''
},
/**
* Fill the given FormData object with the field's internal value.
*/
fill(formData) {
formData.append('product_id', this.form.product_id)
formData.append('quantity', this.form.quantity)
formData.append('total', this.form.total)
formData.append('cost_amount', this.form.price)
},
/**
* Set the search string to be used to filter the select field.
*/
performSearch(event) {
this.search = event
this.searchProducts()
},
/**
* Clear the current selection for the field.
*/
clearSelection() {
this.selectedOption = null
this.search = ''
this.$refs.searchable.close()
},
/**
* Select the given option.
*/
selectOption(option) {
this.selectedOption = option
this.value = option.value.id
},
handleChange() {
this.$store.commit(`${this.resourceName}/updateFilterState`, {
filterClass: this.filterKey,
value: this.value,
})
this.$emit('change')
},
serializeOptions(options) {
return options.map(item => {
return {
label: item.name,
value: item
}
})
},
updateProductTotal() {
if (this.form.price && this.form.quantity) {
this.form.total = this.form.price * this.form.quantity;
}
setTimeout(() => {
this.updateOveralProductTotal()
}, 200);
},
updateOveralProductTotal() {
let totalElement = document.querySelector('[dusk="readonly_total"]');
if (! totalElement) {
return;
}
let total = 0;
document.querySelectorAll('[dusk="product-item-total"]').forEach(item => {
total += Number(item.value)
})
totalElement.value = total
},
searchProducts() {
if (! this.search && this.search.length < 1) {
return;
}
Nova.$progress.start()
Nova.request().get(`${window.location.origin}/api/v1/search-product?internal=1&q=${encodeURIComponent(this.search)}`, {
headers: {
Accept: 'application/json',
'Api-Token': 'hello-bad-mf-s',
},
}).then(response => {
if (response.status !== 200) {
this.clearSelection();
return;
}
this.options = this.serializeOptions(response.data.data);
})
Nova.$progress.done()
}
},
computed: {},
}
</script>

View File

@@ -0,0 +1,7 @@
import DetailField from './components/DetailField'
import FormField from './components/FormField'
Nova.booting((app, store) => {
app.component('detail-inventory-history-items', DetailField)
app.component('form-inventory-history-items', FormField)
})