Report.vue 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  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. />
  122. <div class="textarea-counter">
  123. {{ charactersRemaining }}
  124. </div>
  125. </div>
  126. </div>
  127. </div>
  128. </div>
  129. <div slot="footer">
  130. <a class="button is-success" @click="create()" href="#">
  131. <i class="material-icons save-changes">done</i>
  132. <span>&nbsp;Create</span>
  133. </a>
  134. <a
  135. class="button is-danger"
  136. href="#"
  137. @click="
  138. closeModal({
  139. sector: 'station',
  140. modal: 'report'
  141. })
  142. "
  143. >
  144. <span>&nbsp;Cancel</span>
  145. </a>
  146. </div>
  147. </modal>
  148. </template>
  149. <script>
  150. import { mapState, mapActions } from "vuex";
  151. import Toast from "toasters";
  152. import Modal from "./Modal.vue";
  153. import io from "../../io";
  154. export default {
  155. components: { Modal },
  156. data() {
  157. return {
  158. isPreviousSongActive: false,
  159. isCurrentSongActive: true,
  160. report: {
  161. resolved: false,
  162. songId: "",
  163. description: "",
  164. issues: [
  165. { name: "Video", reasons: [] },
  166. { name: "Title", reasons: [] },
  167. { name: "Duration", reasons: [] },
  168. { name: "Artists", reasons: [] },
  169. { name: "Thumbnail", reasons: [] }
  170. ]
  171. },
  172. issues: [
  173. {
  174. name: "Video",
  175. reasons: [
  176. "Doesn't exist",
  177. "It's private",
  178. "It's not available in my country"
  179. ]
  180. },
  181. {
  182. name: "Title",
  183. reasons: ["Incorrect", "Inappropriate"]
  184. },
  185. {
  186. name: "Duration",
  187. reasons: [
  188. "Skips too soon",
  189. "Skips too late",
  190. "Starts too soon",
  191. "Starts too late"
  192. ]
  193. },
  194. {
  195. name: "Artists",
  196. reasons: ["Incorrect", "Inappropriate"]
  197. },
  198. {
  199. name: "Thumbnail",
  200. reasons: ["Incorrect", "Inappropriate", "Doesn't exist"]
  201. }
  202. ]
  203. };
  204. },
  205. computed: {
  206. charactersRemaining() {
  207. return 400 - this.report.description.length;
  208. },
  209. ...mapState({
  210. currentSong: state => state.station.currentSong,
  211. previousSong: state => state.station.previousSong
  212. })
  213. },
  214. mounted() {
  215. io.getSocket(socket => {
  216. this.socket = socket;
  217. });
  218. this.report.songId = this.currentSong.songId;
  219. },
  220. methods: {
  221. create() {
  222. console.log(this.report);
  223. this.socket.emit("reports.create", this.report, res => {
  224. new Toast({ content: res.message, timeout: 4000 });
  225. if (res.status === "success")
  226. this.closeModal({
  227. sector: "station",
  228. modal: "report"
  229. });
  230. });
  231. },
  232. highlight(type) {
  233. if (type === "currentSong") {
  234. this.report.songId = this.currentSong.songId;
  235. this.isPreviousSongActive = false;
  236. this.isCurrentSongActive = true;
  237. } else if (type === "previousSong") {
  238. this.report.songId = this.previousSong.songId;
  239. this.isCurrentSongActive = false;
  240. this.isPreviousSongActive = true;
  241. }
  242. },
  243. toggleIssue(name, reason) {
  244. for (let z = 0; z < this.report.issues.length; z += 1) {
  245. if (this.report.issues[z].name === name) {
  246. if (this.report.issues[z].reasons.indexOf(reason) > -1) {
  247. this.report.issues[z].reasons.splice(
  248. this.report.issues[z].reasons.indexOf(reason),
  249. 1
  250. );
  251. } else this.report.issues[z].reasons.push(reason);
  252. }
  253. }
  254. },
  255. ...mapActions("modals", ["closeModal"])
  256. }
  257. };
  258. </script>
  259. <style lang="scss" scoped>
  260. @import "styles/global.scss";
  261. h6 {
  262. margin-bottom: 15px;
  263. }
  264. .song-type:first-of-type {
  265. padding-left: 0;
  266. }
  267. .song-type:last-of-type {
  268. padding-right: 0;
  269. }
  270. .media-content {
  271. display: flex;
  272. align-items: center;
  273. height: 64px;
  274. }
  275. .radio-controls .control {
  276. display: flex;
  277. align-items: center;
  278. }
  279. .textarea-counter {
  280. text-align: right;
  281. }
  282. @media screen and (min-width: 769px) {
  283. .radio-controls .control-label {
  284. padding-top: 0 !important;
  285. }
  286. }
  287. .edit-report-wrapper {
  288. padding: 20px;
  289. }
  290. .is-highlight-active {
  291. border: 3px $primary-color solid;
  292. }
  293. </style>