358 lines
14 KiB
TypeScript
358 lines
14 KiB
TypeScript
import React from 'react';
|
|
import { X, Building, Mail, Phone, MapPin, Globe, FileText, DollarSign, Users, Calendar } from 'lucide-react';
|
|
import { VendorModalProps } from '../types/vendor';
|
|
|
|
const VendorDetailsModal: React.FC<VendorModalProps> = ({
|
|
vendor,
|
|
isOpen,
|
|
onClose,
|
|
onApprove,
|
|
onReject
|
|
}) => {
|
|
console.log('VendorDetailsModal props:', { isOpen, vendor: vendor?.id, vendorName: vendor ? `${vendor.firstName} ${vendor.lastName}` : null });
|
|
|
|
if (!isOpen || !vendor) return null;
|
|
|
|
const formatRoleName = (role: string) => {
|
|
if (role.startsWith('channel_partner_')) {
|
|
return 'Vendor';
|
|
} else if (role.startsWith('reseller_')) {
|
|
return 'Reseller';
|
|
} else if (role.startsWith('system_')) {
|
|
return 'System Admin';
|
|
}
|
|
return role.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase());
|
|
};
|
|
|
|
const formatUserType = (userType: string) => {
|
|
if (userType === 'channel_partner') {
|
|
return 'Vendor';
|
|
} else if (userType === 'reseller') {
|
|
return 'Reseller';
|
|
}
|
|
return userType.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase());
|
|
};
|
|
|
|
const formatCurrency = (amount: number) => {
|
|
return new Intl.NumberFormat('en-IN', {
|
|
style: 'currency',
|
|
currency: 'INR',
|
|
minimumFractionDigits: 0,
|
|
maximumFractionDigits: 0
|
|
}).format(amount);
|
|
};
|
|
|
|
return (
|
|
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-[9999] p-4" style={{ backdropFilter: 'blur(4px)' }}>
|
|
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-2xl max-w-2xl w-full max-h-[90vh] overflow-y-auto">
|
|
{/* Header */}
|
|
<div className="flex items-center justify-between p-6 border-b border-gray-200 dark:border-gray-700">
|
|
<div className="flex items-center space-x-3">
|
|
<Building className="w-6 h-6 text-blue-600" />
|
|
<h2 className="text-xl font-semibold text-gray-900 dark:text-white">
|
|
Vendor Details
|
|
</h2>
|
|
</div>
|
|
<button
|
|
onClick={onClose}
|
|
className="text-gray-400 hover:text-gray-600 dark:hover:text-gray-300"
|
|
>
|
|
<X className="w-5 h-5" />
|
|
</button>
|
|
</div>
|
|
|
|
{/* Content */}
|
|
<div className="p-6 space-y-6">
|
|
{/* Basic Information */}
|
|
<div className="space-y-4">
|
|
<h3 className="text-lg font-medium text-gray-900 dark:text-white border-b border-gray-200 dark:border-gray-700 pb-2">
|
|
Basic Information
|
|
</h3>
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
|
|
Full Name
|
|
</label>
|
|
<p className="text-gray-900 dark:text-white">
|
|
{vendor.firstName} {vendor.lastName}
|
|
</p>
|
|
</div>
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
|
|
Email
|
|
</label>
|
|
<p className="text-gray-900 dark:text-white flex items-center">
|
|
<Mail className="w-4 h-4 mr-2" />
|
|
{vendor.email}
|
|
</p>
|
|
</div>
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
|
|
Phone
|
|
</label>
|
|
<p className="text-gray-900 dark:text-white flex items-center">
|
|
<Phone className="w-4 h-4 mr-2" />
|
|
{vendor.phone || 'N/A'}
|
|
</p>
|
|
</div>
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
|
|
Company
|
|
</label>
|
|
<p className="text-gray-900 dark:text-white flex items-center">
|
|
<Building className="w-4 h-4 mr-2" />
|
|
{vendor.company}
|
|
</p>
|
|
</div>
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
|
|
Role
|
|
</label>
|
|
<p className="text-gray-900 dark:text-white">
|
|
{formatRoleName(vendor.role)}
|
|
</p>
|
|
</div>
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
|
|
User Type
|
|
</label>
|
|
<p className="text-gray-900 dark:text-white">
|
|
{formatUserType(vendor.userType)}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Business Information */}
|
|
{(vendor.companyType || vendor.registrationNumber || vendor.gstNumber || vendor.panNumber) && (
|
|
<div className="space-y-4">
|
|
<h3 className="text-lg font-medium text-gray-900 dark:text-white border-b border-gray-200 dark:border-gray-700 pb-2">
|
|
Business Information
|
|
</h3>
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
{vendor.companyType && (
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
|
|
Company Type
|
|
</label>
|
|
<p className="text-gray-900 dark:text-white">
|
|
{vendor.companyType.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase())}
|
|
</p>
|
|
</div>
|
|
)}
|
|
{vendor.registrationNumber && (
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
|
|
Registration Number
|
|
</label>
|
|
<p className="text-gray-900 dark:text-white">
|
|
{vendor.registrationNumber}
|
|
</p>
|
|
</div>
|
|
)}
|
|
{vendor.gstNumber && (
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
|
|
GST Number
|
|
</label>
|
|
<p className="text-gray-900 dark:text-white">
|
|
{vendor.gstNumber}
|
|
</p>
|
|
</div>
|
|
)}
|
|
{vendor.panNumber && (
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
|
|
PAN Number
|
|
</label>
|
|
<p className="text-gray-900 dark:text-white">
|
|
{vendor.panNumber}
|
|
</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* Financial Information */}
|
|
{(vendor.annualRevenue || vendor.employeeCount || vendor.yearsInBusiness) && (
|
|
<div className="space-y-4">
|
|
<h3 className="text-lg font-medium text-gray-900 dark:text-white border-b border-gray-200 dark:border-gray-700 pb-2">
|
|
Financial Information
|
|
</h3>
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
{vendor.annualRevenue && (
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
|
|
Annual Revenue
|
|
</label>
|
|
<p className="text-gray-900 dark:text-white flex items-center">
|
|
<DollarSign className="w-4 h-4 mr-2" />
|
|
{formatCurrency(vendor.annualRevenue)}
|
|
</p>
|
|
</div>
|
|
)}
|
|
{vendor.employeeCount && (
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
|
|
Employee Count
|
|
</label>
|
|
<p className="text-gray-900 dark:text-white flex items-center">
|
|
<Users className="w-4 h-4 mr-2" />
|
|
{vendor.employeeCount} employees
|
|
</p>
|
|
</div>
|
|
)}
|
|
{vendor.yearsInBusiness && (
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
|
|
Years in Business
|
|
</label>
|
|
<p className="text-gray-900 dark:text-white flex items-center">
|
|
<Calendar className="w-4 h-4 mr-2" />
|
|
{vendor.yearsInBusiness} years
|
|
</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* Address Information */}
|
|
{vendor.address && (
|
|
<div className="space-y-4">
|
|
<h3 className="text-lg font-medium text-gray-900 dark:text-white border-b border-gray-200 dark:border-gray-700 pb-2">
|
|
Address Information
|
|
</h3>
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
|
|
Address
|
|
</label>
|
|
<p className="text-gray-900 dark:text-white flex items-start">
|
|
<MapPin className="w-4 h-4 mr-2 mt-0.5 flex-shrink-0" />
|
|
{vendor.address}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* Additional Information */}
|
|
{(vendor.website || vendor.businessLicense || vendor.taxId || vendor.industry) && (
|
|
<div className="space-y-4">
|
|
<h3 className="text-lg font-medium text-gray-900 dark:text-white border-b border-gray-200 dark:border-gray-700 pb-2">
|
|
Additional Information
|
|
</h3>
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
{vendor.website && (
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
|
|
Website
|
|
</label>
|
|
<p className="text-gray-900 dark:text-white flex items-center">
|
|
<Globe className="w-4 h-4 mr-2" />
|
|
<a href={vendor.website} target="_blank" rel="noopener noreferrer" className="text-blue-600 hover:text-blue-800">
|
|
{vendor.website}
|
|
</a>
|
|
</p>
|
|
</div>
|
|
)}
|
|
{vendor.businessLicense && (
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
|
|
Business License
|
|
</label>
|
|
<p className="text-gray-900 dark:text-white flex items-center">
|
|
<FileText className="w-4 h-4 mr-2" />
|
|
{vendor.businessLicense}
|
|
</p>
|
|
</div>
|
|
)}
|
|
{vendor.taxId && (
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
|
|
Tax ID
|
|
</label>
|
|
<p className="text-gray-900 dark:text-white">
|
|
{vendor.taxId}
|
|
</p>
|
|
</div>
|
|
)}
|
|
{vendor.industry && (
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
|
|
Industry
|
|
</label>
|
|
<p className="text-gray-900 dark:text-white">
|
|
{vendor.industry}
|
|
</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* Rejection Information */}
|
|
{vendor.rejectionReason && (
|
|
<div className="space-y-4">
|
|
<h3 className="text-lg font-medium text-gray-900 dark:text-white border-b border-gray-200 dark:border-gray-700 pb-2">
|
|
Rejection Information
|
|
</h3>
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
|
|
Rejection Reason
|
|
</label>
|
|
<p className="text-gray-900 dark:text-white bg-red-50 dark:bg-red-900/20 p-3 rounded-lg">
|
|
{vendor.rejectionReason}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* Timestamp */}
|
|
<div className="space-y-4">
|
|
<h3 className="text-lg font-medium text-gray-900 dark:text-white border-b border-gray-200 dark:border-gray-700 pb-2">
|
|
Timestamp
|
|
</h3>
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
|
|
Created At
|
|
</label>
|
|
<p className="text-gray-900 dark:text-white flex items-center">
|
|
<Calendar className="w-4 h-4 mr-2" />
|
|
{new Date(vendor.createdAt).toLocaleString()}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Footer */}
|
|
<div className="flex items-center justify-end space-x-3 p-6 border-t border-gray-200 dark:border-gray-700">
|
|
<button
|
|
onClick={onClose}
|
|
className="px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50 dark:bg-gray-700 dark:text-gray-300 dark:border-gray-600 dark:hover:bg-gray-600"
|
|
>
|
|
Close
|
|
</button>
|
|
{vendor.status === 'pending' && (
|
|
<>
|
|
<button
|
|
onClick={() => onReject(vendor.id, '')}
|
|
className="px-4 py-2 text-sm font-medium text-white bg-red-600 border border-transparent rounded-md hover:bg-red-700"
|
|
>
|
|
Reject
|
|
</button>
|
|
<button
|
|
onClick={() => onApprove(vendor.id)}
|
|
className="px-4 py-2 text-sm font-medium text-white bg-green-600 border border-transparent rounded-md hover:bg-green-700"
|
|
>
|
|
Approve
|
|
</button>
|
|
</>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default VendorDetailsModal;
|