272 lines
19 KiB
TypeScript
272 lines
19 KiB
TypeScript
'use client';
|
||
|
||
import { Plus, X, Save, Battery } from 'lucide-react';
|
||
import type { CompanySettings } from '../page';
|
||
|
||
interface BatteryInvestmentSettingsProps {
|
||
settings: CompanySettings;
|
||
setSettings: React.Dispatch<React.SetStateAction<CompanySettings>>;
|
||
activeBatteryTab: number;
|
||
setActiveBatteryTab: (n: number) => void;
|
||
addBatteryPlan: boolean;
|
||
setAddBatteryPlan: (v: boolean) => void;
|
||
newBatteryName: string;
|
||
setNewBatteryName: (v: string) => void;
|
||
newBatteryStatus: string;
|
||
setNewBatteryStatus: (v: string) => void;
|
||
newBatteryTarget: number;
|
||
setNewBatteryTarget: (n: number) => void;
|
||
newBatteryStart: string;
|
||
setNewBatteryStart: (v: string) => void;
|
||
newBatteryEnd: string;
|
||
setNewBatteryEnd: (v: string) => void;
|
||
newBatteryMin: number;
|
||
setNewBatteryMin: (n: number) => void;
|
||
newBatteryMax: number;
|
||
setNewBatteryMax: (n: number) => void;
|
||
newBatteryDuration: number;
|
||
setNewBatteryDuration: (n: number) => void;
|
||
newBatteryLock: number;
|
||
setNewBatteryLock: (n: number) => void;
|
||
newBatteryPenalty: number;
|
||
setNewBatteryPenalty: (n: number) => void;
|
||
newBatteryProfitShare: number;
|
||
setNewBatteryProfitShare: (n: number) => void;
|
||
newBatteryDesc: string;
|
||
setNewBatteryDesc: (v: string) => void;
|
||
newBatteryBasePrice: number;
|
||
setNewBatteryBasePrice: (n: number) => void;
|
||
newBatteryMinQuantity: number;
|
||
setNewBatteryMinQuantity: (n: number) => void;
|
||
createBatteryPlan: () => void;
|
||
handleSave: () => void;
|
||
}
|
||
|
||
export default function BatteryInvestmentSettings({
|
||
settings, setSettings,
|
||
activeBatteryTab, setActiveBatteryTab,
|
||
addBatteryPlan, setAddBatteryPlan,
|
||
newBatteryName, setNewBatteryName,
|
||
newBatteryStatus, setNewBatteryStatus,
|
||
newBatteryTarget, setNewBatteryTarget,
|
||
newBatteryStart, setNewBatteryStart,
|
||
newBatteryEnd, setNewBatteryEnd,
|
||
newBatteryMin, setNewBatteryMin,
|
||
newBatteryMax, setNewBatteryMax,
|
||
newBatteryDuration, setNewBatteryDuration,
|
||
newBatteryLock, setNewBatteryLock,
|
||
newBatteryPenalty, setNewBatteryPenalty,
|
||
newBatteryProfitShare, setNewBatteryProfitShare,
|
||
newBatteryDesc, setNewBatteryDesc,
|
||
newBatteryBasePrice, setNewBatteryBasePrice,
|
||
newBatteryMinQuantity, setNewBatteryMinQuantity,
|
||
createBatteryPlan, handleSave,
|
||
}: BatteryInvestmentSettingsProps) {
|
||
const calculatedMinInvestment = newBatteryMinQuantity * newBatteryBasePrice;
|
||
return (
|
||
<div className="p-6 space-y-6">
|
||
<div className="flex items-center justify-between">
|
||
<h3 className="text-lg font-semibold text-slate-800 flex items-center gap-2">
|
||
<Battery className="w-5 h-5 text-emerald-600 animate-pulse" />
|
||
Battery Investment Plans
|
||
</h3>
|
||
</div>
|
||
|
||
<div className="flex items-center justify-between bg-emerald-50 border border-emerald-200 rounded-xl p-4">
|
||
<div>
|
||
<h4 className="font-semibold text-emerald-800">Battery Investment Plans ({(settings.plans as any).batteryInvestment?.length || 0})</h4>
|
||
<p className="text-sm text-emerald-600">Manage high-yield battery pack investment plans for partners</p>
|
||
</div>
|
||
<button onClick={() => { setAddBatteryPlan(true); setNewBatteryName(''); }} className="px-4 py-2 bg-emerald-600 text-white rounded-lg text-sm font-medium flex items-center gap-2 hover:bg-emerald-700 transition-colors">
|
||
<Plus className="w-4 h-4" /> New Plan
|
||
</button>
|
||
</div>
|
||
|
||
{addBatteryPlan && (
|
||
<div className="bg-white rounded-xl border border-emerald-300 overflow-hidden shadow-sm">
|
||
<div className="bg-emerald-50 px-4 py-3 border-b border-emerald-100 flex items-center justify-between">
|
||
<div>
|
||
<h4 className="font-semibold text-emerald-800">New Battery Investment Plan</h4>
|
||
<p className="text-sm text-emerald-600 mt-1">Configure high-yield battery fleet assets</p>
|
||
</div>
|
||
<button onClick={() => setAddBatteryPlan(false)} className="text-emerald-600 hover:text-emerald-800">
|
||
<X className="w-5 h-5" />
|
||
</button>
|
||
</div>
|
||
<div className="p-4">
|
||
<div className="grid lg:grid-cols-3 gap-4">
|
||
<div>
|
||
<label className="text-sm text-slate-600">Plan Name</label>
|
||
<input type="text" value={newBatteryName} onChange={(e) => setNewBatteryName(e.target.value)} placeholder="e.g., Standard Battery Plan" 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">Status</label>
|
||
<select value={newBatteryStatus} onChange={(e) => setNewBatteryStatus(e.target.value)} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1">
|
||
<option value="active">Active</option>
|
||
<option value="paused">Paused</option>
|
||
<option value="closed">Closed</option>
|
||
</select>
|
||
</div>
|
||
<div>
|
||
<label className="text-sm text-slate-600">Target Amount (৳)</label>
|
||
<input type="number" value={newBatteryTarget} onChange={(e) => setNewBatteryTarget(parseInt(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">Start Date</label>
|
||
<input type="date" value={newBatteryStart} onChange={(e) => setNewBatteryStart(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">End Date</label>
|
||
<input type="date" value={newBatteryEnd} onChange={(e) => setNewBatteryEnd(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">Battery Base Price (৳)</label>
|
||
<input type="number" value={newBatteryBasePrice} onChange={(e) => setNewBatteryBasePrice(parseInt(e.target.value))} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1" placeholder="Single battery unit cost" />
|
||
</div>
|
||
<div>
|
||
<label className="text-sm text-slate-600">Minimum Quantity (Packs)</label>
|
||
<input type="number" value={newBatteryMinQuantity} onChange={(e) => setNewBatteryMinQuantity(parseInt(e.target.value))} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1" placeholder="Min battery packs to invest" />
|
||
</div>
|
||
<div>
|
||
<label className="text-sm text-slate-600">Min Investment (৳)</label>
|
||
<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>
|
||
<label className="text-sm text-slate-600">Max Investment (৳)</label>
|
||
<input type="number" value={newBatteryMax} onChange={(e) => setNewBatteryMax(parseInt(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">Duration (Months)</label>
|
||
<input type="number" value={newBatteryDuration} onChange={(e) => setNewBatteryDuration(parseInt(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">Lock-in Period (Months)</label>
|
||
<input type="number" value={newBatteryLock} onChange={(e) => setNewBatteryLock(parseInt(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">Early Exit Penalty (%)</label>
|
||
<input type="number" value={newBatteryPenalty} onChange={(e) => setNewBatteryPenalty(parseInt(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">Profit Share Percent (%)</label>
|
||
<input type="number" value={newBatteryProfitShare} onChange={(e) => setNewBatteryProfitShare(parseInt(e.target.value))} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1" />
|
||
</div>
|
||
</div>
|
||
<div className="mt-4">
|
||
<label className="text-sm text-slate-600">Description</label>
|
||
<textarea value={newBatteryDesc} onChange={(e) => setNewBatteryDesc(e.target.value)} placeholder="Enter battery investment plan description" className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1" rows={2} />
|
||
</div>
|
||
<button onClick={createBatteryPlan} className="mt-4 px-4 py-2 bg-emerald-600 text-white rounded-lg text-sm font-medium hover:bg-emerald-700 transition-colors">Create Plan</button>
|
||
</div>
|
||
</div>
|
||
)}
|
||
|
||
<div className="flex gap-2 border-b border-slate-200">
|
||
{((settings.plans as any).batteryInvestment || []).map((plan: any, idx: number) => (
|
||
<button key={idx} onClick={() => setActiveBatteryTab(idx)} className={`px-4 py-2 text-sm font-medium border-b-2 -mb-px ${activeBatteryTab === idx ? 'border-emerald-500 text-emerald-600 font-bold' : 'border-transparent text-slate-500 hover:text-slate-700'}`}> {plan.name}</button>
|
||
))}
|
||
</div>
|
||
|
||
{((settings.plans as any).batteryInvestment || []).length > 0 && ((settings.plans as any).batteryInvestment || []).map((plan: any, idx: number) => idx === activeBatteryTab && (
|
||
<div key={idx} className="bg-white rounded-xl border border-slate-200 overflow-hidden shadow-sm">
|
||
<div className="bg-emerald-50/50 px-4 py-3 border-b border-emerald-100 flex items-center justify-between">
|
||
<div>
|
||
<h4 className="font-semibold text-emerald-800">{plan.name}</h4>
|
||
<p className="text-sm text-emerald-600 mt-1">{plan.description}</p>
|
||
</div>
|
||
<div className="flex items-center gap-2">
|
||
<span className={`px-2.5 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>
|
||
<button
|
||
onClick={() => {
|
||
const updated = ((settings.plans as any).batteryInvestment || []).filter((_: any, i: number) => i !== idx);
|
||
setSettings({ ...settings, plans: { ...settings.plans, batteryInvestment: updated } });
|
||
setActiveBatteryTab(0);
|
||
}}
|
||
className="p-1.5 text-red-600 hover:bg-red-50 rounded-lg transition-colors"
|
||
title="Delete Plan"
|
||
>
|
||
<X className="w-4 h-4" />
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div className="p-4">
|
||
<div className="grid lg:grid-cols-3 gap-4">
|
||
<div>
|
||
<label className="text-sm text-slate-600">Plan Name</label>
|
||
<input type="text" value={plan.name} onChange={(e) => { const updated = [...((settings.plans as any).batteryInvestment || [])]; updated[idx].name = e.target.value; setSettings({ ...settings, plans: { ...settings.plans, batteryInvestment: 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">Status</label>
|
||
<select value={plan.status} onChange={(e) => { const updated = [...((settings.plans as any).batteryInvestment || [])]; updated[idx].status = e.target.value; setSettings({ ...settings, plans: { ...settings.plans, batteryInvestment: updated } }); }} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1">
|
||
<option value="active">Active</option>
|
||
<option value="paused">Paused</option>
|
||
<option value="closed">Closed</option>
|
||
</select>
|
||
</div>
|
||
<div>
|
||
<label className="text-sm text-slate-600">Target Amount (৳)</label>
|
||
<input type="number" value={plan.targetAmount} onChange={(e) => { const updated = [...((settings.plans as any).batteryInvestment || [])]; updated[idx].targetAmount = parseInt(e.target.value); setSettings({ ...settings, plans: { ...settings.plans, batteryInvestment: 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">Start Date</label>
|
||
<input type="date" value={plan.startDate} onChange={(e) => { const updated = [...((settings.plans as any).batteryInvestment || [])]; updated[idx].startDate = e.target.value; setSettings({ ...settings, plans: { ...settings.plans, batteryInvestment: 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">End Date</label>
|
||
<input type="date" value={plan.endDate} onChange={(e) => { const updated = [...((settings.plans as any).batteryInvestment || [])]; updated[idx].endDate = e.target.value; setSettings({ ...settings, plans: { ...settings.plans, batteryInvestment: 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">Battery Base Price (৳)</label>
|
||
<input type="number" value={plan.batteryBasePrice} onChange={(e) => { const updated = [...((settings.plans as any).batteryInvestment || [])]; updated[idx].batteryBasePrice = parseInt(e.target.value); setSettings({ ...settings, plans: { ...settings.plans, batteryInvestment: 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 (Packs)</label>
|
||
<input type="number" value={plan.minQuantity} onChange={(e) => { const updated = [...((settings.plans as any).batteryInvestment || [])]; updated[idx].minQuantity = parseInt(e.target.value); setSettings({ ...settings, plans: { ...settings.plans, batteryInvestment: 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">Min Investment (৳)</label>
|
||
<div className="flex items-center gap-2 mt-1">
|
||
<input type="number" value={plan.batteryBasePrice * 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 × Price</span>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<label className="text-sm text-slate-600">Max Investment (৳)</label>
|
||
<input type="number" value={plan.maxInvestment} onChange={(e) => { const updated = [...((settings.plans as any).batteryInvestment || [])]; updated[idx].maxInvestment = parseInt(e.target.value); setSettings({ ...settings, plans: { ...settings.plans, batteryInvestment: 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">Duration (Months)</label>
|
||
<input type="number" value={plan.durationMonths} onChange={(e) => { const updated = [...((settings.plans as any).batteryInvestment || [])]; updated[idx].durationMonths = parseInt(e.target.value); setSettings({ ...settings, plans: { ...settings.plans, batteryInvestment: 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">Lock-in Period (Months)</label>
|
||
<input type="number" value={plan.lockInMonths} onChange={(e) => { const updated = [...((settings.plans as any).batteryInvestment || [])]; updated[idx].lockInMonths = parseInt(e.target.value); setSettings({ ...settings, plans: { ...settings.plans, batteryInvestment: 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">Early Exit Penalty (%)</label>
|
||
<input type="number" value={plan.earlyExitPenalty} onChange={(e) => { const updated = [...((settings.plans as any).batteryInvestment || [])]; updated[idx].earlyExitPenalty = parseInt(e.target.value); setSettings({ ...settings, plans: { ...settings.plans, batteryInvestment: 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">Profit Share Percent (%)</label>
|
||
<input type="number" value={plan.profitSharePercent} onChange={(e) => { const updated = [...((settings.plans as any).batteryInvestment || [])]; updated[idx].profitSharePercent = parseInt(e.target.value); setSettings({ ...settings, plans: { ...settings.plans, batteryInvestment: updated } }); }} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1" />
|
||
</div>
|
||
</div>
|
||
<div className="mt-4">
|
||
<label className="text-sm text-slate-600">Description</label>
|
||
<textarea value={plan.description} onChange={(e) => { const updated = [...((settings.plans as any).batteryInvestment || [])]; updated[idx].description = e.target.value; setSettings({ ...settings, plans: { ...settings.plans, batteryInvestment: updated } }); }} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1" rows={2} />
|
||
</div>
|
||
<div className="mt-4 flex justify-end">
|
||
<button onClick={handleSave} className="px-4 py-2 bg-emerald-600 text-white rounded-lg text-sm font-medium flex items-center gap-2 hover:bg-emerald-700 transition-colors shadow-sm">
|
||
<Save className="w-4 h-4" /> Save Changes
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
);
|
||
}
|