update
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
import { useState, useEffect } from 'react';
|
||||
import Link from 'next/link';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
import { useParams, useRouter, useSearchParams } from 'next/navigation';
|
||||
import { investors as initialInvestors, bikes as initialBikes, transactions as initialTransactions, rentalPayments as initialRentalPayments } from '@/data/mockData';
|
||||
import type { Investor } from '@/data/mockData';
|
||||
import toast from 'react-hot-toast';
|
||||
@@ -77,8 +77,18 @@ function SectionCard({ title, icon: Icon, children, headerBg = 'bg-slate-50', he
|
||||
export default function InvestorDetailPage() {
|
||||
const params = useParams();
|
||||
const router = useRouter();
|
||||
const searchParams = useSearchParams();
|
||||
const investorId = params.id as string;
|
||||
|
||||
const [activeTab, setActiveTab] = useState('overview');
|
||||
|
||||
useEffect(() => {
|
||||
const tab = searchParams?.get('tab');
|
||||
if (tab) {
|
||||
setActiveTab(tab);
|
||||
}
|
||||
}, [searchParams]);
|
||||
|
||||
const [investors, setInvestors] = useState<Investor[]>(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
const stored = localStorage.getItem('jaiben_investors');
|
||||
@@ -139,7 +149,6 @@ export default function InvestorDetailPage() {
|
||||
|
||||
// Investor transactions are filtered below
|
||||
|
||||
const [activeTab, setActiveTab] = useState('overview');
|
||||
const [showEditModal, setShowEditModal] = useState(false);
|
||||
const [showAssignBikeModal, setShowAssignBikeModal] = useState(false);
|
||||
const [selectedBikeId, setSelectedBikeId] = useState('');
|
||||
@@ -2064,16 +2073,51 @@ export default function InvestorDetailPage() {
|
||||
<Banknote className="w-5 h-5 text-slate-500" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="font-semibold text-slate-800">{account.bankName}</p>
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
<p className="font-semibold text-slate-800">{account.bankName}</p>
|
||||
{account.verified ? (
|
||||
<span className="flex items-center gap-0.5 text-[10px] bg-green-100 text-green-700 px-2 py-0.5 rounded-full font-semibold">
|
||||
<Check className="w-2.5 h-2.5 text-green-600" /> Verified
|
||||
</span>
|
||||
) : (
|
||||
<span className="flex items-center gap-0.5 text-[10px] bg-amber-100 text-amber-700 px-2 py-0.5 rounded-full font-semibold">
|
||||
<Clock className="w-2.5 h-2.5 text-amber-600 animate-pulse" /> Pending
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<p className="text-xs text-slate-500">{account.branch}</p>
|
||||
</div>
|
||||
</div>
|
||||
<button onClick={() => {
|
||||
setEditingBankAccount(account);
|
||||
setShowBankModal(true);
|
||||
}} className="p-1.5 hover:bg-slate-100 rounded-lg text-slate-500">
|
||||
<Edit className="w-4 h-4" />
|
||||
</button>
|
||||
<div className="flex items-center gap-1.5">
|
||||
{!account.verified && (
|
||||
<button
|
||||
onClick={() => {
|
||||
setInvestors(prev => prev.map(inv => {
|
||||
if (inv.id === investorId) {
|
||||
return {
|
||||
...inv,
|
||||
bankAccounts: inv.bankAccounts?.map((ba: any) =>
|
||||
ba.id === account.id ? { ...ba, verified: true } : ba
|
||||
)
|
||||
};
|
||||
}
|
||||
return inv;
|
||||
}));
|
||||
toast.success(`${account.bankName} verified successfully!`);
|
||||
}}
|
||||
className="flex items-center gap-1 text-xs bg-green-600 hover:bg-green-700 text-white px-2.5 py-1 rounded-lg transition-all font-semibold shadow-sm"
|
||||
title="Verify Bank Account"
|
||||
>
|
||||
<Check className="w-3.5 h-3.5" /> Verify
|
||||
</button>
|
||||
)}
|
||||
<button onClick={() => {
|
||||
setEditingBankAccount(account);
|
||||
setShowBankModal(true);
|
||||
}} className="p-1.5 hover:bg-slate-100 rounded-lg text-slate-500">
|
||||
<Edit className="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-2 text-sm">
|
||||
<div className="flex justify-between">
|
||||
@@ -2110,7 +2154,7 @@ export default function InvestorDetailPage() {
|
||||
|
||||
<div>
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h3 className="font-semibold text-slate-800">Mobile Banking</h3>
|
||||
<h3 className="font-semibold text-slate-800">Mobile Banking ({(investor.mobileBanking ? 1 : 0) + (investor.additionalMobileBanking?.length || 0)})</h3>
|
||||
<button onClick={() => {
|
||||
setEditingMobileBanking({ provider: '', number: '', isPrimary: !investor.mobileBanking });
|
||||
setEditingMobileIndex(null);
|
||||
@@ -2124,16 +2168,45 @@ export default function InvestorDetailPage() {
|
||||
<div className="flex items-center gap-3 p-3 bg-purple-50 rounded-lg">
|
||||
<Phone className="w-5 h-5 text-purple-500" />
|
||||
<div className="flex-1">
|
||||
<p className="text-xs text-purple-600 font-medium">{investor.mobileBanking}</p>
|
||||
<div className="flex items-center gap-2">
|
||||
<p className="text-xs text-purple-600 font-medium">{investor.mobileBanking}</p>
|
||||
{investor.mobileBankingVerified ? (
|
||||
<span className="flex items-center gap-0.5 text-[9px] bg-green-100 text-green-700 px-1.5 py-0.5 rounded-full font-semibold">
|
||||
<Check className="w-2.5 h-2.5 text-green-600" /> Verified
|
||||
</span>
|
||||
) : (
|
||||
<span className="flex items-center gap-0.5 text-[9px] bg-amber-100 text-amber-700 px-1.5 py-0.5 rounded-full font-semibold">
|
||||
<Clock className="w-2.5 h-2.5 text-amber-600 animate-pulse" /> Pending
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<p className="text-xs text-slate-400">{investor.mobileBankingNumber}</p>
|
||||
</div>
|
||||
<button onClick={() => {
|
||||
setEditingMobileBanking({ provider: investor.mobileBanking || '', number: investor.mobileBankingNumber || '', isPrimary: true });
|
||||
setEditingMobileIndex(-1);
|
||||
setShowMobileBankingModal(true);
|
||||
}} className="p-1 hover:bg-purple-100 rounded">
|
||||
<Edit className="w-4 h-4 text-purple-500" />
|
||||
</button>
|
||||
<div className="flex items-center gap-1.5">
|
||||
{!investor.mobileBankingVerified && (
|
||||
<button
|
||||
onClick={() => {
|
||||
setInvestors(prev => prev.map(inv => {
|
||||
if (inv.id === investorId) {
|
||||
return { ...inv, mobileBankingVerified: true };
|
||||
}
|
||||
return inv;
|
||||
}));
|
||||
toast.success(`${investor.mobileBanking} verified successfully!`);
|
||||
}}
|
||||
className="flex items-center gap-1 text-[10px] bg-green-600 hover:bg-green-700 text-white px-2 py-0.5 rounded transition-colors font-medium shadow-sm"
|
||||
>
|
||||
<Check className="w-3.5 h-3.5" /> Verify
|
||||
</button>
|
||||
)}
|
||||
<button onClick={() => {
|
||||
setEditingMobileBanking({ provider: investor.mobileBanking || '', number: investor.mobileBankingNumber || '', isPrimary: true });
|
||||
setEditingMobileIndex(-1);
|
||||
setShowMobileBankingModal(true);
|
||||
}} className="p-1 hover:bg-purple-100 rounded text-purple-500">
|
||||
<Edit className="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
{investor.additionalMobileBanking?.map((mb, idx) => (
|
||||
@@ -2143,21 +2216,48 @@ export default function InvestorDetailPage() {
|
||||
<p className="text-xs text-slate-500">{mb.provider}</p>
|
||||
<p className="font-medium text-slate-700">{mb.number}</p>
|
||||
</div>
|
||||
{mb.verified ? (
|
||||
<span className="text-xs bg-green-100 text-green-700 px-2 py-1 rounded-full">Verified</span>
|
||||
) : (
|
||||
<span className="text-xs bg-amber-100 text-amber-700 px-2 py-1 rounded-full">Pending</span>
|
||||
)}
|
||||
<button onClick={() => {
|
||||
setEditingMobileBanking({ provider: mb.provider, number: mb.number, isPrimary: false });
|
||||
setEditingMobileIndex(idx);
|
||||
setShowMobileBankingModal(true);
|
||||
}} className="p-1 hover:bg-slate-200 rounded">
|
||||
<Edit className="w-4 h-4 text-slate-400" />
|
||||
</button>
|
||||
<button onClick={() => alert(`Delete mobile banking ${mb.provider}`)} className="p-1 hover:bg-red-50 rounded">
|
||||
<Trash2 className="w-4 h-4 text-red-400" />
|
||||
</button>
|
||||
<div className="flex items-center gap-1.5">
|
||||
{mb.verified ? (
|
||||
<span className="flex items-center gap-0.5 text-[9px] bg-green-100 text-green-700 px-1.5 py-0.5 rounded-full font-semibold">
|
||||
<Check className="w-2.5 h-2.5 text-green-600" /> Verified
|
||||
</span>
|
||||
) : (
|
||||
<>
|
||||
<span className="flex items-center gap-0.5 text-[9px] bg-amber-100 text-amber-700 px-1.5 py-0.5 rounded-full font-semibold">
|
||||
<Clock className="w-2.5 h-2.5 text-amber-600 animate-pulse" /> Pending
|
||||
</span>
|
||||
<button
|
||||
onClick={() => {
|
||||
setInvestors(prev => prev.map(inv => {
|
||||
if (inv.id === investorId) {
|
||||
return {
|
||||
...inv,
|
||||
additionalMobileBanking: inv.additionalMobileBanking?.map((a: any, i: number) =>
|
||||
i === idx ? { ...a, verified: true } : a
|
||||
)
|
||||
};
|
||||
}
|
||||
return inv;
|
||||
}));
|
||||
toast.success(`${mb.provider} verified successfully!`);
|
||||
}}
|
||||
className="flex items-center gap-1 text-[10px] bg-green-600 hover:bg-green-700 text-white px-2 py-0.5 rounded transition-colors font-medium shadow-sm"
|
||||
>
|
||||
<Check className="w-3.5 h-3.5" /> Verify
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
<button onClick={() => {
|
||||
setEditingMobileBanking({ provider: mb.provider, number: mb.number, isPrimary: false });
|
||||
setEditingMobileIndex(idx);
|
||||
setShowMobileBankingModal(true);
|
||||
}} className="p-1 hover:bg-slate-200 rounded">
|
||||
<Edit className="w-4 h-4 text-slate-400" />
|
||||
</button>
|
||||
<button onClick={() => alert(`Delete mobile banking ${mb.provider}`)} className="p-1 hover:bg-red-50 rounded">
|
||||
<Trash2 className="w-4 h-4 text-red-400" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
{(!investor.mobileBanking && (!investor.additionalMobileBanking || investor.additionalMobileBanking.length === 0)) && (
|
||||
|
||||
Reference in New Issue
Block a user