feat: add investor co-ownership tracking and management fields to battery details view
This commit is contained in:
@@ -994,6 +994,47 @@ export default function BatteryDetailPage({ params }: { params: Promise<{ id: st
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{battery.investorId && (
|
||||||
|
<div className="bg-emerald-50 rounded-xl border border-emerald-200 p-5 mb-6">
|
||||||
|
<div className="flex items-center justify-between mb-4">
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<div className="w-10 h-10 rounded-lg bg-emerald-100 flex items-center justify-center">
|
||||||
|
<Handshake className="w-5 h-5 text-emerald-600" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 className="font-semibold text-emerald-800">Investor Co-Ownership Details</h3>
|
||||||
|
<span className="text-xs text-emerald-600 bg-emerald-100 px-2 py-0.5 rounded-full font-medium">Active Investment</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
||||||
|
<div className="bg-white rounded-lg p-3 border border-emerald-100/50">
|
||||||
|
<p className="text-xs text-emerald-600 mb-1">Investor Name</p>
|
||||||
|
<Link href={`/admin/investors/${battery.investorId}`} className="font-bold text-slate-800 hover:text-accent hover:underline flex items-center gap-1">
|
||||||
|
{battery.investorName} <TrendingUp className="w-3.5 h-3.5 text-emerald-500" />
|
||||||
|
</Link>
|
||||||
|
<p className="text-xs text-slate-400">ID: {battery.investorId}</p>
|
||||||
|
</div>
|
||||||
|
<div className="bg-white rounded-lg p-3 border border-emerald-100/50">
|
||||||
|
<p className="text-xs text-emerald-600 mb-1">Ownership Share (%)</p>
|
||||||
|
<p className="font-bold text-emerald-700 text-lg">{battery.investorSharePercentage}%</p>
|
||||||
|
<p className="text-xs text-slate-400">Share of Daily Rent Revenue</p>
|
||||||
|
</div>
|
||||||
|
<div className="bg-white rounded-lg p-3 border border-emerald-100/50">
|
||||||
|
<p className="text-xs text-emerald-600 mb-1">Invested Amount</p>
|
||||||
|
<p className="font-bold text-slate-800">৳{(battery.investedAmount || 0).toLocaleString()}</p>
|
||||||
|
<p className="text-xs text-slate-400">Total Capital Contributed</p>
|
||||||
|
</div>
|
||||||
|
<div className="bg-white rounded-lg p-3 border border-emerald-100/50">
|
||||||
|
<p className="text-xs text-emerald-600 mb-1">Investor Daily Payout</p>
|
||||||
|
<p className="font-bold text-emerald-600">৳{(((battery.rentPrice || 150) * (battery.investorSharePercentage || 0)) / 100).toLocaleString()}/day</p>
|
||||||
|
<p className="text-xs text-slate-400">Calculated from Daily Rent</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{showEditModal && (
|
{showEditModal && (
|
||||||
<EditBatteryModal
|
<EditBatteryModal
|
||||||
battery={battery}
|
battery={battery}
|
||||||
@@ -1157,6 +1198,52 @@ function EditBatteryModal({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="border-t border-slate-100 pt-4 mt-4">
|
||||||
|
<h3 className="text-sm font-bold text-slate-800 mb-3">Investor Assignment (Co-Ownership)</h3>
|
||||||
|
<div className="grid grid-cols-2 gap-4">
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-slate-700 mb-1">Investor ID</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={formData.investorId || ''}
|
||||||
|
onChange={(e) => handleChange('investorId', e.target.value)}
|
||||||
|
placeholder="INV-001"
|
||||||
|
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-slate-700 mb-1">Investor Name</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={formData.investorName || ''}
|
||||||
|
onChange={(e) => handleChange('investorName', e.target.value)}
|
||||||
|
placeholder="Tahmid Rahman"
|
||||||
|
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-slate-700 mb-1">Ownership Share (%)</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
value={formData.investorSharePercentage || 0}
|
||||||
|
onChange={(e) => handleChange('investorSharePercentage', parseInt(e.target.value))}
|
||||||
|
placeholder="60"
|
||||||
|
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-slate-700 mb-1">Invested Amount (৳)</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
value={formData.investedAmount || 0}
|
||||||
|
onChange={(e) => handleChange('investedAmount', parseInt(e.target.value))}
|
||||||
|
placeholder="45000"
|
||||||
|
className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="p-5 border-t border-slate-100 flex gap-3 sticky bottom-0 bg-white">
|
<div className="p-5 border-t border-slate-100 flex gap-3 sticky bottom-0 bg-white">
|
||||||
<button onClick={onClose} className="flex-1 py-2.5 px-4 border border-slate-200 rounded-lg font-semibold text-sm hover:bg-slate-50">
|
<button onClick={onClose} className="flex-1 py-2.5 px-4 border border-slate-200 rounded-lg font-semibold text-sm hover:bg-slate-50">
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import Link from 'next/link';
|
|||||||
import {
|
import {
|
||||||
Battery, Plus, Search, Filter, X, Download, Upload, MoreHorizontal,
|
Battery, Plus, Search, Filter, X, Download, Upload, MoreHorizontal,
|
||||||
BatteryCharging, BatteryWarning, BatteryFull, Zap, Thermometer,
|
BatteryCharging, BatteryWarning, BatteryFull, Zap, Thermometer,
|
||||||
Activity, Clock, MapPin, Bike, User, History, TrendingUp, DollarSign,
|
Activity, Clock, MapPin, Bike, User, History, TrendingUp, DollarSign, Handshake,
|
||||||
Eye, Edit, Trash2, RefreshCw, CheckCircle, AlertTriangle, ChevronRight,
|
Eye, Edit, Trash2, RefreshCw, CheckCircle, AlertTriangle, ChevronRight,
|
||||||
ArrowUpDown, Calendar, Gauge, Timer
|
ArrowUpDown, Calendar, Gauge, Timer
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
@@ -65,6 +65,10 @@ interface Battery {
|
|||||||
bmsData?: BMSData;
|
bmsData?: BMSData;
|
||||||
deposit?: number;
|
deposit?: number;
|
||||||
rentPrice?: number;
|
rentPrice?: number;
|
||||||
|
investorId?: string;
|
||||||
|
investorName?: string;
|
||||||
|
investorSharePercentage?: number;
|
||||||
|
investedAmount?: number;
|
||||||
history: BatteryHistory[];
|
history: BatteryHistory[];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,6 +107,10 @@ const mockBatteries: Battery[] = [
|
|||||||
purchasePrice: 45000,
|
purchasePrice: 45000,
|
||||||
deposit: 5000,
|
deposit: 5000,
|
||||||
rentPrice: 150,
|
rentPrice: 150,
|
||||||
|
investorId: 'INV-001',
|
||||||
|
investorName: 'Tahmid Rahman',
|
||||||
|
investorSharePercentage: 60,
|
||||||
|
investedAmount: 45000,
|
||||||
warrantyExpiry: '2027-01-15',
|
warrantyExpiry: '2027-01-15',
|
||||||
status: 'in-use',
|
status: 'in-use',
|
||||||
currentSoc: 78,
|
currentSoc: 78,
|
||||||
@@ -737,27 +745,7 @@ export default function BatteriesPage() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Details Modal */}
|
|
||||||
{showDetailsModal && selectedBattery && (
|
|
||||||
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
|
|
||||||
<div className="bg-white rounded-xl shadow-xl w-full max-w-2xl max-h-[90vh] overflow-hidden flex flex-col">
|
|
||||||
<div className="p-5 border-b border-slate-100 flex items-center justify-between">
|
|
||||||
<h2 className="text-lg font-bold text-slate-800">Battery Details</h2>
|
|
||||||
<button onClick={() => setShowDetailsModal(false)} className="p-2 hover:bg-slate-100 rounded-lg">
|
|
||||||
<X className="w-5 h-5 text-slate-400" />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<BatteryDetails
|
|
||||||
battery={selectedBattery}
|
|
||||||
bikes={mockBikes}
|
|
||||||
bikers={mockBikers}
|
|
||||||
stations={mockStations}
|
|
||||||
onAssign={handleAssignToBike}
|
|
||||||
onClose={() => setShowDetailsModal(false)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* History Modal */}
|
{/* History Modal */}
|
||||||
{showHistoryModal && selectedBattery && (
|
{showHistoryModal && selectedBattery && (
|
||||||
|
|||||||
Reference in New Issue
Block a user