Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 

315 linhas
7.6 KiB

  1. <template>
  2. <div id="gtblank-init">
  3. <video autoplay muted loop class="video-bg">
  4. <source src="/gt-blank-init-bg.mp4" type="video/mp4">
  5. </video>
  6. <div class="selection-text">{{selectionText}}</div>
  7. <div class="otf">
  8. <!-- <h1 style="padding-top:1em">Party</h1> -->
  9. <div class="form-wrapper">
  10. </div>
  11. <template v-if="status && status.open">
  12. <form v-if="!success" class="input-form" @submit.prevent="onClickTheButton" style="margin-top: 5vh">
  13. <div class="input-headline">gtblank-init 2022-11-11 rsvp</div>
  14. <input class="input-text" v-model="anzeigename" placeholder="nickname (public)" size="1" />
  15. <input class="input-text" v-model="name" placeholder="full name (for orga reasons)" size="1" />
  16. <input class="input-text" v-model="email" placeholder="email (for self service)" size="1" />
  17. <input class="input-btn" type="submit" :value="(sending ? 'sending ...' : 'join')" :disabled="(sending ? true : false)" />
  18. <div v-if="error">
  19. oh no something went wrong!<br>
  20. {{errorReason.detail}}
  21. </div>
  22. </form>
  23. <div v-if="showHelp" style="margin-bottom: 1em;">
  24. *robot voice* give us your data for the reservation!
  25. </div>
  26. <div v-if="success">
  27. <p style="font-size: 6vw">
  28. Thanks!
  29. </p>
  30. <button @click="resetForm" class="input-btn">✓ see you there!</button>
  31. </div>
  32. </template>
  33. <template v-if="status && !status.open">
  34. {{status.reason}}
  35. </template>
  36. <vue-word-cloud class="wordcloud" style="height: 70vh; width: 80%" :words="words"
  37. font-family="'JetBrains Mono'" />
  38. <div v-if="status && status.open" class="details" ref="details">
  39. official start 21:00<br>
  40. augasse 2-6, 1090 wien<br>
  41. <small>
  42. alte wu -> enter main entrance -> turn right to "ateliers" <br>
  43. <a href="https://www.openstreetmap.org/?mlat=48.23201&mlon=16.35773#map=19/48.23201/16.35773" target="_blank">location pin @ osm.org</a>
  44. </small>
  45. </div>
  46. </div>
  47. <!-- :color="() => { return nameColors[Math.floor(Math.random() * nameColors.length)] }" -->
  48. </div>
  49. </template>
  50. <script>
  51. import VueWordCloud from 'vuewordcloud';
  52. export default {
  53. name: 'Invitation',
  54. data() {
  55. return {
  56. anzeigename: '',
  57. name: '',
  58. email: '',
  59. status: null,
  60. newsletter: false,
  61. guests: [],
  62. sending: false,
  63. showHelp: false,
  64. selection: null,
  65. selectionText: null,
  66. success: false,
  67. error: false,
  68. errorReason: null,
  69. }
  70. },
  71. components: {
  72. [VueWordCloud.name]: VueWordCloud,
  73. },
  74. computed: {
  75. nameColors() {
  76. return ['White']
  77. },
  78. words() {
  79. const names = this.guests.map(guest => {
  80. return guest.anzeigename
  81. })
  82. const nameLengths = names.map(name => {
  83. return name.length
  84. })
  85. const maxNameLength = Math.max(...nameLengths)
  86. return this.guests.map(guest => {
  87. const nameLength = guest.anzeigename.length
  88. let size = maxNameLength - nameLength + 12
  89. return [` ${guest.anzeigename} `, size]
  90. })
  91. },
  92. // guestlist() {
  93. // return this.guests.map( (g) => {
  94. // g.name = g.anzeigename
  95. // return g
  96. // })
  97. // }
  98. },
  99. methods: {
  100. async fetchStatus() {
  101. const response = await fetch(`${process.env.VUE_APP_API_URL}status`)
  102. const data = await response.json()
  103. this.status = data
  104. },
  105. async fetchGuests() {
  106. const response = await fetch(`${process.env.VUE_APP_API_URL}guest`)
  107. const data = await response.json()
  108. this.guests = data
  109. },
  110. async onClickTheButton() {
  111. if (this.name.length == 0) {
  112. this.showHelp = true
  113. return false
  114. }
  115. this.showHelp = false
  116. this.sending = true
  117. let data = {
  118. anzeigename: this.anzeigename,
  119. name: this.name,
  120. email: this.email,
  121. newsletter: false,
  122. }
  123. const response = await fetch(
  124. `${process.env.VUE_APP_API_URL}guest`, {
  125. method: 'POST',
  126. headers: {
  127. 'Content-Type': 'application/json',
  128. },
  129. body: JSON.stringify(data),
  130. }
  131. )
  132. if (response.status === 200) {
  133. this.anzeigename = ''
  134. this.name = ''
  135. this.email = ''
  136. this.success = true
  137. this.fetchGuests()
  138. } else {
  139. this.success = false
  140. this.fetchGuests()
  141. this.error = true
  142. this.errorReason = await response.json()
  143. }
  144. this.sending = false
  145. return false
  146. },
  147. resetForm () {
  148. this.anzeigename = ''
  149. this.name = ''
  150. this.email = ''
  151. this.success = false
  152. },
  153. },
  154. mounted() {
  155. this.fetchStatus()
  156. this.fetchGuests()
  157. document.addEventListener('selectionchange', () => {
  158. this.selection = document.getSelection()
  159. // console.log(this.selection)
  160. if (this.selection) {
  161. this.selectionText = this.selection.toString()
  162. }
  163. });
  164. // this.$refs.details.$el
  165. },
  166. }
  167. </script>
  168. <style>
  169. :root {
  170. cursor: url('cursor.png'), auto;
  171. }
  172. #gtblank-init {
  173. background: #999;
  174. }
  175. .video-bg {
  176. position: fixed;
  177. right: 0;
  178. bottom: 0;
  179. min-width: 100%;
  180. min-height: 100%;
  181. }
  182. a {
  183. color: inherit;
  184. cursor: inherit;
  185. }
  186. .otf {
  187. width: 100%;
  188. /* background-color: rgb(167, 204, 247); */
  189. /* background-image: url('bg.gif'); */
  190. background-size: cover;
  191. display: flex;
  192. flex-direction: column;
  193. align-items: center;
  194. min-height: 100vh;
  195. position: relative;
  196. }
  197. .input-headline {
  198. color: #000;
  199. mix-blend-mode: multiply;
  200. font-size: 4vh;
  201. margin-bottom: .8vh;
  202. text-align: center;
  203. }
  204. .input-form {
  205. display: flex;
  206. flex-direction: column;
  207. width: 100%;
  208. max-width: 800px;
  209. mix-blend-mode: hard-light;
  210. margin-top: 4vh;
  211. z-index: 9;
  212. position: relative;
  213. }
  214. .input-text,
  215. .input-btn,
  216. .input-cb {
  217. color: #000;
  218. background: #fff;
  219. font-size: 2.8vh;
  220. font-family: 'JetBrains Mono', monospace;
  221. border: 0;
  222. padding: .5em 1em;
  223. line-height: 1.4;
  224. max-width: 100%;
  225. cursor: inherit;
  226. }
  227. .input-btn {
  228. color: #000;
  229. background-color: #01ffcf;
  230. }
  231. .input-btn:hover {
  232. background: #00d9b1;
  233. }
  234. .input-checkbox {
  235. margin: 0 1em 0 0;
  236. }
  237. @media screen and (max-width: 1000px) {
  238. .form-wrapper {
  239. margin-top: 4em;
  240. }
  241. .input-text,
  242. .input-btn {
  243. width: 100%;
  244. max-width: 100%;
  245. min-width: 0;
  246. text-align: center;
  247. }
  248. /* .input-form {
  249. position: absolute;
  250. bottom: 0;
  251. display: flex;
  252. flex-direction: column;
  253. } */
  254. }
  255. .input-text {
  256. width: auto;
  257. flex-grow: 1;
  258. }
  259. .wordcloud {
  260. mix-blend-mode: overlay;
  261. }
  262. .details {
  263. color: #000;
  264. background-color: #fff;
  265. font-size: 30px;
  266. max-width: 80em;
  267. margin: 3% 3% 200px;
  268. padding: 3%;
  269. mix-blend-mode: lighten;
  270. box-shadow: 10px 10px 0 #000fee, -10px -10px 0 #3400ee;
  271. }
  272. .share {
  273. max-width: 30em;
  274. width: 80%;
  275. mix-blend-mode: soft-light;
  276. }
  277. .share:hover {
  278. mix-blend-mode: difference;
  279. }
  280. .selection-text {
  281. position: fixed;
  282. z-index: 9999;
  283. font-size: 10vh;
  284. line-height: 1em;
  285. pointer-events: none;
  286. color: #fff;
  287. mix-blend-mode: difference;
  288. top: 10%;
  289. }
  290. </style>