feat: implement editable profile sections and update layout in investor details page
This commit is contained in:
1542
src/app/admin/investors/[id]/page copy.tsx
Normal file
1542
src/app/admin/investors/[id]/page copy.tsx
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -30,10 +30,6 @@ interface InvestmentSettingsProps {
|
|||||||
setNewInvestLock: (n: number) => void;
|
setNewInvestLock: (n: number) => void;
|
||||||
newInvestPenalty: number;
|
newInvestPenalty: number;
|
||||||
setNewInvestPenalty: (n: number) => void;
|
setNewInvestPenalty: (n: number) => void;
|
||||||
newInvestMonthly: number;
|
|
||||||
setNewInvestMonthly: (n: number) => void;
|
|
||||||
newInvestTotal: number;
|
|
||||||
setNewInvestTotal: (n: number) => void;
|
|
||||||
newInvestFicoSingleRent: number;
|
newInvestFicoSingleRent: number;
|
||||||
setNewInvestFicoSingleRent: (n: number) => void;
|
setNewInvestFicoSingleRent: (n: number) => void;
|
||||||
newInvestFicoRentToOwn: number;
|
newInvestFicoRentToOwn: number;
|
||||||
@@ -42,6 +38,10 @@ interface InvestmentSettingsProps {
|
|||||||
setNewInvestFicoShareEv: (n: number) => void;
|
setNewInvestFicoShareEv: (n: number) => void;
|
||||||
newInvestDesc: string;
|
newInvestDesc: string;
|
||||||
setNewInvestDesc: (v: string) => void;
|
setNewInvestDesc: (v: string) => void;
|
||||||
|
newInvestEvBasePrice: number;
|
||||||
|
setNewInvestEvBasePrice: (n: number) => void;
|
||||||
|
newInvestMinQuantity: number;
|
||||||
|
setNewInvestMinQuantity: (n: number) => void;
|
||||||
createInvestPlan: () => void;
|
createInvestPlan: () => void;
|
||||||
handleSave: () => void;
|
handleSave: () => void;
|
||||||
}
|
}
|
||||||
@@ -60,14 +60,15 @@ export default function InvestmentSettings({
|
|||||||
newInvestDuration, setNewInvestDuration,
|
newInvestDuration, setNewInvestDuration,
|
||||||
newInvestLock, setNewInvestLock,
|
newInvestLock, setNewInvestLock,
|
||||||
newInvestPenalty, setNewInvestPenalty,
|
newInvestPenalty, setNewInvestPenalty,
|
||||||
newInvestMonthly, setNewInvestMonthly,
|
|
||||||
newInvestTotal, setNewInvestTotal,
|
|
||||||
newInvestFicoSingleRent, setNewInvestFicoSingleRent,
|
newInvestFicoSingleRent, setNewInvestFicoSingleRent,
|
||||||
newInvestFicoRentToOwn, setNewInvestFicoRentToOwn,
|
newInvestFicoRentToOwn, setNewInvestFicoRentToOwn,
|
||||||
newInvestFicoShareEv, setNewInvestFicoShareEv,
|
newInvestFicoShareEv, setNewInvestFicoShareEv,
|
||||||
newInvestDesc, setNewInvestDesc,
|
newInvestDesc, setNewInvestDesc,
|
||||||
|
newInvestEvBasePrice, setNewInvestEvBasePrice,
|
||||||
|
newInvestMinQuantity, setNewInvestMinQuantity,
|
||||||
createInvestPlan, handleSave,
|
createInvestPlan, handleSave,
|
||||||
}: InvestmentSettingsProps) {
|
}: InvestmentSettingsProps) {
|
||||||
|
const calculatedMinInvestment = newInvestMinQuantity * newInvestEvBasePrice;
|
||||||
return (
|
return (
|
||||||
<div className="p-6 space-y-6">
|
<div className="p-6 space-y-6">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
@@ -121,9 +122,20 @@ export default function InvestmentSettings({
|
|||||||
<label className="text-sm text-slate-600">End Date</label>
|
<label className="text-sm text-slate-600">End Date</label>
|
||||||
<input type="date" value={newInvestEnd} onChange={(e) => setNewInvestEnd(e.target.value)} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1" />
|
<input type="date" value={newInvestEnd} onChange={(e) => setNewInvestEnd(e.target.value)} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1" />
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="text-sm text-slate-600">EV Base Price (৳)</label>
|
||||||
|
<input type="number" value={newInvestEvBasePrice} onChange={(e) => setNewInvestEvBasePrice(parseInt(e.target.value))} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1" placeholder="Single EV cost" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="text-sm text-slate-600">Minimum Quantity (Bikes)</label>
|
||||||
|
<input type="number" value={newInvestMinQuantity} onChange={(e) => setNewInvestMinQuantity(parseInt(e.target.value))} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1" placeholder="Min bikes to invest" />
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label className="text-sm text-slate-600">Min Investment (৳)</label>
|
<label className="text-sm text-slate-600">Min Investment (৳)</label>
|
||||||
<input type="number" value={newInvestMin} onChange={(e) => setNewInvestMin(parseInt(e.target.value))} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1" />
|
<div className="flex items-center gap-2 mt-1">
|
||||||
|
<input type="number" value={calculatedMinInvestment} disabled className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm bg-slate-100" />
|
||||||
|
<span className="text-xs text-slate-500 whitespace-nowrap">= Qty × Base Price</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label className="text-sm text-slate-600">Max Investment (৳)</label>
|
<label className="text-sm text-slate-600">Max Investment (৳)</label>
|
||||||
@@ -141,14 +153,6 @@ export default function InvestmentSettings({
|
|||||||
<label className="text-sm text-slate-600">Early Exit Penalty (%)</label>
|
<label className="text-sm text-slate-600">Early Exit Penalty (%)</label>
|
||||||
<input type="number" value={newInvestPenalty} onChange={(e) => setNewInvestPenalty(parseInt(e.target.value))} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1" />
|
<input type="number" value={newInvestPenalty} onChange={(e) => setNewInvestPenalty(parseInt(e.target.value))} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
|
||||||
<label className="text-sm text-slate-600">Monthly Return (%)</label>
|
|
||||||
<input type="number" step="0.1" value={newInvestMonthly} onChange={(e) => setNewInvestMonthly(parseFloat(e.target.value))} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label className="text-sm text-slate-600">Total Return (%)</label>
|
|
||||||
<input type="number" step="0.1" value={newInvestTotal} onChange={(e) => setNewInvestTotal(parseFloat(e.target.value))} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1" />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-3 gap-4 mt-4">
|
<div className="grid grid-cols-3 gap-4 mt-4">
|
||||||
<div>
|
<div>
|
||||||
@@ -183,7 +187,7 @@ export default function InvestmentSettings({
|
|||||||
<div key={idx} className="bg-white rounded-xl border border-slate-200 overflow-hidden">
|
<div key={idx} className="bg-white rounded-xl border border-slate-200 overflow-hidden">
|
||||||
<div className="bg-amber-50 px-4 py-3 border-b border-amber-100 flex items-center justify-between">
|
<div className="bg-amber-50 px-4 py-3 border-b border-amber-100 flex items-center justify-between">
|
||||||
<div>
|
<div>
|
||||||
<h4 className="font-semibold text-amber-800">{plan.name} - {plan.monthlyReturnPercent}% per month</h4>
|
<h4 className="font-semibold text-amber-800">{plan.name}</h4>
|
||||||
<p className="text-sm text-amber-600 mt-1">{plan.description}</p>
|
<p className="text-sm text-amber-600 mt-1">{plan.description}</p>
|
||||||
</div>
|
</div>
|
||||||
<span className={`px-2 py-1 rounded-full text-xs font-medium ${plan.status === 'active' ? 'bg-green-100 text-green-700' : 'bg-red-100 text-red-700'}`}>{plan.status}</span>
|
<span className={`px-2 py-1 rounded-full text-xs font-medium ${plan.status === 'active' ? 'bg-green-100 text-green-700' : 'bg-red-100 text-red-700'}`}>{plan.status}</span>
|
||||||
@@ -214,9 +218,20 @@ export default function InvestmentSettings({
|
|||||||
<label className="text-sm text-slate-600">End Date</label>
|
<label className="text-sm text-slate-600">End Date</label>
|
||||||
<input type="date" value={plan.endDate} onChange={(e) => { const updated = [...settings.plans.investment]; updated[idx].endDate = e.target.value; setSettings({ ...settings, plans: { ...settings.plans, investment: updated } }); }} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1" />
|
<input type="date" value={plan.endDate} onChange={(e) => { const updated = [...settings.plans.investment]; updated[idx].endDate = e.target.value; setSettings({ ...settings, plans: { ...settings.plans, investment: updated } }); }} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1" />
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="text-sm text-slate-600">EV Base Price (৳)</label>
|
||||||
|
<input type="number" value={plan.evBasePrice} onChange={(e) => { const updated = [...settings.plans.investment]; updated[idx].evBasePrice = parseInt(e.target.value); setSettings({ ...settings, plans: { ...settings.plans, investment: updated } }); }} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="text-sm text-slate-600">Minimum Quantity (Bikes)</label>
|
||||||
|
<input type="number" value={plan.minQuantity} onChange={(e) => { const updated = [...settings.plans.investment]; updated[idx].minQuantity = parseInt(e.target.value); setSettings({ ...settings, plans: { ...settings.plans, investment: updated } }); }} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1" />
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label className="text-sm text-slate-600">Min Investment (৳)</label>
|
<label className="text-sm text-slate-600">Min Investment (৳)</label>
|
||||||
<input type="number" value={plan.minInvestment} onChange={(e) => { const updated = [...settings.plans.investment]; updated[idx].minInvestment = parseInt(e.target.value); setSettings({ ...settings, plans: { ...settings.plans, investment: updated } }); }} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1" />
|
<div className="flex items-center gap-2 mt-1">
|
||||||
|
<input type="number" value={plan.evBasePrice * plan.minQuantity} disabled className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm bg-slate-100" />
|
||||||
|
<span className="text-xs text-slate-500 whitespace-nowrap">= Qty × Base Price</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label className="text-sm text-slate-600">Max Investment (৳)</label>
|
<label className="text-sm text-slate-600">Max Investment (৳)</label>
|
||||||
@@ -234,14 +249,6 @@ export default function InvestmentSettings({
|
|||||||
<label className="text-sm text-slate-600">Early Exit Penalty (%)</label>
|
<label className="text-sm text-slate-600">Early Exit Penalty (%)</label>
|
||||||
<input type="number" value={plan.earlyExitPenalty} onChange={(e) => { const updated = [...settings.plans.investment]; updated[idx].earlyExitPenalty = parseInt(e.target.value); setSettings({ ...settings, plans: { ...settings.plans, investment: updated } }); }} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1" />
|
<input type="number" value={plan.earlyExitPenalty} onChange={(e) => { const updated = [...settings.plans.investment]; updated[idx].earlyExitPenalty = parseInt(e.target.value); setSettings({ ...settings, plans: { ...settings.plans, investment: updated } }); }} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
|
||||||
<label className="text-sm text-slate-600">Monthly Return (%)</label>
|
|
||||||
<input type="number" step="0.1" value={plan.monthlyReturnPercent} onChange={(e) => { const updated = [...settings.plans.investment]; updated[idx].monthlyReturnPercent = parseFloat(e.target.value); setSettings({ ...settings, plans: { ...settings.plans, investment: updated } }); }} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label className="text-sm text-slate-600">Total Return (%)</label>
|
|
||||||
<input type="number" step="0.1" value={plan.totalReturnPercent} onChange={(e) => { const updated = [...settings.plans.investment]; updated[idx].totalReturnPercent = parseFloat(e.target.value); setSettings({ ...settings, plans: { ...settings.plans, investment: updated } }); }} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1" />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-3 gap-4 mt-4">
|
<div className="grid grid-cols-3 gap-4 mt-4">
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -184,13 +184,13 @@ export interface CompanySettings {
|
|||||||
id: string;
|
id: string;
|
||||||
tier: string;
|
tier: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
minQuantity: number;
|
||||||
|
evBasePrice: number;
|
||||||
minInvestment: number;
|
minInvestment: number;
|
||||||
maxInvestment: number;
|
maxInvestment: number;
|
||||||
monthlyReturnPercent: number;
|
|
||||||
durationMonths: number;
|
durationMonths: number;
|
||||||
profitSharePercent: number;
|
profitSharePercent: number;
|
||||||
lockInMonths: number;
|
lockInMonths: number;
|
||||||
totalReturnPercent: number;
|
|
||||||
earlyExitPenalty: number;
|
earlyExitPenalty: number;
|
||||||
startDate: string;
|
startDate: string;
|
||||||
endDate: string;
|
endDate: string;
|
||||||
@@ -695,13 +695,13 @@ const initialSettings: CompanySettings = {
|
|||||||
id: 'inv_demo_1',
|
id: 'inv_demo_1',
|
||||||
name: '1 Bike Plan',
|
name: '1 Bike Plan',
|
||||||
tier: 'Economy',
|
tier: 'Economy',
|
||||||
minInvestment: 50000,
|
minQuantity: 1,
|
||||||
maxInvestment: 100000,
|
evBasePrice: 200000,
|
||||||
monthlyReturnPercent: 2,
|
minInvestment: 200000,
|
||||||
|
maxInvestment: 1000000,
|
||||||
durationMonths: 12,
|
durationMonths: 12,
|
||||||
profitSharePercent: 50,
|
profitSharePercent: 50,
|
||||||
lockInMonths: 3,
|
lockInMonths: 3,
|
||||||
totalReturnPercent: 24,
|
|
||||||
earlyExitPenalty: 10,
|
earlyExitPenalty: 10,
|
||||||
startDate: '2026-01-01',
|
startDate: '2026-01-01',
|
||||||
endDate: '2026-12-31',
|
endDate: '2026-12-31',
|
||||||
@@ -716,13 +716,13 @@ const initialSettings: CompanySettings = {
|
|||||||
id: 'inv_demo_2',
|
id: 'inv_demo_2',
|
||||||
name: '5 Bike Plan',
|
name: '5 Bike Plan',
|
||||||
tier: 'Standard',
|
tier: 'Standard',
|
||||||
minInvestment: 150000,
|
minQuantity: 5,
|
||||||
maxInvestment: 500000,
|
evBasePrice: 180000,
|
||||||
monthlyReturnPercent: 2.5,
|
minInvestment: 900000,
|
||||||
|
maxInvestment: 5000000,
|
||||||
durationMonths: 24,
|
durationMonths: 24,
|
||||||
profitSharePercent: 50,
|
profitSharePercent: 50,
|
||||||
lockInMonths: 6,
|
lockInMonths: 6,
|
||||||
totalReturnPercent: 60,
|
|
||||||
earlyExitPenalty: 10,
|
earlyExitPenalty: 10,
|
||||||
startDate: '2026-01-01',
|
startDate: '2026-01-01',
|
||||||
endDate: '2026-12-31',
|
endDate: '2026-12-31',
|
||||||
@@ -846,16 +846,16 @@ export default function CompanySettingsPage() {
|
|||||||
const [newInvestEnd, setNewInvestEnd] = useState('2026-12-31');
|
const [newInvestEnd, setNewInvestEnd] = useState('2026-12-31');
|
||||||
const [newInvestMin, setNewInvestMin] = useState(10000);
|
const [newInvestMin, setNewInvestMin] = useState(10000);
|
||||||
const [newInvestMax, setNewInvestMax] = useState(100000);
|
const [newInvestMax, setNewInvestMax] = useState(100000);
|
||||||
const [newInvestMonthly, setNewInvestMonthly] = useState(2);
|
|
||||||
const [newInvestDuration, setNewInvestDuration] = useState(12);
|
const [newInvestDuration, setNewInvestDuration] = useState(12);
|
||||||
const [newInvestLock, setNewInvestLock] = useState(3);
|
const [newInvestLock, setNewInvestLock] = useState(3);
|
||||||
const [newInvestTotal, setNewInvestTotal] = useState(24);
|
|
||||||
const [newInvestPenalty, setNewInvestPenalty] = useState(10);
|
const [newInvestPenalty, setNewInvestPenalty] = useState(10);
|
||||||
const [newInvestProfitShare, setNewInvestProfitShare] = useState(50);
|
const [newInvestProfitShare, setNewInvestProfitShare] = useState(50);
|
||||||
const [newInvestFicoSingleRent, setNewInvestFicoSingleRent] = useState(45);
|
const [newInvestFicoSingleRent, setNewInvestFicoSingleRent] = useState(45);
|
||||||
const [newInvestFicoRentToOwn, setNewInvestFicoRentToOwn] = useState(55);
|
const [newInvestFicoRentToOwn, setNewInvestFicoRentToOwn] = useState(55);
|
||||||
const [newInvestFicoShareEv, setNewInvestFicoShareEv] = useState(60);
|
const [newInvestFicoShareEv, setNewInvestFicoShareEv] = useState(60);
|
||||||
const [newInvestDesc, setNewInvestDesc] = useState('');
|
const [newInvestDesc, setNewInvestDesc] = useState('');
|
||||||
|
const [newInvestEvBasePrice, setNewInvestEvBasePrice] = useState(200000);
|
||||||
|
const [newInvestMinQuantity, setNewInvestMinQuantity] = useState(1);
|
||||||
|
|
||||||
const createInvestPlan = () => {
|
const createInvestPlan = () => {
|
||||||
if (newInvestName.trim() && typeof window !== 'undefined') {
|
if (newInvestName.trim() && typeof window !== 'undefined') {
|
||||||
@@ -863,13 +863,13 @@ export default function CompanySettingsPage() {
|
|||||||
id: 'inv_' + Date.now(),
|
id: 'inv_' + Date.now(),
|
||||||
name: newInvestName,
|
name: newInvestName,
|
||||||
tier: newInvestTier,
|
tier: newInvestTier,
|
||||||
minInvestment: newInvestMin,
|
evBasePrice: newInvestEvBasePrice,
|
||||||
|
minQuantity: newInvestMinQuantity,
|
||||||
|
minInvestment: newInvestEvBasePrice * newInvestMinQuantity,
|
||||||
maxInvestment: newInvestMax,
|
maxInvestment: newInvestMax,
|
||||||
monthlyReturnPercent: newInvestMonthly,
|
|
||||||
durationMonths: newInvestDuration,
|
durationMonths: newInvestDuration,
|
||||||
profitSharePercent: newInvestProfitShare,
|
profitSharePercent: newInvestProfitShare,
|
||||||
lockInMonths: newInvestLock,
|
lockInMonths: newInvestLock,
|
||||||
totalReturnPercent: newInvestTotal,
|
|
||||||
earlyExitPenalty: newInvestPenalty,
|
earlyExitPenalty: newInvestPenalty,
|
||||||
startDate: newInvestStart,
|
startDate: newInvestStart,
|
||||||
endDate: newInvestEnd,
|
endDate: newInvestEnd,
|
||||||
@@ -1306,12 +1306,12 @@ export default function CompanySettingsPage() {
|
|||||||
newInvestDuration={newInvestDuration} setNewInvestDuration={setNewInvestDuration}
|
newInvestDuration={newInvestDuration} setNewInvestDuration={setNewInvestDuration}
|
||||||
newInvestLock={newInvestLock} setNewInvestLock={setNewInvestLock}
|
newInvestLock={newInvestLock} setNewInvestLock={setNewInvestLock}
|
||||||
newInvestPenalty={newInvestPenalty} setNewInvestPenalty={setNewInvestPenalty}
|
newInvestPenalty={newInvestPenalty} setNewInvestPenalty={setNewInvestPenalty}
|
||||||
newInvestMonthly={newInvestMonthly} setNewInvestMonthly={setNewInvestMonthly}
|
|
||||||
newInvestTotal={newInvestTotal} setNewInvestTotal={setNewInvestTotal}
|
|
||||||
newInvestFicoSingleRent={newInvestFicoSingleRent} setNewInvestFicoSingleRent={setNewInvestFicoSingleRent}
|
newInvestFicoSingleRent={newInvestFicoSingleRent} setNewInvestFicoSingleRent={setNewInvestFicoSingleRent}
|
||||||
newInvestFicoRentToOwn={newInvestFicoRentToOwn} setNewInvestFicoRentToOwn={setNewInvestFicoRentToOwn}
|
newInvestFicoRentToOwn={newInvestFicoRentToOwn} setNewInvestFicoRentToOwn={setNewInvestFicoRentToOwn}
|
||||||
newInvestFicoShareEv={newInvestFicoShareEv} setNewInvestFicoShareEv={setNewInvestFicoShareEv}
|
newInvestFicoShareEv={newInvestFicoShareEv} setNewInvestFicoShareEv={setNewInvestFicoShareEv}
|
||||||
newInvestDesc={newInvestDesc} setNewInvestDesc={setNewInvestDesc}
|
newInvestDesc={newInvestDesc} setNewInvestDesc={setNewInvestDesc}
|
||||||
|
newInvestEvBasePrice={newInvestEvBasePrice} setNewInvestEvBasePrice={setNewInvestEvBasePrice}
|
||||||
|
newInvestMinQuantity={newInvestMinQuantity} setNewInvestMinQuantity={setNewInvestMinQuantity}
|
||||||
createInvestPlan={createInvestPlan} handleSave={handleSave}
|
createInvestPlan={createInvestPlan} handleSave={handleSave}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user