Olivier Massot 3 лет назад
Родитель
Сommit
08e589ec0c
4 измененных файлов с 270 добавлено и 3 удалено
  1. 6 1
      lang/fr-FR.js
  2. 4 2
      nuxt.config.js
  3. 2 0
      package.json
  4. 258 0
      pages/events/_id.vue

+ 6 - 1
lang/fr-FR.js

@@ -91,6 +91,11 @@ export default (_context, _locale) => {
     on_day: 'Le',
     from_day: 'Du',
     to_day: 'au',
-    more_to_know: 'En savoir plus'
+    more_to_know: 'En savoir plus',
+    description: 'Description',
+    keywords: 'Mots-clés',
+    share: 'Partager',
+    share_on: 'Partager sur',
+    share_by_email: 'Partager par email',
   })
 }

+ 4 - 2
nuxt.config.js

@@ -52,7 +52,8 @@ export default {
     // https://go.nuxtjs.dev/typescript
     '@nuxt/typescript-build',
     // https://go.nuxtjs.dev/vuetify
-    '@nuxtjs/vuetify'
+    '@nuxtjs/vuetify',
+    '@nuxtjs/fontawesome'
   ],
 
   // Modules: https://go.nuxtjs.dev/config-modules
@@ -74,7 +75,8 @@ export default {
         ]
       }
     ],
-    '@nuxtjs/date-fns'
+    '@nuxtjs/date-fns',
+    'vue-social-sharing/nuxt'
   ],
   dateFns: {
     defaultLocale: 'fr-FR',

+ 2 - 0
package.json

@@ -26,6 +26,7 @@
     "@fortawesome/vue-fontawesome": "^2.0.2",
     "@nuxtjs/axios": "^5.13.6",
     "@nuxtjs/date-fns": "^1.5.0",
+    "@nuxtjs/fontawesome": "^1.1.2",
     "@nuxtjs/i18n": "^7.0.3",
     "core-js": "^3.15.1",
     "date-fns": "^2.29.1",
@@ -35,6 +36,7 @@
     "nuxt": "^2.15.7",
     "nuxt-fontawesome": "^0.4.0",
     "nuxt-leaflet": "^0.0.25",
+    "vue-social-sharing": "^3.0.9",
     "vue2-leaflet": "^2.7.1",
     "vue2-leaflet-markercluster": "^3.1.0",
     "vuetify": "^2.5.5"

+ 258 - 0
pages/events/_id.vue

@@ -0,0 +1,258 @@
+<template>
+  <LayoutContainer>
+    <header class="mb-4">
+      <v-layout>
+        <v-btn
+          :to="{path: '/events', query: { theme: theme, hideTitle: hideTitle }}"
+          nuxt
+          plain
+        >
+          <font-awesome-icon class="icon mr-1" :icon="['fas', 'chevron-left']" />
+          {{ $t('go_back') }}
+        </v-btn>
+      </v-layout>
+    </header>
+
+    <v-container class="content">
+      <v-row>
+        <v-col cols="6" class="pr-6">
+          <img
+            v-if="publicEvent.imageId"
+            :src="publicEvent.imageId ? 'https://api.opentalent.fr/app.php/_internal/secure/files/' + publicEvent.imageId + '/raw' : '/images/event-default.jpg'"
+            alt="banner"
+            style="max-width: 100%"
+          >
+        </v-col>
+        <v-col cols="6" class="pl-6">
+          <v-container class="d-flex flex-column" style="min-height: 100%">
+            <v-row class="py-2">
+              <h2>{{ publicEvent.name }}</h2>
+            </v-row>
+            <v-row class="py-2">
+              <table class="infos">
+                <tr v-if="publicEvent.datetimeStart" class="pa-1">
+                  <td class="pt-1">
+                    <font-awesome-icon :icon="['fas', 'calendar']" class="icon mr-2" />
+                  </td>
+                  <td class="pa-1">
+                    <span>
+                      {{ dateUtils.formatDateIntervalFor(new Date(publicEvent.datetimeStart), new Date(publicEvent.datetimeEnd), false) }}
+                    </span>
+                  </td>
+                </tr>
+
+                <tr v-if="publicEvent.address.addressCity">
+                  <td class="pt-1">
+                    <font-awesome-icon class="icon" :icon="['fas', 'map-marker-alt']" />
+                  </td>
+                  <td class="pa-1">
+                    <span v-if="publicEvent.roomName" style="white-space: pre-line;">{{ publicEvent.roomName }}<br></span>
+                    <span v-if="publicEvent.address.streetAddress" style="white-space: pre-line;">{{ publicEvent.address.streetAddress }}<br></span>
+                    <span>{{ publicEvent.address.addressCity }}</span>
+                  </td>
+                </tr>
+              </table>
+            </v-row>
+            <v-row class="py-2 flex">
+              <h4 class="mt-2 mb-3">
+                {{ $t('description') }}
+              </h4>
+              <p class="flex">
+                {{ publicEvent.description }}
+              </p>
+            </v-row>
+            <v-row v-if="publicEvent.url" justify="end" class="py-2">
+              <v-btn :href="publicEvent.url" target="_blank">{{ $t("more_to_know") }}</v-btn>
+            </v-row>
+          </v-container>
+        </v-col>
+      </v-row>
+      <v-row>
+        <v-col cols="12">
+          <v-responsive width="100%" height="300px">
+            <no-ssr>
+              <l-map
+                id="map"
+                :zoom="13"
+                :center="[publicEvent.address.latitude, publicEvent.address.longitude]"
+                :options="{ scrollWheelZoom: false, zoomSnap: 0.25 }"
+              >
+                <l-tile-layer
+                  url="http://{s}.tile.osm.org/{z}/{x}/{y}.png"
+                  attribution="&copy; <a href='http://osm.org/copyright'>OpenStreetMap</a> contributors"
+                />
+                <l-marker
+                  :key="publicEvent.id"
+                  :lat-lng="[publicEvent.address.latitude, publicEvent.address.longitude]"
+                >
+                  <l-popup>
+                    <b>{{ publicEvent.name }}</b><br>
+                    <span v-if="publicEvent.mapAddress">
+                      {{ publicEvent.address.postalCode }} {{ publicEvent.address.addressCity }}
+                    </span><br>
+                  </l-popup>
+                </l-marker>
+              </l-map>
+            </no-ssr>
+          </v-responsive>
+        </v-col>
+      </v-row>
+      <v-row align-content="space-between">
+        <v-col cols="2">
+        </v-col>
+        <v-spacer />
+        <v-col cols="5" class="d-flex flex-column align-end">
+          <h5 class="ma-2">
+            {{ $t('share') }}
+          </h5>
+          <div class="d-flex flex-row align-items-end flex-wrap">
+            <ShareNetwork
+              v-for="socialNetwork in socialNetworks"
+              :key="socialNetwork.network"
+              :network="socialNetwork.network"
+              :url="localUrl"
+              :title="publicEvent.name"
+              :description="publicEvent.description"
+              hashtags="opentalent,event"
+              :media="publicEvent.imageId ? 'https://api.opentalent.fr/app.php/_internal/secure/files/' + publicEvent.imageId + '/raw' : '/images/event-default.jpg'"
+              class="social-link"
+            >
+              <a
+                :title="$t('share_on') + ' ' + socialNetwork.name"
+                :style="{color: socialNetwork.color}"
+              >
+                <font-awesome-icon
+                  class="icon social-icon"
+                  :icon="socialNetwork.icon"
+                />
+              </a>
+            </ShareNetwork>
+          </div>
+        </v-col>
+      </v-row>
+    </v-container>
+
+  </LayoutContainer>
+</template>
+
+
+<script lang="ts">
+import Vue from 'vue'
+// eslint-disable-next-line import/no-named-as-default
+import EventsProvider from '~/services/data/EventsProvider'
+import DatesUtils from "~/services/utils/dateUtils";
+
+export default Vue.extend({
+  data () {
+    return {
+      theme: this.$route.query.theme ?? 'orange',
+      hideTitle: this.$route.query.hideTitle === 'true',
+      dateUtils: new DatesUtils(this.$dateFns, this.$t, this.$i18n),
+      localUrl: location.href,
+      socialNetworks: [
+        { network: 'facebook', name: 'Facebook', icon: ['fab', 'facebook-f'], color: '#1877f2' },
+        { network: 'messenger', name: 'Messenger', icon: ['fab', 'facebook-messenger'], color: '#0084ff' },
+        { network: 'twitter', name: 'Twitter', icon: ['fab', 'twitter'], color: '#1da1f2' },
+        { network: 'reddit', name: 'Reddit', icon: ['fab', 'reddit-alien'], color: '#ff4500' },
+        { network: 'telegram', name: 'Telegram', icon: ['fab', 'telegram-plane'], color: '#0088cc' },
+        { network: 'whatsapp', name: 'Whatsapp', icon: ['fab', 'whatsapp'], color: '#25d366' },
+        { network: 'email', name: 'Email', icon: ['fa', 'envelope'], color: '#333333' },
+      ] // @see https://nicolasbeauvais.github.io/vue-social-sharing/?path=/story/vuesocialsharing--multiple-share-networks
+    }
+  },
+  async asyncData ({
+                     params, $axios
+                   }): Promise<{ publicEvent: PublicEvent }> {
+    return await new EventsProvider($axios).getById(params.id).then((res) => {
+      return { publicEvent: res }
+    })
+  }
+})
+</script>
+
+<style scoped lang="scss">
+@import 'assets/style/variables.scss';
+
+.content {
+  margin: 18px 10%;
+  max-width: 80%;
+}
+
+h2 {
+  color: var(--v-primary-base);
+  font-size: 22px;
+  text-transform: uppercase;
+}
+
+h4 {
+  color: #666;
+  border-bottom: solid 1px var(--v-primary-base);
+  font-size: 22px;
+}
+
+.content {
+  color: #4d4d4d;
+}
+
+.infos {
+  text-transform: uppercase;
+  font-weight: 700;
+}
+
+@media screen and (min-width: 600px) {
+  .description {
+    border-right: solid 2px var(--v-primary-base);
+    width: 45%;
+    padding-right: 5%;
+  }
+
+  .contact {
+    width: 45%;
+    padding-left: 5%;
+  }
+}
+
+.contact td {
+  padding: 6px 12px;
+}
+
+.contact .icon {
+  color: var(--v-primary-base);
+}
+
+.social-link {
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  padding: 6px;
+  text-decoration: none;
+  position:relative;
+}
+
+.social-link:hover {
+  text-decoration: underline;
+}
+
+.social-icon {
+  font-size: 22px;
+  margin: auto 6px;
+}
+
+.social-link:before {
+  display:block;
+  content:" ";
+  position:absolute;
+  z-index:100;
+  background:rgba(255, 255, 255, 0.3);
+  top:0;
+  left:0;
+  right:0;
+  bottom:0;
+  opacity:0;
+}
+.social-link:hover:before {
+  opacity:1;
+}
+
+</style>
+