Report.vue 6.5 KB

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