DiscountModal.vue 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. <template lang="pug">
  2. modal(
  3. name='product-discount'
  4. transition='nice-modal-fade'
  5. :classes="['v--modal', 'product-discount']"
  6. @before-close='beforeClose'
  7. )
  8. form
  9. .discount-item
  10. label.discount-label Precio unitario
  11. input.discount-input(
  12. readonly
  13. :value='(!item || item.price) | currency(...options)'
  14. )
  15. .discount-item
  16. label.discount-label Precio mínimo
  17. input.discount-input(
  18. readonly
  19. :value='(!item || item.minimumPrice) | currency(...options)'
  20. )
  21. .discount-item
  22. label.discount-label Precio máximo
  23. input.discount-input(
  24. readonly
  25. :value='(!item || item.maximumPrice) | currency(...options)'
  26. )
  27. hr
  28. .discount-item
  29. label.discount-label Precio aplicado
  30. input.discount-input(
  31. autofocus
  32. v-model='formattedAmmount'
  33. :class="{'discount-input-invalid': !isValid()}"
  34. )
  35. .discount-item
  36. label.discount-label {{ discount < 0 ? 'Ganancia' : 'Descuento' }}
  37. input.discount-input(
  38. readonly
  39. :value='discount | absolute | currency(...options)'
  40. )
  41. .discount-options
  42. button.discount-button(
  43. :disabled='isValid() === false'
  44. @click.prevent='onAccept'
  45. ) Aceptar
  46. button.discount-button(@click.prevent='onCancel') Cancelar
  47. </template>
  48. <script>
  49. export default {
  50. props: {
  51. item: {
  52. type: Object,
  53. default: {
  54. price: 0,
  55. minimumPrice: 0,
  56. maximumPrice: 0
  57. }
  58. },
  59. options: {
  60. type: Object,
  61. default: {
  62. symbol: '$',
  63. position: 'before',
  64. thousandsSeparator: '.',
  65. decimalPlaces: 2,
  66. decimalSeparator: ','
  67. }
  68. },
  69. show: {
  70. type: Boolean,
  71. default: false
  72. }
  73. },
  74. computed: {
  75. formattedAmmount: {
  76. get() {
  77. let formatted = this.$options.filters.currency(this.ammount, {...this.options})
  78. return this.ammount !== 0 ? formatted : formatted.replace(/\d/, '')
  79. },
  80. set(value) {
  81. value = value.replace(/[\.|,](\d{0,2}$)/, '?$1').split(/\?/)
  82. value[0] = value[0].replace(/[^0-9]/g, '')
  83. value = Number.parseFloat(value.join('.')) || 0
  84. this.ammount = value
  85. this.computeDiscount()
  86. }
  87. }
  88. },
  89. watch: {
  90. show(value) {
  91. if (value) {
  92. this.$modal.show('product-discount')
  93. } else {
  94. this.ammount = 0
  95. this.discount = 0
  96. this.$modal.hide('product-discount')
  97. }
  98. }
  99. },
  100. methods: {
  101. beforeClose(e) {
  102. if (this.show) {
  103. e.stop()
  104. }
  105. },
  106. onAccept(e) {
  107. this.$emit('onAccept', this.ammount)
  108. },
  109. onCancel() {
  110. this.$emit('onCancel')
  111. },
  112. computeDiscount() {
  113. if (this.ammount !== 0) {
  114. this.discount = this.item.price - this.ammount
  115. } else {
  116. this.discount = 0
  117. }
  118. },
  119. isValid() {
  120. if (!this.item) {
  121. return false
  122. }
  123. if (this.ammount === 0) {
  124. return false
  125. }
  126. if (this.item.minimumPrice === 0 && this.item.maximumPrice === 0) {
  127. return true
  128. }
  129. if (this.ammount >= this.item.minimumPrice && this.ammount <= this.item.maximumPrice) {
  130. return true
  131. }
  132. return false
  133. }
  134. },
  135. data() {
  136. return {
  137. discount: 0,
  138. ammount: 0
  139. }
  140. }
  141. }
  142. </script>
  143. <style lang="sass">
  144. @import '../../assets/variables'
  145. .product-discount
  146. width: 600px
  147. height: 340px !important
  148. form
  149. width: 100%
  150. height: 290px
  151. padding: 15px
  152. .discount-item
  153. width: 100%
  154. height: 45px
  155. margin-bottom: 10px
  156. &:nth-child(1)
  157. .discount-input
  158. border: none
  159. &:nth-child(2), &:nth-child(3), &:nth-child(6)
  160. height: 35px
  161. margin-bottom: 5px
  162. .discount-label
  163. width: 30%
  164. height: 35px
  165. font-size: 10pt
  166. color: $app-dark-color
  167. .discount-input
  168. width: 70%
  169. height: 35px
  170. font-size: 18pt
  171. text-align: right
  172. border: none
  173. .discount-label
  174. width: 30%
  175. height: 45px
  176. font-size: 14pt
  177. .discount-input
  178. width: 70%
  179. height: 45px
  180. font-size: 28pt
  181. text-align: right
  182. border-radius: 0
  183. &.discount-input-invalid
  184. border-color: $app-error-color
  185. box-shadow: 1px 1px 2px $app-error-color, -1px -1px 2px $app-error-color
  186. &:focus
  187. outline: none
  188. .discount-options
  189. float: right
  190. .discount-button
  191. width: 160px
  192. height: 40px
  193. border: none
  194. box-shadow: none
  195. border-radius: 0
  196. margin-right: 5px
  197. background: $app-main-color
  198. color: $app-bg-color
  199. </style>