Index.vue 8.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. <script setup>
  2. import { ref, watch, computed, onMounted } from 'vue'
  3. import { Inertia } from '@inertiajs/inertia'
  4. import { Head, useForm, usePage } from '@inertiajs/inertia-vue3'
  5. import dayjs from 'dayjs'
  6. import throttle from 'lodash/throttle'
  7. import pickBy from 'lodash/pickBy'
  8. import AppButton from '@/components/AppButton.vue'
  9. import AppPagination from '@/components/AppPagination.vue'
  10. import AppMenu from '@/components/AppMenu.vue'
  11. import AppDropdown from '@/components/AppDropdown.vue'
  12. import AppLayout from '@/layouts/AppLayout.vue'
  13. import { IndexTable } from './TableHeader'
  14. const props = defineProps({
  15. transactions: Object,
  16. transactionsStatus: Array,
  17. filters: Object,
  18. outlets: Array,
  19. })
  20. const filterForm = useForm({
  21. search: props.filters.search,
  22. dates: null,
  23. startDate: props.filters.startDate,
  24. endDate: props.filters.endDate,
  25. outlet: props.filters.outlet,
  26. })
  27. onMounted(() => {
  28. if (props.filters.startDate || props.filters.endDate) {
  29. if (props.filters.endDate) {
  30. filterForm.dates = [new Date(props.filters.startDate), new Date(props.filters.endDate)]
  31. } else {
  32. filterForm.dates = [new Date(props.filters.startDate), null]
  33. }
  34. }
  35. })
  36. watch(filterForm, () => {
  37. if (filterForm.dates) {
  38. if (filterForm.dates[1]) {
  39. filterForm.startDate = dayjs(filterForm.dates[0]).format('YYYY-MM-DD')
  40. filterForm.endDate = dayjs(filterForm.dates[1]).format('YYYY-MM-DD')
  41. } else {
  42. filterForm.startDate = dayjs(filterForm.dates[0]).format('YYYY-MM-DD')
  43. filterForm.endDate = null
  44. }
  45. } else {
  46. filterForm.endDate = null
  47. filterForm.startDate = null
  48. }
  49. Inertia.get(
  50. '/transactions',
  51. pickBy({
  52. search: filterForm.search,
  53. startDate: filterForm.startDate,
  54. endDate: filterForm.endDate,
  55. outlet: filterForm.outlet,
  56. }),
  57. {
  58. preserveState: true,
  59. }
  60. )
  61. })
  62. const filterReset = () => {
  63. Inertia.get('/transactions')
  64. }
  65. const transactionId = ref()
  66. const updateStatusDialogShow = ref(false)
  67. const updateStatusForm = useForm({
  68. transaction_status_id: null,
  69. })
  70. const updateStatusSubmit = () => {
  71. updateStatusForm.put(route('transactions.update', transactionId.value), {
  72. onSuccess: () => {
  73. updateStatusDialogShow.value = false
  74. },
  75. })
  76. }
  77. const updateStatusItems = ref([])
  78. const overlayMenu = ref()
  79. const overlayItems = ref([])
  80. const startPrinting = (transactionNumber) => {
  81. Inertia.get(`/thermal-printing/${transactionNumber}`)
  82. }
  83. const overlayToggle = (event, data) => {
  84. overlayItems.value =
  85. data.transactionStatusId == 4
  86. ? [
  87. {
  88. label: 'Lihat detail',
  89. icon: 'pi pi-eye',
  90. to: route('transactions.show', data.id),
  91. },
  92. {
  93. label: 'Cetak ulang',
  94. icon: 'pi pi-print',
  95. command() {
  96. startPrinting(data.transactionNumber)
  97. },
  98. },
  99. ]
  100. : [
  101. {
  102. label: 'Perbaharui status',
  103. icon: 'pi pi-refresh',
  104. command() {
  105. updateStatusDialogShow.value = true
  106. },
  107. },
  108. {
  109. label: 'Lihat detail',
  110. icon: 'pi pi-eye',
  111. to: route('transactions.show', data.id),
  112. },
  113. {
  114. label: 'Cetak ulang',
  115. icon: 'pi pi-print',
  116. command() {
  117. startPrinting(data.transactionNumber)
  118. },
  119. },
  120. ]
  121. updateStatusItems.value = props.transactionsStatus.filter((val) => val.value >= data.transactionStatusId)
  122. updateStatusForm.transaction_status_id = data.transactionStatusId
  123. transactionId.value = data.id
  124. overlayMenu.value.toggle(event)
  125. }
  126. </script>
  127. <template>
  128. <Head title="Daftar Transaksi" />
  129. <AppLayout>
  130. <DataTable
  131. responsive-layout="scroll"
  132. column-resize-mode="expand"
  133. :value="transactions.data"
  134. :row-hover="true"
  135. :striped-rows="true"
  136. >
  137. <template #header>
  138. <h1>Transaksi</h1>
  139. <div class="grid">
  140. <div class="col-12 md:col-8">
  141. <div class="grid">
  142. <div class="col-12 md:col-3">
  143. <InputText class="w-full" placeholder="cari..." v-model="filterForm.search" />
  144. </div>
  145. <div class="col-12 md:col-3">
  146. <Calendar
  147. class="w-full"
  148. v-model="filterForm.dates"
  149. selection-mode="range"
  150. placeholder="filter waktu..."
  151. date-format="dd/mm/yy"
  152. :manual-input="false"
  153. />
  154. </div>
  155. <div v-if="$page.props.auth.user.role_id === 1" class="col-12 md:col-3">
  156. <Dropdown
  157. class="w-full"
  158. placeholder="pilih outlet..."
  159. v-model="filterForm.outlet"
  160. option-label="label"
  161. option-value="value"
  162. :options="outlets"
  163. />
  164. </div>
  165. <div class="col-auto mt-2 ml-2">
  166. <Button label="reset" class="p-button-link" @click="filterReset" />
  167. </div>
  168. </div>
  169. </div>
  170. <div
  171. v-if="$page.props.auth.user.role_id !== 1"
  172. class="col-12 md:col-4 flex flex-column md:flex-row justify-content-end"
  173. >
  174. <AppButton
  175. label="Tambah Transaksi"
  176. class="p-button-outlined md:w-16rem"
  177. icon="pi pi-pencil"
  178. :href="route('transactions.create')"
  179. />
  180. </div>
  181. </div>
  182. </template>
  183. <Column
  184. v-for="indexTable in IndexTable"
  185. :field="indexTable.field"
  186. :header="indexTable.header"
  187. :key="indexTable.field"
  188. >
  189. <template #body="{ data, field }">
  190. <template v-if="field === 'transactionNumber'">
  191. <p class="font-bold">{{ data[field] }}</p>
  192. <p>{{ data.createdAt }}</p>
  193. </template>
  194. <template v-else-if="field === 'customer'">
  195. <p class="font-bold">{{ data.customer.number }}</p>
  196. <p>{{ data.customer.name }}</p>
  197. <p>{{ data.customer.phone }}</p>
  198. </template>
  199. <template v-else-if="field === 'transactionStatusName'">
  200. <Badge v-if="data['transactionStatusId'] === 1" :value="data[field]"></Badge>
  201. <Badge v-else-if="data['transactionStatusId'] === 2" :value="data[field]" severity="warning"></Badge>
  202. <Badge v-else :value="data[field]" severity="success"></Badge>
  203. </template>
  204. <template v-else>
  205. {{ data[field] }}
  206. </template>
  207. </template>
  208. </Column>
  209. <Column>
  210. <template #body="slotProps">
  211. <Button
  212. icon="pi pi-angle-double-down"
  213. class="p-button-rounded p-button-text"
  214. aria-controls="overlay_menu"
  215. @click="overlayToggle($event, slotProps.data)"
  216. />
  217. <AppMenu id="overlay_menu" ref="overlayMenu" :popup="true" :model="overlayItems" />
  218. </template>
  219. </Column>
  220. </DataTable>
  221. <AppPagination :links="transactions.links" />
  222. <Dialog
  223. modal
  224. v-model:visible="updateStatusDialogShow"
  225. class="p-fluid"
  226. header="Perbaharui Status"
  227. :style="{ width: '450px' }"
  228. :breakpoints="{ '960px': '75vw' }"
  229. @hide="updateStatusDialogShow"
  230. >
  231. <div class="grid">
  232. <div class="col-12">
  233. <AppDropdown
  234. label="Perbaharui Status"
  235. placeholder="pilih satu"
  236. v-model="updateStatusForm.transaction_status_id"
  237. :error="updateStatusForm.error"
  238. :options="updateStatusItems"
  239. />
  240. </div>
  241. </div>
  242. <template #footer>
  243. <div class="flex justify-content-end">
  244. <Button
  245. label="Simpan"
  246. icon="pi pi-check"
  247. class="p-button-text"
  248. :disabled="updateStatusForm.processing"
  249. @click="updateStatusSubmit"
  250. />
  251. </div>
  252. </template>
  253. </Dialog>
  254. </AppLayout>
  255. </template>