Show.vue 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. <template>
  2. <div v-if="isUser">
  3. <main-header />
  4. <div class="container">
  5. <img class="avatar" src="/assets/notes.png" />
  6. <h2 class="has-text-centered username">@{{ user.username }}</h2>
  7. <h5>A member since {{ user.createdAt }}</h5>
  8. <div
  9. v-if="role === 'admin' && userId !== user._id"
  10. class="admin-functionality"
  11. >
  12. <a
  13. v-if="user.role == 'default'"
  14. class="button is-small is-info is-outlined"
  15. @click="changeRank('admin')"
  16. >Promote to Admin</a
  17. >
  18. <a
  19. v-if="user.role == 'admin'"
  20. class="button is-small is-danger is-outlined"
  21. @click="changeRank('default')"
  22. >Demote to User</a
  23. >
  24. </div>
  25. <nav class="level">
  26. <div class="level-item has-text-centered">
  27. <p class="heading">
  28. Rank
  29. </p>
  30. <p class="title role">
  31. {{ user.role }}
  32. </p>
  33. </div>
  34. <div class="level-item has-text-centered">
  35. <p class="heading">
  36. Songs Requested
  37. </p>
  38. <p class="title">
  39. {{ user.statistics.songsRequested }}
  40. </p>
  41. </div>
  42. <div class="level-item has-text-centered">
  43. <p class="heading">
  44. Likes
  45. </p>
  46. <p class="title">
  47. {{ user.liked.length }}
  48. </p>
  49. </div>
  50. <div class="level-item has-text-centered">
  51. <p class="heading">
  52. Dislikes
  53. </p>
  54. <p class="title">
  55. {{ user.disliked.length }}
  56. </p>
  57. </div>
  58. </nav>
  59. </div>
  60. <main-footer />
  61. </div>
  62. </template>
  63. <script>
  64. import { mapState } from "vuex";
  65. import { Toast } from "vue-roaster";
  66. import MainHeader from "../MainHeader.vue";
  67. import MainFooter from "../MainFooter.vue";
  68. import io from "../../io";
  69. export default {
  70. components: { MainHeader, MainFooter },
  71. data() {
  72. return {
  73. user: {},
  74. isUser: false
  75. };
  76. },
  77. computed: mapState({
  78. role: state => state.user.auth.role,
  79. userId: state => state.user.auth.userId
  80. }),
  81. mounted() {
  82. io.getSocket(socket => {
  83. this.socket = socket;
  84. this.socket.emit(
  85. "users.findByUsername",
  86. this.$route.params.username,
  87. res => {
  88. if (res.status === "error") this.$router.go("/404");
  89. else {
  90. this.user = res.data;
  91. this.user.createdAt = moment(
  92. this.user.createdAt
  93. ).format("LL");
  94. this.isUser = true;
  95. }
  96. }
  97. );
  98. });
  99. },
  100. methods: {
  101. changeRank(newRank) {
  102. this.socket.emit(
  103. "users.updateRole",
  104. this.user._id,
  105. newRank === "admin" ? "admin" : "default",
  106. res => {
  107. if (res.status === "error")
  108. Toast.methods.addToast(res.message, 2000);
  109. else this.user.role = newRank;
  110. Toast.methods.addToast(
  111. `User ${this.$route.params.username}'s rank has been changed to: ${newRank}`,
  112. 2000
  113. );
  114. }
  115. );
  116. }
  117. }
  118. };
  119. </script>
  120. <style lang="scss" scoped>
  121. @import "styles/global.scss";
  122. .container {
  123. padding: 25px;
  124. }
  125. .avatar {
  126. border-radius: 50%;
  127. width: 250px;
  128. display: block;
  129. margin: auto;
  130. }
  131. h5 {
  132. text-align: center;
  133. margin-bottom: 25px;
  134. font-size: 17px;
  135. }
  136. .role {
  137. text-transform: capitalize;
  138. }
  139. .level {
  140. margin-top: 40px;
  141. }
  142. .admin-functionality {
  143. text-align: center;
  144. margin: 0 auto;
  145. }
  146. @media (max-width: 350px) {
  147. .username {
  148. font-size: 2.9rem;
  149. word-wrap: break-all;
  150. }
  151. }
  152. </style>