You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

291 lines
9.2 KiB

7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
  1. <template>
  2. <div class="panel panel-default scorecard" v-if="show">
  3. <div class="panel-heading">
  4. <div class="team">
  5. <span class="team-icon" :style="'background-color: #'+tweet.team_color"></span>
  6. <span class="team-name">{{ tweet.team_name }}</span>
  7. </div>
  8. <h2>{{ tweet.mission }}</h2>
  9. <button type="button" class="close" v-on:click="dismiss"><span>&times;</span></button>
  10. </div>
  11. <div class="panel-body">
  12. <div class="row">
  13. <div class="col-md-8">
  14. <div class="profile">
  15. <img :src="tweet.player_photo" :style="'border-color: #'+tweet.team_color">
  16. <span><a :href="'https://twitter.com/'+tweet.player_username">@{{ tweet.player_username }}</a></span>
  17. </div>
  18. <div class="tweet">
  19. <div class="text">{{ tweet.text }}</div>
  20. <div v-if="tweet.photos">
  21. <div :class="'multi-photo photos-'+tweet.photos.length" v-if="tweet.photos">
  22. <div v-for="img in tweet.photos" class="photo" :style="'background-image:url('+img+')'" :data-featherlight="img">
  23. <img :src="img">
  24. </div>
  25. </div>
  26. <div class="multi-photo-clear"></div>
  27. </div>
  28. </div>
  29. <div class="tweet-reply">
  30. <textarea class="form-control" rows="2" v-model="replyText" style="margin-bottom: 4px;"></textarea>
  31. <button type="submit" class="btn btn-primary" :disabled="isTweetReplyDisabled">Reply</button>
  32. <div class="clear"></div>
  33. </div>
  34. <div class="tweet-actions">
  35. <button type="button" class="btn btn-success" v-on:click="scoreTweet" :disabled="isAcceptDisabled">Accept</button>
  36. <button type="button" class="btn btn-danger" v-on:click="rejectTweet">Reject</button>
  37. </div>
  38. </div>
  39. <div class="col-md-4">
  40. <!-- MISSION 1 #transitspy -->
  41. <template v-if="tweet.mission_id == 1">
  42. <p class="instructions">
  43. The photo must show the sign with the transit line
  44. </p>
  45. <div class="form-group">
  46. <select class="form-control" v-model="selectedTransitLine">
  47. <option value=""></option>
  48. <option v-for="line in lines" :value="line.id">{{ line.name }}</option>
  49. </select>
  50. </div>
  51. <div class="form-group">
  52. <input type="text" v-model="selectedNonTrimetLine" placeholder="Non-Trimet Line" class="form-control">
  53. </div>
  54. </template>
  55. <!-- MISSION 2 #intercept -->
  56. <template v-if="tweet.mission_id == 2">
  57. <p class="instructions">
  58. <ul>
  59. <li>Photo must show the sign with the transit center</li>
  60. <li>Bonus points if another team and their pennant are visible!</li>
  61. </ul>
  62. </p>
  63. <div class="form-group">
  64. <select class="form-control" v-model="selectedTransitCenter">
  65. <option value=""></option>
  66. <option v-for="stop in centers" :value="stop.id">{{ stop.name }}</option>
  67. </select>
  68. </div>
  69. <div class="form-group">
  70. <div class="checkbox">
  71. <label>
  72. <input type="checkbox" v-model="selectedPhotoHasAnotherTeam">
  73. Another team is in the photo
  74. </label>
  75. </div>
  76. </div>
  77. </template>
  78. <!-- MISSION 3 #airlair -->
  79. <template v-if="tweet.mission_id == 3">
  80. <p class="instructions">
  81. <ul>
  82. <li>Make sure this photo is on the tram or at the top tram station</li>
  83. <li>Reject if it shows the rooftop with the code!</li>
  84. </ul>
  85. </p>
  86. </template>
  87. <!-- MISSION 4 #transittea -->
  88. <template v-if="tweet.mission_id == 4">
  89. <p class="instructions">
  90. <ul>
  91. <li>The photo must include the radio</li>
  92. <li>Reject if it shows the decoded message</li>
  93. </ul>
  94. </p>
  95. </template>
  96. <!-- MISSION 5 #sing -->
  97. <template v-if="tweet.mission_id == 5">
  98. <p class="instructions">
  99. Accept a photo of either a team member singing, or a photo of tipping the bus driver
  100. </p>
  101. <div class="form-group">
  102. <label>
  103. <input type="checkbox" v-model="selectedM5Singing">
  104. Singing
  105. </label>
  106. <br>
  107. <label>
  108. <input type="checkbox" v-model="selectedM5Tipping">
  109. Tipping the driver
  110. </label>
  111. </div>
  112. </template>
  113. <!-- MISSION 6 #passport -->
  114. <template v-if="tweet.mission_id == 6">
  115. <p class="instructions">
  116. The photo must show all team members with their completed visas
  117. </p>
  118. </template>
  119. <!-- MISSION 7 #document -->
  120. <template v-if="tweet.mission_id == 7">
  121. <p class="instructions">
  122. Accept a photo that completes one of the below documents:
  123. </p>
  124. <div class="form-group">
  125. <div v-for="doc in documents" class="radio">
  126. <label>
  127. <input type="radio" name="selectedDocument" v-model="selectedDocument" :value="doc.id">
  128. {{ doc.description }}
  129. </label>
  130. </div>
  131. </div>
  132. </template>
  133. </div>
  134. </div>
  135. </div>
  136. </div>
  137. </template>
  138. <script>
  139. module.exports = {
  140. props: ['show', 'tweet'],
  141. data () {
  142. return {
  143. documents: [],
  144. centers: [],
  145. lines: [],
  146. replyText: '',
  147. selectedDocument: null,
  148. selectedTransitCenter: null,
  149. selectedTransitLine: null,
  150. selectedNonTrimetLine: '',
  151. selectedPhotoHasAnotherTeam: false,
  152. selectedM5Singing: false,
  153. selectedM5Tipping: false
  154. }
  155. },
  156. computed: {
  157. isAcceptDisabled() {
  158. if(this.show) {
  159. switch(this.tweet.mission_id) {
  160. case 1:
  161. return this.selectedTransitLine == null && this.selectedNonTrimetLine == '';
  162. case 2:
  163. return this.selectedTransitCenter == null;
  164. case 3:
  165. case 4:
  166. case 6:
  167. // Nothing to check
  168. return false;
  169. case 5:
  170. return this.selectedM5Singing == false && this.selectedM5Tipping == false;
  171. case 7:
  172. return this.selectedDocument == null;
  173. default:
  174. return true;
  175. }
  176. } else {
  177. return true;
  178. }
  179. },
  180. isTweetReplyDisabled() {
  181. return this.replyText == '';
  182. }
  183. },
  184. methods: {
  185. clearState() {
  186. this.selectedDocument = null;
  187. this.selectedTransitCenter = null;
  188. this.selectedTransitLine = null;
  189. this.selectedNonTrimetLine = '';
  190. this.selectedPhotoHasAnotherTeam = false;
  191. this.selectedM5Singing = false;
  192. this.selectedM5Tipping = false;
  193. this.replyText = '';
  194. },
  195. dismiss() {
  196. this.clearState();
  197. this.$emit('dismiss');
  198. },
  199. rejectTweet() {
  200. $.post("/dashboard/reject-tweet", {
  201. tweet_id: this.tweet.tweet_id
  202. }, function() {
  203. this.clearState();
  204. this.$emit('complete');
  205. }.bind(this));
  206. },
  207. scoreTweet() {
  208. var score_data = {};
  209. switch(this.tweet.mission_id) {
  210. case 1:
  211. score_data['m1_complete'] = 1;
  212. score_data['m1_transit_line_id'] = this.selectedTransitLine;
  213. score_data['m1_non_trimet'] = this.selectedNonTrimetLine;
  214. break;
  215. case 2:
  216. score_data['m2_complete'] = this.selectedTransitCenter ? 1 : 0;
  217. score_data['m2_transit_center_id'] = this.selectedTransitCenter;
  218. score_data['m2_with_other_team'] = this.selectedPhotoHasAnotherTeam ? 1 : 0;
  219. break;
  220. case 3:
  221. score_data['m3_complete'] = 1;
  222. break;
  223. case 4:
  224. score_data['m4_complete'] = 1;
  225. break;
  226. case 5:
  227. score_data['m5_complete'] = this.selectedM5Singing ? 1 : 0;
  228. score_data['m5_tip'] = this.selectedM5Tipping ? 1 : 0;
  229. break;
  230. case 6:
  231. score_data['m6_complete'] = 1;
  232. break;
  233. case 7:
  234. score_data['m7_document_id'] = this.selectedDocument;
  235. break;
  236. }
  237. $.post("/dashboard/score-tweet", {
  238. tweet_id: this.tweet.tweet_id,
  239. score_data: score_data
  240. }, function(){
  241. this.clearState();
  242. this.$emit('complete');
  243. }.bind(this));
  244. }
  245. },
  246. watch: {
  247. // https://vuejs.org/v2/guide/computed.html#Watchers
  248. show: function(val) {
  249. if(val) {
  250. // https://vuejs.org/v2/guide/reactivity.html#Async-Update-Queue
  251. Vue.nextTick(function() {
  252. $(".multi-photo .photo").featherlight();
  253. }.bind(this));
  254. }
  255. }
  256. },
  257. created() {
  258. $.get("/dashboard/dropdowns", function(response){
  259. this.centers = response.transit_centers;
  260. this.lines = response.transit_lines;
  261. this.documents = response.documents;
  262. }.bind(this));
  263. }
  264. }
  265. </script>