feat(admin): add document preview functionality to adult verification
- Implemented a preview section for adult verification documents, allowing users to view images and PDFs inline. - Added localization support for preview titles and messages in German, English, and Spanish. - Enhanced the component's state management to handle preview visibility and cleanup.
This commit is contained in:
@@ -42,6 +42,9 @@
|
||||
"reject": "Ablehnen",
|
||||
"resetPending": "Auf Prüfung setzen",
|
||||
"openDocument": "Dokument ansehen",
|
||||
"previewTitle": "Nachweis-Vorschau",
|
||||
"closePreview": "Vorschau schließen",
|
||||
"previewUnavailable": "Für diesen Dateityp ist hier keine Vorschau verfügbar.",
|
||||
"empty": "Keine passenden Anfragen gefunden.",
|
||||
"loadError": "Die Freigaben konnten nicht geladen werden.",
|
||||
"updateError": "Der Status konnte nicht geändert werden.",
|
||||
|
||||
@@ -42,6 +42,9 @@
|
||||
"reject": "Reject",
|
||||
"resetPending": "Set pending",
|
||||
"openDocument": "Open document",
|
||||
"previewTitle": "Proof preview",
|
||||
"closePreview": "Close preview",
|
||||
"previewUnavailable": "No inline preview is available for this file type.",
|
||||
"empty": "No matching requests found.",
|
||||
"loadError": "Could not load approvals.",
|
||||
"updateError": "Could not update the status.",
|
||||
|
||||
@@ -42,6 +42,9 @@
|
||||
"reject": "Rechazar",
|
||||
"resetPending": "Poner en revisión",
|
||||
"openDocument": "Abrir documento",
|
||||
"previewTitle": "Vista previa de la prueba",
|
||||
"closePreview": "Cerrar vista previa",
|
||||
"previewUnavailable": "No hay vista previa integrada para este tipo de archivo.",
|
||||
"empty": "No se han encontrado solicitudes.",
|
||||
"loadError": "No se pudieron cargar las aprobaciones.",
|
||||
"updateError": "No se pudo actualizar el estado.",
|
||||
|
||||
@@ -66,6 +66,24 @@
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section v-if="previewUrl" class="adult-verification__preview surface-card">
|
||||
<div class="adult-verification__preview-header">
|
||||
<div>
|
||||
<strong>{{ $t('admin.adultVerification.previewTitle') }}</strong>
|
||||
<span v-if="previewRow">{{ previewRow.username }} · {{ previewRow.adultVerificationRequest?.originalName }}</span>
|
||||
</div>
|
||||
<button type="button" class="secondary" @click="clearPreview">
|
||||
{{ $t('admin.adultVerification.closePreview') }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<img v-if="isImagePreview" :src="previewUrl" class="adult-verification__preview-image" />
|
||||
<iframe v-else-if="isPdfPreview" :src="previewUrl" class="adult-verification__preview-pdf" />
|
||||
<div v-else class="adult-verification__state">
|
||||
{{ $t('admin.adultVerification.previewUnavailable') }}
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -79,7 +97,10 @@ export default {
|
||||
return {
|
||||
loading: false,
|
||||
statusFilter: 'pending',
|
||||
rows: []
|
||||
rows: [],
|
||||
previewUrl: '',
|
||||
previewMimeType: '',
|
||||
previewRow: null
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -90,6 +111,12 @@ export default {
|
||||
{ value: 'rejected', label: this.$t('admin.adultVerification.filters.rejected') },
|
||||
{ value: 'all', label: this.$t('admin.adultVerification.filters.all') }
|
||||
];
|
||||
},
|
||||
isImagePreview() {
|
||||
return this.previewMimeType.startsWith('image/');
|
||||
},
|
||||
isPdfPreview() {
|
||||
return this.previewMimeType === 'application/pdf';
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -109,6 +136,7 @@ export default {
|
||||
},
|
||||
async changeFilter(filter) {
|
||||
this.statusFilter = filter;
|
||||
this.clearPreview();
|
||||
await this.load();
|
||||
},
|
||||
async setStatus(row, status) {
|
||||
@@ -125,16 +153,28 @@ export default {
|
||||
const response = await apiClient.get(`/api/admin/users/${row.id}/adult-verification/document`, {
|
||||
responseType: 'blob'
|
||||
});
|
||||
const url = window.URL.createObjectURL(response.data);
|
||||
window.open(url, '_blank', 'noopener');
|
||||
window.setTimeout(() => window.URL.revokeObjectURL(url), 10000);
|
||||
this.clearPreview();
|
||||
this.previewMimeType = response.data.type || '';
|
||||
this.previewUrl = window.URL.createObjectURL(response.data);
|
||||
this.previewRow = row;
|
||||
} catch (error) {
|
||||
showApiError(this, error, this.$t('admin.adultVerification.documentError'));
|
||||
}
|
||||
},
|
||||
clearPreview() {
|
||||
if (this.previewUrl) {
|
||||
window.URL.revokeObjectURL(this.previewUrl);
|
||||
}
|
||||
this.previewUrl = '';
|
||||
this.previewMimeType = '';
|
||||
this.previewRow = null;
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
await this.load();
|
||||
},
|
||||
beforeUnmount() {
|
||||
this.clearPreview();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -147,7 +187,8 @@ export default {
|
||||
|
||||
.adult-verification__hero,
|
||||
.adult-verification__filters,
|
||||
.adult-verification__list {
|
||||
.adult-verification__list,
|
||||
.adult-verification__preview {
|
||||
background: linear-gradient(180deg, rgba(255, 252, 247, 0.97), rgba(250, 244, 235, 0.95));
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-lg);
|
||||
@@ -232,10 +273,41 @@ export default {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.adult-verification__preview-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
.adult-verification__preview-header > div {
|
||||
display: grid;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.adult-verification__preview-image,
|
||||
.adult-verification__preview-pdf {
|
||||
width: 100%;
|
||||
border-radius: var(--radius-md);
|
||||
border: 1px solid rgba(93, 64, 55, 0.08);
|
||||
background: rgba(255, 255, 255, 0.78);
|
||||
}
|
||||
|
||||
.adult-verification__preview-image {
|
||||
max-height: 70vh;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.adult-verification__preview-pdf {
|
||||
min-height: 70vh;
|
||||
}
|
||||
|
||||
@media (max-width: 760px) {
|
||||
.adult-verification__hero,
|
||||
.adult-verification__filters,
|
||||
.adult-verification__list {
|
||||
.adult-verification__list,
|
||||
.adult-verification__preview {
|
||||
padding: 18px;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user