diff options
Diffstat (limited to 'src/components/item_selector.vue')
-rw-r--r-- | src/components/item_selector.vue | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/src/components/item_selector.vue b/src/components/item_selector.vue new file mode 100644 index 0000000..5dc9b84 --- /dev/null +++ b/src/components/item_selector.vue @@ -0,0 +1,176 @@ +<script setup lang="ts"> +import { ref, toRaw, onMounted } from 'vue' +import axios from 'axios' +import { useToast } from 'vue-toast-notification' +import InvoiceItem from "./../classes/invoice_item" + +const props = defineProps(["invoiceId"]) +const emit = defineEmits(["added"]) + +const toast = useToast({ + position: 'top-right' +}) + +const gettingData = ref(true) // for when getting all item(s) +const submitting = ref(false) // shows spinner on add button +const allItems = ref([]) + +const item = ref(new InvoiceItem()) +const itemSelection = ref(null) + +const getAllItems = async () => { + allItems.value = [] + gettingData.value = true + + try { + const r = await axios.get('/item') + if (r.status === 200) { + allItems.value = r.data.data + } else if (r.status === 204) { + toast.warning('No items found') + } + } catch (err) { + toast.error('An unhandled exception occoured. Please check logs') + console.error(err) + } + + gettingData.value = false +} + +const submit = async (e: Event) => { + e.preventDefault() + submitting.value = true + + try { + await axios.post(`/invoice/${props.invoiceId}/item`, toRaw(item.value)) + itemSelection.value = null + item.value = new InvoiceItem() + emit("added") + } catch (err: any) { + const statusCode: any = err.request.status + const res: any = JSON.parse(err.request.response) + + switch (statusCode) { + case 400: + toast.error(res.error) + break + case 409: + toast.error(res.error) + break + default: + console.error(err) + toast.error('An unhandled exception occoured. Please check logs') + } + } + + submitting.value = false +} + +// when item is selected, +// set item to the newly selected item +const itemSelected = async () => { + const is: any = toRaw(itemSelection.value) + const i = new InvoiceItem() + i.Name = is.Name + i.Description = is.Description + i.HSN = is.HSN + i.UnitPrice = is.UnitPrice + i.GSTPercentage = is.GSTPercentage + i.UnitOfMeasure = is.UnitOfMeasure + i.BrandName = is.Brand.Name + i.Quantity = "1" + + item.value = i +} + +onMounted(() => { + getAllItems() +}) +</script> + +<template> + <form class="row g-3" v-on:submit="submit"> + <div class="col-md-1"><!-- spacer --></div> + + <div class="col-md-3"> + <label for="item-brand-input" class="form-label">Item</label> + <select + v-model="itemSelection" + @change="itemSelected()" + class="form-select" + aria-label="Select Item" + id="item-input" + > + <option selected disabled value="null">Select Item</option> + <option v-for="item in allItems" :value="item" :key="item['id']"> + {{ item["Name"] }} ({{ item["Brand"]["Name"] }}) + </option> + </select> + </div> + + <div class="col-md-3"> + <label for="inputDescription" class="form-label">Description</label> + <input + type="text" + class="form-control" + id="inputDescription" + v-model="item.Description" + /> + </div> + + <div class="col-md-1"> + <label for="inputHSN" class="form-label">HSN</label> + <input + type="text" + class="form-control" + id="inputHSN" + v-model="item.HSN" + /> + </div> + + <div class="col-md-1"> + <label for="inputQty" class="form-label">Quantity {{ item.UnitOfMeasure === "" ? "" : `(${item.UnitOfMeasure})` }}</label> + <input + type="text" + class="form-control" + id="inputQty" + v-model="item.Quantity" + /> + </div> + + <div class="col-md-1"> + <label for="inputUnitPrice" class="form-label">Unit Price</label> + <input + type="text" + class="form-control" + id="inputUnitPrice" + v-model="item.UnitPrice" + /> + </div> + + <div class="col-md-1"> + <label for="inputGST" class="form-label">GST (%)</label> + <input + type="text" + class="form-control" + id="inputGST" + v-model="item.GSTPercentage" + /> + </div> + + <div class="col-md-10"><!-- spacer --></div> + + <div class="col-md-1 d-flex align-items-end justify-content-end"> + <button + type="submit" + class="btn btn-primary btn-block" + :class="{ disabled: submitting || gettingData || itemSelection === null }" + > + Add + <div v-if="submitting" class="spinner-border spinner-border-sm ms-1" role="status"> + <span class="sr-only"></span> + </div> + </button> + </div> + </form> +</template> |