IdCard.vue 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. <template>
  2. <v-card class="id-card">
  3. <div
  4. v-if="!appStore.altchaPayload || !idCardData"
  5. class="skeleton-container"
  6. >
  7. <div class="layout">
  8. <v-skeleton-loader
  9. type="image"
  10. :max-height="110"
  11. boilerplate
  12. />
  13. <v-skeleton-loader
  14. type="article"
  15. :max-height="110"
  16. boilerplate
  17. />
  18. </div>
  19. <v-btn v-if="!appStore.altchaPayload" flat class="btn-overlay" @click="onClick">
  20. <v-icon class="fas fa-eye" />
  21. </v-btn>
  22. <v-progress-circular v-else :indeterminate="true" class="btn-overlay" />
  23. <AltchaValidation
  24. v-if="showCaptcha"
  25. @verified="onVerified"
  26. />
  27. </div>
  28. <div v-else-if="idCardData">
  29. <div class="layout">
  30. <v-img
  31. :src="'data:image/png;base64,' + idCardData.photo"
  32. :height="110"
  33. />
  34. <div class="details">
  35. <div>Olivier Massot</div>
  36. <div>{{ idCardData.place }}</div>
  37. <div>{{ $t('id_age', { years: idCardData.age }) }}</div>
  38. <div>{{ $t(idCardData.status) }}</div>
  39. </div>
  40. </div>
  41. </div>
  42. </v-card>
  43. </template>
  44. <script setup lang="ts">
  45. import type { Ref } from '@vue/reactivity'
  46. import type { ComputedRef } from 'vue'
  47. const appStore = useAppStore()
  48. const downloadRequested: Ref<boolean> = ref(false)
  49. const showCaptcha: ComputedRef<boolean> = computed(() => {
  50. return downloadRequested.value && !appStore.altchaPayload
  51. })
  52. interface IdCardData {
  53. photo: string,
  54. age: number,
  55. place: string,
  56. status: string
  57. }
  58. const idCardData: Ref<IdCardData | null> = ref(null)
  59. const onClick = () => {
  60. if (appStore.altchaPayload) {
  61. submit()
  62. } else {
  63. downloadRequested.value = true
  64. }
  65. }
  66. const onVerified = () => {
  67. if (!downloadRequested.value) {
  68. return
  69. }
  70. downloadRequested.value = false
  71. setTimeout(() => {
  72. submit()
  73. }, 100)
  74. }
  75. const submit = async () => {
  76. const url = 'https://api.ogene.fr/api/id-card?payload=' + (appStore.altchaPayload ?? '');
  77. try {
  78. const response = await fetch(url, {
  79. method: 'GET',
  80. });
  81. if (!response.ok) {
  82. throw new Error(`HTTP error! status: ${response.status}`);
  83. }
  84. idCardData.value = await response.json();
  85. } catch (error) {
  86. console.error('There was a problem with the fetch operation: ', error);
  87. }
  88. }
  89. </script>
  90. <style scoped lang="scss">
  91. .id-card {
  92. width: 280px;
  93. height: 140px;
  94. max-width: 280px;
  95. max-height: 140px;
  96. min-width: 280px;
  97. min-height: 140px;
  98. padding: 15px;
  99. }
  100. .layout {
  101. display: flex;
  102. flex-direction: row;
  103. >*:first-child {
  104. width: 40%;
  105. }
  106. >* {
  107. width: 70%;
  108. }
  109. .v-skeleton-loader {
  110. :deep(.v-skeleton-loader__image) {
  111. max-height: 100%;
  112. }
  113. :deep(.v-skeleton-loader__article) {
  114. max-height: 100%;
  115. }
  116. :deep(.v-skeleton-loader__heading) {
  117. margin: 6px 16px;
  118. }
  119. }
  120. }
  121. .skeleton-container {
  122. position: relative;
  123. height: 100%;
  124. }
  125. .btn-overlay {
  126. position: absolute;
  127. top: 0;
  128. left: 0;
  129. width: 100%;
  130. height: 100% !important;
  131. display: flex;
  132. justify-content: center;
  133. align-items: center;
  134. opacity: 0.5;
  135. :deep(.v-icon) {
  136. font-size: 28px;
  137. }
  138. }
  139. altcha-widget {
  140. position: absolute;
  141. top: 15px; /* Ajustez cette valeur en fonction de la hauteur de votre bouton */
  142. left: 30px;
  143. background: rgb(var(--v-theme-surface));
  144. border-radius: 4px;
  145. z-index: 10;
  146. }
  147. .details {
  148. font-size: 13px;
  149. >div {
  150. margin: 2px 0;
  151. }
  152. }
  153. </style>