From b6fa23dd060f2fb10459c5efbb95830fca7504d0 Mon Sep 17 00:00:00 2001 From: Joey Collado Date: Wed, 11 Feb 2026 20:38:51 +0800 Subject: [PATCH 1/5] feature/Security: Institutional Verification Flow (KYC Mock) --- .../shared/verification-progress.tsx | 368 ++++++++++++++++++ client/components/views/dashboard-view.tsx | 1 + "\357\200\272" | 6 + 3 files changed, 375 insertions(+) create mode 100644 client/components/shared/verification-progress.tsx create mode 100644 "\357\200\272" diff --git a/client/components/shared/verification-progress.tsx b/client/components/shared/verification-progress.tsx new file mode 100644 index 0000000..a9afccf --- /dev/null +++ b/client/components/shared/verification-progress.tsx @@ -0,0 +1,368 @@ +"use client"; + +import React, { useState, useEffect, useMemo, useRef } from "react"; +import { motion, AnimatePresence } from "framer-motion"; +import { + ShieldCheck, + Scan, + UserCheck, + Activity, + Loader2, + AlertCircle, + RefreshCw, +} from "lucide-react"; +import { Card, CardContent } from "@/components/ui/card"; +import { Badge } from "@/components/ui/badge"; +import { Progress } from "@/components/ui/progress"; +import { Button } from "@/components/ui/button"; + +// type definitions so that ui can't enter an undefined state +export type VerificationStatus = + | "idle" + | "scanning" + | "liveness" + | "analyzing" + | "completed" + | "failed"; + +interface VerificationProgressProps { + status?: VerificationStatus; + onComplete?: () => void; + isSimulated?: boolean; +} + +// stages +const STAGES = [ + { id: "scanning", label: "ID Scan", icon: Scan }, + { id: "liveness", label: "Liveness", icon: UserCheck }, + { id: "analyzing", label: "Analysis", icon: Activity }, +] as const; + +export function VerificationProgress({ + status: externalStatus = "idle", //the control + onComplete, + isSimulated = true, //set to false for control otherwise true if automated rendering +}: VerificationProgressProps) { + + const [mounted, setMounted] = useState(false); + const [internalStatus, setInternalStatus] = + useState("idle"); + const [resetKey, setResetKey] = useState(0); + + const onCompleteRef = useRef(onComplete); + + useEffect(() => { + onCompleteRef.current = onComplete; + }, [onComplete]); + + // Determine if we listen to the simulation or an external API prop + const currentStatus = isSimulated ? internalStatus : externalStatus; + + useEffect(() => { + setMounted(true); + }, []); + + // engine flow of simulation logic, this handles the automated transition of 3 stages + useEffect(() => { + // stop if not simulated, not mounted, or if already in completed state + if (!isSimulated || !mounted || internalStatus === "failed" || internalStatus === "completed") return; + + const sequence: VerificationStatus[] = [ + "scanning", + "liveness", + "analyzing", + "completed", + ]; + + // find current position in the sequence + let currentIdx = sequence.indexOf(internalStatus); + if (currentIdx === -1) currentIdx = 0; + + // instant feel + const timer = setInterval(() => { + const nextIdx = currentIdx + 1; + if (nextIdx < sequence.length) { + setInternalStatus(sequence[nextIdx]); + } else { + setInternalStatus("completed"); + // Accessing the stable ref ensures we don't trigger infinite loops in Next.js 16 + onCompleteRef.current?.(); + clearInterval(timer); + } + }, 800); + + return () => clearInterval(timer); + + // logic simulation integrity trigger + }, [isSimulated, mounted, resetKey, internalStatus]); + + const currentStepIndex = useMemo(() => { + // calculates the progress bar without rerunning on every render + const statusMap: Record = { + idle: 0, + scanning: 0, + liveness: 1, + analyzing: 2, + completed: 3, + failed: 1, // failure visually resets the progress to the liveness step + }; + return statusMap[currentStatus]; + }, [currentStatus]); + + if (!mounted) return null; + + return ( +
+ + + + {/* Active processing state - shown during scanning, liveness, and analysis stages */} + {currentStatus !== "completed" && currentStatus !== "failed" ? ( + + {/* Header */} +
+
+

+ Security Protocol +

+

+ Identity Verification +

+
+ + {currentStatus.toUpperCase()} + +
+ + {/* Stages and progress bar */} +
+ +
+ {STAGES.map((stage, idx) => { + const Icon = stage.icon; + const isActive = idx === currentStepIndex; + const isPassed = idx < currentStepIndex; + + return ( +
+
+ +
+ + {stage.label} + +
+ ); + })} +
+
+ + {/* scanner animation */} +
+ +
+
+ + + {currentStatus === "scanning" && "SCANNING_DOCUMENT..."} + {currentStatus === "liveness" && + "MATCHING_BIOMETRICS..."} + {currentStatus === "analyzing" && + "COMPUTING_HASH_VERIFICATION..."} + +
+
+
+
+ ) : currentStatus === "completed" ? ( + /* Success state - Displays the pulsating green shield and verified status */ + +
+ {/* Pulsating bloom effect */} + + + {/* Glowing Shield Container with pulse */} + + + +
+ +
+ + Verified + + + Identity successfully verified. + +
+ + {/* Final state status badge with pulse verification */} + + + KYC_VERIFIED + + +
+ ) : ( + /* Failure state */ + +
+ +
+
+

+ Verification Failed +

+

+ Security mismatch detected during biometrics. +

+
+ +
+ )} +
+
+
+ + {/* Temporary manual testing for debugging controls */} +
+ + +
+
+ ); +} \ No newline at end of file diff --git a/client/components/views/dashboard-view.tsx b/client/components/views/dashboard-view.tsx index cf0a50a..b2a77e2 100644 --- a/client/components/views/dashboard-view.tsx +++ b/client/components/views/dashboard-view.tsx @@ -4,6 +4,7 @@ import Image from 'next/image' import { PortfolioOverview } from '@/components/portfolio-overview' import { AssetAllocationChart } from '@/components/asset-allocation-chart' import { ShariaCertificationHub } from '@/components/sharia-certification-hub' +import { VerificationProgress } from '@/components/shared/verification-progress' export function DashboardView() { return ( diff --git "a/\357\200\272" "b/\357\200\272" new file mode 100644 index 0000000..ae87b91 --- /dev/null +++ "b/\357\200\272" @@ -0,0 +1,6 @@ +Merge branch 'dev' of https://github.com/hyperstack-solidity/apax into apax-3 +# Please enter a commit message to explain why this merge is necessary, +# especially if it merges an updated upstream into a topic branch. +# +# Lines starting with '#' will be ignored, and an empty message aborts +# the commit. From a415d139cc9fd9df5940fdc8f12b669b64b267dc Mon Sep 17 00:00:00 2001 From: Joey Collado Date: Wed, 11 Feb 2026 20:51:01 +0800 Subject: [PATCH 2/5] cleanup --- client/components/shared/verification-progress.tsx | 2 +- client/components/views/dashboard-view.tsx | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/client/components/shared/verification-progress.tsx b/client/components/shared/verification-progress.tsx index a9afccf..ff89d7a 100644 --- a/client/components/shared/verification-progress.tsx +++ b/client/components/shared/verification-progress.tsx @@ -41,7 +41,7 @@ const STAGES = [ export function VerificationProgress({ status: externalStatus = "idle", //the control onComplete, - isSimulated = true, //set to false for control otherwise true if automated rendering + isSimulated = false, //set to false for control otherwise true if automated rendering }: VerificationProgressProps) { const [mounted, setMounted] = useState(false); diff --git a/client/components/views/dashboard-view.tsx b/client/components/views/dashboard-view.tsx index b2a77e2..cf0a50a 100644 --- a/client/components/views/dashboard-view.tsx +++ b/client/components/views/dashboard-view.tsx @@ -4,7 +4,6 @@ import Image from 'next/image' import { PortfolioOverview } from '@/components/portfolio-overview' import { AssetAllocationChart } from '@/components/asset-allocation-chart' import { ShariaCertificationHub } from '@/components/sharia-certification-hub' -import { VerificationProgress } from '@/components/shared/verification-progress' export function DashboardView() { return ( From 7b89d35a82c91a680fc603d9abf407817551f654 Mon Sep 17 00:00:00 2001 From: Joey Collado Date: Wed, 11 Feb 2026 21:30:48 +0800 Subject: [PATCH 3/5] turn scanning animation into reusable component --- client/components/shared/scanning-beam.tsx | 38 ++++++++++ .../shared/verification-progress.tsx | 75 ++++++------------- 2 files changed, 59 insertions(+), 54 deletions(-) create mode 100644 client/components/shared/scanning-beam.tsx diff --git a/client/components/shared/scanning-beam.tsx b/client/components/shared/scanning-beam.tsx new file mode 100644 index 0000000..598f336 --- /dev/null +++ b/client/components/shared/scanning-beam.tsx @@ -0,0 +1,38 @@ +"use client"; + +import React from "react"; +import { motion } from "framer-motion"; + +interface ScanningBeamProps { + duration?: number; + className?: string; +} + +export function ScanningBeam({ + duration = 1.2, + className = "", +}: ScanningBeamProps) { + return ( + +
+
+ +
+
+
+
+ +
+
+ + ); +} diff --git a/client/components/shared/verification-progress.tsx b/client/components/shared/verification-progress.tsx index ff89d7a..e93fc1a 100644 --- a/client/components/shared/verification-progress.tsx +++ b/client/components/shared/verification-progress.tsx @@ -15,6 +15,7 @@ import { Card, CardContent } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Progress } from "@/components/ui/progress"; import { Button } from "@/components/ui/button"; +import { ScanningBeam } from "@/components/shared/scanning-beam"; // type definitions so that ui can't enter an undefined state export type VerificationStatus = @@ -41,7 +42,7 @@ const STAGES = [ export function VerificationProgress({ status: externalStatus = "idle", //the control onComplete, - isSimulated = false, //set to false for control otherwise true if automated rendering + isSimulated = true, //set to false for control otherwise true if automated rendering }: VerificationProgressProps) { const [mounted, setMounted] = useState(false); @@ -113,7 +114,7 @@ export function VerificationProgress({ return (
- + {/* Active processing state - shown during scanning, liveness, and analysis stages */} @@ -163,14 +164,14 @@ export function VerificationProgress({ return (
- {/* scanner animation */} -
- -
+ {/* scanner animation container */} +
+ +
@@ -236,41 +229,15 @@ export function VerificationProgress({ ease: [0.16, 1, 0.3, 1], scale: { type: "spring", damping: 15, stiffness: 100 } }} - className="py-10 flex flex-col items-center text-center space-y-6" + className="py-10 flex flex-col items-center text-center space-y-6 pointer-events-none" >
- {/* Pulsating bloom effect */} - - - {/* Glowing Shield Container with pulse */} - - - + +
@@ -298,7 +265,7 @@ export function VerificationProgress({ animate={{ opacity: 1, y: 0 }} transition={{ delay: 0.5 }} > - + KYC_VERIFIED @@ -312,7 +279,7 @@ export function VerificationProgress({ transition={{ type: "spring", damping: 10, stiffness: 200 }} className="py-10 flex flex-col items-center text-center space-y-6" > -
+
@@ -326,7 +293,7 @@ export function VerificationProgress({
+ + {/* Portfolio Overview Stats */} diff --git "a/\357\200\272" "b/\357\200\272" deleted file mode 100644 index ae87b91..0000000 --- "a/\357\200\272" +++ /dev/null @@ -1,6 +0,0 @@ -Merge branch 'dev' of https://github.com/hyperstack-solidity/apax into apax-3 -# Please enter a commit message to explain why this merge is necessary, -# especially if it merges an updated upstream into a topic branch. -# -# Lines starting with '#' will be ignored, and an empty message aborts -# the commit. From 16b3cec7b8b1c462f480283ad4b35986d7ead2bf Mon Sep 17 00:00:00 2001 From: Joey Collado Date: Wed, 11 Feb 2026 21:41:08 +0800 Subject: [PATCH 5/5] cleanup --- client/components/views/dashboard-view.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/client/components/views/dashboard-view.tsx b/client/components/views/dashboard-view.tsx index dd12abb..cf0a50a 100644 --- a/client/components/views/dashboard-view.tsx +++ b/client/components/views/dashboard-view.tsx @@ -4,7 +4,6 @@ import Image from 'next/image' import { PortfolioOverview } from '@/components/portfolio-overview' import { AssetAllocationChart } from '@/components/asset-allocation-chart' import { ShariaCertificationHub } from '@/components/sharia-certification-hub' -import { VerificationProgress } from '../shared/verification-progress' export function DashboardView() { return ( @@ -45,8 +44,6 @@ export function DashboardView() {
- - {/* Portfolio Overview Stats */}