Create.vue 5.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. <script setup>
  2. import { computed, watch, ref } from 'vue'
  3. import { Inertia } from '@inertiajs/inertia'
  4. import { Head, useForm, usePage } from '@inertiajs/inertia-vue3'
  5. import AppLayout from '@/layouts/AppLayout.vue'
  6. import AppAutocompleteBasic from '@/components/AppAutocompleteBasic.vue'
  7. import AppInputNumber from '@/components/AppInputNumber.vue'
  8. import AppDropdown from '@/components/AppDropdown.vue'
  9. import AppInputText from '@/components/AppInputText.vue'
  10. defineProps({
  11. members: {
  12. type: Array,
  13. default: [],
  14. },
  15. typeMembers: Array,
  16. })
  17. const errors = computed(() => usePage().props.value.errors)
  18. watch(errors, () => {
  19. form.clearErrors()
  20. })
  21. const memberDialogShow = ref(false)
  22. const memberDialogOnHide = () => {
  23. formMember.reset()
  24. formMember.clearErrors()
  25. usePage().props.value.errors = {}
  26. usePage().props.value.flash.error = null
  27. }
  28. const memberOnComplete = (event) => {
  29. Inertia.reload({
  30. data: { search: event.query },
  31. only: ['members'],
  32. })
  33. }
  34. const memberOnSelected = (event) => {
  35. form.member = event.value
  36. }
  37. const formMember = useForm({
  38. name: null,
  39. phone: null,
  40. plat_number: null,
  41. type_member_id: null,
  42. })
  43. const submitMember = () => {
  44. formMember.post(route('members.store'), {
  45. onSuccess: () => {
  46. formMember.reset()
  47. memberDialogShow.value = !memberDialogShow.value
  48. },
  49. })
  50. }
  51. const form = useForm({
  52. balance: null,
  53. member: null,
  54. })
  55. const submit = () => {
  56. form
  57. .transform((data) => ({
  58. balance: data.balance,
  59. member_id: data.member.id,
  60. }))
  61. .post(route('top-ups.store'), { onSuccess: () => form.reset() })
  62. }
  63. </script>
  64. <template>
  65. <Head title="Top Up" />
  66. <AppLayout>
  67. <div class="grid">
  68. <div class="col-12 md:col-8">
  69. <Card>
  70. <template #title> Top Up </template>
  71. <template #content>
  72. <div class="grid">
  73. <div class="col-12 md:col-6">
  74. <AppInputNumber v-model="form.balance" label="Saldo" placeholder="saldo" :error="form.errors.balance" />
  75. </div>
  76. <div class="col-12 md:col-6">
  77. <AppAutocompleteBasic
  78. empty
  79. label="Member"
  80. field="platNumber"
  81. placeholder="member"
  82. v-model="form.member"
  83. :error="form.errors.member_id"
  84. :suggestions="members"
  85. @complete="memberOnComplete"
  86. @item-select="memberOnSelected"
  87. >
  88. <template #item="slotProps">
  89. <template v-if="slotProps.item">
  90. <div class="flex flex-column">
  91. <span>{{ slotProps.item.name }}</span>
  92. <span class="font-bold">{{ slotProps.item.phone }}</span>
  93. <span class="font-bold">{{ slotProps.item.platNumber }}</span>
  94. </div>
  95. </template>
  96. </template>
  97. <template #empty>
  98. <span
  99. class="cursor-pointer"
  100. style="color: var(--primary-color)"
  101. @click="memberDialogShow = !memberDialogShow"
  102. >
  103. Tambah Member
  104. </span>
  105. </template>
  106. </AppAutocompleteBasic>
  107. </div>
  108. </div>
  109. </template>
  110. <template #footer>
  111. <div class="flex flex-column md:flex-row justify-content-end">
  112. <Button
  113. label="Simpan"
  114. icon="pi pi-check"
  115. class="p-button-outlined"
  116. :disabled="form.processing"
  117. @click="submit"
  118. />
  119. </div>
  120. </template>
  121. </Card>
  122. </div>
  123. </div>
  124. <Dialog
  125. modal
  126. v-model:visible="memberDialogShow"
  127. class="p-fluid"
  128. header="Tambah Member"
  129. :style="{ width: '450px' }"
  130. :breakpoints="{ '960px': '75vw' }"
  131. @hide="memberDialogOnHide"
  132. >
  133. <div class="grid">
  134. <div class="col-12 md:col-6">
  135. <AppInputText v-model="formMember.name" label="Nama" placeholder="nama" :error="formMember.errors.name" />
  136. </div>
  137. <div class="col-12 md:col-6">
  138. <AppInputText
  139. v-model="formMember.phone"
  140. label="Nomor HP"
  141. placeholder="nomor hp"
  142. :error="formMember.errors.phone"
  143. />
  144. </div>
  145. <div class="col-12 md:col-6">
  146. <AppInputText
  147. v-model="formMember.plat_number"
  148. label="Plat Kendaraan"
  149. placeholder="plat kendaraan"
  150. :error="formMember.errors.plat_number"
  151. />
  152. </div>
  153. <div class="col-12 md:col-6">
  154. <AppDropdown
  155. label="Jenis member"
  156. placeholder="pilih satu"
  157. v-model="formMember.type_member_id"
  158. :options="typeMembers"
  159. :error="formMember.errors.type_member_id"
  160. />
  161. </div>
  162. </div>
  163. <template #footer>
  164. <div class="flex flex-column md:flex-row justify-content-end">
  165. <Button
  166. label="Simpan"
  167. icon="pi pi-check"
  168. class="p-button-outlined"
  169. :disabled="formMember.processing"
  170. @click="submitMember"
  171. />
  172. </div>
  173. </template>
  174. </Dialog>
  175. </AppLayout>
  176. </template>