Create.vue 9.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. <script setup>
  2. import { computed, watch, watchEffect } from 'vue'
  3. import { Inertia } from '@inertiajs/inertia'
  4. import { once } from 'lodash'
  5. import { ppn } from '@/utils/helpers'
  6. import { optionStatus } from './config'
  7. import { cartTable } from './config'
  8. import Details from './Components/Details.vue'
  9. import Cart from './Components/Cart.vue'
  10. import { useProductCart } from './Composables/useProductCart'
  11. import { useDialog } from './Composables/useDialog'
  12. import { useForm } from '@/composables/useForm'
  13. import AppInputText from '@/components/AppInputText.vue'
  14. import AppInputNumber from '@/components/AppInputNumber.vue'
  15. import AppDropdown from '@/components/AppDropdown.vue'
  16. import AppAutoComplete from '@/components/AppAutoComplete.vue'
  17. import DashboardLayout from '@/layouts/Dashboard/DashboardLayout.vue'
  18. const props = defineProps({
  19. number: String,
  20. ppn: Number,
  21. suppliers: {
  22. type: Array,
  23. default: [],
  24. },
  25. products: {
  26. type: Array,
  27. default: [],
  28. },
  29. productPurchase: Object,
  30. })
  31. const form = useForm({
  32. status: 'pending',
  33. price: null,
  34. qty: null,
  35. supplier: null,
  36. product: null,
  37. ppn: props.ppn,
  38. checkedPpn: false,
  39. })
  40. const onSubmit = () => {
  41. form
  42. .transform((data) => ({
  43. number: props.number,
  44. status: data.status,
  45. ppn: data.checkedPpn,
  46. supplier_id: data.supplier.id,
  47. products: productCart,
  48. }))
  49. .post(route('purchases.store'), {
  50. onSuccess: () => {
  51. form.reset()
  52. onClearProductCart()
  53. },
  54. })
  55. }
  56. watchEffect(() => {
  57. if (props.productPurchase?.number) {
  58. form.price = props.productPurchase.price
  59. form.qty = props.productPurchase.qty
  60. } else {
  61. form.price = null
  62. }
  63. })
  64. watch(
  65. () => form.product,
  66. () => {
  67. if (form.product?.number) {
  68. Inertia.reload({
  69. data: {
  70. productNumber: form.product.number,
  71. supplierId: form.supplier.id,
  72. },
  73. only: ['productPurchase'],
  74. })
  75. }
  76. }
  77. )
  78. const productUnit = computed(() => form.product?.unit)
  79. const productPurchasePrice = computed(() => props.productPurchase?.price)
  80. const productPurchasePpn = computed(() => props.productPurchase?.ppn)
  81. const productPurchaseQty = computed(() => props.productPurchase?.qty)
  82. const dropdownStatus = computed(() => {
  83. return optionStatus.filter((val) => val.value != 'success')
  84. })
  85. const {
  86. productCart,
  87. productErrors,
  88. onClearProductCart,
  89. onAddProduct,
  90. onDeleteProduct,
  91. totalProductPrice,
  92. } = useProductCart(form)
  93. const { onShowCreateProduct, onShowCreateSupplier } = useDialog()
  94. </script>
  95. <template>
  96. <DashboardLayout title="Tambah Pembelian">
  97. <DynamicDialog />
  98. <div class="grid">
  99. <div class="col-12 md:col-8">
  100. <div class="grid">
  101. <div class="col-12">
  102. <Card>
  103. <template #title> Transaksi </template>
  104. <template #content>
  105. <div class="grid">
  106. <div class="col-12 md:col-6">
  107. <AppDropdown
  108. label="Status"
  109. placeholder="status"
  110. :options="dropdownStatus"
  111. :error="form.errors.status"
  112. v-model="form.status"
  113. />
  114. </div>
  115. <div class="col-12 md:col-6">
  116. <AppAutoComplete
  117. empty
  118. label="Supplier"
  119. placeholder="supplier"
  120. field="name"
  121. refresh-data="suppliers"
  122. v-model="form.supplier"
  123. :error="form.errors.suppliers_id"
  124. :suggestions="suppliers"
  125. >
  126. <template #item="slotProps">
  127. <template v-if="slotProps.item">
  128. <div class="flex flex-column">
  129. <span>{{ slotProps.item.name }}</span>
  130. <span>{{ slotProps.item.phone }}</span>
  131. </div>
  132. </template>
  133. </template>
  134. <template #empty>
  135. <span
  136. class="cursor-pointer"
  137. style="color: var(--primary-color)"
  138. @click="onShowCreateSupplier"
  139. >
  140. Tambah Supplier
  141. </span>
  142. </template>
  143. </AppAutoComplete>
  144. </div>
  145. </div>
  146. </template>
  147. </Card>
  148. </div>
  149. <div class="col-12">
  150. <Card>
  151. <template #title>Produk</template>
  152. <template #content>
  153. <div class="grid">
  154. <div class="col-12 md:col-6">
  155. <AppAutoComplete
  156. :disabled="!form.supplier?.id"
  157. empty
  158. label="Produk"
  159. placeholder="produk"
  160. field="name"
  161. refresh-data="products"
  162. v-model="form.product"
  163. :error="form.errors.product"
  164. :suggestions="products"
  165. >
  166. <template #item="slotProps">
  167. <template v-if="slotProps.item">
  168. <div class="flex flex-column">
  169. <span>{{ slotProps.item.number }}</span>
  170. <span>{{ slotProps.item.name }}</span>
  171. </div>
  172. </template>
  173. </template>
  174. <template #empty>
  175. <span
  176. class="cursor-pointer"
  177. style="color: var(--primary-color)"
  178. @click="onShowCreateProduct"
  179. >
  180. Tambah Produk
  181. </span>
  182. </template>
  183. </AppAutoComplete>
  184. </div>
  185. <div class="col-12 md:col-6">
  186. <AppInputText
  187. disabled
  188. label="Satuan"
  189. placeholder="satuan"
  190. v-model="productUnit"
  191. />
  192. </div>
  193. <Divider type="dashed" />
  194. <div class="col-12">
  195. <h3 class="text-lg">Riwayat Produk Sebelumnya</h3>
  196. </div>
  197. <div class="col-12 md:col-6">
  198. <AppInputNumber
  199. disabled
  200. class="mb-0"
  201. label="Harga "
  202. placeholder="harga"
  203. v-model="productPurchasePrice"
  204. />
  205. <span v-if="productPurchasePpn" class="text-xs">
  206. Harga sudah termasuk PPN {{ ppn }} %
  207. </span>
  208. </div>
  209. <div class="col-12 md:col-6">
  210. <AppInputText
  211. disabled
  212. label="Kuantitas"
  213. placeholder="kuantitas"
  214. type="number"
  215. v-model="productPurchaseQty"
  216. />
  217. </div>
  218. <Divider type="dashed" />
  219. <div class="col-12 md:col-6">
  220. <AppInputNumber
  221. :disabled="!form.product?.id"
  222. label="Harga Terbaru"
  223. placeholder="harga terbaru"
  224. v-model="form.price"
  225. />
  226. </div>
  227. <div class="col-12 md:col-6">
  228. <AppInputText
  229. :disabled="!form.product?.id"
  230. label="Kuantitas"
  231. placeholder="kuantitas"
  232. type="number"
  233. v-model="form.qty"
  234. />
  235. </div>
  236. </div>
  237. </template>
  238. <template #footer>
  239. <div class="flex flex-column md:flex-row justify-content-end">
  240. <Button
  241. label="Tambah Produk"
  242. icon="pi pi-check"
  243. class="p-button-outlined"
  244. :class="{ 'p-button-danger': productErrors.length }"
  245. :disabled="
  246. !form.price ||
  247. !Number(form.qty) ||
  248. !form.product?.number ||
  249. productErrors.length
  250. "
  251. @click="onAddProduct"
  252. />
  253. </div>
  254. </template>
  255. </Card>
  256. </div>
  257. <div class="col-12">
  258. <Cart
  259. title="Keranjang Produk"
  260. :product-cart="productCart"
  261. :header-table="cartTable"
  262. :btn-edit-show="false"
  263. v-model:checked-ppn="form.checkedPpn"
  264. @delete="onDeleteProduct"
  265. />
  266. </div>
  267. </div>
  268. </div>
  269. <div class="col-12 md:col-4">
  270. <Details
  271. title="Detail Pembelian"
  272. message="Pastikan semua produk sudah benar"
  273. :number="number"
  274. :status="form.status"
  275. :person="form.supplier"
  276. :product="form.product"
  277. :price="totalProductPrice()"
  278. :disabled="
  279. form.processing ||
  280. !form.status ||
  281. !form.supplier?.id ||
  282. productCart.length === 0
  283. "
  284. @submit="onSubmit"
  285. />
  286. </div>
  287. </div>
  288. </DashboardLayout>
  289. </template>