From c3ead879ad7d7f6d6ee049b04ad15fc3794e63c5 Mon Sep 17 00:00:00 2001 From: shafin-r Date: Tue, 9 Sep 2025 00:54:06 +0600 Subject: [PATCH] feat(auth): add verification feature in settings --- app/(tabs)/settings/page.tsx | 14 +++++ app/(tabs)/settings/verify/page.tsx | 96 +++++++++++++++++++++++++++++ app/exam/exam-screen/page.tsx | 6 +- components/ui/input-otp.tsx | 77 +++++++++++++++++++++++ package-lock.json | 11 ++++ package.json | 1 + public/images/icons/otp.svg | 1 + 7 files changed, 205 insertions(+), 1 deletion(-) create mode 100644 app/(tabs)/settings/verify/page.tsx create mode 100644 components/ui/input-otp.tsx create mode 100644 public/images/icons/otp.svg diff --git a/app/(tabs)/settings/page.tsx b/app/(tabs)/settings/page.tsx index 40c18f5..1e1fdd7 100644 --- a/app/(tabs)/settings/page.tsx +++ b/app/(tabs)/settings/page.tsx @@ -4,6 +4,7 @@ import BackgroundWrapper from "@/components/BackgroundWrapper"; import { Avatar, AvatarFallback } from "@/components/ui/avatar"; import { useAuthStore } from "@/stores/authStore"; import { + BadgeCheck, Bookmark, ChartColumn, ChevronRight, @@ -59,6 +60,19 @@ const SettingsPage = () => {
+ +
+ + + ); +}; + +export default VerificationScreen; diff --git a/app/exam/exam-screen/page.tsx b/app/exam/exam-screen/page.tsx index 6a13147..6efa89b 100644 --- a/app/exam/exam-screen/page.tsx +++ b/app/exam/exam-screen/page.tsx @@ -1,7 +1,7 @@ "use client"; import React, { useEffect, useState } from "react"; -import { useRouter, useSearchParams } from "next/navigation"; +import { usePathname, useRouter, useSearchParams } from "next/navigation"; import Header from "@/components/Header"; import QuestionItem from "@/components/QuestionItem"; import BackgroundWrapper from "@/components/BackgroundWrapper"; @@ -10,6 +10,7 @@ import { useTimerStore } from "@/stores/timerStore"; export default function ExamPage() { const router = useRouter(); + const pathname = usePathname(); const searchParams = useSearchParams(); const test_id = searchParams.get("test_id") || ""; const type = searchParams.get("type") || ""; @@ -136,3 +137,6 @@ export default function ExamPage() { ); } +function cancelExam() { + throw new Error("Function not implemented."); +} diff --git a/components/ui/input-otp.tsx b/components/ui/input-otp.tsx new file mode 100644 index 0000000..51e54f0 --- /dev/null +++ b/components/ui/input-otp.tsx @@ -0,0 +1,77 @@ +"use client"; + +import * as React from "react"; +import { OTPInput, OTPInputContext } from "input-otp"; +import { MinusIcon } from "lucide-react"; + +import { cn } from "@/lib/utils"; + +function InputOTP({ + className, + containerClassName, + ...props +}: React.ComponentProps & { + containerClassName?: string; +}) { + return ( + + ); +} + +function InputOTPGroup({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ); +} + +function InputOTPSlot({ + index, + className, + ...props +}: React.ComponentProps<"div"> & { + index: number; +}) { + const inputOTPContext = React.useContext(OTPInputContext); + const { char, hasFakeCaret, isActive } = inputOTPContext?.slots[index] ?? {}; + + return ( +
+ {char} + {hasFakeCaret && ( +
+
+
+ )} +
+ ); +} + +function InputOTPSeparator({ ...props }: React.ComponentProps<"div">) { + return ( +
+ +
+ ); +} + +export { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator }; diff --git a/package-lock.json b/package-lock.json index 33fd5b4..b8d146f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "capacitor-secure-storage-plugin": "^0.11.0", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", + "input-otp": "^1.4.2", "lucide-react": "^0.523.0", "next": "15.3.2", "react": "^19.0.0", @@ -4652,6 +4653,16 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/input-otp": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/input-otp/-/input-otp-1.4.2.tgz", + "integrity": "sha512-l3jWwYNvrEa6NTCt7BECfCm48GvwuZzkoeG3gBL2w4CHeOXW3eKFmf9UNYkNfYc3mxMrthMnxjIE07MT0zLBQA==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc" + } + }, "node_modules/internal-slot": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", diff --git a/package.json b/package.json index 548da4b..8ec4279 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "capacitor-secure-storage-plugin": "^0.11.0", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", + "input-otp": "^1.4.2", "lucide-react": "^0.523.0", "next": "15.3.2", "react": "^19.0.0", diff --git a/public/images/icons/otp.svg b/public/images/icons/otp.svg new file mode 100644 index 0000000..cf9d9c3 --- /dev/null +++ b/public/images/icons/otp.svg @@ -0,0 +1 @@ + \ No newline at end of file