Repository: credebl/studio
Pull request #992: Feat/verification-connection
Author: login: sanjaykhondal-aw
Created: 2025-05-22T13:27:11Z | Merged: 2025-05-22T17:12:20Z

## WHAT

- Implemented UI to send proof request with single connection by integrating send proof request API V1.
- Implemented UI to select connection, schema, credential-definition and attributes.
- Implemented UI to send proof request with multiple connections by integrating send proof request API V2.
- Implemented UI to select multiple connection, schemas, credential-definitions and attribures.

![Screenshot from 2025-05-22 17-50-58](https://github.com/user-attachments/assets/b0da9122-04b7-4010-939a-fd4df3fbf931)
![Screenshot from 2025-05-22 17-51-18](https://github.com/user-attachments/assets/42a272fa-84b8-4890-bec5-825727ebbfe2)
![Screenshot from 2025-05-22 17-51-48](https://github.com/user-attachments/assets/aca3f69c-fe00-4be8-ac6a-dfc41f12a230)



Diff:
diff --git a/nextjs/src/app/issue/page.tsx b/nextjs/src/app/issue/page.tsx
deleted file mode 100644
index 7ca97fea6..000000000
--- a/nextjs/src/app/issue/page.tsx
+++ /dev/null
@@ -1,5 +0,0 @@
-import React from 'react'
-
-const page = (): React.JSX.Element => <div>Issue</div>
-
-export default page
diff --git a/nextjs/src/app/organizations/verification/verify-credentials/schema/attributes/page.tsx b/nextjs/src/app/organizations/verification/verify-credentials/schema/attributes/page.tsx
new file mode 100644
index 000000000..27d280941
--- /dev/null
+++ b/nextjs/src/app/organizations/verification/verify-credentials/schema/attributes/page.tsx
@@ -0,0 +1,10 @@
+import EmailAttributesSelection from '@/features/verification/components/EmailAttributesSelection'
+import React from 'react'
+
+const page = (): React.JSX.Element => (
+  <div>
+    <EmailAttributesSelection />
+  </div>
+)
+
+export default page
diff --git a/nextjs/src/app/organizations/verification/verify-credentials/schema/attributes/verification-email/page.tsx b/nextjs/src/app/organizations/verification/verify-credentials/schema/attributes/verification-email/page.tsx
new file mode 100644
index 000000000..11644ac37
--- /dev/null
+++ b/nextjs/src/app/organizations/verification/verify-credentials/schema/attributes/verification-email/page.tsx
@@ -0,0 +1,6 @@
+// import EmailVerification from '@/features/verification/components/EmailVerification'
+import React from 'react'
+
+const page = (): React.JSX.Element => <div>{/* <EmailVerification /> */}</div>
+
+export default page
diff --git a/nextjs/src/app/organizations/verification/verify-credentials/schema/cred-defs/attributes/page.tsx b/nextjs/src/app/organizations/verification/verify-credentials/schema/cred-defs/attributes/page.tsx
new file mode 100644
index 000000000..27d280941
--- /dev/null
+++ b/nextjs/src/app/organizations/verification/verify-credentials/schema/cred-defs/attributes/page.tsx
@@ -0,0 +1,10 @@
+import EmailAttributesSelection from '@/features/verification/components/EmailAttributesSelection'
+import React from 'react'
+
+const page = (): React.JSX.Element => (
+  <div>
+    <EmailAttributesSelection />
+  </div>
+)
+
+export default page
diff --git a/nextjs/src/app/organizations/verification/verify-credentials/schema/cred-defs/attributes/verification-email/page.tsx b/nextjs/src/app/organizations/verification/verify-credentials/schema/cred-defs/attributes/verification-email/page.tsx
new file mode 100644
index 000000000..11644ac37
--- /dev/null
+++ b/nextjs/src/app/organizations/verification/verify-credentials/schema/cred-defs/attributes/verification-email/page.tsx
@@ -0,0 +1,6 @@
+// import EmailVerification from '@/features/verification/components/EmailVerification'
+import React from 'react'
+
+const page = (): React.JSX.Element => <div>{/* <EmailVerification /> */}</div>
+
+export default page
diff --git a/nextjs/src/app/organizations/verification/verify-credentials/schema/cred-defs/page.tsx b/nextjs/src/app/organizations/verification/verify-credentials/schema/cred-defs/page.tsx
new file mode 100644
index 000000000..f8bdc6c2f
--- /dev/null
+++ b/nextjs/src/app/organizations/verification/verify-credentials/schema/cred-defs/page.tsx
@@ -0,0 +1,8 @@
+// import EmailCredDefSelection from '@/features/verification/components/EmailCredDefSelection'
+import React from 'react'
+
+const page = (): React.JSX.Element => (
+  <div>{/* <EmailCredDefSelection /> */}</div>
+)
+
+export default page
diff --git a/nextjs/src/app/organizations/verification/verify-credentials/schema/page.tsx b/nextjs/src/app/organizations/verification/verify-credentials/schema/page.tsx
new file mode 100644
index 000000000..789db0cb5
--- /dev/null
+++ b/nextjs/src/app/organizations/verification/verify-credentials/schema/page.tsx
@@ -0,0 +1,10 @@
+import React from 'react'
+import VerificationSchemasList from '@/features/verification/components/VerificationSchemasList'
+
+const page = (): React.JSX.Element => (
+  <div>
+    <VerificationSchemasList />
+  </div>
+)
+
+export default page
diff --git a/nextjs/src/app/organizations/verification/verify-credentials/schemas/connections/page.tsx b/nextjs/src/app/organizations/verification/verify-credentials/schemas/connections/page.tsx
new file mode 100644
index 000000000..ffbb5118b
--- /dev/null
+++ b/nextjs/src/app/organizations/verification/verify-credentials/schemas/connections/page.tsx
@@ -0,0 +1,10 @@
+import Connections from '@/features/verification/components/Connections'
+import React from 'react'
+
+const page = (): React.JSX.Element => (
+  <div>
+    <Connections />
+  </div>
+)
+
+export default page
diff --git a/nextjs/src/app/organizations/verification/verify-credentials/schemas/cred-defs/connections/page.tsx b/nextjs/src/app/organizations/verification/verify-credentials/schemas/cred-defs/connections/page.tsx
new file mode 100644
index 000000000..ffbb5118b
--- /dev/null
+++ b/nextjs/src/app/organizations/verification/verify-credentials/schemas/cred-defs/connections/page.tsx
@@ -0,0 +1,10 @@
+import Connections from '@/features/verification/components/Connections'
+import React from 'react'
+
+const page = (): React.JSX.Element => (
+  <div>
+    <Connections />
+  </div>
+)
+
+export default page
diff --git a/nextjs/src/app/organizations/verification/verify-credentials/schemas/cred-defs/page.tsx b/nextjs/src/app/organizations/verification/verify-credentials/schemas/cred-defs/page.tsx
new file mode 100644
index 000000000..f90bd6ed6
--- /dev/null
+++ b/nextjs/src/app/organizations/verification/verify-credentials/schemas/cred-defs/page.tsx
@@ -0,0 +1,6 @@
+// import CredDefSelection from '@/features/verification/components/CredDefSelection'
+import React from 'react'
+
+const page = (): React.JSX.Element => <div>{/* <CredDefSelection /> */}</div>
+
+export default page
diff --git a/nextjs/src/app/organizations/verification/verify-credentials/schemas/page.tsx b/nextjs/src/app/organizations/verification/verify-credentials/schemas/page.tsx
new file mode 100644
index 000000000..789db0cb5
--- /dev/null
+++ b/nextjs/src/app/organizations/verification/verify-credentials/schemas/page.tsx
@@ -0,0 +1,10 @@
+import React from 'react'
+import VerificationSchemasList from '@/features/verification/components/VerificationSchemasList'
+
+const page = (): React.JSX.Element => (
+  <div>
+    <VerificationSchemasList />
+  </div>
+)
+
+export default page
diff --git a/nextjs/src/components/BackButton.tsx b/nextjs/src/components/BackButton.tsx
index 894ce1de2..8df48cb80 100644
--- a/nextjs/src/components/BackButton.tsx
+++ b/nextjs/src/components/BackButton.tsx
@@ -5,13 +5,25 @@ import { Button } from './ui/button'
 import { JSX } from 'react'
 import { useRouter } from 'next/navigation'
 
-const BackButton = (): JSX.Element => {
+interface BackButtonProps {
+  path?: string
+}
+
+const BackButton = ({ path }: BackButtonProps): JSX.Element => {
   const router = useRouter()
 
+  const handleClick = (): void => {
+    if (path) {
+      router.push(path)
+    } else {
+      router.back()
+    }
+  }
+
   return (
     <Button
       variant="outline"
-      onClick={() => router.back()}
+      onClick={handleClick}
       className="border-ring hover:bg-primary mb-4 flex items-center gap-2 rounded-xl border px-4 py-2 transition-colors"
     >
       <ArrowLeft size={18} />
diff --git a/nextjs/src/components/CustomCheckbox.tsx b/nextjs/src/components/CustomCheckbox.tsx
index 1bad4d5dd..2d30c2f02 100644
--- a/nextjs/src/components/CustomCheckbox.tsx
+++ b/nextjs/src/components/CustomCheckbox.tsx
@@ -32,12 +32,12 @@ const CustomCheckbox: React.FC<ICustomCheckboxProps> = ({
           {' '}
           <input
             type="checkbox"
-            checked={checked}
+            checked={Boolean(checked)}
             onChange={handleCheckboxChange}
             className="hidden"
           />
           <div
-            className={`h-full w-full border-2 ${checked ? 'bg-primary-700' : ''}`}
+            className={`h-full w-full border-2 ${checked ? 'bg-primary' : ''}`}
             style={{
               borderColor: 'rgb(31 78 173 / var(--tw-bg-opacity))',
               position: 'relative',
@@ -45,7 +45,7 @@ const CustomCheckbox: React.FC<ICustomCheckboxProps> = ({
           >
             {checked && (
               <svg
-                className="absolute top-0 left-0 h-full w-full text-[var(--color-white)]"
+                className="absolute top-0 left-0 h-full w-full"
                 viewBox="0 0 24 24"
                 fill="none"
                 stroke="currentColor"
diff --git a/nextjs/src/components/DataTable/index.tsx b/nextjs/src/components/DataTable/index.tsx
index dcc90410b..56c0ef707 100644
--- a/nextjs/src/components/DataTable/index.tsx
+++ b/nextjs/src/components/DataTable/index.tsx
@@ -33,11 +33,11 @@ const DataTable: React.FC<DataTableProps> = ({
             <table className="divide-muted dark:divide-muted min-w-full divide-y">
               <thead className="bg-muted dark:bg-muted">
                 <tr>
-                  {header.map((ele:TableHeader, index:number) => (
+                  {header.map((ele: TableHeader, index: number) => (
                     <th
                       key={index}
                       scope="col"
-                      className={`text-muted-foreground p-4 text-left text-xs font-medium tracking-wider uppercase dark:text-white ${ele.width ?? ''} ${
+                      className={`text-muted-foreground p-4 text-left text-xs font-medium tracking-wider uppercase ${ele.width ?? ''} ${
                         index === 0 && isEmailVerification ? 'pl-12' : ''
                       }`}
                     >
@@ -50,7 +50,7 @@ const DataTable: React.FC<DataTableProps> = ({
                     </th>
                   ))}
                   {(displaySelect || showBtn) && (
-                    <th className="text-muted-foreground p-4 text-left text-xs font-medium tracking-wider uppercase dark:text-white">
+                    <th className="text-muted-foreground p-4 text-left text-xs font-medium tracking-wider uppercase">
                       Action
                     </th>
                   )}
@@ -69,7 +69,7 @@ const DataTable: React.FC<DataTableProps> = ({
                         (cell: TableCellData, cellIndex: number) => (
                           <td
                             key={cellIndex}
-                            className="text-foreground p-4 align-middle text-sm font-normal whitespace-nowrap dark:text-white"
+                            className="text-foreground p-4 align-middle text-sm font-normal whitespace-nowrap"
                           >
                             <div>{cell.data}</div>
                             {cell.subData && (
@@ -81,7 +81,7 @@ const DataTable: React.FC<DataTableProps> = ({
                         ),
                       )}
                       {(displaySelect || showBtn) && (
-                        <td className="text-foreground p-4 align-middle text-sm font-normal whitespace-nowrap dark:text-white">
+                        <td className="text-foreground p-4 align-middle text-sm font-normal whitespace-nowrap">
                           {showBtn && (
                             <button
                               onClick={() => callback?.(row.clickId)}
diff --git a/nextjs/src/config/Constant.tsx b/nextjs/src/config/Constant.tsx
new file mode 100644
index 000000000..6add29eaf
--- /dev/null
+++ b/nextjs/src/config/Constant.tsx
@@ -0,0 +1,34 @@
+import { JSX } from 'react'
+
+export const Create = (): JSX.Element => (
+  <div className="shrink-0 pr-3">
+    <svg
+      xmlns="http://www.w3.org/2000/svg"
+      width="15"
+      height="15"
+      fill="none"
+      viewBox="0 0 24 24"
+    >
+      <path
+        fill="#fff"
+        d="M21.89 9.89h-7.78V2.11a2.11 2.11 0 1 0-4.22 0v7.78H2.11a2.11 2.11 0 1 0 0 4.22h7.78v7.78a2.11 2.11 0 1 0 4.22 0v-7.78h7.78a2.11 2.11 0 1 0 0-4.22Z"
+      />
+    </svg>
+  </div>
+)
+
+export const SchemaEndorsement = (): JSX.Element => (
+  <svg
+    className="mt-1 mr-2 shrink-0"
+    xmlns="http://www.w3.org/2000/svg"
+    width="20"
+    height="20"
+    fill="none"
+    viewBox="0 0 25 25"
+  >
+    <path
+      fill="#fff"
+      d="M21.094 0H3.906A3.906 3.906 0 0 0 0 3.906v12.5a3.906 3.906 0 0 0 3.906 3.907h.781v3.906a.781.781 0 0 0 1.335.553l4.458-4.46h10.614A3.906 3.906 0 0 0 25 16.407v-12.5A3.907 3.907 0 0 0 21.094 0Zm2.343 16.406a2.343 2.343 0 0 1-2.343 2.344H10.156a.782.782 0 0 0-.553.228L6.25 22.333V19.53a.781.781 0 0 0-.781-.781H3.906a2.344 2.344 0 0 1-2.344-2.344v-12.5a2.344 2.344 0 0 1 2.344-2.344h17.188a2.343 2.343 0 0 1 2.343 2.344v12.5Zm-3.184-5.951a.81.81 0 0 1-.17.254l-3.125 3.125a.781.781 0 0 1-1.105-1.106l1.792-1.79h-7.489a2.343 2.343 0 0 0-2.344 2.343.781.781 0 1 1-1.562 0 3.906 3.906 0 0 1 3.906-3.906h7.49l-1.793-1.79a.78.78 0 0 1 .254-1.277.781.781 0 0 1 .852.17l3.125 3.125a.79.79 0 0 1 .169.852Z"
+    />
+  </svg>
+)
diff --git a/nextjs/src/features/organization/connectionIssuance/components/ConnectionList.tsx b/nextjs/src/features/organization/connectionIssuance/components/ConnectionList.tsx
index b980f6d38..2c9b6de18 100644
--- a/nextjs/src/features/organization/connectionIssuance/components/ConnectionList.tsx
+++ b/nextjs/src/features/organization/connectionIssuance/components/ConnectionList.tsx
@@ -277,7 +277,7 @@ const ConnectionList = (props: {
         className="mb-4 flex items-center justify-between"
         id="issued-credentials-list"
       >
-        <h1 className="ml-1 text-xl font-semibold text-gray-900 sm:text-2xl dark:text-white">
+        <h1 className="text-primary ml-1 text-xl font-semibold sm:text-2xl">
           Connection List
         </h1>
       </div>
diff --git a/nextjs/src/features/schemas/components/SchemaCard.tsx b/nextjs/src/features/schemas/components/SchemaCard.tsx
index 2976d2d29..a553fc83f 100644
--- a/nextjs/src/features/schemas/components/SchemaCard.tsx
+++ b/nextjs/src/features/schemas/components/SchemaCard.tsx
@@ -8,6 +8,7 @@ import {
   ISchemaData,
 } from '../type/schemas-interface'
 import React, { useState } from 'react'
+import { usePathname, useRouter } from 'next/navigation'
 
 import { Button } from '@/components/ui/button'
 import CopyDid from '@/config/CopyDid'
@@ -17,25 +18,32 @@ import DateTooltip from '@/components/DateTooltip'
 import { ShieldCheck } from 'lucide-react'
 import { dateConversion } from '@/utils/DateConversion'
 import { limitedAttributesLength } from '@/config/CommonConstant'
-import { useRouter } from 'next/navigation'
 
 const SchemaCard = (props: ISchemaCardProps): React.JSX.Element => {
-  const [, setIsSelected] = useState(false)
+  const [isSelected, setIsSelected] = useState(false)
   const router = useRouter()
 
-  const isSelectedSchema = props.selectedSchemas?.some(
-    (selectedSchema) =>
-      selectedSchema.schemaId === props.schemaId ||
-      selectedSchema.schemaLedgerId === props.schemaId,
-  )
+  const pathname = usePathname()
+  const isVerificationPage = pathname.includes('verification')
+
+  // const isSelectedSchema = props.selectedSchemas?.some(
+  //   (selectedSchema) =>
+  //     selectedSchema.schemaId === props.schemaId ||
+  //     selectedSchema.schemaLedgerId === props.schemaId,
+  // )
 
   const AttributesList: React.FC<{
     attributes: IAttributes[]
     limitedAttributes?: boolean
   }> = ({ attributes, limitedAttributes }) => {
     const isLimited =
-      limitedAttributes !== false && attributes.length > limitedAttributesLength
-    const displayedAttributes = isLimited ? attributes.slice(0, 3) : attributes
+      limitedAttributes !== false &&
+      Array.isArray(attributes) &&
+      attributes.length > limitedAttributesLength
+
+    const displayedAttributes = isLimited
+      ? attributes.slice(0, 3)
+      : (attributes ?? [])
 
     return (
       <div className="text-foreground flex flex-wrap items-center text-base font-semibold">
@@ -93,6 +101,10 @@ const SchemaCard = (props: ISchemaCardProps): React.JSX.Element => {
   )
 
   const handleCardClick = (): void => {
+    if (isVerificationPage) {
+      return
+    }
+
     if (!props.w3cSchema && !hasNestedAttributes && props.schemaId) {
       router.push(`/organizations/schemas/${props.schemaId}`)
     }
@@ -108,7 +120,7 @@ const SchemaCard = (props: ISchemaCardProps): React.JSX.Element => {
   return (
     <Card
       className={`border-border relative h-full w-full overflow-hidden rounded-xl border shadow-xl transition-transform duration-300 ${
-        props.w3cSchema || props.isClickable === false
+        props.w3cSchema || props.isClickable === false || isVerificationPage
           ? 'cursor-default'
           : 'cursor-pointer hover:scale-[1.02] hover:shadow-lg'
       } ${hasNestedAttributes ? 'pointer-events-none opacity-80' : ''}`}
@@ -217,7 +229,8 @@ const SchemaCard = (props: ISchemaCardProps): React.JSX.Element => {
 
         {props.showCheckbox && !hasNestedAttributes && (
           <CustomCheckbox
-            isSelectedSchema={isSelectedSchema}
+            // isSelectedSchema={Boolean(isSelectedSchema)}
+            isSelectedSchema={Boolean(isSelected)}
             onChange={handleCheckboxChange}
             showCheckbox={props.showCheckbox}
             schemaData={{
diff --git a/nextjs/src/features/schemas/type/schemas-interface.ts b/nextjs/src/features/schemas/type/schemas-interface.ts
index 9efeab68a..9c238d6c7 100644
--- a/nextjs/src/features/schemas/type/schemas-interface.ts
+++ b/nextjs/src/features/schemas/type/schemas-interface.ts
@@ -31,7 +31,7 @@ export interface IAttributesDetails {
 export interface ISchemaCardProps {
   className?: string
   schemaName: string
-  selectedSchemas: ISchema[]
+  selectedSchemas?: ISchema[]
   version: string
   schemaId: string
   issuerDid: string
@@ -40,14 +40,14 @@ export interface ISchemaCardProps {
   created: string
   isClickable?: boolean
   showCheckbox?: boolean
-  onClickCallback: (SchemaData: {
+  onClickCallback?: (SchemaData: {
     schemaId: string
     attributes: string[]
     issuerDid: string
     created: string
   }) => void
 
-  onClickW3CCallback: (W3CSchemaData: {
+  onClickW3CCallback?: (W3CSchemaData: {
     schemaId: string
     schemaName: string
     version: string
diff --git a/nextjs/src/features/verification/components/ConnectionList.tsx b/nextjs/src/features/verification/components/ConnectionList.tsx
index 71b1c6218..d0f546101 100644
--- a/nextjs/src/features/verification/components/ConnectionList.tsx
+++ b/nextjs/src/features/verification/components/ConnectionList.tsx
@@ -14,11 +14,9 @@ import {
 import { useAppDispatch, useAppSelector } from '@/lib/hooks'
 
 import { AlertComponent } from '@/components/AlertComponent'
-import { AxiosResponse } from 'axios'
 import DateTooltip from '@/components/DateTooltip'
 import { ITableData } from '@/components/DataTable/interface'
 import SortDataTable from './SortDataTable'
-import { apiStatusCodes } from '@/config/CommonConstant'
 import { dateConversion } from '@/utils/DateConversion'
 
 const initialPageState = {
@@ -49,9 +47,9 @@ const ConnectionList = (props: {
   const [totalItem, setTotalItem] = useState(0)
   const [error, setError] = useState<string | null>(null)
   const [pageInfo, setPageInfo] = useState({
-    totalItem: '',
-    nextPage: '',
-    lastPage: '',
+    totalItem: 0,
+    nextPage: 0,
+    lastPage: 0,
   })
 
   const dispatch = useAppDispatch()
@@ -133,7 +131,7 @@ const ConnectionList = (props: {
           })
           setConnectionList(updateConnectionList)
         }}
-        className="h-4 w-4 cursor-pointer rounded-lg border-gray-300 bg-gray-100 text-blue-600 dark:border-gray-600 dark:bg-gray-700 dark:ring-offset-gray-800"
+        className="h-4 w-4 cursor-pointer rounded-lg"
       />
     </div>
   )
@@ -153,13 +151,11 @@ const ConnectionList = (props: {
                   { data: renderCheckbox(ele, isChecked, connections) },
                   { data: theirLabel },
                   { data: connectionId },
+
                   {
                     data: (
-                      <DateTooltip
-                        date={createDateTime}
-                        id="verification_connecetion_list"
-                      >
-                        {dateConversion(createDateTime)}
+                      <DateTooltip date={createDateTime}>
+                        <div> {dateConversion(createDateTime)}</div>
                       </DateTooltip>
                     ),
                   },
@@ -203,26 +199,31 @@ const ConnectionList = (props: {
         orgId,
       })
 
-      const { data } = response as unknown as AxiosResponse
-
-      if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) {
-        setTotalItem(data?.data.totalItems)
-        const { totalItems, nextPage, lastPage } = data.data
+      if (response && typeof response === 'object') {
+        const {
+          totalItems,
+          nextPage,
+          lastPage,
+          data: connectionsDataByOrgId,
+        } = response
 
         setPageInfo({
           totalItem: totalItems,
           nextPage,
           lastPage,
         })
-        const connectionsDataByOrgId = data?.data?.data
+
         setConnectionList(connectionsDataByOrgId)
+        setTotalItem(totalItems)
         setError(null)
       } else {
+        // If API returned void or unexpected structure
         setConnectionList([])
+        setError('Failed to fetch connections.')
       }
-    } catch {
+    } catch (error) {
       setConnectionList([])
-      setError(error as string)
+      setError((error as Error).message)
     } finally {
       setLoading(false)
     }
@@ -341,7 +342,7 @@ const ConnectionList = (props: {
         isSort={true}
         isPagination={true}
         message={'No Connections'}
-        discription={'You don\'t have any connections yet'}
+        discription={'You dont have any connections yet'}
       ></SortDataTable>
     </div>
   )
diff --git a/nextjs/src/features/verification/components/Connections.tsx b/nextjs/src/features/verification/components/Connections.tsx
index 5f9a3044f..e232550c6 100644
--- a/nextjs/src/features/verification/components/Connections.tsx
+++ b/nextjs/src/features/verification/components/Connections.tsx
@@ -216,17 +216,16 @@ const Connections = (): JSX.Element => {
           }),
         )
 
-        const groupedAttributes = checkedW3CAttributes.reduce<Record<string, CheckedW3CAttribute[]>>(
-          (acc, curr) => {
-            const { schemaName } = curr
-            if (!acc[schemaName]) {
-              acc[schemaName] = []
-            }
-            acc[schemaName].push(curr)
-            return acc
-          },
-          {},
-        )
+        const groupedAttributes = checkedW3CAttributes.reduce<
+          Record<string, CheckedW3CAttribute[]>
+        >((acc, curr) => {
+          const { schemaName } = curr
+          if (!acc[schemaName]) {
+            acc[schemaName] = []
+          }
+          acc[schemaName].push(curr)
+          return acc
+        }, {})
 
         verifyCredentialPayload = {
           connectionId:
@@ -317,7 +316,7 @@ const Connections = (): JSX.Element => {
           </div>
         </div>
 
-        <div className="mb-4 border-b border-gray-200 dark:border-gray-700">
+        <div className="mb-4 border-b">
           <ul
             className="-mb-px flex flex-wrap text-center text-sm font-medium"
             id="myTab"
@@ -358,7 +357,7 @@ const Connections = (): JSX.Element => {
             </div>
           )}
           <div
-            className="rounded-lg bg-gray-50 dark:bg-gray-900"
+            className="rounded-lg"
             id="profile"
             role="tabpanel"
             aria-labelledby="profile-tab"
@@ -367,11 +366,11 @@ const Connections = (): JSX.Element => {
           </div>
         </div>
         <div className="mb-4 flex items-center justify-between pt-3">
-          <h1 className="ml-1 text-xl font-semibold text-gray-900 sm:text-2xl dark:text-white">
+          <h1 className="ml-1 text-xl font-semibold sm:text-2xl">
             Selected Users
           </h1>
         </div>
-        <div className="rounded-lg border border-gray-200 bg-white p-4 shadow-sm sm:p-6 2xl:col-span-2 dark:border-gray-700 dark:bg-gray-800">
+        <div className="rounded-lg border p-4 shadow-sm sm:p-6 2xl:col-span-2">
           <DataTable
             header={selectedConnectionHeader}
             data={selectedConnectionList}
diff --git a/nextjs/src/features/verification/components/EmailAttributesSelection.tsx b/nextjs/src/features/verification/components/EmailAttributesSelection.tsx
new file mode 100644
index 000000000..8c0bc49da
--- /dev/null
+++ b/nextjs/src/features/verification/components/EmailAttributesSelection.tsx
@@ -0,0 +1,530 @@
+/* eslint-disable max-lines */
+'use client'
+
+import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
+import { JSX, useEffect, useState } from 'react'
+import { apiStatusCodes, predicatesConditions } from '@/config/CommonConstant'
+import { useAppDispatch, useAppSelector } from '@/lib/hooks'
+
+import { AxiosResponse } from 'axios'
+import BackButton from '@/components/BackButton'
+import { Button } from '@/components/ui/button'
+import CustomCheckbox from '@/components/CustomCheckbox'
+import DataTable from '@/components/DataTable'
+import { DidMethod } from '@/common/enums'
+import { ISelectedAttributes } from '../type/interface'
+import { ITableData } from '@/components/DataTable/interface'
+import { TableHeader } from './SortDataTable'
+import { X } from 'lucide-react'
+import { getOrganizationById } from '@/app/api/organization'
+import { pathRoutes } from '@/config/pathRoutes'
+import { setSelectedAttributeData } from '@/lib/verificationSlice'
+import { useRouter } from 'next/navigation'
+
+interface NumberAttribute {
+  selectedOption: string | null
+  value: string | number | null
+}
+
+const EmailAttributesSelection = (): JSX.Element => {
+  const [attributeList, setAttributeList] = useState<ITableData[]>([])
+  const [proofReqSuccess, setProofReqSuccess] = useState<string | null>(null)
+  const [errMsg, setErrMsg] = useState<string | null>(null)
+  const [display, setDisplay] = useState<boolean | undefined>(false)
+  const [loading, setLoading] = useState<boolean>(true)
+  const [attributeData, setAttributeData] = useState<
+    ISelectedAttributes[] | null
+  >(null)
+  const [w3cSchema, setW3cSchema] = useState<boolean>(false)
+  const [isConnectionProof, setIsConnectionProof] = useState<boolean>(false)
+
+  const dispatch = useAppDispatch()
+  const router = useRouter()
+  const orgId = useAppSelector((state) => state.organization.orgId)
+
+  const verificationRouteType = useAppSelector(
+    (state) => state.verification.routeType,
+  )
+
+  const getSelectedCredDefData = '[]'
+
+  const selectedSchemaAttributes = useAppSelector(
+    (state) => state.verification.selectedSchemas,
+  )
+  const ConnectionVerification = async (): Promise<void> => {
+    if (verificationRouteType === 'Connection') {
+      setIsConnectionProof(true)
+    } else {
+      setIsConnectionProof(false)
+    }
+  }
+  useEffect(() => {
+    ConnectionVerification()
+  }, [])
+
+  const handleAttributeChange = async (
+    attributeName: string,
+    changeType: 'checkbox' | 'input' | 'select',
+    value: string | boolean,
+    schemaId?: string | undefined,
+    credDefId?: string | undefined,
+  ): Promise<void> => {
+    const updatedAttributes =
+      attributeData?.map((attribute) => {
+        if (
+          attribute.attributeName === attributeName &&
+          attribute.schemaId === schemaId &&
+          attribute.credDefId === credDefId
+        ) {
+          switch (changeType) {
+            case 'checkbox':
+              return {
+                ...attribute,
+                isChecked: value as boolean,
+                value: (value as boolean) ? attribute.value : '',
+                selectedOption: attribute?.condition || 'Select',
+                inputError: '',
+                selectError: '',
+              }
+            case 'input':
+              return {
+                ...attribute,
+                value: value as string,
+                inputError: '',
+              }
+            case 'select':
+              return {
+                ...attribute,
+                selectedOption: value as string,
+                selectError: '',
+              }
+            default:
+              return attribute
+          }
+        }
+        return attribute
+      }) ?? []
+
+    setAttributeData(updatedAttributes)
+
+    dispatch(setSelectedAttributeData(updatedAttributes))
+  }
+
+  const getOrgDetails = async (): Promise<void> => {
+    setLoading(true)
+
+    const response = await getOrganizationById(orgId)
+    const { data } = response as AxiosResponse
+    if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) {
+      const did = data?.data?.org_agents?.[0]?.orgDid
+
+      if (
+        did.includes(DidMethod.POLYGON) ||
+        did.includes(DidMethod.KEY) ||
+        did.includes(DidMethod.WEB)
+      ) {
+        setW3cSchema(true)
+      } else if (did.includes(DidMethod.INDY)) {
+        setW3cSchema(false)
+      }
+    }
+
+    setLoading(false)
+  }
+
+  useEffect(() => {
+    getOrgDetails()
+  }, [])
+
+  const isInvalidNumberAttribute = (attribute: NumberAttribute): boolean => {
+    const isOptionInvalid =
+      attribute.selectedOption === null ||
+      attribute.selectedOption === '' ||
+      attribute.selectedOption === 'Select'
+    const isValueInvalid = attribute.value === null || attribute.value === ''
+
+    if (!isOptionInvalid && isValueInvalid) {
+      setErrMsg('Value is required')
+      return true
+    } else if (!isValueInvalid && isOptionInvalid) {
+      setErrMsg('Condition is required')
+      return true
+    }
+    return false
+  }
+
+  const hasInvalidNumberAttributes = (): boolean => {
+    const numberAttributes = attributeData?.filter(
+      (attr) => attr.dataType === 'number' && attr.isChecked,
+    )
+
+    for (const attribute of numberAttributes || []) {
+      if (isInvalidNumberAttribute(attribute)) {
+        return true
+      }
+    }
+
+    return false
+  }
+  const redirectToAppropriatePage = (): void => {
+    switch (true) {
+      case w3cSchema && isConnectionProof:
+        router.push(pathRoutes.organizations.verification.W3CConnections)
+        break
+      case !w3cSchema && isConnectionProof:
+        router.push(pathRoutes.organizations.verification.connections)
+        break
+      case w3cSchema && !isConnectionProof:
+        router.push(pathRoutes.organizations.verification.w3cEmailVerification)
+        break
+      default:
+        router.push(pathRoutes.organizations.verification.emailVerification)
+        break
+    }
+  }
+  const handleSubmit = (): void => {
+    setErrMsg(null)
+
+    if (hasInvalidNumberAttributes()) {
+      setErrMsg('Please check the number fields.')
+      return
+    }
+
+    redirectToAppropriatePage()
+  }
+
+  const loadAttributesData = async (): Promise<void> => {
+    setLoading(true)
+
+    try {
+      setAttributeData([])
+
+      if (w3cSchema) {
+        const parsedW3CSchemaDetails = selectedSchemaAttributes
+
+        if (
+          Array.isArray(parsedW3CSchemaDetails) &&
+          parsedW3CSchemaDetails.length > 0
+        ) {
+          const allAttributes = parsedW3CSchemaDetails.flatMap((schema) => {
+            if (schema.attributes && Array.isArray(schema.attributes)) {
+              return schema.attributes.map((attribute) => ({
+                ...attribute,
+                schemaName: schema.name,
+                credDefName: '',
+                schemaId: schema.schemaLedgerId,
+                credDefId: '',
+              }))
+            }
+            return []
+          })
+
+          const inputArray = allAttributes.map((attribute) => ({
+            displayName: attribute.displayName,
+            attributeName: attribute.attributeName,
+            isChecked: false,
+            value: '',
+            condition: '',
+            options: predicatesConditions,
+            dataType: attribute.schemaDataType,
+            schemaName: attribute.schemaName ?? '',
+            credDefName: attribute.credDefName,
+            schemaId: attribute.schemaId ?? '',
+            credDefId: attribute.credDefId,
+            selectedOption: 'Select',
+            inputError: '',
+            selectError: '',
+          }))
+
+          setAttributeData(inputArray)
+        } else {
+          console.error('W3C schema details are not in the expected format.')
+        }
+      } else {
+        const selectedCredDefs = getSelectedCredDefData || []
+
+        const parsedSchemaDetails = selectedSchemaAttributes || []
+        if (
+          Array.isArray(parsedSchemaDetails) &&
+          parsedSchemaDetails.length > 0
+        ) {
+          const allAttributes = parsedSchemaDetails.flatMap((schema) => {
+            if (schema.attributes && Array.isArray(schema.attributes)) {
+              return schema.attributes.flatMap((attribute) => {
+                const matchingCredDefs = Array.isArray(selectedCredDefs)
+                  ? selectedCredDefs.filter(
+                      (credDef) =>
+                        credDef.schemaLedgerId === schema.schemaLedgerId,
+                    )
+                  : []
+
+                return matchingCredDefs.map((credDef) => ({
+                  displayName: attribute.displayName,
+                  attributeName: attribute.attributeName,
+                  isChecked: false,
+                  value: '',
+                  condition: '',
+                  options: predicatesConditions,
+                  dataType: attribute.schemaDataType,
+                  schemaName: schema.schemaLedgerId?.split(':')[2] || '',
+                  credDefName: credDef.tag,
+                  schemaId: schema.schemaId,
+                  credDefId: credDef.credentialDefinitionId,
+                  selectedOption: 'Select',
+                  inputError: '',
+                  selectError: '',
+                }))
+              })
+            }
+            return []
+          })
+
+          setAttributeData(allAttributes)
+        } else {
+          console.error('Parsed schema details are not in the expected format.')
+        }
+      }
+    } catch (error) {
+      console.error('Error fetching data:', error)
+    } finally {
+      setLoading(false)
+    }
+  }
+
+  useEffect(() => {
+    loadAttributesData()
+  }, [w3cSchema])
+
+  const attributeFunction = async (): Promise<void> => {
+    if (!attributeData) {
+      return
+    }
+
+    const attributes: ITableData[] = attributeData.map((attribute) => {
+      const commonCellProps = {
+        // eslint-disable-next-line no-empty-function
+        handleChange: (): void => {},
+        inputType: 'custom',
+      }
+
+      return {
+        data: [
+          {
+            ...commonCellProps,
+            data: (
+              <div className="flex items-center">
+                <CustomCheckbox
+                  showCheckbox={true}
+                  isVerificationUsingEmail={true}
+                  onChange={(checked: boolean) => {
+                    handleAttributeChange(
+                      attribute?.attributeName,
+                      'checkbox',
+                      checked,
+                      attribute?.schemaId,
+                      attribute?.credDefId,
+                    )
+                  }}
+                  isSelectedSchema={false}
+                />
+              </div>
+            ),
+          },
+          {
+            ...commonCellProps,
+            data: attribute?.displayName || '',
+          },
+          {
+            ...commonCellProps,
+            data: !w3cSchema ? (
+              <div className="relative flex items-center">
+                {attribute?.dataType === 'number' && (
+                  <select
+                    disabled={!attribute?.isChecked}
+                    value={attribute?.selectedOption}
+                    onChange={(e) =>
+                      handleAttributeChange(
+                        attribute?.attributeName,
+                        'select',
+                        e.target.value,
+                        attribute?.schemaId,
+                        attribute?.credDefId,
+                      )
+                    }
+                    className={`${
+                      !attribute?.isChecked
+                        ? 'cursor-not-allowed opacity-50'
+                        : 'cursor-pointer'
+                    } border-border rounded-md border p-1`}
+                  >
+                    {attribute?.options?.map((option) => (
+                      <option key={option?.value} value={option?.value}>
+                        {option?.label}
+                      </option>
+                    ))}
+                  </select>
+                )}
+                {attribute?.selectError && (
+                  <div className="absolute bottom-[-16px] text-xs text-[--var(--destructive)]">
+                    {attribute?.selectError}
+                  </div>
+                )}
+              </div>
+            ) : (
+              <div />
+            ),
+          },
+          {
+            ...commonCellProps,
+            data: !w3cSchema ? (
+              <div className="relative flex flex-col items-start">
+                {attribute?.dataType === 'number' && (
+                  <input
+                    type="number"
+                    value={attribute?.value}
+                    onChange={(e) =>
+                      handleAttributeChange(
+                        attribute?.attributeName,
+                        'input',
+                        e.target.value,
+                        attribute?.schemaId,
+                        attribute?.credDefId,
+                      )
+                    }
+                    disabled={!attribute?.isChecked}
+                    className={`${
+                      !attribute?.isChecked
+                        ? 'cursor-not-allowed opacity-50'
+                        : 'cursor-pointer'
+                    } rounded-md border border-black p-1 dark:border-gray-300 dark:bg-gray-700 dark:text-white dark:placeholder-gray-400`}
+                  />
+                )}
+                {attribute?.inputError && (
+                  <div className="absolute bottom-[-16px] text-xs text-[--var(--destructive)]">
+                    {attribute?.inputError}
+                  </div>
+                )}
+              </div>
+            ) : (
+              <div />
+            ),
+          },
+          {
+            ...commonCellProps,
+            data: attribute.schemaName || '',
+          },
+          {
+            ...commonCellProps,
+            data: attribute.credDefName || '',
+          },
+        ],
+      }
+    })
+
+    setAttributeList(attributes)
+    setDisplay(attributeData.some((a) => a.dataType === 'number'))
+  }
+
+  useEffect(() => {
+    const fetchAttributes = async (): Promise<void> => {
+      if (attributeData) {
+        await attributeFunction()
+      }
+    }
+
+    fetchAttributes()
+  }, [attributeData])
+
+  const header = [
+    { columnName: '', width: 'w-0.5' },
+    { columnName: 'Attributes' },
+    display && !w3cSchema && { columnName: 'Condition' },
+    display && !w3cSchema && { columnName: 'Value', width: 'w-0.75' },
+    { columnName: 'Schema Name' },
+    !w3cSchema && { columnName: 'Cred Def Name' },
+  ]
+
+  return (
+    <div className="px-4 pt-2">
+      <div className="col-span-full mb-4 xl:mb-2">
+        <div className="flex w-full items-center justify-end">
+          <BackButton
+            path={
+              w3cSchema
+                ? pathRoutes.organizations.verification.email
+                : pathRoutes.organizations.verification.emailCredDef
+            }
+          />
+        </div>
+      </div>
+
+      {(proofReqSuccess || errMsg) && (
+        <div className="relative p-2">
+          <Alert
+            className={`pr-10 ${
+              proofReqSuccess ? 'text-success' : 'text-error'
+            }`}
+          >
+            <AlertTitle className="font-semibold">
+              {proofReqSuccess ? 'Success' : 'Error'}
+            </AlertTitle>
+            <AlertDescription>{proofReqSuccess ?? errMsg}</AlertDescription>
+            <Button
+              className="text-muted-foreground hover:text-foreground absolute top-3 right-3"
+              onClick={() => {
+                setProofReqSuccess(null)
+                setErrMsg(null)
+              }}
+              aria-label="Dismiss"
+            >
+              <X className="h-4 w-4" />
+            </Button>
+          </Alert>
+        </div>
+      )}
+      <div
+        className={
+          'font-montserrat flex flex-col p-2 text-left text-base leading-6 font-semibold tracking-normal sm:flex-row sm:justify-between sm:space-x-2'
+        }
+      >
+        <h1 className="mr-auto ml-1 text-xl font-semibold sm:text-2xl">
+          Attributes
+        </h1>
+      </div>
+      <div className="rounded-lg border p-6 shadow-sm sm:p-6 2xl:col-span-2">
+        <DataTable
+          header={header.filter(Boolean) as TableHeader[]}
+          data={attributeList}
+          loading={loading}
+        ></DataTable>
+      </div>
+
+      <div className="flex w-full items-center justify-end">
+        <Button
+          onClick={handleSubmit}
+          disabled={!attributeData?.some((ele) => ele.isChecked)}
+          className="mt-2 ml-auto rounded-lg text-center text-base font-medium sm:w-auto"
+        >
+          <svg
+            xmlns="http://www.w3.org/2000/svg"
+            className="h-5 w-5 text-current"
+            fill="none"
+            viewBox="0 0 24 24"
+          >
+            <path
+              fill="currentColor"
+              d="M12.516 6.444a.556.556 0 1 0-.787.787l4.214 4.214H4.746a.558.558 0 0 0 0 1.117h11.191l-4.214 4.214a.556.556 0 0 0 .396.95.582.582 0 0 0 .397-.163l5.163-5.163a.553.553 0 0 0 .162-.396.576.576 0 0 0-.162-.396l-5.163-5.164Z"
+            />
+            <path
+              fill="currentColor"
+              d="M12.001 0a12 12 0 0 0-8.484 20.485c4.686 4.687 12.283 4.687 16.969 0 4.686-4.685 4.686-12.282 0-16.968A11.925 11.925 0 0 0 12.001 0Zm0 22.886c-6 0-10.884-4.884-10.884-10.885C1.117 6.001 6 1.116 12 1.116s10.885 4.885 10.885 10.885S18.001 22.886 12 22.886Z"
+            />
+          </svg>
+          Continue
+        </Button>
+      </div>
+    </div>
+  )
+}
+
+export default EmailAttributesSelection
diff --git a/nextjs/src/features/verification/components/SortDataTable.tsx b/nextjs/src/features/verification/components/SortDataTable.tsx
index 3ea5b158e..81b60dd24 100644
--- a/nextjs/src/features/verification/components/SortDataTable.tsx
+++ b/nextjs/src/features/verification/components/SortDataTable.tsx
@@ -121,9 +121,9 @@ const SortDataTable: React.FC<IDataTable> = ({
   ]
 
   return (
-    <section className="w-full bg-gray-50 dark:bg-gray-900">
+    <section className="w-full">
       <div className="mx-auto min-h-80">
-        <div className="relative overflow-hidden bg-white shadow-md sm:rounded-lg dark:bg-gray-800">
+        <div className="relative overflow-hidden shadow-md sm:rounded-lg">
           {isHeader && (
             <div className="flex flex-col items-center justify-between space-y-3 p-3 sm:flex-row sm:space-y-0 sm:space-x-4">
               <div className="w-full sm:w-1/2">
@@ -177,7 +177,7 @@ const SortDataTable: React.FC<IDataTable> = ({
                   <div className="flex w-full items-center space-x-3 sm:w-auto">
                     <select
                       id="small"
-                      className="block w-full rounded-lg border border-gray-300 bg-gray-50 p-2 text-sm text-gray-900 focus:border-blue-500 focus:ring-blue-500 dark:border-gray-600 dark:bg-gray-700 dark:text-white dark:placeholder-gray-400 dark:focus:border-blue-500 dark:focus:ring-blue-500"
+                      className="block w-full rounded-lg border p-2 text-sm"
                       name="selectedValue"
                       value={selectedValue}
                       onChange={handleSortByValues}
@@ -194,7 +194,7 @@ const SortDataTable: React.FC<IDataTable> = ({
             </div>
           )}
           <div className="overflow-x-auto">
-            <table className="w-full divide-y divide-gray-200 dark:divide-gray-600">
+            <table className="w-full divide-y">
               <thead className="bg-secondary text-secondary-foreground">
                 <tr>
                   {header &&
@@ -203,29 +203,22 @@ const SortDataTable: React.FC<IDataTable> = ({
                       <th
                         key={ele.columnName}
                         scope="col"
-                        className={`p-4 text-left text-xs font-medium tracking-wider text-gray-500 uppercase dark:text-white ${ele.width}`}
+                        className={`text-muted-foreground p-4 text-left text-xs font-medium tracking-wider uppercase ${ele.width}`}
                       >
                         <div>{ele.columnName}</div>
                         {ele.subColumnName && (
-                          <div className="flex text-gray-500">
-                            {ele.subColumnName}{' '}
-                          </div>
+                          <div className="flex">{ele.subColumnName} </div>
                         )}
                       </th>
                     ))}
                 </tr>
               </thead>
-              <tbody className="bg-white dark:bg-gray-800">
+              <tbody className="">
                 {loading ? (
-                  <tr className="text-center">
-                    <td
-                      className="p-2 text-center text-gray-500"
-                      colSpan={header.length}
-                    >
-                      <div>
-                        <div className="mb-4 flex w-full items-center justify-center text-center">
-                          <Loader />
-                        </div>
+                  <tr key="loading-row" className="text-center">
+                    <td className="p-2 text-center" colSpan={header.length}>
+                      <div className="mb-4 flex w-full items-center justify-center text-center">
+                        <Loader />
                       </div>
                     </td>
                   </tr>
@@ -235,15 +228,15 @@ const SortDataTable: React.FC<IDataTable> = ({
 
                     return (
                       <tr
-                        key={ele.clickId}
+                        key={index}
                         className={`${
                           index % 2 !== 0 ? 'bg-gray-50 dark:bg-gray-700' : ''
                         }`}
                       >
                         {ele.data.map((subEle, subIndex) => (
                           <td
-                            key={`${subEle.data}-${subEle.subData}-${subIndex}`}
-                            className="p-4 align-middle text-sm font-normal whitespace-nowrap text-gray-900 dark:text-white"
+                            key={`row-${ele.clickId}-col-${subIndex}`}
+                            className="p-4 align-middle text-sm font-normal whitespace-nowrap"
                           >
                             <div>
                               <div>{subEle.data}</div>
@@ -255,11 +248,7 @@ const SortDataTable: React.FC<IDataTable> = ({
                         {showSelectButton && (
                           <td>
                             <Button
-                              onClick={() => {
-                                if (callback) {
-                                  callback(ele?.clickId)
-                                }
-                              }}
+                              onClick={() => callback?.(ele?.clickId)}
                               className="bg-primary hover:bg-primary-800 mt-2 mr-2 mb-2 rounded-lg px-5 py-2.5 text-center text-sm font-medium focus:ring-4 focus:outline-none"
                             >
                               Select
@@ -270,11 +259,8 @@ const SortDataTable: React.FC<IDataTable> = ({
                     )
                   })
                 ) : (
-                  <tr className="text-center">
-                    <td
-                      className="p-2 text-center text-gray-500"
-                      colSpan={header.length}
-                    >
+                  <tr key="empty-row" className="text-center">
+                    <td className="p-2 text-center" colSpan={header.length}>
                       <div className="mx-auto flex h-full w-full items-center justify-center">
                         <EmptyMessage
                           title={message}
@@ -295,15 +281,12 @@ const SortDataTable: React.FC<IDataTable> = ({
               aria-label="Table navigation"
             >
               {!loading && data?.length > 0 && (
-                <span className="mt-2 text-sm font-normal text-gray-500 dark:text-gray-400">
+                <span className="mt-2 text-sm font-normal">
                   Showing{' '}
-                  <span className="font-semibold text-gray-900 dark:text-white">
+                  <span className="font-semibold">
                     {startItem}-{endItem}
                   </span>{' '}
-                  of{' '}
-                  <span className="font-semibold text-gray-900 dark:text-white">
-                    {totalItem}
-                  </span>
+                  of <span className="font-semibold">{totalItem}</span>
                 </span>
               )}
               {lastPage > 1 && data?.length > 0 && (
diff --git a/nextjs/src/features/verification/components/VerificationSchemasList.tsx b/nextjs/src/features/verification/components/VerificationSchemasList.tsx
new file mode 100644
index 000000000..43a2257e8
--- /dev/null
+++ b/nextjs/src/features/verification/components/VerificationSchemasList.tsx
@@ -0,0 +1,551 @@
+/* eslint-disable max-lines */
+'use client'
+
+import { DidMethod, Features, SchemaTypes } from '@/common/enums'
+import { IAttributesDetails, ISchema, ISchemaData } from '../type/interface'
+import { JSX, useEffect, useState } from 'react'
+import {
+  Pagination,
+  PaginationContent,
+  PaginationItem,
+  PaginationLink,
+  PaginationNext,
+  PaginationPrevious,
+} from '@/components/ui/pagination'
+import {
+  Select,
+  SelectContent,
+  SelectItem,
+  SelectTrigger,
+  SelectValue,
+} from '@/components/ui/select'
+import { apiStatusCodes, itemPerPage } from '@/config/CommonConstant'
+import { getAllSchemas, getAllSchemasByOrgId } from '@/app/api/schema'
+import {
+  setSchemaAttributes,
+  setSchemaId,
+  setSelectedSchemasData,
+  setW3CSchemaAttributes,
+} from '@/lib/verificationSlice'
+import { useAppDispatch, useAppSelector } from '@/lib/hooks'
+
+import { Alert } from '@/components/ui/alert'
+import { AxiosResponse } from 'axios'
+import { Button } from '@/components/ui/button'
+import { Create } from '@/config/Constant'
+import { EmptyMessage } from '@/components/EmptyMessage'
+import { IconSearch } from '@tabler/icons-react'
+import { Input } from '@/components/ui/input'
+import Loader from '@/components/Loader'
+import PageContainer from '@/components/layout/page-container'
+import RoleViewButton from '@/components/RoleViewButton'
+import SchemaCard from '@/features/schemas/components/SchemaCard'
+import { getOrganizationById } from '@/app/api/organization'
+import { pathRoutes } from '@/config/pathRoutes'
+import { useRouter } from 'next/navigation'
+
+const VerificationSchemasList = (): JSX.Element => {
+  const [schemasList, setSchemasList] = useState([])
+  const [schemasDetailsErr, setSchemasDetailsErr] = useState<string | null>('')
+  const [loading, setLoading] = useState<boolean>(true)
+  const [allSchemasFlag, setAllSchemasFlag] = useState<boolean>(false)
+  const [schemasListParameter, setSchemasListParameter] = useState({
+    itemPerPage,
+    page: 1,
+    search: '',
+    sortBy: 'id',
+    sortingOrder: 'desc',
+    allSearch: '',
+  })
+  const [walletStatus, setWalletStatus] = useState(false)
+  const [totalItems, setTotalItems] = useState(0)
+  const [searchValue, setSearchValue] = useState('')
+  const [selectedSchemas, setSelectedSchemas] = useState<ISchema[]>([])
+  const [selectedSchemaArray, setSelectedSchemaArray] = useState<ISchema[]>([])
+
+  const [w3cSchema, setW3cSchema] = useState<boolean>(false)
+  const [isNoLedger, setIsNoLedger] = useState<boolean>(false)
+  const [schemaType, setSchemaType] = useState('')
+
+  const route = useRouter()
+  const dispatch = useAppDispatch()
+  const organizationId = useAppSelector((state) => state.organization.orgId)
+  const ledgerId = useAppSelector((state) => state.organization.ledgerId)
+
+  const getSchemaListDetails = async (): Promise<void> => {
+    try {
+      setLoading(true)
+      let schemasList = null
+      if (allSchemasFlag) {
+        schemasList = await getAllSchemas(
+          schemasListParameter,
+          schemaType,
+          ledgerId,
+        )
+      } else {
+        schemasList = await getAllSchemasByOrgId(
+          schemasListParameter,
+          organizationId,
+        )
+      }
+
+      const { data } = schemasList as AxiosResponse
+
+      if (schemasList === 'Schema records not found') {
+        setLoading(false)
+        setSchemasList([])
+      }
+
+      if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) {
+        if (data?.data?.data) {
+          setTotalItems(data?.data?.lastPage)
+          setSchemasList(data?.data?.data)
+          setLoading(false)
+        } else {
+          setLoading(false)
+          if (schemasList !== 'Schema records not found') {
+            setSchemasDetailsErr(schemasList as string)
+          }
+        }
+      } else {
+        setLoading(false)
+        if (schemasList !== 'Schema records not found') {
+          setSchemasDetailsErr(schemasList as string)
+        }
+      }
+      setTimeout(() => {
+        setSchemasDetailsErr('')
+      }, 3000)
+    } catch (error) {
+      console.error('Error while fetching schema list:', error)
+      setLoading(false)
+    }
+  }
+
+  useEffect(() => {
+    getSchemaListDetails()
+  }, [schemasListParameter, allSchemasFlag])
+
+  const onSchemaListParameterSearch = async (
+    event: React.ChangeEvent<HTMLInputElement>,
+  ): Promise<void> => {
+    event.preventDefault()
+    const inputValue = event.target.value
+    setSearchValue(inputValue)
+
+    setSchemasListParameter((prevParams) => ({
+      ...prevParams,
+      ...(allSchemasFlag ? { allSearch: inputValue } : { search: inputValue }),
+      page: 1,
+    }))
+  }
+
+  const handleSchemaSelection = (
+    schemaId: string,
+    attributes: IAttributesDetails[],
+    issuerId: string,
+    created: string,
+    checked: boolean,
+  ): void => {
+    const schemaDetails = {
+      schemaId,
+      attributes,
+      issuerId,
+      createdDate: created,
+    }
+
+    if (checked) {
+      setSelectedSchemas((prevSelectedSchemas) => [
+        ...prevSelectedSchemas,
+        schemaDetails,
+      ])
+    } else {
+      setSelectedSchemas((prevSelectedSchemas) =>
+        prevSelectedSchemas.filter((schema) => schema.schemaId !== schemaId),
+      )
+    }
+  }
+
+  const handleW3cSchemas = async (
+    checked: boolean,
+    schemaData?: ISchemaData,
+  ): Promise<void> => {
+    if (!schemaData) {
+      return
+    }
+
+    const schema: ISchema = {
+      ...schemaData,
+      schemaId: schemaData.schemaId ?? '',
+      createdDate: schemaData.createDateTime,
+    }
+
+    const updateSchemas = (prevSchemas: ISchema[]): ISchema[] => {
+      let updatedSchemas = [...prevSchemas]
+      if (checked) {
+        updatedSchemas = [...updatedSchemas, schema]
+      } else {
+        updatedSchemas = updatedSchemas.filter(
+          (schemas) => schemas?.schemaLedgerId !== schema?.schemaLedgerId,
+        )
+      }
+
+      return updatedSchemas
+    }
+
+    setSelectedSchemas((prevSchemas) => {
+      if (!Array.isArray(prevSchemas)) {
+        console.error('Previous schemas is not an array:', prevSchemas)
+        return []
+      }
+
+      const updatedSchemas = updateSchemas(prevSchemas)
+      setSelectedSchemaArray(updatedSchemas)
+      dispatch(setSelectedSchemasData(updatedSchemas))
+      return updatedSchemas
+    })
+  }
+
+  const fetchOrganizationDetails = async (): Promise<void> => {
+    setLoading(true)
+    const response = await getOrganizationById(organizationId)
+    const { data } = response as AxiosResponse
+    if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) {
+      const did = data?.data?.org_agents?.[0]?.orgDid
+
+      if (data?.data?.org_agents && data?.data?.org_agents?.length > 0) {
+        setWalletStatus(true)
+      }
+      if (
+        did.includes(DidMethod.POLYGON) ||
+        did.includes(DidMethod.KEY) ||
+        did.includes(DidMethod.WEB)
+      ) {
+        setW3cSchema(true)
+        setSchemaType(SchemaTypes.schema_W3C)
+      }
+      if (did.includes(DidMethod.INDY)) {
+        setW3cSchema(false)
+        setSchemaType(SchemaTypes.schema_INDY)
+      }
+      if (did.includes(DidMethod.KEY) || did.includes(DidMethod.WEB)) {
+        setIsNoLedger(true)
+      }
+    }
+    setLoading(false)
+  }
+
+  const handleContinue = async (): Promise<void> => {
+    const schemaIds = selectedSchemas?.map((schema) => schema?.schemaId)
+    dispatch(setSchemaId(schemaIds))
+
+    const schemaAttributes = selectedSchemas.map((schema) => ({
+      schemaId: schema.schemaId,
+      attributes: schema.attributes,
+    }))
+
+    dispatch(setSchemaAttributes(schemaAttributes))
+    route.push(`${pathRoutes.organizations.verification.emailCredDef}`)
+  }
+
+  const handleW3CSchemaDetails = async (): Promise<void> => {
+    const w3cSchemaAttributes = selectedSchemaArray
+      .filter((schema) => schema.schemaLedgerId)
+      .map((schema) => ({
+        schemaId: schema.schemaLedgerId ?? '',
+        attributes: schema.attributes,
+        schemaName: schema.name ?? '',
+      }))
+
+    dispatch(setW3CSchemaAttributes(w3cSchemaAttributes))
+    route.push(`${pathRoutes.organizations.verification.w3cAttributes}`)
+  }
+
+  const options = ['All schemas']
+  const optionsWithDefault = ['Organizations schema', ...options]
+
+  const handleFilter = async (value: string): Promise<void> => {
+    const selectedFilter = value
+    setAllSchemasFlag(selectedFilter === 'All schemas')
+
+    setSchemasListParameter((prevParams) => ({
+      ...prevParams,
+      page: 1,
+      search: '',
+      allSearch: '',
+    }))
+    setSearchValue('')
+  }
+  useEffect(() => {
+    fetchOrganizationDetails()
+    setSearchValue('')
+  }, [])
+
+  const createSchemaButtonTitle = {
+    title: 'Create',
+    svg: <Create />,
+    toolTip: 'Create new schema',
+  }
+
+  const emptySchemaListTitle = 'No Schemas'
+  const emptySchemaListDescription = 'Get started by creating a new Schema'
+  const emptySchemaListBtn = { title: 'Create Schema', svg: <Create /> }
+  return (
+    <PageContainer>
+      <div className="px-4 pt-2">
+        <div>
+          <div>
+            <div className="mb-4 flex flex-wrap items-center justify-between gap-4">
+              <h1 className="text-primary-foreground mr-auto ml-1 text-xl font-semibold sm:text-2xl">
+                Schemas
+              </h1>
+              <div className="relative w-full sm:max-w-sm">
+                <Input
+                  type="text"
+                  placeholder="Search..."
+                  value={searchValue}
+                  onChange={onSchemaListParameterSearch}
+                  className="bg-background text-muted-foreground focus-visible:ring-primary h-10 rounded-lg pr-4 pl-10 text-sm shadow-sm focus-visible:ring-1"
+                />
+                <IconSearch className="text-muted-foreground absolute top-1/2 left-3 h-5 w-5 -translate-y-1/2" />
+              </div>
+
+              <Select
+                defaultValue="Organization's schema"
+                onValueChange={handleFilter}
+              >
+                <SelectTrigger className="focus:border-primary focus:ring-primary dark:focus:border-primary dark:focus:ring-primary min-h-[42px] w-[230px] rounded-lg border p-2.5 text-sm">
+                  <SelectValue placeholder="Select schema type" />
+                </SelectTrigger>
+                <SelectContent>
+                  {optionsWithDefault.map((opt) => (
+                    <SelectItem key={opt} value={opt}>
+                      {opt}
+                    </SelectItem>
+                  ))}
+                </SelectContent>
+              </Select>
+              <div className="bg-primary text-foreground flex space-x-2">
+                {walletStatus ? (
+                  <RoleViewButton
+                    title={createSchemaButtonTitle.toolTip}
+                    buttonTitle={createSchemaButtonTitle.title}
+                    feature={Features.CRETAE_SCHEMA}
+                    svgComponent={createSchemaButtonTitle.svg}
+                    onClickEvent={() => {
+                      route.push(`${pathRoutes.organizations.createSchema}`)
+                    }}
+                  />
+                ) : (
+                  <RoleViewButton
+                    buttonTitle={createSchemaButtonTitle.title}
+                    feature={Features.CRETAE_SCHEMA}
+                    svgComponent={createSchemaButtonTitle.svg}
+                    onClickEvent={() => {
+                      route.push(`${pathRoutes.organizations.dashboard}`)
+                    }}
+                  />
+                )}
+              </div>
+            </div>
+          </div>
+          {schemasDetailsErr !== '' && (
+            <Alert color="failure">
+              <span>
+                <p>{schemasDetailsErr}</p>
+              </span>
+            </Alert>
+          )}
+
+          {schemasList && schemasList.length > 0 ? (
+            <div
+              className="Flex-wrap"
+              style={{ display: 'flex', flexDirection: 'column' }}
+            >
+              <div className="mt-0 mb-4 grid w-full grid-cols-1 gap-4 xl:grid-cols-2 2xl:grid-cols-2">
+                {schemasList &&
+                  schemasList.length > 0 &&
+                  schemasList.map((element) => (
+                    <div
+                      className="px-0 sm:px-2"
+                      key={element['schemaLedgerId']}
+                    >
+                      <SchemaCard
+                        selectedSchemas={selectedSchemas}
+                        schemaName={element['name']}
+                        version={element['version']}
+                        schemaId={element['schemaLedgerId']}
+                        issuerDid={element['issuerId']}
+                        attributes={element['attributes']}
+                        created={element['createDateTime']}
+                        showCheckbox={true}
+                        isClickable={false}
+                        w3cSchema={w3cSchema}
+                        noLedger={isNoLedger}
+                        isVerificationUsingEmail={true}
+                        onChange={(checked) => {
+                          w3cSchema
+                            ? handleW3cSchemas(checked, element)
+                            : handleSchemaSelection(
+                                element['schemaLedgerId'],
+                                element['attributes'],
+                                element['issuerId'],
+                                element['createDateTime'],
+                                checked,
+                              )
+                        }}
+                      />
+                    </div>
+                  ))}
+              </div>
+
+              <div className="mb-4 flex items-center justify-end">
+                <Button
+                  onClick={w3cSchema ? handleW3CSchemaDetails : handleContinue}
+                  disabled={selectedSchemas.length === 0}
+                  className="flex items-center gap-2 rounded-lg px-4 py-4 text-base font-medium sm:w-auto"
+                >
+                  <svg
+                    xmlns="http://www.w3.org/2000/svg"
+                    className="h-5 w-5 text-current"
+                    fill="none"
+                    viewBox="0 0 24 24"
+                  >
+                    <path
+                      fill="currentColor"
+                      d="M12.516 6.444a.556.556 0 1 0-.787.787l4.214 4.214H4.746a.558.558 0 0 0 0 1.117h11.191l-4.214 4.214a.556.556 0 0 0 .396.95.582.582 0 0 0 .397-.163l5.163-5.163a.553.553 0 0 0 .162-.396.576.576 0 0 0-.162-.396l-5.163-5.164Z"
+                    />
+                    <path
+                      fill="currentColor"
+                      d="M12.001 0a12 12 0 0 0-8.484 20.485c4.686 4.687 12.283 4.687 16.969 0 4.686-4.685 4.686-12.282 0-16.968A11.925 11.925 0 0 0 12.001 0Zm0 22.886c-6 0-10.884-4.884-10.884-10.885C1.117 6.001 6 1.116 12 1.116s10.885 4.885 10.885 10.885S18.001 22.886 12 22.886Z"
+                    />
+                  </svg>
+                  Continue
+                </Button>
+              </div>
+              <div
+                className="mb-4 flex items-center justify-end"
+                id="schemasPagination"
+              >
+                {totalItems > 1 && (
+                  <div className="mt-6 flex justify-end">
+                    <Pagination>
+                      <PaginationContent>
+                        {schemasListParameter.page > 1 && (
+                          <PaginationItem>
+                            <PaginationPrevious
+                              href="#"
+                              onClick={(e) => {
+                                e.preventDefault()
+                                setSchemasListParameter((prev) => ({
+                                  ...prev,
+                                  page: prev.page - 1,
+                                }))
+                              }}
+                            />
+                          </PaginationItem>
+                        )}
+
+                        {Array.from({ length: totalItems })
+                          .map((_, i) => i + 1)
+                          .filter(
+                            (page) =>
+                              page === 1 ||
+                              page === totalItems ||
+                              Math.abs(page - schemasListParameter.page) <= 1,
+                          )
+                          .reduce<(number | string)[]>((acc, page, i, arr) => {
+                            if (
+                              i > 0 &&
+                              typeof page === 'number' &&
+                              typeof arr[i - 1] === 'number' &&
+                              page - (arr[i - 1] as number) > 1
+                            ) {
+                              acc.push('...')
+                            }
+                            acc.push(page)
+                            return acc
+                          }, [])
+                          .map((page, idx) => {
+                            if (page === '...') {
+                              return (
+                                <span
+                                  key={`ellipsis-${idx}`}
+                                  className="text-muted-foreground px-2"
+                                >
+                                  ...
+                                </span>
+                              )
+                            }
+
+                            return (
+                              <PaginationItem key={page}>
+                                <PaginationLink
+                                  href="#"
+                                  onClick={(e) => {
+                                    e.preventDefault()
+                                    setSchemasListParameter((prev) => ({
+                                      ...prev,
+                                      page: page as number,
+                                    }))
+                                  }}
+                                  className={`rounded-lg px-4 py-2 ${
+                                    schemasListParameter.page === page
+                                      ? 'bg-primary text-[var(--color-white)]'
+                                      : 'bg-background text-muted-foreground'
+                                  }`}
+                                >
+                                  {page}
+                                </PaginationLink>
+                              </PaginationItem>
+                            )
+                          })}
+
+                        {schemasListParameter.page < totalItems && (
+                          <PaginationItem>
+                            <PaginationNext
+                              href="#"
+                              onClick={(e) => {
+                                e.preventDefault()
+                                setSchemasListParameter((prev) => ({
+                                  ...prev,
+                                  page: prev.page + 1,
+                                }))
+                              }}
+                            />
+                          </PaginationItem>
+                        )}
+                      </PaginationContent>
+                    </Pagination>
+                  </div>
+                )}
+              </div>
+            </div>
+          ) : (
+            <div>
+              {loading ? (
+                <div className="mb-4 flex items-center justify-center">
+                  <Loader />
+                </div>
+              ) : (
+                <div className="border-border bg-background rounded-lg border shadow-sm sm:p-6 2xl:col-span-2">
+                  <EmptyMessage
+                    title={emptySchemaListTitle}
+                    description={emptySchemaListDescription}
+                    buttonContent={emptySchemaListBtn.title}
+                    svgComponent={emptySchemaListBtn.svg}
+                    onClick={() => {
+                      route.push(`${pathRoutes.organizations.createSchema}`)
+                    }}
+                  />
+                </div>
+              )}
+            </div>
+          )}
+        </div>
+      </div>
+    </PageContainer>
+  )
+}
+
+export default VerificationSchemasList
diff --git a/nextjs/src/features/verification/type/interface.ts b/nextjs/src/features/verification/type/interface.ts
index 056dd880a..6d3f57de5 100644
--- a/nextjs/src/features/verification/type/interface.ts
+++ b/nextjs/src/features/verification/type/interface.ts
@@ -109,7 +109,7 @@ export interface ISelectedAttributes {
   selectError: string
 }
 
-interface IEmailData {
+export interface IEmailData {
   email: string
 }
 export interface IEmailValues {
diff --git a/nextjs/src/lib/verificationSlice.ts b/nextjs/src/lib/verificationSlice.ts
index 16d7779d0..1900dd61c 100644
--- a/nextjs/src/lib/verificationSlice.ts
+++ b/nextjs/src/lib/verificationSlice.ts
@@ -1,4 +1,5 @@
 import {
+  CredDefData,
   ISchema,
   ISchemaAttributeData,
   ISelectedAttributes,
@@ -18,6 +19,9 @@ interface VerificationState {
   selectedConnections: LocalOrgs[]
   selectedUser: SelectedUsers[]
   w3cSchemaAttributes: IW3CSchemaAttributeItem[]
+  CRED_DEF_ID: string
+  CredDefData: CredDefData[]
+  SCHEMA_CRED_DEFS: CredDefData[]
 }
 
 const initialState: VerificationState = {
@@ -30,6 +34,9 @@ const initialState: VerificationState = {
   selectedConnections: [],
   selectedUser: [],
   w3cSchemaAttributes: [],
+  CRED_DEF_ID: '',
+  CredDefData: [],
+  SCHEMA_CRED_DEFS: [],
 }
 
 const verificationSlice = createSlice({
@@ -51,7 +58,10 @@ const verificationSlice = createSlice({
     setSchemaId(state, action: PayloadAction<string[] | null>) {
       state.schemaId = action.payload
     },
-    setSelectedAttributeData(state, action: PayloadAction<ISelectedAttributes[]>) {
+    setSelectedAttributeData(
+      state,
+      action: PayloadAction<ISelectedAttributes[]>,
+    ) {
       state.attributeData = action.payload
     },
     setSelectedConnections(state, action: PayloadAction<LocalOrgs[]>) {
@@ -60,9 +70,21 @@ const verificationSlice = createSlice({
     setSelectedUser(state, action: PayloadAction<SelectedUsers[]>) {
       state.selectedUser = action.payload
     },
-    setW3CSchemaAttributes(state, action: PayloadAction<IW3CSchemaAttributeItem[]>) {
+    setW3CSchemaAttributes(
+      state,
+      action: PayloadAction<IW3CSchemaAttributeItem[]>,
+    ) {
       state.w3cSchemaAttributes = action.payload
     },
+    setCredDefId: (state, action: PayloadAction<string>) => {
+      state.CRED_DEF_ID = action.payload
+    },
+    setCredDefData: (state, action: PayloadAction<CredDefData[]>) => {
+      state.CredDefData = action.payload
+    },
+    setSchemaCredDefs: (state, action: PayloadAction<CredDefData[]>) => {
+      state.SCHEMA_CRED_DEFS = action.payload
+    },
     resetVerificationState(state) {
       state.schemaAttributes = []
       state.selectedSchemas = []
@@ -73,6 +95,9 @@ const verificationSlice = createSlice({
       state.selectedConnections = []
       state.selectedUser = []
       state.w3cSchemaAttributes = []
+      state.CRED_DEF_ID = ''
+      state.CredDefData = []
+      state.SCHEMA_CRED_DEFS = []
     },
     resetAttributeData(state) {
       state.attributeData = []
@@ -101,6 +126,15 @@ const verificationSlice = createSlice({
     resetRouteType(state) {
       state.routeType = ''
     },
+    resetCredDefId(state) {
+      state.CRED_DEF_ID = ''
+    },
+    resetCredDefData(state) {
+      state.CredDefData = []
+    },
+    resetSchemaCredDefs(state) {
+      state.SCHEMA_CRED_DEFS = []
+    },
   },
 })
 
@@ -114,6 +148,9 @@ export const {
   setSelectedConnections,
   setSelectedUser,
   setW3CSchemaAttributes,
+  setCredDefId,
+  setCredDefData,
+  setSchemaCredDefs,
   resetVerificationState,
   resetAttributeData,
   resetSelectedSchemas,
@@ -124,6 +161,9 @@ export const {
   resetSchemaId,
   resetOrgId,
   resetRouteType,
+  resetCredDefId,
+  resetCredDefData,
+  resetSchemaCredDefs,
 } = verificationSlice.actions
 
 export default verificationSlice.reducer


Reviews:
user: login: pranalidhanavade
body: LGTM
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-22T13:33:28Z
user: login: shitrerohit
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-22T14:15:05Z
user: login: sanjaykhondal-aw
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-22T14:35:24Z
user: login: sanjaykhondal-aw
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-22T14:35:37Z
user: login: sanjaykhondal-aw
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-22T14:36:02Z
user: login: sanjaykhondal-aw
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-22T14:38:25Z
user: login: shitrerohit
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-22T14:40:39Z

Review comments:
diff_hunk: @@ -0,0 +1,6 @@
+// import EmailVerification from '@/features/verification/components/EmailVerification'
path: nextjs/src/app/organizations/verification/verify-credentials/schema/cred-defs/attributes/verification-email/page.tsx
user: login: shitrerohit
body: Remove commented code
created_at: 2025-05-22T13:43:27Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,534 @@
+/* eslint-disable max-lines */
+'use client'
+
+import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
+import { JSX, useEffect, useState } from 'react'
+import { apiStatusCodes, predicatesConditions } from '@/config/CommonConstant'
+import { useAppDispatch, useAppSelector } from '@/lib/hooks'
+
+import { AxiosResponse } from 'axios'
+import BackButton from '@/components/BackButton'
+import { Button } from '@/components/ui/button'
+import CustomCheckbox from '@/components/CustomCheckbox'
+import DataTable from '@/components/DataTable'
+import { DidMethod } from '@/common/enums'
+import { ISelectedAttributes } from '../type/interface'
+import { ITableData } from '@/components/DataTable/interface'
+import { TableHeader } from './SortDataTable'
+import { X } from 'lucide-react'
+import { getOrganizationById } from '@/app/api/organization'
+import { pathRoutes } from '@/config/pathRoutes'
+import { setSelectedAttributeData } from '@/lib/verificationSlice'
+import { useRouter } from 'next/navigation'
+
+interface NumberAttribute {
+  selectedOption: string | null
+  value: string | number | null
+}
+
+const EmailAttributesSelection = (): JSX.Element => {
+  const [attributeList, setAttributeList] = useState<ITableData[]>([])
+  const [proofReqSuccess, setProofReqSuccess] = useState<string | null>(null)
+  const [errMsg, setErrMsg] = useState<string | null>(null)
+  const [display, setDisplay] = useState<boolean | undefined>(false)
+  const [loading, setLoading] = useState<boolean>(true)
+  const [attributeData, setAttributeData] = useState<
+    ISelectedAttributes[] | null
+  >(null)
+  const [w3cSchema, setW3cSchema] = useState<boolean>(false)
+  const [isConnectionProof, setIsConnectionProof] = useState<boolean>(false)
+
+  const dispatch = useAppDispatch()
+  const router = useRouter()
+  const orgId = useAppSelector((state) => state.organization.orgId)
+
+  const verificationRouteType = useAppSelector(
+    (state) => state.verification.routeType,
+  )
+
+  const getSelectedCredDefData = '[]'
+
+  const selectedSchemaAttributes = useAppSelector(
+    (state) => state.verification.selectedSchemas,
+  )
+  const ConnectionVerification = async (): Promise<void> => {
+    if (verificationRouteType === 'Connection') {
+      setIsConnectionProof(true)
+    } else {
+      setIsConnectionProof(false)
+    }
+  }
+  useEffect(() => {
+    ConnectionVerification()
+  }, [])
+
+  const handleAttributeChange = async (
+    attributeName: string,
+    changeType: 'checkbox' | 'input' | 'select',
+    value: string | boolean,
+    schemaId?: string | undefined,
+    credDefId?: string | undefined,
+  ): Promise<void> => {
+    const updatedAttributes =
+      attributeData?.map((attribute) => {
+        if (
+          attribute.attributeName === attributeName &&
+          attribute.schemaId === schemaId &&
+          attribute.credDefId === credDefId
+        ) {
+          switch (changeType) {
+            case 'checkbox':
+              return {
+                ...attribute,
+                isChecked: value as boolean,
+                value: (value as boolean) ? attribute.value : '',
+                selectedOption: attribute?.condition || 'Select',
+                inputError: '',
+                selectError: '',
+              }
+            case 'input':
+              return {
+                ...attribute,
+                value: value as string,
+                inputError: '',
+              }
+            case 'select':
+              return {
+                ...attribute,
+                selectedOption: value as string,
+                selectError: '',
+              }
+            default:
+              return attribute
+          }
+        }
+        return attribute
+      }) ?? []
+
+    setAttributeData(updatedAttributes)
+
+    dispatch(setSelectedAttributeData(updatedAttributes))
+  }
+
+  const getOrgDetails = async (): Promise<void> => {
+    setLoading(true)
+
+    const response = await getOrganizationById(orgId)
+    const { data } = response as AxiosResponse
+    if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) {
+      const did = data?.data?.org_agents?.[0]?.orgDid
+
+      if (
+        did.includes(DidMethod.POLYGON) ||
+        did.includes(DidMethod.KEY) ||
+        did.includes(DidMethod.WEB)
+      ) {
+        setW3cSchema(true)
+      } else if (did.includes(DidMethod.INDY)) {
+        setW3cSchema(false)
+      }
+    }
+
+    setLoading(false)
+  }
+
+  useEffect(() => {
+    getOrgDetails()
+  }, [])
+
+  const isInvalidNumberAttribute = (attribute: NumberAttribute): boolean => {
+    const isOptionInvalid =
+      attribute.selectedOption === null ||
+      attribute.selectedOption === '' ||
+      attribute.selectedOption === 'Select'
+    const isValueInvalid = attribute.value === null || attribute.value === ''
+
+    if (!isOptionInvalid && isValueInvalid) {
+      setErrMsg('Value is required')
+      return true
+    } else if (!isValueInvalid && isOptionInvalid) {
+      setErrMsg('Condition is required')
+      return true
+    }
+    return false
+  }
+
+  const hasInvalidNumberAttributes = (): boolean => {
+    const numberAttributes = attributeData?.filter(
+      (attr) => attr.dataType === 'number' && attr.isChecked,
+    )
+
+    for (const attribute of numberAttributes || []) {
+      if (isInvalidNumberAttribute(attribute)) {
+        return true
+      }
+    }
+
+    return false
+  }
+  const redirectToAppropriatePage = (): void => {
+    switch (true) {
+      case w3cSchema && isConnectionProof:
+        router.push(pathRoutes.organizations.verification.W3CConnections)
+        break
+      case !w3cSchema && isConnectionProof:
+        router.push(pathRoutes.organizations.verification.connections)
+        break
+      case w3cSchema && !isConnectionProof:
+        router.push(pathRoutes.organizations.verification.w3cEmailVerification)
+        break
+      default:
+        router.push(pathRoutes.organizations.verification.emailVerification)
+        break
+    }
+  }
+  const handleSubmit = (): void => {
+    setErrMsg(null)
+
+    if (w3cSchema) {
path: nextjs/src/features/verification/components/EmailAttributesSelection.tsx
user: login: shitrerohit
body: Please remove this condition
created_at: 2025-05-22T13:59:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,534 @@
+/* eslint-disable max-lines */
+'use client'
+
+import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
+import { JSX, useEffect, useState } from 'react'
+import { apiStatusCodes, predicatesConditions } from '@/config/CommonConstant'
+import { useAppDispatch, useAppSelector } from '@/lib/hooks'
+
+import { AxiosResponse } from 'axios'
+import BackButton from '@/components/BackButton'
+import { Button } from '@/components/ui/button'
+import CustomCheckbox from '@/components/CustomCheckbox'
+import DataTable from '@/components/DataTable'
+import { DidMethod } from '@/common/enums'
+import { ISelectedAttributes } from '../type/interface'
+import { ITableData } from '@/components/DataTable/interface'
+import { TableHeader } from './SortDataTable'
+import { X } from 'lucide-react'
+import { getOrganizationById } from '@/app/api/organization'
+import { pathRoutes } from '@/config/pathRoutes'
+import { setSelectedAttributeData } from '@/lib/verificationSlice'
+import { useRouter } from 'next/navigation'
+
+interface NumberAttribute {
+  selectedOption: string | null
+  value: string | number | null
+}
+
+const EmailAttributesSelection = (): JSX.Element => {
+  const [attributeList, setAttributeList] = useState<ITableData[]>([])
+  const [proofReqSuccess, setProofReqSuccess] = useState<string | null>(null)
+  const [errMsg, setErrMsg] = useState<string | null>(null)
+  const [display, setDisplay] = useState<boolean | undefined>(false)
+  const [loading, setLoading] = useState<boolean>(true)
+  const [attributeData, setAttributeData] = useState<
+    ISelectedAttributes[] | null
+  >(null)
+  const [w3cSchema, setW3cSchema] = useState<boolean>(false)
+  const [isConnectionProof, setIsConnectionProof] = useState<boolean>(false)
+
+  const dispatch = useAppDispatch()
+  const router = useRouter()
+  const orgId = useAppSelector((state) => state.organization.orgId)
+
+  const verificationRouteType = useAppSelector(
+    (state) => state.verification.routeType,
+  )
+
+  const getSelectedCredDefData = '[]'
+
+  const selectedSchemaAttributes = useAppSelector(
+    (state) => state.verification.selectedSchemas,
+  )
+  const ConnectionVerification = async (): Promise<void> => {
+    if (verificationRouteType === 'Connection') {
+      setIsConnectionProof(true)
+    } else {
+      setIsConnectionProof(false)
+    }
+  }
+  useEffect(() => {
+    ConnectionVerification()
+  }, [])
+
+  const handleAttributeChange = async (
+    attributeName: string,
+    changeType: 'checkbox' | 'input' | 'select',
+    value: string | boolean,
+    schemaId?: string | undefined,
+    credDefId?: string | undefined,
+  ): Promise<void> => {
+    const updatedAttributes =
+      attributeData?.map((attribute) => {
+        if (
+          attribute.attributeName === attributeName &&
+          attribute.schemaId === schemaId &&
+          attribute.credDefId === credDefId
+        ) {
+          switch (changeType) {
+            case 'checkbox':
+              return {
+                ...attribute,
+                isChecked: value as boolean,
+                value: (value as boolean) ? attribute.value : '',
+                selectedOption: attribute?.condition || 'Select',
+                inputError: '',
+                selectError: '',
+              }
+            case 'input':
+              return {
+                ...attribute,
+                value: value as string,
+                inputError: '',
+              }
+            case 'select':
+              return {
+                ...attribute,
+                selectedOption: value as string,
+                selectError: '',
+              }
+            default:
+              return attribute
+          }
+        }
+        return attribute
+      }) ?? []
+
+    setAttributeData(updatedAttributes)
+
+    dispatch(setSelectedAttributeData(updatedAttributes))
+  }
+
+  const getOrgDetails = async (): Promise<void> => {
+    setLoading(true)
+
+    const response = await getOrganizationById(orgId)
+    const { data } = response as AxiosResponse
+    if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) {
+      const did = data?.data?.org_agents?.[0]?.orgDid
+
+      if (
+        did.includes(DidMethod.POLYGON) ||
+        did.includes(DidMethod.KEY) ||
+        did.includes(DidMethod.WEB)
+      ) {
+        setW3cSchema(true)
+      } else if (did.includes(DidMethod.INDY)) {
+        setW3cSchema(false)
+      }
+    }
+
+    setLoading(false)
+  }
+
+  useEffect(() => {
+    getOrgDetails()
+  }, [])
+
+  const isInvalidNumberAttribute = (attribute: NumberAttribute): boolean => {
+    const isOptionInvalid =
+      attribute.selectedOption === null ||
+      attribute.selectedOption === '' ||
+      attribute.selectedOption === 'Select'
+    const isValueInvalid = attribute.value === null || attribute.value === ''
+
+    if (!isOptionInvalid && isValueInvalid) {
+      setErrMsg('Value is required')
+      return true
+    } else if (!isValueInvalid && isOptionInvalid) {
+      setErrMsg('Condition is required')
+      return true
+    }
+    return false
+  }
+
+  const hasInvalidNumberAttributes = (): boolean => {
+    const numberAttributes = attributeData?.filter(
+      (attr) => attr.dataType === 'number' && attr.isChecked,
+    )
+
+    for (const attribute of numberAttributes || []) {
+      if (isInvalidNumberAttribute(attribute)) {
+        return true
+      }
+    }
+
+    return false
+  }
+  const redirectToAppropriatePage = (): void => {
+    switch (true) {
+      case w3cSchema && isConnectionProof:
+        router.push(pathRoutes.organizations.verification.W3CConnections)
+        break
+      case !w3cSchema && isConnectionProof:
+        router.push(pathRoutes.organizations.verification.connections)
+        break
+      case w3cSchema && !isConnectionProof:
+        router.push(pathRoutes.organizations.verification.w3cEmailVerification)
+        break
+      default:
+        router.push(pathRoutes.organizations.verification.emailVerification)
+        break
+    }
+  }
+  const handleSubmit = (): void => {
+    setErrMsg(null)
+
+    if (w3cSchema) {
+      redirectToAppropriatePage()
+      return
+    }
+
+    if (hasInvalidNumberAttributes()) {
path: nextjs/src/features/verification/components/EmailAttributesSelection.tsx
user: login: shitrerohit
body: Please display an appropriate alert if no action is taken on this button.
created_at: 2025-05-22T14:01:42Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,534 @@
+/* eslint-disable max-lines */
+'use client'
+
+import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
+import { JSX, useEffect, useState } from 'react'
+import { apiStatusCodes, predicatesConditions } from '@/config/CommonConstant'
+import { useAppDispatch, useAppSelector } from '@/lib/hooks'
+
+import { AxiosResponse } from 'axios'
+import BackButton from '@/components/BackButton'
+import { Button } from '@/components/ui/button'
+import CustomCheckbox from '@/components/CustomCheckbox'
+import DataTable from '@/components/DataTable'
+import { DidMethod } from '@/common/enums'
+import { ISelectedAttributes } from '../type/interface'
+import { ITableData } from '@/components/DataTable/interface'
+import { TableHeader } from './SortDataTable'
+import { X } from 'lucide-react'
+import { getOrganizationById } from '@/app/api/organization'
+import { pathRoutes } from '@/config/pathRoutes'
+import { setSelectedAttributeData } from '@/lib/verificationSlice'
+import { useRouter } from 'next/navigation'
+
+interface NumberAttribute {
+  selectedOption: string | null
+  value: string | number | null
+}
+
+const EmailAttributesSelection = (): JSX.Element => {
+  const [attributeList, setAttributeList] = useState<ITableData[]>([])
+  const [proofReqSuccess, setProofReqSuccess] = useState<string | null>(null)
+  const [errMsg, setErrMsg] = useState<string | null>(null)
+  const [display, setDisplay] = useState<boolean | undefined>(false)
+  const [loading, setLoading] = useState<boolean>(true)
+  const [attributeData, setAttributeData] = useState<
+    ISelectedAttributes[] | null
+  >(null)
+  const [w3cSchema, setW3cSchema] = useState<boolean>(false)
+  const [isConnectionProof, setIsConnectionProof] = useState<boolean>(false)
+
+  const dispatch = useAppDispatch()
+  const router = useRouter()
+  const orgId = useAppSelector((state) => state.organization.orgId)
+
+  const verificationRouteType = useAppSelector(
+    (state) => state.verification.routeType,
+  )
+
+  const getSelectedCredDefData = '[]'
+
+  const selectedSchemaAttributes = useAppSelector(
+    (state) => state.verification.selectedSchemas,
+  )
+  const ConnectionVerification = async (): Promise<void> => {
+    if (verificationRouteType === 'Connection') {
+      setIsConnectionProof(true)
+    } else {
+      setIsConnectionProof(false)
+    }
+  }
+  useEffect(() => {
+    ConnectionVerification()
+  }, [])
+
+  const handleAttributeChange = async (
+    attributeName: string,
+    changeType: 'checkbox' | 'input' | 'select',
+    value: string | boolean,
+    schemaId?: string | undefined,
+    credDefId?: string | undefined,
+  ): Promise<void> => {
+    const updatedAttributes =
+      attributeData?.map((attribute) => {
+        if (
+          attribute.attributeName === attributeName &&
+          attribute.schemaId === schemaId &&
+          attribute.credDefId === credDefId
+        ) {
+          switch (changeType) {
+            case 'checkbox':
+              return {
+                ...attribute,
+                isChecked: value as boolean,
+                value: (value as boolean) ? attribute.value : '',
+                selectedOption: attribute?.condition || 'Select',
+                inputError: '',
+                selectError: '',
+              }
+            case 'input':
+              return {
+                ...attribute,
+                value: value as string,
+                inputError: '',
+              }
+            case 'select':
+              return {
+                ...attribute,
+                selectedOption: value as string,
+                selectError: '',
+              }
+            default:
+              return attribute
+          }
+        }
+        return attribute
+      }) ?? []
+
+    setAttributeData(updatedAttributes)
+
+    dispatch(setSelectedAttributeData(updatedAttributes))
+  }
+
+  const getOrgDetails = async (): Promise<void> => {
+    setLoading(true)
+
+    const response = await getOrganizationById(orgId)
+    const { data } = response as AxiosResponse
+    if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) {
+      const did = data?.data?.org_agents?.[0]?.orgDid
+
+      if (
+        did.includes(DidMethod.POLYGON) ||
+        did.includes(DidMethod.KEY) ||
+        did.includes(DidMethod.WEB)
+      ) {
+        setW3cSchema(true)
+      } else if (did.includes(DidMethod.INDY)) {
+        setW3cSchema(false)
+      }
+    }
+
+    setLoading(false)
+  }
+
+  useEffect(() => {
+    getOrgDetails()
+  }, [])
+
+  const isInvalidNumberAttribute = (attribute: NumberAttribute): boolean => {
+    const isOptionInvalid =
+      attribute.selectedOption === null ||
+      attribute.selectedOption === '' ||
+      attribute.selectedOption === 'Select'
+    const isValueInvalid = attribute.value === null || attribute.value === ''
+
+    if (!isOptionInvalid && isValueInvalid) {
+      setErrMsg('Value is required')
+      return true
+    } else if (!isValueInvalid && isOptionInvalid) {
+      setErrMsg('Condition is required')
+      return true
+    }
+    return false
+  }
+
+  const hasInvalidNumberAttributes = (): boolean => {
+    const numberAttributes = attributeData?.filter(
+      (attr) => attr.dataType === 'number' && attr.isChecked,
+    )
+
+    for (const attribute of numberAttributes || []) {
+      if (isInvalidNumberAttribute(attribute)) {
+        return true
+      }
+    }
+
+    return false
+  }
+  const redirectToAppropriatePage = (): void => {
+    switch (true) {
+      case w3cSchema && isConnectionProof:
+        router.push(pathRoutes.organizations.verification.W3CConnections)
+        break
+      case !w3cSchema && isConnectionProof:
+        router.push(pathRoutes.organizations.verification.connections)
+        break
+      case w3cSchema && !isConnectionProof:
+        router.push(pathRoutes.organizations.verification.w3cEmailVerification)
+        break
+      default:
+        router.push(pathRoutes.organizations.verification.emailVerification)
+        break
+    }
+  }
+  const handleSubmit = (): void => {
+    setErrMsg(null)
+
+    if (w3cSchema) {
+      redirectToAppropriatePage()
+      return
+    }
+
+    if (hasInvalidNumberAttributes()) {
+      return
+    }
+
+    redirectToAppropriatePage()
+  }
+
+  const loadAttributesData = async (): Promise<void> => {
+    setLoading(true)
+
+    try {
+      setAttributeData([])
+
+      if (w3cSchema) {
+        const parsedW3CSchemaDetails = selectedSchemaAttributes
+
+        if (
+          Array.isArray(parsedW3CSchemaDetails) &&
+          parsedW3CSchemaDetails.length > 0
+        ) {
+          const allAttributes = parsedW3CSchemaDetails.flatMap((schema) => {
+            if (schema.attributes && Array.isArray(schema.attributes)) {
+              return schema.attributes.map((attribute) => ({
+                ...attribute,
+                schemaName: schema.name,
+                credDefName: '',
+                schemaId: schema.schemaLedgerId,
+                credDefId: '',
+              }))
+            }
+            return []
+          })
+
+          const inputArray = allAttributes.map((attribute) => ({
+            displayName: attribute.displayName,
+            attributeName: attribute.attributeName,
+            isChecked: false,
+            value: '',
+            condition: '',
+            options: predicatesConditions,
+            dataType: attribute.schemaDataType,
+            schemaName: attribute.schemaName ?? '',
+            credDefName: attribute.credDefName,
+            schemaId: attribute.schemaId ?? '',
+            credDefId: attribute.credDefId,
+            selectedOption: 'Select',
+            inputError: '',
+            selectError: '',
+          }))
+
+          setAttributeData(inputArray)
+        } else {
+          console.error('W3C schema details are not in the expected format.')
+        }
+      } else {
+        const selectedCredDefs = getSelectedCredDefData || []
+
+        const parsedSchemaDetails = selectedSchemaAttributes || []
+        if (
+          Array.isArray(parsedSchemaDetails) &&
+          parsedSchemaDetails.length > 0
+        ) {
+          const allAttributes = parsedSchemaDetails.flatMap((schema) => {
+            if (schema.attributes && Array.isArray(schema.attributes)) {
+              return schema.attributes.flatMap((attribute) => {
+                const matchingCredDefs = Array.isArray(selectedCredDefs)
+                  ? selectedCredDefs.filter(
+                      (credDef) =>
+                        credDef.schemaLedgerId === schema.schemaLedgerId,
+                    )
+                  : []
+
+                return matchingCredDefs.map((credDef) => ({
+                  displayName: attribute.displayName,
+                  attributeName: attribute.attributeName,
+                  isChecked: false,
+                  value: '',
+                  condition: '',
+                  options: predicatesConditions,
+                  dataType: attribute.schemaDataType,
+                  schemaName: schema.schemaLedgerId?.split(':')[2] || '',
+                  credDefName: credDef.tag,
+                  schemaId: schema.schemaId,
+                  credDefId: credDef.credentialDefinitionId,
+                  selectedOption: 'Select',
+                  inputError: '',
+                  selectError: '',
+                }))
+              })
+            }
+            return []
+          })
+
+          setAttributeData(allAttributes)
+        } else {
+          console.error('Parsed schema details are not in the expected format.')
+        }
+      }
+    } catch (error) {
+      console.error('Error fetching data:', error)
+    } finally {
+      setLoading(false)
+    }
+  }
+
+  useEffect(() => {
+    loadAttributesData()
+  }, [w3cSchema])
+
+  const attributeFunction = async (): Promise<void> => {
+    if (!attributeData) {
+      return
+    }
+
+    const attributes: ITableData[] = attributeData.map((attribute) => {
+      const commonCellProps = {
+        // eslint-disable-next-line no-empty-function
path: nextjs/src/features/verification/components/EmailAttributesSelection.tsx
user: login: shitrerohit
body: Please check the rule for allowing the empty function in props
created_at: 2025-05-22T14:12:05Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,534 @@
+/* eslint-disable max-lines */
+'use client'
+
+import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
+import { JSX, useEffect, useState } from 'react'
+import { apiStatusCodes, predicatesConditions } from '@/config/CommonConstant'
+import { useAppDispatch, useAppSelector } from '@/lib/hooks'
+
+import { AxiosResponse } from 'axios'
+import BackButton from '@/components/BackButton'
+import { Button } from '@/components/ui/button'
+import CustomCheckbox from '@/components/CustomCheckbox'
+import DataTable from '@/components/DataTable'
+import { DidMethod } from '@/common/enums'
+import { ISelectedAttributes } from '../type/interface'
+import { ITableData } from '@/components/DataTable/interface'
+import { TableHeader } from './SortDataTable'
+import { X } from 'lucide-react'
+import { getOrganizationById } from '@/app/api/organization'
+import { pathRoutes } from '@/config/pathRoutes'
+import { setSelectedAttributeData } from '@/lib/verificationSlice'
+import { useRouter } from 'next/navigation'
+
+interface NumberAttribute {
+  selectedOption: string | null
+  value: string | number | null
+}
+
+const EmailAttributesSelection = (): JSX.Element => {
+  const [attributeList, setAttributeList] = useState<ITableData[]>([])
+  const [proofReqSuccess, setProofReqSuccess] = useState<string | null>(null)
+  const [errMsg, setErrMsg] = useState<string | null>(null)
+  const [display, setDisplay] = useState<boolean | undefined>(false)
+  const [loading, setLoading] = useState<boolean>(true)
+  const [attributeData, setAttributeData] = useState<
+    ISelectedAttributes[] | null
+  >(null)
+  const [w3cSchema, setW3cSchema] = useState<boolean>(false)
+  const [isConnectionProof, setIsConnectionProof] = useState<boolean>(false)
+
+  const dispatch = useAppDispatch()
+  const router = useRouter()
+  const orgId = useAppSelector((state) => state.organization.orgId)
+
+  const verificationRouteType = useAppSelector(
+    (state) => state.verification.routeType,
+  )
+
+  const getSelectedCredDefData = '[]'
+
+  const selectedSchemaAttributes = useAppSelector(
+    (state) => state.verification.selectedSchemas,
+  )
+  const ConnectionVerification = async (): Promise<void> => {
+    if (verificationRouteType === 'Connection') {
+      setIsConnectionProof(true)
+    } else {
+      setIsConnectionProof(false)
+    }
+  }
+  useEffect(() => {
+    ConnectionVerification()
+  }, [])
+
+  const handleAttributeChange = async (
+    attributeName: string,
+    changeType: 'checkbox' | 'input' | 'select',
+    value: string | boolean,
+    schemaId?: string | undefined,
+    credDefId?: string | undefined,
+  ): Promise<void> => {
+    const updatedAttributes =
+      attributeData?.map((attribute) => {
+        if (
+          attribute.attributeName === attributeName &&
+          attribute.schemaId === schemaId &&
+          attribute.credDefId === credDefId
+        ) {
+          switch (changeType) {
+            case 'checkbox':
+              return {
+                ...attribute,
+                isChecked: value as boolean,
+                value: (value as boolean) ? attribute.value : '',
+                selectedOption: attribute?.condition || 'Select',
+                inputError: '',
+                selectError: '',
+              }
+            case 'input':
+              return {
+                ...attribute,
+                value: value as string,
+                inputError: '',
+              }
+            case 'select':
+              return {
+                ...attribute,
+                selectedOption: value as string,
+                selectError: '',
+              }
+            default:
+              return attribute
+          }
+        }
+        return attribute
+      }) ?? []
+
+    setAttributeData(updatedAttributes)
+
+    dispatch(setSelectedAttributeData(updatedAttributes))
+  }
+
+  const getOrgDetails = async (): Promise<void> => {
+    setLoading(true)
+
+    const response = await getOrganizationById(orgId)
+    const { data } = response as AxiosResponse
+    if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) {
+      const did = data?.data?.org_agents?.[0]?.orgDid
+
+      if (
+        did.includes(DidMethod.POLYGON) ||
+        did.includes(DidMethod.KEY) ||
+        did.includes(DidMethod.WEB)
+      ) {
+        setW3cSchema(true)
+      } else if (did.includes(DidMethod.INDY)) {
+        setW3cSchema(false)
+      }
+    }
+
+    setLoading(false)
+  }
+
+  useEffect(() => {
+    getOrgDetails()
+  }, [])
+
+  const isInvalidNumberAttribute = (attribute: NumberAttribute): boolean => {
+    const isOptionInvalid =
+      attribute.selectedOption === null ||
+      attribute.selectedOption === '' ||
+      attribute.selectedOption === 'Select'
+    const isValueInvalid = attribute.value === null || attribute.value === ''
+
+    if (!isOptionInvalid && isValueInvalid) {
+      setErrMsg('Value is required')
+      return true
+    } else if (!isValueInvalid && isOptionInvalid) {
+      setErrMsg('Condition is required')
+      return true
+    }
+    return false
+  }
+
+  const hasInvalidNumberAttributes = (): boolean => {
+    const numberAttributes = attributeData?.filter(
+      (attr) => attr.dataType === 'number' && attr.isChecked,
+    )
+
+    for (const attribute of numberAttributes || []) {
+      if (isInvalidNumberAttribute(attribute)) {
+        return true
+      }
+    }
+
+    return false
+  }
+  const redirectToAppropriatePage = (): void => {
+    switch (true) {
+      case w3cSchema && isConnectionProof:
+        router.push(pathRoutes.organizations.verification.W3CConnections)
+        break
+      case !w3cSchema && isConnectionProof:
+        router.push(pathRoutes.organizations.verification.connections)
+        break
+      case w3cSchema && !isConnectionProof:
+        router.push(pathRoutes.organizations.verification.w3cEmailVerification)
+        break
+      default:
+        router.push(pathRoutes.organizations.verification.emailVerification)
+        break
+    }
+  }
+  const handleSubmit = (): void => {
+    setErrMsg(null)
+
+    if (w3cSchema) {
path: nextjs/src/features/verification/components/EmailAttributesSelection.tsx
user: login: sanjaykhondal-aw
body: Resolve
created_at: 2025-05-22T14:35:24Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,534 @@
+/* eslint-disable max-lines */
+'use client'
+
+import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
+import { JSX, useEffect, useState } from 'react'
+import { apiStatusCodes, predicatesConditions } from '@/config/CommonConstant'
+import { useAppDispatch, useAppSelector } from '@/lib/hooks'
+
+import { AxiosResponse } from 'axios'
+import BackButton from '@/components/BackButton'
+import { Button } from '@/components/ui/button'
+import CustomCheckbox from '@/components/CustomCheckbox'
+import DataTable from '@/components/DataTable'
+import { DidMethod } from '@/common/enums'
+import { ISelectedAttributes } from '../type/interface'
+import { ITableData } from '@/components/DataTable/interface'
+import { TableHeader } from './SortDataTable'
+import { X } from 'lucide-react'
+import { getOrganizationById } from '@/app/api/organization'
+import { pathRoutes } from '@/config/pathRoutes'
+import { setSelectedAttributeData } from '@/lib/verificationSlice'
+import { useRouter } from 'next/navigation'
+
+interface NumberAttribute {
+  selectedOption: string | null
+  value: string | number | null
+}
+
+const EmailAttributesSelection = (): JSX.Element => {
+  const [attributeList, setAttributeList] = useState<ITableData[]>([])
+  const [proofReqSuccess, setProofReqSuccess] = useState<string | null>(null)
+  const [errMsg, setErrMsg] = useState<string | null>(null)
+  const [display, setDisplay] = useState<boolean | undefined>(false)
+  const [loading, setLoading] = useState<boolean>(true)
+  const [attributeData, setAttributeData] = useState<
+    ISelectedAttributes[] | null
+  >(null)
+  const [w3cSchema, setW3cSchema] = useState<boolean>(false)
+  const [isConnectionProof, setIsConnectionProof] = useState<boolean>(false)
+
+  const dispatch = useAppDispatch()
+  const router = useRouter()
+  const orgId = useAppSelector((state) => state.organization.orgId)
+
+  const verificationRouteType = useAppSelector(
+    (state) => state.verification.routeType,
+  )
+
+  const getSelectedCredDefData = '[]'
+
+  const selectedSchemaAttributes = useAppSelector(
+    (state) => state.verification.selectedSchemas,
+  )
+  const ConnectionVerification = async (): Promise<void> => {
+    if (verificationRouteType === 'Connection') {
+      setIsConnectionProof(true)
+    } else {
+      setIsConnectionProof(false)
+    }
+  }
+  useEffect(() => {
+    ConnectionVerification()
+  }, [])
+
+  const handleAttributeChange = async (
+    attributeName: string,
+    changeType: 'checkbox' | 'input' | 'select',
+    value: string | boolean,
+    schemaId?: string | undefined,
+    credDefId?: string | undefined,
+  ): Promise<void> => {
+    const updatedAttributes =
+      attributeData?.map((attribute) => {
+        if (
+          attribute.attributeName === attributeName &&
+          attribute.schemaId === schemaId &&
+          attribute.credDefId === credDefId
+        ) {
+          switch (changeType) {
+            case 'checkbox':
+              return {
+                ...attribute,
+                isChecked: value as boolean,
+                value: (value as boolean) ? attribute.value : '',
+                selectedOption: attribute?.condition || 'Select',
+                inputError: '',
+                selectError: '',
+              }
+            case 'input':
+              return {
+                ...attribute,
+                value: value as string,
+                inputError: '',
+              }
+            case 'select':
+              return {
+                ...attribute,
+                selectedOption: value as string,
+                selectError: '',
+              }
+            default:
+              return attribute
+          }
+        }
+        return attribute
+      }) ?? []
+
+    setAttributeData(updatedAttributes)
+
+    dispatch(setSelectedAttributeData(updatedAttributes))
+  }
+
+  const getOrgDetails = async (): Promise<void> => {
+    setLoading(true)
+
+    const response = await getOrganizationById(orgId)
+    const { data } = response as AxiosResponse
+    if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) {
+      const did = data?.data?.org_agents?.[0]?.orgDid
+
+      if (
+        did.includes(DidMethod.POLYGON) ||
+        did.includes(DidMethod.KEY) ||
+        did.includes(DidMethod.WEB)
+      ) {
+        setW3cSchema(true)
+      } else if (did.includes(DidMethod.INDY)) {
+        setW3cSchema(false)
+      }
+    }
+
+    setLoading(false)
+  }
+
+  useEffect(() => {
+    getOrgDetails()
+  }, [])
+
+  const isInvalidNumberAttribute = (attribute: NumberAttribute): boolean => {
+    const isOptionInvalid =
+      attribute.selectedOption === null ||
+      attribute.selectedOption === '' ||
+      attribute.selectedOption === 'Select'
+    const isValueInvalid = attribute.value === null || attribute.value === ''
+
+    if (!isOptionInvalid && isValueInvalid) {
+      setErrMsg('Value is required')
+      return true
+    } else if (!isValueInvalid && isOptionInvalid) {
+      setErrMsg('Condition is required')
+      return true
+    }
+    return false
+  }
+
+  const hasInvalidNumberAttributes = (): boolean => {
+    const numberAttributes = attributeData?.filter(
+      (attr) => attr.dataType === 'number' && attr.isChecked,
+    )
+
+    for (const attribute of numberAttributes || []) {
+      if (isInvalidNumberAttribute(attribute)) {
+        return true
+      }
+    }
+
+    return false
+  }
+  const redirectToAppropriatePage = (): void => {
+    switch (true) {
+      case w3cSchema && isConnectionProof:
+        router.push(pathRoutes.organizations.verification.W3CConnections)
+        break
+      case !w3cSchema && isConnectionProof:
+        router.push(pathRoutes.organizations.verification.connections)
+        break
+      case w3cSchema && !isConnectionProof:
+        router.push(pathRoutes.organizations.verification.w3cEmailVerification)
+        break
+      default:
+        router.push(pathRoutes.organizations.verification.emailVerification)
+        break
+    }
+  }
+  const handleSubmit = (): void => {
+    setErrMsg(null)
+
+    if (w3cSchema) {
+      redirectToAppropriatePage()
+      return
+    }
+
+    if (hasInvalidNumberAttributes()) {
+      return
+    }
+
+    redirectToAppropriatePage()
+  }
+
+  const loadAttributesData = async (): Promise<void> => {
+    setLoading(true)
+
+    try {
+      setAttributeData([])
+
+      if (w3cSchema) {
+        const parsedW3CSchemaDetails = selectedSchemaAttributes
+
+        if (
+          Array.isArray(parsedW3CSchemaDetails) &&
+          parsedW3CSchemaDetails.length > 0
+        ) {
+          const allAttributes = parsedW3CSchemaDetails.flatMap((schema) => {
+            if (schema.attributes && Array.isArray(schema.attributes)) {
+              return schema.attributes.map((attribute) => ({
+                ...attribute,
+                schemaName: schema.name,
+                credDefName: '',
+                schemaId: schema.schemaLedgerId,
+                credDefId: '',
+              }))
+            }
+            return []
+          })
+
+          const inputArray = allAttributes.map((attribute) => ({
+            displayName: attribute.displayName,
+            attributeName: attribute.attributeName,
+            isChecked: false,
+            value: '',
+            condition: '',
+            options: predicatesConditions,
+            dataType: attribute.schemaDataType,
+            schemaName: attribute.schemaName ?? '',
+            credDefName: attribute.credDefName,
+            schemaId: attribute.schemaId ?? '',
+            credDefId: attribute.credDefId,
+            selectedOption: 'Select',
+            inputError: '',
+            selectError: '',
+          }))
+
+          setAttributeData(inputArray)
+        } else {
+          console.error('W3C schema details are not in the expected format.')
+        }
+      } else {
+        const selectedCredDefs = getSelectedCredDefData || []
+
+        const parsedSchemaDetails = selectedSchemaAttributes || []
+        if (
+          Array.isArray(parsedSchemaDetails) &&
+          parsedSchemaDetails.length > 0
+        ) {
+          const allAttributes = parsedSchemaDetails.flatMap((schema) => {
+            if (schema.attributes && Array.isArray(schema.attributes)) {
+              return schema.attributes.flatMap((attribute) => {
+                const matchingCredDefs = Array.isArray(selectedCredDefs)
+                  ? selectedCredDefs.filter(
+                      (credDef) =>
+                        credDef.schemaLedgerId === schema.schemaLedgerId,
+                    )
+                  : []
+
+                return matchingCredDefs.map((credDef) => ({
+                  displayName: attribute.displayName,
+                  attributeName: attribute.attributeName,
+                  isChecked: false,
+                  value: '',
+                  condition: '',
+                  options: predicatesConditions,
+                  dataType: attribute.schemaDataType,
+                  schemaName: schema.schemaLedgerId?.split(':')[2] || '',
+                  credDefName: credDef.tag,
+                  schemaId: schema.schemaId,
+                  credDefId: credDef.credentialDefinitionId,
+                  selectedOption: 'Select',
+                  inputError: '',
+                  selectError: '',
+                }))
+              })
+            }
+            return []
+          })
+
+          setAttributeData(allAttributes)
+        } else {
+          console.error('Parsed schema details are not in the expected format.')
+        }
+      }
+    } catch (error) {
+      console.error('Error fetching data:', error)
+    } finally {
+      setLoading(false)
+    }
+  }
+
+  useEffect(() => {
+    loadAttributesData()
+  }, [w3cSchema])
+
+  const attributeFunction = async (): Promise<void> => {
+    if (!attributeData) {
+      return
+    }
+
+    const attributes: ITableData[] = attributeData.map((attribute) => {
+      const commonCellProps = {
+        // eslint-disable-next-line no-empty-function
path: nextjs/src/features/verification/components/EmailAttributesSelection.tsx
user: login: sanjaykhondal-aw
body: Resolve
created_at: 2025-05-22T14:35:37Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,534 @@
+/* eslint-disable max-lines */
+'use client'
+
+import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
+import { JSX, useEffect, useState } from 'react'
+import { apiStatusCodes, predicatesConditions } from '@/config/CommonConstant'
+import { useAppDispatch, useAppSelector } from '@/lib/hooks'
+
+import { AxiosResponse } from 'axios'
+import BackButton from '@/components/BackButton'
+import { Button } from '@/components/ui/button'
+import CustomCheckbox from '@/components/CustomCheckbox'
+import DataTable from '@/components/DataTable'
+import { DidMethod } from '@/common/enums'
+import { ISelectedAttributes } from '../type/interface'
+import { ITableData } from '@/components/DataTable/interface'
+import { TableHeader } from './SortDataTable'
+import { X } from 'lucide-react'
+import { getOrganizationById } from '@/app/api/organization'
+import { pathRoutes } from '@/config/pathRoutes'
+import { setSelectedAttributeData } from '@/lib/verificationSlice'
+import { useRouter } from 'next/navigation'
+
+interface NumberAttribute {
+  selectedOption: string | null
+  value: string | number | null
+}
+
+const EmailAttributesSelection = (): JSX.Element => {
+  const [attributeList, setAttributeList] = useState<ITableData[]>([])
+  const [proofReqSuccess, setProofReqSuccess] = useState<string | null>(null)
+  const [errMsg, setErrMsg] = useState<string | null>(null)
+  const [display, setDisplay] = useState<boolean | undefined>(false)
+  const [loading, setLoading] = useState<boolean>(true)
+  const [attributeData, setAttributeData] = useState<
+    ISelectedAttributes[] | null
+  >(null)
+  const [w3cSchema, setW3cSchema] = useState<boolean>(false)
+  const [isConnectionProof, setIsConnectionProof] = useState<boolean>(false)
+
+  const dispatch = useAppDispatch()
+  const router = useRouter()
+  const orgId = useAppSelector((state) => state.organization.orgId)
+
+  const verificationRouteType = useAppSelector(
+    (state) => state.verification.routeType,
+  )
+
+  const getSelectedCredDefData = '[]'
+
+  const selectedSchemaAttributes = useAppSelector(
+    (state) => state.verification.selectedSchemas,
+  )
+  const ConnectionVerification = async (): Promise<void> => {
+    if (verificationRouteType === 'Connection') {
+      setIsConnectionProof(true)
+    } else {
+      setIsConnectionProof(false)
+    }
+  }
+  useEffect(() => {
+    ConnectionVerification()
+  }, [])
+
+  const handleAttributeChange = async (
+    attributeName: string,
+    changeType: 'checkbox' | 'input' | 'select',
+    value: string | boolean,
+    schemaId?: string | undefined,
+    credDefId?: string | undefined,
+  ): Promise<void> => {
+    const updatedAttributes =
+      attributeData?.map((attribute) => {
+        if (
+          attribute.attributeName === attributeName &&
+          attribute.schemaId === schemaId &&
+          attribute.credDefId === credDefId
+        ) {
+          switch (changeType) {
+            case 'checkbox':
+              return {
+                ...attribute,
+                isChecked: value as boolean,
+                value: (value as boolean) ? attribute.value : '',
+                selectedOption: attribute?.condition || 'Select',
+                inputError: '',
+                selectError: '',
+              }
+            case 'input':
+              return {
+                ...attribute,
+                value: value as string,
+                inputError: '',
+              }
+            case 'select':
+              return {
+                ...attribute,
+                selectedOption: value as string,
+                selectError: '',
+              }
+            default:
+              return attribute
+          }
+        }
+        return attribute
+      }) ?? []
+
+    setAttributeData(updatedAttributes)
+
+    dispatch(setSelectedAttributeData(updatedAttributes))
+  }
+
+  const getOrgDetails = async (): Promise<void> => {
+    setLoading(true)
+
+    const response = await getOrganizationById(orgId)
+    const { data } = response as AxiosResponse
+    if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) {
+      const did = data?.data?.org_agents?.[0]?.orgDid
+
+      if (
+        did.includes(DidMethod.POLYGON) ||
+        did.includes(DidMethod.KEY) ||
+        did.includes(DidMethod.WEB)
+      ) {
+        setW3cSchema(true)
+      } else if (did.includes(DidMethod.INDY)) {
+        setW3cSchema(false)
+      }
+    }
+
+    setLoading(false)
+  }
+
+  useEffect(() => {
+    getOrgDetails()
+  }, [])
+
+  const isInvalidNumberAttribute = (attribute: NumberAttribute): boolean => {
+    const isOptionInvalid =
+      attribute.selectedOption === null ||
+      attribute.selectedOption === '' ||
+      attribute.selectedOption === 'Select'
+    const isValueInvalid = attribute.value === null || attribute.value === ''
+
+    if (!isOptionInvalid && isValueInvalid) {
+      setErrMsg('Value is required')
+      return true
+    } else if (!isValueInvalid && isOptionInvalid) {
+      setErrMsg('Condition is required')
+      return true
+    }
+    return false
+  }
+
+  const hasInvalidNumberAttributes = (): boolean => {
+    const numberAttributes = attributeData?.filter(
+      (attr) => attr.dataType === 'number' && attr.isChecked,
+    )
+
+    for (const attribute of numberAttributes || []) {
+      if (isInvalidNumberAttribute(attribute)) {
+        return true
+      }
+    }
+
+    return false
+  }
+  const redirectToAppropriatePage = (): void => {
+    switch (true) {
+      case w3cSchema && isConnectionProof:
+        router.push(pathRoutes.organizations.verification.W3CConnections)
+        break
+      case !w3cSchema && isConnectionProof:
+        router.push(pathRoutes.organizations.verification.connections)
+        break
+      case w3cSchema && !isConnectionProof:
+        router.push(pathRoutes.organizations.verification.w3cEmailVerification)
+        break
+      default:
+        router.push(pathRoutes.organizations.verification.emailVerification)
+        break
+    }
+  }
+  const handleSubmit = (): void => {
+    setErrMsg(null)
+
+    if (w3cSchema) {
+      redirectToAppropriatePage()
+      return
+    }
+
+    if (hasInvalidNumberAttributes()) {
path: nextjs/src/features/verification/components/EmailAttributesSelection.tsx
user: login: sanjaykhondal-aw
body: Resolved
created_at: 2025-05-22T14:36:01Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,6 @@
+// import EmailVerification from '@/features/verification/components/EmailVerification'
path: nextjs/src/app/organizations/verification/verify-credentials/schema/cred-defs/attributes/verification-email/page.tsx
user: login: sanjaykhondal-aw
body: This code will be needed in the next component, so it's currently commented out
created_at: 2025-05-22T14:38:25Z
author_association: CONTRIBUTOR

PR comments:
user: login: sonarqubecloud[bot]
created_at: 2025-05-22T14:11:38Z
body: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=credebl_studio&pullRequest=992) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [13 New issues](https://sonarcloud.io/project/issues?id=credebl_studio&pullRequest=992&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=credebl_studio&pullRequest=992&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=credebl_studio&pullRequest=992&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=credebl_studio&pullRequest=992&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [1.7% Duplication on New Code](https://sonarcloud.io/component_measures?id=credebl_studio&pullRequest=992&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=credebl_studio&pullRequest=992)


author_association: NONE