CartItem.vue 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. <template lang="pug">
  2. li.cart-item(:class="{'cart-item-invalid': !isValid()}")
  3. h3.item-name {{ item.displayName }}
  4. input.item-quantity(type='number' v-model.number='quantity' @focus='onFocus' @blur='onBlur')
  5. span.item-x x
  6. span.item-price {{ item.price | currency(...options) }}
  7. span.item-equals =
  8. span.item-subtotal {{ (item.price * (item.quantity || 1)) | currency(...options) }}
  9. .cart-item-options-wrapper
  10. .cart-item-options
  11. .cart-item-option(class='fa fa-plus' @click='onClickIncrement')
  12. .cart-item-option(class='fa fa-minus' @click='onClickDecrement')
  13. .cart-item-option(class='fa fa-money' @click='onClickMoney')
  14. .cart-item-option(class='fa fa-undo' @click='onClickUndo')
  15. .cart-item-option(class='fa fa-trash' @click='onClickDelete')
  16. </template>
  17. <script>
  18. export default {
  19. props: {
  20. index: {
  21. type: Number,
  22. default: -1,
  23. required: true
  24. },
  25. item: {
  26. type: Object,
  27. default: null
  28. },
  29. options: {
  30. type: Object,
  31. default: {
  32. symbol: '$',
  33. position: 'before',
  34. thousandsSeparator: '.',
  35. decimalPlaces: 2,
  36. decimalSeparator: ','
  37. }
  38. }
  39. },
  40. computed: {
  41. quantity: {
  42. get() {
  43. return this.item.quantity
  44. },
  45. set(value) {
  46. this.input = !value ? 1 : value
  47. if (this.editing) {
  48. this.handleEditing(value)
  49. return
  50. }
  51. this.computeQuantity()
  52. }
  53. }
  54. },
  55. watch: {
  56. item: {
  57. handler(value) {
  58. this.onChange(value)
  59. },
  60. deep: true,
  61. immediate: true
  62. }
  63. },
  64. methods: {
  65. handleEditing(value) {
  66. if (value === '') {
  67. clearTimeout(this.inputDaemon)
  68. return
  69. }
  70. if (this.inputDaemon !== null) {
  71. clearTimeout(this.inputDaemon)
  72. }
  73. this.inputDaemon = setTimeout(() => {
  74. this.computeQuantity()
  75. }, 300)
  76. },
  77. computeQuantity() {
  78. if (this.input > this.item.quantity) {
  79. this.onClickIncrement()
  80. } else {
  81. this.onClickDecrement()
  82. }
  83. },
  84. onFocus() {
  85. this.editing = true
  86. this.input = 0
  87. },
  88. onBlur() {
  89. this.editing = false
  90. this.input = 0
  91. },
  92. onInputChange(e) {
  93. console.log(e)
  94. },
  95. onChange(item) {
  96. this.$emit('onChange', item)
  97. },
  98. onClickIncrement() {
  99. this.$emit('onClickIncrement', {
  100. id: this.item.id,
  101. quantity: this.editing ? this.input : 1
  102. })
  103. },
  104. onClickDecrement() {
  105. this.$emit('onClickDecrement', {
  106. id: this.item.id,
  107. quantity: this.editing ? this.input : -1
  108. })
  109. },
  110. onClickMoney() {
  111. this.$emit('onClickMoney', this.item)
  112. },
  113. onClickUndo() {
  114. this.$emit('onClickUndo', this.item)
  115. },
  116. onClickDelete() {
  117. this.$emit('onClickDelete', {
  118. id: this.item.id
  119. })
  120. },
  121. isValid() {
  122. return this.item.price > 0
  123. }
  124. },
  125. data() {
  126. return {
  127. editing: false,
  128. input: 0,
  129. inputDaemon: null
  130. }
  131. }
  132. }
  133. </script>
  134. <style lang="sass">
  135. @import '../../assets/variables'
  136. .cart-item
  137. width: 100%
  138. height: 90px
  139. list-style: none outside none
  140. border-bottom: 1px solid $app-border-color
  141. box-sizing: border-box
  142. position: relative
  143. &.cart-item-invalid
  144. border-bottom: 2px solid $app-error-color
  145. &:nth-child(1)
  146. border-top: 1px solid $app-border-color
  147. &:hover
  148. transition-duration: 1000ms
  149. border-bottom: 2px solid $app-main-color
  150. .item-name
  151. width: 100%
  152. height: 20px
  153. margin: 10px 0 5px 0
  154. float: left
  155. font-size: 8pt
  156. display: inline-block
  157. .item-quantity
  158. width: 60px
  159. height: 28px
  160. margin-top: 6px
  161. text-align: right
  162. float: left
  163. display: inline-block
  164. user-select: none
  165. cursor: pointer
  166. border-radius: 0
  167. .item-x
  168. width: 20px
  169. height: 20px
  170. margin-top: 12px
  171. text-align: right
  172. float: left
  173. display: inline-block
  174. .item-price
  175. width: 80px
  176. height: 20px
  177. margin-top: 12px
  178. text-align: right
  179. float: left
  180. display: inline-block
  181. .item-equals
  182. width: 20px
  183. height: 20px
  184. margin-top: 12px
  185. text-align: center
  186. float: left
  187. display: inline-block
  188. .item-subtotal
  189. width: 100px
  190. height: 20px
  191. margin-top: 12px
  192. text-align: right
  193. font-weight: bold
  194. display: inline-block
  195. .cart-item-options-wrapper
  196. width: 100%
  197. height: 20px
  198. position: absolute
  199. bottom: 0
  200. display: flex
  201. justify-content: center
  202. .cart-item-options
  203. width: 120px
  204. height: 20px
  205. border: 1px solid #d3d3d3
  206. border-bottom: none
  207. display: flex
  208. justify-content: center
  209. .cart-item-option
  210. width: 18px
  211. height: 18px
  212. margin: 0 5px
  213. color: #666
  214. &:hover
  215. cursor: pointer
  216. &.fa
  217. padding-left: 2px
  218. line-height: 20px
  219. &.fa-plus:hover
  220. color: #2196f3
  221. &.fa-minus:hover
  222. color: #ffc107
  223. &.fa-money:hover
  224. color: #4caf50
  225. &.fa-undo:hover
  226. color: #3f51b5
  227. &.fa-trash:hover
  228. color: #f44336
  229. </style>