+
+ {/* Main Navigation Tabs */}
+
- {tabs.map((tab) => (
- tab.type === page1 && setActiveTab(tab.id)}
- className={`cursor-pointer relative pb-3 text-sm font-medium transition-all duration-200
- ${activeTab === tab.id
- ? "text-blue-600 after:absolute after:bottom-0 after:left-0 after:right-0 after:h-0.5 after:bg-blue-600"
- : "text-gray-600 hover:text-blue-500"
+ {tabs.map((tab) =>
+ tab.type === page1 && (
+ handleMainTabClick(tab.id)}
+ className={`cursor-pointer relative pb-3 text-sm font-medium transition-all duration-200
+ ${
+ activeTab === tab.id
+ ? "text-blue-600 after:absolute after:bottom-0 after:left-0 after:right-0 after:h-0.5 after:bg-blue-600"
+ : "text-gray-600 hover:text-blue-500"
}`}
- >
- {tab.label}
-
- ))}
+ >
+ {tab.label}
+
+ )
+ )}
- {/* Main Content Area */}
-
{renderContent()}
+ {/* Content with Aside Navigation */}
+
+ {/* Fixed Aside Navigation - Shows subsections of active tab */}
+ {activeTab === 'userProfile' &&
+
+
+
t.id === activeTab)?.label || ""}
+ />
+
+
+}
+ {/* Scrollable Main Content */}
+
+ {renderContent()}
+
+
-
>
)
}
diff --git a/src/components/setting/SettingNav.tsx b/src/components/setting/SettingNav.tsx
index 4eda089..38e1397 100644
--- a/src/components/setting/SettingNav.tsx
+++ b/src/components/setting/SettingNav.tsx
@@ -34,7 +34,7 @@ const SettingNav = () => {
diff --git a/src/components/setting/Signature/AddSignatureModal.tsx b/src/components/setting/Signature/AddSignatureModal.tsx
new file mode 100644
index 0000000..a6ef255
--- /dev/null
+++ b/src/components/setting/Signature/AddSignatureModal.tsx
@@ -0,0 +1,382 @@
+import React, { useEffect, useState } from 'react';
+// import { X, Upload, Edit3, Image, Cloud, HardDrive, Droplets } from 'lucide-react';
+import { AiOutlineClose, AiOutlineUpload, AiOutlineEdit } from 'react-icons/ai';
+import { MdImage, MdCloudUpload, MdStorage } from 'react-icons/md';
+import api from '../../../config/api';
+
+
+interface AddSignatureModalProps {
+ setShowAddSignature?: (value: boolean) => void;
+}
+interface Account {
+ id: number;
+ isDefault: boolean;
+ name: string;
+}
+
+interface UserData {
+ id: string;
+ firstName: string;
+ lastName: string;
+ email: string;
+ language: string;
+ account: Account;
+}
+
+const AddSignatureModal: React.FC
= ({ setShowAddSignature }) => {
+ const [activeTab, setActiveTab] = useState<'choose' | 'draw' | 'upload'>('choose');
+ const [fullName, setFullName] = useState('');
+ const [initials, setInitials] = useState('');
+
+ // Sample signature options for the CHOOSE tab
+ const signatureOptions = [
+ { id: 1, name: 'print', initials: 'LA', style: 'print' },
+ { id: 2, name: 'cursive', initials: 'LA', style: 'cursive' },
+ { id: 3, name: 'script', initials: 'LA', style: 'script' },
+ { id: 4, name: 'elegant', initials: 'LA', style: 'elegant' },
+ { id: 5, name: 'modern', initials: 'LA', style: 'modern' },
+ { id: 6, name: 'classic', initials: 'LA', style: 'classic' },
+ ];
+
+ const [selectedSignature, setSelectedSignature] = useState(1);
+
+ // Store the actual file
+ const [file1, setFile1] = useState(null);
+ const [file2, setFile2] = useState(null);
+
+ // Store the preview URL
+ const [preview1, setPreview1] = useState(null);
+ const [preview2, setPreview2] = useState(null);
+
+ //user
+ const [user, setUser] = useState({
+ id: "",
+ firstName: "",
+ lastName: "",
+ email: "",
+ language: "",
+ account: {
+ id: 0,
+ isDefault: false,
+ name: "",
+ },
+ });
+
+ // Navigation items
+ const navigationItems = [
+ { id: 'choose', label: 'Choose', icon: },
+ { id: 'draw', label: 'Draw', icon: },
+ { id: 'upload', label: 'Upload', icon: },
+ ];
+
+ // Cleanup preview URLs when component unmounts or image changes
+ useEffect(() => {
+ return () => {
+ if (preview1) URL.revokeObjectURL(preview1);
+ if (preview2) URL.revokeObjectURL(preview2);
+ };
+ }, [preview1, preview2]);
+
+ const handleImageChange = (
+ e: React.ChangeEvent,
+ setFile: React.Dispatch>,
+ setPreview: React.Dispatch>
+ ) => {
+ const file = e.target.files?.[0];
+ if (file) {
+ setFile(file);
+ const previewUrl = URL.createObjectURL(file);
+ setPreview(previewUrl);
+ }
+ };
+
+
+ const renderContent = () => {
+ switch (activeTab) {
+ case 'choose':
+ return (
+
+
+
Choose Signature Style
+
Select from pre-designed signature styles
+
+
+
+
+ {signatureOptions.map((option) => (
+
+
setSelectedSignature(option.id)}
+ className="w-4 h-4 text-blue-600 focus:ring-blue-500"
+ />
+
+
+
Signed by:
+
+ {fullName || option.name}
+
+
+ dca3e646-62cd-4cc...
+
+
+
+
DS
+
+ {initials || option.initials}
+
+
+
+
+ ))}
+
+
+
+ );
+
+ case 'draw':
+ return (
+
+
+
Draw Signature
+
Create your signature by drawing directly on the canvas
+
+
+
+
+ {/* Draw area 1 */}
+
+
Full Signature
+
+
+ {/*
*/}
+
Click and drag to draw your signature
+
Use mouse or touch to create your signature
+
+
+
+ {/* Draw area 2 */}
+
+
Initials
+
+
+ {/*
*/}
+
Draw initials
+
+
+
+
+
+
+
+ {/* */}
+ Clear
+
+
+ Undo
+
+
+ Redo
+
+
+
+
+ );
+
+ case 'upload':
+ return (
+
+
+
Upload Signature
+
+
+
+
+ {/* Upload 1 */}
+
+
Full Signature
+
+ {preview1 ? (
+
+ ) : (
+
+
+
Click to upload or drag and drop
+
PNG, JPG, GIF up to 10MB
+
+ )}
+
+
handleImageChange(e, setFile1, setPreview1)}
+ />
+
+
+ {/* Upload 2 */}
+
+
Initials
+
+ {preview2 ? (
+
+ ) : (
+
+ )}
+
+
handleImageChange(e, setFile2, setPreview2)}
+ />
+
+
+
+
+
+ );
+
+ default:
+ return null;
+ }
+ };
+
+ const getUserDetails = async () => {
+ try {
+ let res = await api.get(`/api/user/details`)
+ console.log("getuser", res)
+ setUser(res?.data)
+ } catch (error) {
+ console.error("Error fetching user details:", error);
+ }
+ }
+
+ useEffect(() => {
+ getUserDetails()
+ }, [])
+
+ return (
+
+
+
+ {/* Sidebar Navigation */}
+
+ {/* Header */}
+
+
+
+
Add Signature
+
Create your digital signature
+
+
+
+
+ {/* Form Inputs */}
+
+
+ {/* Navigation Menu */}
+
+
+ {navigationItems.map((item) => (
+ setActiveTab(item.id as 'choose' | 'draw' | 'upload')}
+ className={`w-full flex items-center space-x-3 px-2 py-2 text-sm font-medium rounded-lg transition-colors ${activeTab === item.id
+ ? 'bg-blue-50 text-blue-700 border border-blue-200'
+ : 'text-gray-600 hover:bg-gray-100 hover:text-gray-900'
+ }`}
+ >
+
+ {item.icon}
+
+
+ {item.label}
+
+ ))}
+
+
+
+
+
+ {/* Main Content Area */}
+
+ {/* Header with close button */}
+
+ {/* Content */}
+
+
setShowAddSignature?.(false)}
+ className="absolute top-2 right-3 p-2 hover:bg-gray-100 rounded-full transition-colors z-20"
+ >
+
+
+ {renderContent()}
+
+
+ {/* Footer Buttons in Main Area */}
+
+ setShowAddSignature?.(false)}
+ >
+ CANCEL
+
+
+ CREATE SIGNATURE
+
+
+
+
+
+
+ );
+};
+
+export default AddSignatureModal;
\ No newline at end of file
diff --git a/src/components/setting/Signature/Signature.tsx b/src/components/setting/Signature/Signature.tsx
new file mode 100644
index 0000000..2d3aafe
--- /dev/null
+++ b/src/components/setting/Signature/Signature.tsx
@@ -0,0 +1,200 @@
+import React, { useState } from 'react';
+import { FiEdit3, FiTrash2, FiPlus, FiMoreVertical } from 'react-icons/fi';
+import AddSignatureModal from './AddSignatureModal';
+
+interface Signature {
+ id: string;
+ signature: string;
+ initial: string;
+ createdAt: string;
+}
+
+const SignatureManager: React.FC = () => {
+ const [signatures, setSignatures] = useState([
+ {
+ id: '1',
+ signature: 'https://www.signwell.com/assets/vip-signatures/muhammad-ali-signature-3f9237f6fc48c3a04ba083117948e16ee7968aae521ae4ccebdfb8f22596ad22.svg',
+ initial: 'AB',
+ createdAt: 'dca3e646-62cd-4cc...'
+ },
+ {
+ id: '2',
+ signature: '∼∼⌒∼∼⌒∼',
+ initial: 'AB',
+ createdAt: 'dca3e646-62cd-4cc...'
+ },
+ {
+ id: '3',
+ signature: 'Digital Signature',
+ initial: 'DS',
+ createdAt: 'dca3e646-62cd-4cc...'
+ }
+ ]);
+
+ const [activeDropdown, setActiveDropdown] = useState(null);
+ const [showAddSignature , setShowAddSignature] = useState(false)
+
+ const handleEdit = (id: string) => {
+ console.log('Edit signature:', id);
+ setActiveDropdown(null);
+ };
+
+ const handleDelete = (id: string) => {
+ setSignatures(signatures.filter(sig => sig.id !== id));
+ setActiveDropdown(null);
+ };
+
+ const toggleDropdown = (id: string) => {
+ setActiveDropdown(activeDropdown === id ? null : id);
+ };
+
+ return (
+
+
+ {/* Header */}
+
+
+
Signatures
+
Add or update your name and signature styles.
+
+
setShowAddSignature((prev) => !prev)}>
+
+ ADD
+
+
+
+ {/* Table Card */}
+
+ {/* Table Header */}
+
+
+
+
Signature
+
+
+
Initial
+
+
+
Actions
+
+
+
+
+ {/* Table Body */}
+
+ {signatures.map((signature, index) => (
+
+ {/* Signature Column */}
+
+
+ {/* Label */}
+
+ Signed by:
+
+
+ {/* Signature Image */}
+
+
+
+
+ {/* Signature ID */}
+
+ {signature.createdAt}
+
+
+
+
+
+ {/* Initial Column */}
+
+
+ {/* Label */}
+
+ DS
+
+
+ {/* Signature Image */}
+
+
+
+
+
+
+
+ {/* Actions Column */}
+
+
+
toggleDropdown(signature.id)}
+ className="bg-gray-100 hover:bg-gray-200 text-gray-700 px-1.5 py-1.5 text-[13px] rounded-lg font-semibold flex items-center transition-all duration-200 border border-gray-300 "
+ >
+ ACTIONS
+
+
+
+ {/* Dropdown Menu */}
+ {activeDropdown === signature.id && (
+
+ handleEdit(signature.id)}
+ className="w-full px-4 py-1 text-left text-gray-500 hover:bg-blue-50 hover:text-blue-700 flex items-center gap-3 text-sm transition-colors duration-150"
+ >
+
+ Edit
+
+ handleDelete(signature.id)}
+ className="w-full px-4 py-1 text-left text-gray-500 hover:bg-red-50 hover:text-red-700 flex items-center gap-3 text-sm transition-colors duration-150"
+ >
+
+ Delete
+
+
+ )}
+
+
+
+ ))}
+
+
+
+ {/* Empty State (if no signatures) */}
+ {signatures.length === 0 && (
+
+
+
+
+
No signatures yet
+
Create your first signature to get started.
+
+
+ ADD SIGNATURE
+
+
+ )}
+
+
+ {/* Click outside to close dropdown */}
+ {activeDropdown && (
+
setActiveDropdown(null)}
+ />
+ )}
+
+ {showAddSignature && (
+
+ )}
+
+ );
+};
+
+export default SignatureManager;
\ No newline at end of file
diff --git a/src/components/setting/UserProfile.tsx b/src/components/setting/UserProfile.tsx
new file mode 100644
index 0000000..ce58abd
--- /dev/null
+++ b/src/components/setting/UserProfile.tsx
@@ -0,0 +1,63 @@
+import { FiX, FiEdit2 } from 'react-icons/fi';
+interface Account {
+ id: number;
+ isDefault: boolean;
+ name: string;
+}
+
+interface UserData {
+ id: string;
+ firstName: string;
+ lastName: string;
+ email: string;
+ language: string;
+ account: Account;
+}
+
+interface UserProfileProps {
+ userData: UserData;
+}
+const UserProfile: React.FC
= ({ userData }) => {
+ const getInitials = (firstName: string, lastName: string) => {
+ return `${firstName.charAt(0)}${lastName.charAt(0)}`.toUpperCase();
+ };
+ return (
+
+ {/* Profile Picture */}
+
+
+ {getInitials(userData.firstName, userData.lastName)}
+
+
+
+ {/* Info Fields */}
+
+ {/* Row: Name */}
+
+
Name
+
+ {userData.firstName} {userData.lastName}
+
+
+
+ {/* Row: Email */}
+
+
Email
+
{userData.email}
+
+
+ {/* Row: Account Name */}
+
+
Account name
+
+ {userData.account.name}
+
+
+
+
+
+
+ );
+};
+
+export default UserProfile
\ No newline at end of file
diff --git a/src/components/transactions/TransactionView.tsx b/src/components/transactions/TransactionView.tsx
index 3251f7d..9f1bbe3 100644
--- a/src/components/transactions/TransactionView.tsx
+++ b/src/components/transactions/TransactionView.tsx
@@ -1,9 +1,12 @@
import { AiFillSignature } from 'react-icons/ai';
-import { useParams } from 'react-router-dom';
+import { Link, useParams } from 'react-router-dom';
import { LuGitGraph } from 'react-icons/lu';
import AccountNav from '../accounts/AccountNav';
import { useEffect, useState } from 'react';
import api from '../../config/api';
+import SigningOrderDiagram from '../../SigningOrderDiagram ';
+import { IoCloseOutline } from 'react-icons/io5';
+import { MdEditDocument } from "react-icons/md";
// Sample recipient data — you can replace this with actual API data later
const recipients = [
@@ -27,6 +30,8 @@ const recipients = [
const TransactionView = () => {
const { accountId, transactionId } = useParams<{ accountId: string, transactionId: string }>();
+ console.log("account" , accountId , transactionId)
+
if (!accountId || !transactionId) {
window.location.href = "/";
@@ -34,6 +39,8 @@ const TransactionView = () => {
}
const [transactionDetails, setTransactionDetails] = useState(null);
+ const [signingOrderModal, setSigningOrderModal] = useState({ open: false });
+ console.log(transactionDetails, "line 37");
const fetchData = async () => {
try {
@@ -57,7 +64,7 @@ const TransactionView = () => {
{/* Header */}
- Complete with Forms Made Easy: {transactionDetails.transaction.name ? transactionDetails.transaction.name : "Untitled"}
+ Complete with Forms Made Easy: { transactionDetails.transaction.name ?? "Untitled"}
@@ -77,18 +84,23 @@ const TransactionView = () => {
>
Sign
*/}
-
+
More
+
+
+ Edit
+
{/* Recipients Section */}
+ {transactionDetails.recipients.length > 0 &&
Signers
-
+
setSigningOrderModal({ ...signingOrderModal, open: true })}>
Signing Graph
@@ -122,6 +134,7 @@ const TransactionView = () => {
))}
+ }
@@ -137,7 +150,11 @@ const TransactionView = () => {
-
1 of 10
+
+ 1 of 10
+
+
+
@@ -146,6 +163,24 @@ const TransactionView = () => {
+
+ {signingOrderModal.open &&
+
+
+
+
Signing Order
+
setSigningOrderModal({ ...signingOrderModal, open: false })}
+ className="text-xl cursor-pointer hover:text-gray-200 transition-all">
+
+
+
+
+
+
+
+
+ }
>
}
>
diff --git a/src/index.css b/src/index.css
index c2230cb..06eb6eb 100644
--- a/src/index.css
+++ b/src/index.css
@@ -74,3 +74,15 @@ canvas {
.animate-text {
animation: textColorChange 2s infinite ease-in-out;
}
+
+@layer utilities {
+ /* Hide scrollbar for Chrome, Safari and Opera */
+ .no-scrollbar::-webkit-scrollbar {
+ display: none;
+ }
+ /* Hide scrollbar for IE, Edge and Firefox */
+ .no-scrollbar {
+ -ms-overflow-style: none; /* IE and Edge */
+ scrollbar-width: none; /* Firefox */
+ }
+ }
\ No newline at end of file