feat: secure KYC storage, Google OAuth, terms gating
This commit is contained in:
@@ -2,17 +2,15 @@
|
||||
|
||||
import { useState } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import Image from "next/image";
|
||||
import { reviewVerificationAction } from "@/features/organizer/actions";
|
||||
|
||||
type Verification = {
|
||||
id: string;
|
||||
fullName: string;
|
||||
/** NIK plaintext, sudah di-decrypt di server sebelum sampai ke komponen ini. */
|
||||
nik: string;
|
||||
birthDate: Date;
|
||||
address: string;
|
||||
ktpImageUrl: string;
|
||||
selfieUrl: string;
|
||||
bankName: string;
|
||||
bankAccountNumber: string;
|
||||
bankAccountName: string;
|
||||
@@ -90,8 +88,14 @@ export function ReviewCard({ verification }: { verification: Verification }) {
|
||||
</div>
|
||||
|
||||
<div className="mt-5 grid gap-4 sm:grid-cols-2">
|
||||
<ImagePreview label="Foto KTP" url={verification.ktpImageUrl} />
|
||||
<ImagePreview label="Selfie + KTP" url={verification.selfieUrl} />
|
||||
<ImagePreview
|
||||
label="Foto KTP"
|
||||
src={`/api/files/kyc/${verification.id}/ktp`}
|
||||
/>
|
||||
<ImagePreview
|
||||
label="Selfie + KTP"
|
||||
src={`/api/files/kyc/${verification.id}/selfie`}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{verification.status === "REJECTED" && verification.rejectionReason && (
|
||||
@@ -196,26 +200,25 @@ function Field({
|
||||
);
|
||||
}
|
||||
|
||||
function ImagePreview({ label, url }: { label: string; url: string }) {
|
||||
function ImagePreview({ label, src }: { label: string; src: string }) {
|
||||
return (
|
||||
<div>
|
||||
<p className="mb-1.5 text-xs font-semibold uppercase tracking-wide text-neutral-500">
|
||||
{label}
|
||||
</p>
|
||||
<a
|
||||
href={url}
|
||||
href={src}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="block overflow-hidden rounded-xl border border-neutral-200 bg-neutral-100"
|
||||
>
|
||||
<div className="relative aspect-[4/3] w-full">
|
||||
<Image
|
||||
src={url}
|
||||
{/* Secure endpoint sends Cache-Control: private,no-store. Use plain <img> to skip Next/Image optimizer. */}
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
src={src}
|
||||
alt={label}
|
||||
fill
|
||||
unoptimized
|
||||
className="object-cover"
|
||||
sizes="(min-width: 640px) 50vw, 100vw"
|
||||
className="h-full w-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
Reference in New Issue
Block a user