Show.vue 3.6 KB

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