您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 

296 行
11 KiB

  1. <template>
  2. <div id="app">
  3. <div class="selection-text">{{selectionText}}</div>
  4. <div class="otf" id="teilnehmen">
  5. <!-- <h1 style="padding-top:1em">Party</h1> -->
  6. <div class="form-wrapper">
  7. </div>
  8. <form v-if="!success" class="input-form" @submit.prevent="onClickTheButton" style="margin-top: 5vh">
  9. <div class="input-headline">reservation</div>
  10. <input class="input-text" v-model="anzeigename" placeholder="nickname (public)" size="1" />
  11. <input class="input-text" v-model="name" placeholder="real name" size="1" />
  12. <input class="input-text" v-model="email" placeholder="email" size="1" />
  13. <!-- <label class="input-cb" for="newsletter">
  14. <input name="newsletter" id="newsletter" type="checkbox" class="input-checkbox" />stay informed
  15. </label> -->
  16. <input class="input-btn" type="submit" :value="(sending ? 'send ...' : 'reserve')" />
  17. <div v-if="error">
  18. oh no something went wrong!<br>
  19. {{errorReason.detail}}
  20. </div>
  21. </form>
  22. <div v-if="showHelp" style="margin-bottom: 1em;">
  23. *robot voice* give us your data for the reservation!
  24. </div>
  25. <div v-if="success">
  26. <p style="font-size: 8vw">
  27. Thanks!
  28. </p>
  29. <button @click="resetForm" class="input-btn">✓ see you there!</button>
  30. </div>
  31. <vue-word-cloud class="wordcloud" style="height: 70vh; width: 80%" :words="words"
  32. :color="() => { return nameColors[Math.floor(Math.random() * nameColors.length)] }"
  33. font-family="'JetBrains Mono'" />
  34. </div>
  35. <!-- <div class="details" ref="details">
  36. TEXT!
  37. </div> -->
  38. <div
  39. v-if="canShare"
  40. @click="share"
  41. style="cursor: pointer; margin-top: 5em;"
  42. >
  43. <svg class="share" fill="#fff" version="1.1" viewBox="0 0 350.22 180.68" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><g transform="translate(-622.81 -392.3)"><path d="m659.49 392.3v16.427h-16.299v19.182h-20.385v50.605h21.942v18.918h17.175v19.63h55.254l-37.054 55.916h30.57l37.054-55.916h190.84v-16.06h15.991v-18.048h18.443v-50.605h-19.999v-20.05h-16.867v-19.998zm6.9343 23.419h263.37v19.998h19.999v41.866h-18.443v16.06h-263.37v-19.63h-21.942v-41.866h20.385z" stroke-width="0" style="paint-order:stroke fill markers"/><g transform="matrix(.42673 0 0 .42673 457.43 276.68)" aria-label="WILLTEILEN"><path d="m590.71 451.07h-21.891l-6.5625-29.859q-0.46875-1.875-1.5-7.4531-0.98437-5.5781-1.4531-9.3281-0.375 3.0469-1.2188 7.5938-0.84375 4.5-1.6875 8.2969-0.79688 3.7969-6.7969 30.75h-21.891l-16.969-68.531h17.859l7.4531 34.359q2.5312 11.391 3.4688 18.141 0.60937-4.7812 2.1562-12.984 1.5938-8.2031 2.9531-13.594l6.0469-25.922h17.156l5.8594 25.922q1.5 6.2344 3.0469 14.391 1.5469 8.1562 2.0625 12.188 0.60937-5.2031 3.3281-18.047l7.5938-34.453h17.859z"/><path d="m616.44 451.07v-68.531h18.609v68.531z"/><path d="m649.86 451.07v-68.531h18.516v53.578h26.391v14.953z"/><path d="m705.74 451.07v-68.531h18.516v53.578h26.391v14.953z"/><path d="m791.85 451.07h-18.516v-53.391h-16.734v-15.141h51.938v15.141h-16.688z"/><path d="m859.02 451.07h-40.688v-68.531h40.688v14.859h-22.172v10.781h20.531v14.859h-20.531v12.938h22.172z"/><path d="m871.02 451.07v-68.531h18.609v68.531z"/><path d="m904.44 451.07v-68.531h18.516v53.578h26.391v14.953z"/><path d="m1001 451.07h-40.687v-68.531h40.687v14.859h-22.172v10.781h20.531v14.859h-20.531v12.938h22.172z"/><path d="m1078.3 451.07h-24.281l-25.031-48.281h-0.4218q0.8906 11.391 0.8906 17.391v30.891h-16.406v-68.531h24.188l24.938 47.625h0.2813q-0.6563-10.359-0.6563-16.641v-30.984h16.5z"/></g></g></svg>
  44. </div>
  45. <a
  46. v-else
  47. href="mailto:?subject=invitation%20-%20oct%2028&body=%40SWK%0D%0Areservation%20required%3A%20reservation.ck.si "
  48. style="cursor: pointer; margin-top: 5em;"
  49. >
  50. <svg class="share" fill="#fff" version="1.1" viewBox="0 0 350.22 180.68" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><g transform="translate(-622.81 -392.3)"><path d="m659.49 392.3v16.427h-16.299v19.182h-20.385v50.605h21.942v18.918h17.175v19.63h55.254l-37.054 55.916h30.57l37.054-55.916h190.84v-16.06h15.991v-18.048h18.443v-50.605h-19.999v-20.05h-16.867v-19.998zm6.9343 23.419h263.37v19.998h19.999v41.866h-18.443v16.06h-263.37v-19.63h-21.942v-41.866h20.385z" stroke-width="0" style="paint-order:stroke fill markers"/><g transform="matrix(.42673 0 0 .42673 457.43 276.68)" aria-label="WILLTEILEN"><path d="m590.71 451.07h-21.891l-6.5625-29.859q-0.46875-1.875-1.5-7.4531-0.98437-5.5781-1.4531-9.3281-0.375 3.0469-1.2188 7.5938-0.84375 4.5-1.6875 8.2969-0.79688 3.7969-6.7969 30.75h-21.891l-16.969-68.531h17.859l7.4531 34.359q2.5312 11.391 3.4688 18.141 0.60937-4.7812 2.1562-12.984 1.5938-8.2031 2.9531-13.594l6.0469-25.922h17.156l5.8594 25.922q1.5 6.2344 3.0469 14.391 1.5469 8.1562 2.0625 12.188 0.60937-5.2031 3.3281-18.047l7.5938-34.453h17.859z"/><path d="m616.44 451.07v-68.531h18.609v68.531z"/><path d="m649.86 451.07v-68.531h18.516v53.578h26.391v14.953z"/><path d="m705.74 451.07v-68.531h18.516v53.578h26.391v14.953z"/><path d="m791.85 451.07h-18.516v-53.391h-16.734v-15.141h51.938v15.141h-16.688z"/><path d="m859.02 451.07h-40.688v-68.531h40.688v14.859h-22.172v10.781h20.531v14.859h-20.531v12.938h22.172z"/><path d="m871.02 451.07v-68.531h18.609v68.531z"/><path d="m904.44 451.07v-68.531h18.516v53.578h26.391v14.953z"/><path d="m1001 451.07h-40.687v-68.531h40.687v14.859h-22.172v10.781h20.531v14.859h-20.531v12.938h22.172z"/><path d="m1078.3 451.07h-24.281l-25.031-48.281h-0.4218q0.8906 11.391 0.8906 17.391v30.891h-16.406v-68.531h24.188l24.938 47.625h0.2813q-0.6563-10.359-0.6563-16.641v-30.984h16.5z"/></g></g></svg>
  51. </a>
  52. </div>
  53. </template>
  54. <script>
  55. import VueWordCloud from 'vuewordcloud';
  56. export default {
  57. name: 'App',
  58. data() {
  59. return {
  60. anzeigename: '',
  61. name: '',
  62. email: '',
  63. newsletter: false,
  64. guests: [],
  65. sending: false,
  66. showHelp: false,
  67. selection: null,
  68. selectionText: null,
  69. success: false,
  70. error: false,
  71. errorReason: null,
  72. }
  73. },
  74. components: {
  75. [VueWordCloud.name]: VueWordCloud,
  76. },
  77. computed: {
  78. nameColors() {
  79. return ['DeepPink', 'Crimson', 'Blue', 'BlueViolet', 'Fuchsia', 'Navy', 'Indigo']
  80. },
  81. words() {
  82. const names = this.guests.map(guest => {
  83. return guest.anzeigename
  84. })
  85. const nameLengths = names.map(name => {
  86. return name.length
  87. })
  88. const maxNameLength = Math.max(...nameLengths)
  89. return this.guests.map(guest => {
  90. const nameLength = guest.anzeigename.length
  91. let size = maxNameLength - nameLength + 12
  92. return [` ${guest.anzeigename} `, size]
  93. })
  94. },
  95. // guestlist() {
  96. // return this.guests.map( (g) => {
  97. // g.name = g.anzeigename
  98. // return g
  99. // })
  100. // }
  101. canShare () {
  102. return !!navigator.share
  103. }
  104. },
  105. methods: {
  106. async fetchGuests() {
  107. const response = await fetch(`${process.env.VUE_APP_API_URL}guest`)
  108. const data = await response.json()
  109. this.guests = data
  110. },
  111. async onClickTheButton() {
  112. if (this.name.length == 0) {
  113. this.showHelp = true
  114. return false
  115. }
  116. this.showHelp = false
  117. this.sending = true
  118. let data = {
  119. anzeigename: this.anzeigename,
  120. name: this.name,
  121. email: this.email,
  122. newsletter: false,
  123. }
  124. const response = await fetch(
  125. `${process.env.VUE_APP_API_URL}guest`, {
  126. method: 'POST',
  127. headers: {
  128. 'Content-Type': 'application/json',
  129. },
  130. body: JSON.stringify(data),
  131. }
  132. )
  133. if (response.status === 200) {
  134. this.anzeigename = ''
  135. this.name = ''
  136. this.email = ''
  137. this.success = true
  138. this.fetchGuests()
  139. } else {
  140. this.success = false
  141. this.fetchGuests()
  142. this.error = true
  143. this.errorReason = await response.json()
  144. }
  145. this.sending = false
  146. return false
  147. },
  148. resetForm () {
  149. this.anzeigename = ''
  150. this.name = ''
  151. this.email = ''
  152. this.success = false
  153. },
  154. async share () {
  155. location.href = "#";
  156. try {
  157. await navigator.share({ url:"https://reservation.ck.si/" })
  158. } catch (err) {
  159. console.log(`Error: ${err}`)
  160. }
  161. }
  162. },
  163. mounted() {
  164. this.fetchGuests()
  165. document.addEventListener('selectionchange', () => {
  166. this.selection = document.getSelection()
  167. // console.log(this.selection)
  168. if (this.selection) {
  169. this.selectionText = this.selection.toString()
  170. }
  171. });
  172. // this.$refs.details.$el
  173. },
  174. }
  175. </script>
  176. <style>
  177. .otf {
  178. width: 100%;
  179. /* background-color: rgb(167, 204, 247); */
  180. /* background-image: url('bg.gif'); */
  181. background-size: cover;
  182. display: flex;
  183. flex-direction: column;
  184. align-items: center;
  185. min-height: 100vh;
  186. position: relative;
  187. }
  188. .input-headline {
  189. color: rgb(255, 255, 255);
  190. font-size: 2.8vh;
  191. margin-bottom: .8vh;
  192. }
  193. .input-form {
  194. display: flex;
  195. flex-direction: column;
  196. width: 100%;
  197. max-width: 800px;
  198. mix-blend-mode: exclusion;
  199. margin-top: 4vh;
  200. z-index: 9;
  201. position: relative;
  202. }
  203. .input-text,
  204. .input-btn,
  205. .input-cb {
  206. color: #000;
  207. background: #fff;
  208. font-size: 2.8vh;
  209. font-family: 'JetBrains Mono', monospace;
  210. border: 0;
  211. padding: .5em 1em;
  212. line-height: 1.4;
  213. max-width: 100%;
  214. }
  215. .input-btn {
  216. color: #fff;
  217. background-color: #1e3a8e;
  218. border-top: 2px solid rgb(0, 0, 0);
  219. cursor: pointer;
  220. }
  221. .input-btn:hover {
  222. color: #fff;
  223. background: #3260eb;
  224. }
  225. .input-checkbox {
  226. margin: 0 1em 0 0;
  227. }
  228. @media screen and (max-width: 1000px) {
  229. .form-wrapper {
  230. margin-top: 4em;
  231. }
  232. .input-text,
  233. .input-btn {
  234. width: 100%;
  235. max-width: 100%;
  236. min-width: 0;
  237. text-align: center;
  238. }
  239. /* .input-form {
  240. position: absolute;
  241. bottom: 0;
  242. display: flex;
  243. flex-direction: column;
  244. } */
  245. }
  246. .input-text {
  247. width: auto;
  248. flex-grow: 1;
  249. }
  250. .details {
  251. color: #fff;
  252. background-color: #000;
  253. font-size: 10vw;
  254. max-width: 80em;
  255. margin: 3% 3% 200px;
  256. padding: 3%;
  257. }
  258. .share {
  259. max-width: 30em;
  260. width: 80%;
  261. mix-blend-mode: soft-light;
  262. }
  263. .share:hover {
  264. mix-blend-mode: difference;
  265. }
  266. .selection-text {
  267. position: fixed;
  268. z-index: 9999;
  269. font-size: 10vh;
  270. line-height: 1em;
  271. pointer-events: none;
  272. color: #ec4b73;
  273. mix-blend-mode: multiply;
  274. top: 10%;
  275. }
  276. </style>