PriceModal.vue 6.1 KB

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