Report.vue 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. <template>
  2. <modal title="Report">
  3. <div slot="body">
  4. <div class="columns song-types">
  5. <div v-if="previousSong !== null" class="column song-type">
  6. <div
  7. class="card is-fullwidth"
  8. :class="{ 'is-highlight-active': isPreviousSongActive }"
  9. @click="highlight('previousSong')"
  10. >
  11. <header class="card-header">
  12. <p class="card-header-title">
  13. Previous Song
  14. </p>
  15. </header>
  16. <div class="card-content">
  17. <article class="media">
  18. <figure class="media-left">
  19. <p class="image is-64x64">
  20. <img
  21. :src="previousSong.thumbnail"
  22. onerror='this.src="/assets/notes-transparent.png"'
  23. />
  24. </p>
  25. </figure>
  26. <div class="media-content">
  27. <div class="content">
  28. <p>
  29. <strong>{{
  30. previousSong.title
  31. }}</strong>
  32. <br />
  33. <small>{{
  34. previousSong.artists.split(" ,")
  35. }}</small>
  36. </p>
  37. </div>
  38. </div>
  39. </article>
  40. </div>
  41. <a
  42. href="#"
  43. class="absolute-a"
  44. @click="highlight('previousSong')"
  45. />
  46. </div>
  47. </div>
  48. <div v-if="currentSong !== {}" class="column song-type">
  49. <div
  50. class="card is-fullwidth"
  51. :class="{ 'is-highlight-active': isCurrentSongActive }"
  52. @click="highlight('currentSong')"
  53. >
  54. <header class="card-header">
  55. <p class="card-header-title">
  56. Current Song
  57. </p>
  58. </header>
  59. <div class="card-content">
  60. <article class="media">
  61. <figure class="media-left">
  62. <p class="image is-64x64">
  63. <img
  64. :src="currentSong.thumbnail"
  65. onerror='this.src="/assets/notes-transparent.png"'
  66. />
  67. </p>
  68. </figure>
  69. <div class="media-content">
  70. <div class="content">
  71. <p>
  72. <strong>{{
  73. currentSong.title
  74. }}</strong>
  75. <br />
  76. <small>{{
  77. currentSong.artists.split(" ,")
  78. }}</small>
  79. </p>
  80. </div>
  81. </div>
  82. </article>
  83. </div>
  84. <a
  85. href="#"
  86. class="absolute-a"
  87. @click="highlight('currentSong')"
  88. />
  89. </div>
  90. </div>
  91. </div>
  92. <div class="edit-report-wrapper">
  93. <div class="columns is-multiline">
  94. <div
  95. v-for="(issue, index) in issues"
  96. class="column is-half"
  97. :key="index"
  98. >
  99. <label class="label">{{ issue.name }}</label>
  100. <p
  101. v-for="(reason, index) in issue.reasons"
  102. class="control"
  103. :key="index"
  104. >
  105. <label class="checkbox">
  106. <input
  107. type="checkbox"
  108. @click="toggleIssue(issue.name, reason)"
  109. />
  110. {{ reason }}
  111. </label>
  112. </p>
  113. </div>
  114. <div class="column">
  115. <label class="label">Other</label>
  116. <textarea
  117. v-model="report.description"
  118. class="textarea"
  119. maxlength="400"
  120. placeholder="Any other details..."
  121. @keyup="updateCharactersRemaining()"
  122. />
  123. <div class="textarea-counter">
  124. {{ charactersRemaining }}
  125. </div>
  126. </div>
  127. </div>
  128. </div>
  129. </div>
  130. <div slot="footer">
  131. <a class="button is-success" @click="create()" href="#">
  132. <i class="material-icons save-changes">done</i>
  133. <span>&nbsp;Create</span>
  134. </a>
  135. <a
  136. class="button is-danger"
  137. href="#"
  138. @click="
  139. closeModal({
  140. sector: 'station',
  141. modal: 'report'
  142. })
  143. "
  144. >
  145. <span>&nbsp;Cancel</span>
  146. </a>
  147. </div>
  148. </modal>
  149. </template>
  150. <script>
  151. import { mapState, mapActions } from "vuex";
  152. import Toast from "toasters";
  153. import Modal from "./Modal.vue";
  154. import io from "../../io";
  155. export default {
  156. components: { Modal },
  157. data() {
  158. return {
  159. charactersRemaining: 400,
  160. isPreviousSongActive: false,
  161. isCurrentSongActive: true,
  162. report: {
  163. resolved: false,
  164. songId: "",
  165. description: "",
  166. issues: [
  167. { name: "Video", reasons: [] },
  168. { name: "Title", reasons: [] },
  169. { name: "Duration", reasons: [] },
  170. { name: "Artists", reasons: [] },
  171. { name: "Thumbnail", reasons: [] }
  172. ]
  173. },
  174. issues: [
  175. {
  176. name: "Video",
  177. reasons: [
  178. "Doesn't exist",
  179. "It's private",
  180. "It's not available in my country"
  181. ]
  182. },
  183. {
  184. name: "Title",
  185. reasons: ["Incorrect", "Inappropriate"]
  186. },
  187. {
  188. name: "Duration",
  189. reasons: [
  190. "Skips too soon",
  191. "Skips too late",
  192. "Starts too soon",
  193. "Starts too late"
  194. ]
  195. },
  196. {
  197. name: "Artists",
  198. reasons: ["Incorrect", "Inappropriate"]
  199. },
  200. {
  201. name: "Thumbnail",
  202. reasons: ["Incorrect", "Inappropriate", "Doesn't exist"]
  203. }
  204. ]
  205. };
  206. },
  207. computed: mapState({
  208. currentSong: state => state.station.currentSong,
  209. previousSong: state => state.station.previousSong
  210. }),
  211. mounted() {
  212. io.getSocket(socket => {
  213. this.socket = socket;
  214. });
  215. this.report.songId = this.currentSong.songId;
  216. },
  217. methods: {
  218. create() {
  219. console.log(this.report);
  220. this.socket.emit("reports.create", this.report, res => {
  221. new Toast({ content: res.message, timeout: 4000 });
  222. if (res.status === "success")
  223. this.closeModal({
  224. sector: "station",
  225. modal: "report"
  226. });
  227. });
  228. },
  229. updateCharactersRemaining() {
  230. this.charactersRemaining =
  231. 400 - document.getElementsByClassName("textarea").value.length;
  232. },
  233. highlight(type) {
  234. if (type === "currentSong") {
  235. this.report.songId = this.currentSong.songId;
  236. this.isPreviousSongActive = false;
  237. this.isCurrentSongActive = true;
  238. } else if (type === "previousSong") {
  239. this.report.songId = this.previousSong.songId;
  240. this.isCurrentSongActive = false;
  241. this.isPreviousSongActive = true;
  242. }
  243. },
  244. toggleIssue(name, reason) {
  245. for (let z = 0; z < this.report.issues.length; z += 1) {
  246. if (this.report.issues[z].name === name) {
  247. if (this.report.issues[z].reasons.indexOf(reason) > -1) {
  248. this.report.issues[z].reasons.splice(
  249. this.report.issues[z].reasons.indexOf(reason),
  250. 1
  251. );
  252. } else this.report.issues[z].reasons.push(reason);
  253. }
  254. }
  255. },
  256. ...mapActions("modals", ["closeModal"])
  257. }
  258. };
  259. </script>
  260. <style lang="scss" scoped>
  261. @import "styles/global.scss";
  262. h6 {
  263. margin-bottom: 15px;
  264. }
  265. .song-type:first-of-type {
  266. padding-left: 0;
  267. }
  268. .song-type:last-of-type {
  269. padding-right: 0;
  270. }
  271. .media-content {
  272. display: flex;
  273. align-items: center;
  274. height: 64px;
  275. }
  276. .radio-controls .control {
  277. display: flex;
  278. align-items: center;
  279. }
  280. .textarea-counter {
  281. text-align: right;
  282. }
  283. @media screen and (min-width: 769px) {
  284. .radio-controls .control-label {
  285. padding-top: 0 !important;
  286. }
  287. }
  288. .edit-report-wrapper {
  289. padding: 20px;
  290. }
  291. .is-highlight-active {
  292. border: 3px $primary-color solid;
  293. }
  294. </style>