_id.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. <template>
  2. <LayoutContainer>
  3. <header class="mb-4">
  4. <v-layout>
  5. <v-btn
  6. v-if="parent"
  7. :to="{path: '/structures', query: { parent: parent, view: view, theme: theme, hideTitle: hideTitle }}"
  8. nuxt
  9. plain
  10. >
  11. <font-awesome-icon class="icon mr-1" :icon="['fas', 'chevron-left']" />
  12. {{ $t('go_back') }}
  13. </v-btn>
  14. </v-layout>
  15. </header>
  16. <v-container class="content">
  17. <v-layout class="flex-row align-center mb-4">
  18. <v-img
  19. v-if="structure.logoId"
  20. :src="'https://api.opentalent.fr/app.php/_internal/secure/files/' + structure.logoId + '/0x60'"
  21. alt="logo"
  22. max-width="60"
  23. />
  24. <h2 class="flex mx-4 d-flex align-center">
  25. {{ structure.name }}
  26. </h2>
  27. <div class="d-flex flex-row align-center">
  28. <a v-if="structure.facebook" :href="structure.facebook" class="facebook" target="_blank" :title="$t('find_us_on') + ' Facebook'">
  29. <font-awesome-icon class="icon social-icon" :icon="['fab', 'facebook']" />
  30. </a>
  31. <a v-if="structure.instagram" :href="structure.instagram" class="instagram" target="_blank" :title="$t('find_us_on') + ' Instagram'">
  32. <font-awesome-icon class="icon social-icon" :icon="['fab', 'instagram-square']" />
  33. </a>
  34. <a v-if="structure.twitter" :href="structure.twitter" class="twitter" target="_blank" title="$t('find_us_on') + ' Twitter'">
  35. <font-awesome-icon class="icon social-icon" :icon="['fab', 'twitter']" />
  36. </a>
  37. <a v-if="structure.youtube" :href="structure.youtube" class="youtube" target="_blank" title="$t('find_us_on') + ' Youtube'">
  38. <font-awesome-icon class="icon social-icon" :icon="['fab', 'youtube']" />
  39. </a>
  40. </div>
  41. </v-layout>
  42. <v-row>
  43. <v-col class="d-flex justify-center" cols="12">
  44. <img
  45. v-if="structure.imageId"
  46. :src="'https://api.opentalent.fr/app.php/_internal/secure/files/' + structure.imageId + '/raw'"
  47. alt="banner"
  48. style="max-height: 300px;max-width: 100%"
  49. >
  50. </v-col>
  51. </v-row>
  52. <v-row>
  53. <v-col cols="12">
  54. <div
  55. v-if="structure.practices"
  56. class="d-flex justify-center flex-wrap"
  57. >
  58. <v-chip
  59. v-for="practice in structure.practices"
  60. :key="practice"
  61. class="ma-1"
  62. label
  63. >
  64. {{ $t(practice) }}
  65. </v-chip>
  66. </div>
  67. </v-col>
  68. </v-row>
  69. <v-row class="mb-4">
  70. <v-col cols="12" class="d-flex flex-row justify-center">
  71. <v-btn
  72. v-for="article in structure.articles"
  73. :key="article.id"
  74. :href="article.link ? ((article.link.match(/https?:\/\/.*/) ? '' : 'https://') + article.link) : ''"
  75. target="_blank"
  76. small
  77. color="primary"
  78. class="ma-2"
  79. :title="article.title"
  80. >
  81. <font-awesome-icon class="icon mr-1" :icon="['fas', 'star']" />
  82. {{ $t('spot_on_from') + ' ' + new Date(article.date).toLocaleDateString($i18n.locale) }}
  83. </v-btn>
  84. </v-col>
  85. </v-row>
  86. <v-divider class="my-2" />
  87. <v-row class="my-2 py-2">
  88. <v-col
  89. cols="12"
  90. sm="6"
  91. class="description"
  92. >
  93. <div class="d-flex flex-row mb-3">
  94. <h4>{{ $t('descriptive') }}</h4>
  95. <v-spacer />
  96. </div>
  97. <div class="pa-2">
  98. <p v-if="structure.description" class="text-justify">
  99. {{ structure.description }}
  100. </p>
  101. <i v-else>({{ $t('no_description') }})</i>
  102. </div>
  103. </v-col>
  104. <v-col
  105. cols="12"
  106. sm="6"
  107. class="contact"
  108. >
  109. <div class="d-flex flex-row mb-3">
  110. <h4>{{ $t('contact') }}</h4>
  111. <v-spacer />
  112. </div>
  113. <table>
  114. <tr
  115. v-if="structure.mapAddress && (structure.mapAddress.postalCode !== structure.postalAddress.postalCode || structure.mapAddress.streetAddress !== structure.postalAddress.streetAddress)"
  116. >
  117. <td style="vertical-align: top">
  118. <font-awesome-icon class="icon" :icon="['fas', 'map-marker-alt']" />
  119. </td>
  120. <td class="mx-2" style="vertical-align: top">
  121. <span v-if="structure.mapAddress.streetAddress" style="white-space: pre-line;">{{ structure.mapAddress.streetAddress }}<br></span>
  122. <span v-if="structure.mapAddress.postalCode">{{ structure.mapAddress.postalCode }} </span>
  123. {{ structure.mapAddress.addressCity }}
  124. </td>
  125. </tr>
  126. <tr v-if="structure.postalAddress">
  127. <td style="vertical-align: top">
  128. <font-awesome-icon class="icon" :icon="['fas', 'envelope']" />
  129. </td>
  130. <td class="mx-2" style="vertical-align: top">
  131. <div style="text-decoration: underline; font-size: 0.9em; margin-bottom: 0.25em;">
  132. {{ $t('to_mail_us') }} :
  133. </div>
  134. <span>{{ structure.name }}<br></span>
  135. <span v-if="structure.postalAddress.streetAddress" style="white-space: pre-line;">{{ structure.postalAddress.streetAddress }}<br></span>
  136. <span v-if="structure.postalAddress.postalCode">{{ structure.postalAddress.postalCode }} </span>
  137. {{ structure.postalAddress.addressCity }}
  138. </td>
  139. </tr>
  140. <tr>
  141. <td>
  142. <font-awesome-icon class="icon" :icon="['fas', 'phone-alt']" />
  143. </td>
  144. <td class="phone">
  145. <div v-if="structure.telphone || structure.mobilPhone">
  146. <a v-if="showTel" :href="'tel:' + (structure.telphone || structure.mobilPhone)" class="neutral">
  147. {{ formatPhoneNumber(structure.telphone || structure.mobilPhone) }}
  148. </a>
  149. <v-btn v-else small @click="showTel = 1">
  150. {{ $t('show_tel') }}
  151. </v-btn>
  152. </div>
  153. <span v-else>-</span>
  154. </td>
  155. </tr>
  156. <tr>
  157. <td>
  158. <font-awesome-icon class="icon" :icon="['fas', 'at']" />
  159. </td>
  160. <td class="mail">
  161. <div v-if="structure.email">
  162. <a v-if="showMail" :href="'mailto:' + structure.email" class="neutral">
  163. {{ structure.email }}
  164. </a>
  165. <v-btn v-else small @click="showMail = 1">
  166. {{ $t('show_email') }}
  167. </v-btn>
  168. </div>
  169. <span v-else>-</span>
  170. </td>
  171. </tr>
  172. <tr>
  173. <td>
  174. <font-awesome-icon class="icon" :icon="['fas', 'globe-europe']" />
  175. </td>
  176. <td class="website">
  177. <a class="neutral" :href="structure.website" target="_blank">{{ structure.website }}</a>
  178. </td>
  179. </tr>
  180. <tr>
  181. <td>
  182. <font-awesome-icon class="icon" :icon="['fas', 'project-diagram']" />
  183. </td>
  184. <td class="network">
  185. <NuxtLink
  186. v-if="parent && (structure.n1Id !== parent)"
  187. class="neutral"
  188. :to="{path: '/structures/' + structure.n1Id, query: { parent: parent, view: view, theme: theme }}"
  189. nuxt
  190. >
  191. {{ structure.n1Name }}
  192. </NuxtLink>
  193. <div v-else>
  194. {{ structure.n1Name }}
  195. </div>
  196. </td>
  197. </tr>
  198. </table>
  199. </v-col>
  200. </v-row>
  201. <v-row v-if="structure.latitude && structure.longitude">
  202. <v-col cols="12">
  203. <v-responsive width="100%" height="450px">
  204. <no-ssr>
  205. <l-map
  206. id="map"
  207. :zoom="13"
  208. :center="[structure.latitude, structure.longitude]"
  209. :options="{ scrollWheelZoom: false, zoomSnap: 0.25 }"
  210. >
  211. <l-tile-layer
  212. url="http://{s}.tile.osm.org/{z}/{x}/{y}.png"
  213. attribution="&copy; <a href='http://osm.org/copyright'>OpenStreetMap</a> contributors"
  214. />
  215. <l-marker
  216. :key="structure.id"
  217. :lat-lng="[structure.latitude, structure.longitude]"
  218. >
  219. <l-popup>
  220. <b>{{ structure.name }}</b><br>
  221. <span v-if="structure.mapAddress">
  222. {{ structure.mapAddress.postalCode }} {{ structure.mapAddress.addressCity }}
  223. </span><br>
  224. <a :href="structure.website" target="_blank">{{ structure.website }}</a>
  225. </l-popup>
  226. </l-marker>
  227. </l-map>
  228. </no-ssr>
  229. </v-responsive>
  230. </v-col>
  231. </v-row>
  232. </v-container>
  233. </LayoutContainer>
  234. </template>
  235. <script lang="ts">
  236. import Vue from 'vue'
  237. // eslint-disable-next-line import/no-named-as-default
  238. import parsePhoneNumber from 'libphonenumber-js'
  239. import StructuresProvider from '~/services/data/StructuresProvider'
  240. export default Vue.extend({
  241. async asyncData ({
  242. params, $axios
  243. }): Promise<{ structure: Structure }> {
  244. return await new StructuresProvider($axios).getById(Number(params.id)).then((res) => {
  245. return { structure: res }
  246. })
  247. },
  248. data (): object {
  249. return {
  250. parent: this.$route.query.parent ? parseInt(this.$route.query.parent as string) : null,
  251. view: this.$route.query.view ?? 'map',
  252. theme: this.$route.query.theme ?? 'orange',
  253. hideTitle: this.$route.query.hideTitle ?? false,
  254. showTel: false,
  255. showMail: false
  256. }
  257. },
  258. methods: {
  259. formatPhoneNumber (number: string): string {
  260. const parsed = parsePhoneNumber(number)
  261. return parsed ? parsed.formatNational() : ''
  262. }
  263. }
  264. })
  265. </script>
  266. <style scoped lang="scss">
  267. @import 'assets/style/variables.scss';
  268. .content {
  269. margin: 18px 10%;
  270. max-width: 80%;
  271. }
  272. h2 {
  273. color: var(--v-primary-base);
  274. font-size: 22px;
  275. }
  276. h4 {
  277. color: #666;
  278. border-bottom: solid 1px var(--v-primary-base);
  279. font-size: 22px;
  280. }
  281. .social-icon {
  282. font-size: 22px;
  283. color: #808080;
  284. margin: auto 8px;
  285. }
  286. .social-icon:hover {
  287. color: #595959;
  288. }
  289. .content {
  290. color: #4d4d4d;
  291. }
  292. @media screen and (min-width: 600px) {
  293. .description {
  294. border-right: solid 2px var(--v-primary-base);
  295. width: 45%;
  296. padding-right: 5%;
  297. }
  298. .contact {
  299. width: 45%;
  300. padding-left: 5%;
  301. }
  302. }
  303. .contact td {
  304. padding: 6px 12px;
  305. }
  306. .contact .icon {
  307. color: var(--v-primary-base);
  308. }
  309. </style>