HeartButton.vue 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. <template>
  2. <label class='heart_button' :class='{"heart_button--unlikeable": !likeable}'>
  3. <input
  4. type='checkbox'
  5. :disabled='!likeable'
  6. :checked='liked'
  7. v-on:change="change"
  8. >
  9. <span class='fa'></span>
  10. <span class='heart_button__count'>{{likes}}</span>
  11. </label>
  12. </template>
  13. <script>
  14. import AjaxErrorHandler from '../assets/js/errorHandler'
  15. export default {
  16. name: 'HeartButton',
  17. props: ['post'],
  18. data () {
  19. return {
  20. changed: false,
  21. liked_: false
  22. }
  23. },
  24. computed: {
  25. likeable () {
  26. let postUsername = this.post.User ?
  27. this.post.User.username :
  28. null
  29. return (
  30. this.$store.state.username &&
  31. postUsername !== this.$store.state.username
  32. )
  33. },
  34. likes: {
  35. get () {
  36. let likes = this.post.Likes.length
  37. if(this.changed) {
  38. return this.liked ? likes+1 : likes-1
  39. } else {
  40. return likes
  41. }
  42. }
  43. },
  44. liked: {
  45. get () {
  46. if(this.changed) {
  47. return this.liked_
  48. } else {
  49. return this.post.Likes.some(u => {
  50. return u.username === this.$store.state.username
  51. })
  52. }
  53. },
  54. set (val) {
  55. this.changed = true
  56. this.liked_ = val
  57. }
  58. }
  59. },
  60. methods: {
  61. change (e) {
  62. let liked = e.target.checked
  63. let id = this.post.id
  64. if(liked) {
  65. this.axios
  66. .put('/api/v1/post/' + id + '/like')
  67. .then(_ => this.liked = true)
  68. .catch((err) => {
  69. e.target.checked = !liked
  70. AjaxErrorHandler(this.$store)(err)
  71. })
  72. } else {
  73. this.axios
  74. .delete('/api/v1/post/' + id + '/like')
  75. .then(_ => this.liked = false)
  76. .catch((err) => {
  77. e.target.checked = !liked
  78. AjaxErrorHandler(this.$store)(err)
  79. })
  80. }
  81. }
  82. }
  83. }
  84. </script>
  85. <style lang='scss' scoped>
  86. @import '../assets/scss/variables.scss';
  87. .heart_button {
  88. cursor: pointer;
  89. @include user-select(none);
  90. @at-root #{&}--unlikeable {
  91. cursor: not-allowed;
  92. }
  93. input {
  94. display: none;
  95. }
  96. #{&}__count {
  97. position: relative;
  98. bottom: 0.0625rem;
  99. }
  100. span.fa {
  101. color: $color__gray--darkest;
  102. transition: text-shadow 0.2s, color 0.2s, filter 0.2s;
  103. font-size: 1.125rem;
  104. &:hover {
  105. filter: brightness(0.9);
  106. }
  107. &::before {
  108. content: "\f004";
  109. }
  110. }
  111. input:checked + span.fa {
  112. color: #E91E63;
  113. }
  114. }
  115. </style>