256 lines
10 KiB
JavaScript
256 lines
10 KiB
JavaScript
import React, { useState, useEffect } from "react";
|
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
|
import { Button } from "@/components/ui/button";
|
|
import { Input } from "@/components/ui/input";
|
|
import { Label } from "@/components/ui/label";
|
|
import { Badge } from "@/components/ui/badge";
|
|
import { Switch } from "@/components/ui/switch";
|
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
|
import { Save, Loader2, Link2, Building2, FileText, Mail, CheckCircle, AlertCircle } from "lucide-react";
|
|
|
|
const ERP_SYSTEMS = [
|
|
{ value: "None", label: "No ERP Integration" },
|
|
{ value: "SAP Ariba", label: "SAP Ariba" },
|
|
{ value: "Fieldglass", label: "SAP Fieldglass" },
|
|
{ value: "CrunchTime", label: "CrunchTime" },
|
|
{ value: "Coupa", label: "Coupa" },
|
|
{ value: "Oracle NetSuite", label: "Oracle NetSuite" },
|
|
{ value: "Workday", label: "Workday" },
|
|
{ value: "Other", label: "Other" },
|
|
];
|
|
|
|
const EDI_FORMATS = [
|
|
{ value: "CSV", label: "CSV (Excel Compatible)" },
|
|
{ value: "EDI 810", label: "EDI 810 (Standard Invoice)" },
|
|
{ value: "cXML", label: "cXML (Ariba/Coupa)" },
|
|
{ value: "JSON", label: "JSON (API Format)" },
|
|
{ value: "Custom", label: "Custom Template" },
|
|
];
|
|
|
|
export default function ERPSettingsTab({ business, onSave, isSaving }) {
|
|
const [settings, setSettings] = useState({
|
|
erp_system: business?.erp_system || "None",
|
|
erp_vendor_id: business?.erp_vendor_id || "",
|
|
erp_cost_center: business?.erp_cost_center || "",
|
|
edi_enabled: business?.edi_enabled || false,
|
|
edi_format: business?.edi_format || "CSV",
|
|
invoice_email: business?.invoice_email || "",
|
|
po_required: business?.po_required || false,
|
|
});
|
|
|
|
useEffect(() => {
|
|
if (business) {
|
|
setSettings({
|
|
erp_system: business.erp_system || "None",
|
|
erp_vendor_id: business.erp_vendor_id || "",
|
|
erp_cost_center: business.erp_cost_center || "",
|
|
edi_enabled: business.edi_enabled || false,
|
|
edi_format: business.edi_format || "CSV",
|
|
invoice_email: business.invoice_email || "",
|
|
po_required: business.po_required || false,
|
|
});
|
|
}
|
|
}, [business]);
|
|
|
|
const handleChange = (field, value) => {
|
|
setSettings(prev => ({ ...prev, [field]: value }));
|
|
};
|
|
|
|
const handleSubmit = () => {
|
|
onSave(settings);
|
|
};
|
|
|
|
const isConfigured = settings.erp_system !== "None" && settings.erp_vendor_id;
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
{/* Status Card */}
|
|
<Card className={`border-2 ${isConfigured ? 'border-green-200 bg-green-50' : 'border-amber-200 bg-amber-50'}`}>
|
|
<CardContent className="p-4">
|
|
<div className="flex items-center gap-3">
|
|
{isConfigured ? (
|
|
<CheckCircle className="w-6 h-6 text-green-600" />
|
|
) : (
|
|
<AlertCircle className="w-6 h-6 text-amber-600" />
|
|
)}
|
|
<div>
|
|
<p className={`font-semibold ${isConfigured ? 'text-green-900' : 'text-amber-900'}`}>
|
|
{isConfigured ? 'ERP Integration Active' : 'ERP Integration Not Configured'}
|
|
</p>
|
|
<p className={`text-sm ${isConfigured ? 'text-green-700' : 'text-amber-700'}`}>
|
|
{isConfigured
|
|
? `Connected to ${settings.erp_system} • Vendor ID: ${settings.erp_vendor_id}`
|
|
: 'Configure ERP settings to enable automated invoice delivery'}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
{/* ERP System Settings */}
|
|
<Card className="border-slate-200 shadow-lg">
|
|
<CardHeader className="bg-slate-50 border-b border-slate-200">
|
|
<CardTitle className="flex items-center gap-2 text-slate-900">
|
|
<Building2 className="w-5 h-5 text-blue-600" />
|
|
ERP System Configuration
|
|
</CardTitle>
|
|
</CardHeader>
|
|
<CardContent className="p-6 space-y-6">
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
<div className="space-y-2">
|
|
<Label className="text-slate-700 font-medium">ERP System</Label>
|
|
<Select
|
|
value={settings.erp_system}
|
|
onValueChange={(value) => handleChange('erp_system', value)}
|
|
>
|
|
<SelectTrigger className="border-slate-200">
|
|
<SelectValue placeholder="Select ERP system" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
{ERP_SYSTEMS.map(erp => (
|
|
<SelectItem key={erp.value} value={erp.value}>{erp.label}</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
<p className="text-xs text-slate-500">Client's procurement or ERP system</p>
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<Label className="text-slate-700 font-medium">Vendor ID in ERP</Label>
|
|
<Input
|
|
value={settings.erp_vendor_id}
|
|
onChange={(e) => handleChange('erp_vendor_id', e.target.value)}
|
|
placeholder="e.g., VND-12345"
|
|
className="border-slate-200"
|
|
/>
|
|
<p className="text-xs text-slate-500">Your vendor identifier in client's system</p>
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<Label className="text-slate-700 font-medium">Default Cost Center</Label>
|
|
<Input
|
|
value={settings.erp_cost_center}
|
|
onChange={(e) => handleChange('erp_cost_center', e.target.value)}
|
|
placeholder="e.g., CC-1001"
|
|
className="border-slate-200"
|
|
/>
|
|
<p className="text-xs text-slate-500">Default cost center for invoice allocation</p>
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<Label className="text-slate-700 font-medium">Invoice Delivery Email</Label>
|
|
<Input
|
|
type="email"
|
|
value={settings.invoice_email}
|
|
onChange={(e) => handleChange('invoice_email', e.target.value)}
|
|
placeholder="ap@client.com"
|
|
className="border-slate-200"
|
|
/>
|
|
<p className="text-xs text-slate-500">Accounts payable email for invoice delivery</p>
|
|
</div>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
{/* EDI Settings */}
|
|
<Card className="border-slate-200 shadow-lg">
|
|
<CardHeader className="bg-slate-50 border-b border-slate-200">
|
|
<CardTitle className="flex items-center gap-2 text-slate-900">
|
|
<Link2 className="w-5 h-5 text-purple-600" />
|
|
EDI / Export Settings
|
|
</CardTitle>
|
|
</CardHeader>
|
|
<CardContent className="p-6 space-y-6">
|
|
<div className="flex items-center justify-between p-4 bg-slate-50 rounded-lg">
|
|
<div>
|
|
<p className="font-medium text-slate-900">Enable EDI Integration</p>
|
|
<p className="text-sm text-slate-500">Automatically format invoices for EDI transmission</p>
|
|
</div>
|
|
<Switch
|
|
checked={settings.edi_enabled}
|
|
onCheckedChange={(checked) => handleChange('edi_enabled', checked)}
|
|
/>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
<div className="space-y-2">
|
|
<Label className="text-slate-700 font-medium">Preferred Export Format</Label>
|
|
<Select
|
|
value={settings.edi_format}
|
|
onValueChange={(value) => handleChange('edi_format', value)}
|
|
>
|
|
<SelectTrigger className="border-slate-200">
|
|
<SelectValue placeholder="Select format" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
{EDI_FORMATS.map(format => (
|
|
<SelectItem key={format.value} value={format.value}>{format.label}</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
<p className="text-xs text-slate-500">Default format for invoice exports</p>
|
|
</div>
|
|
|
|
<div className="flex items-center justify-between p-4 bg-slate-50 rounded-lg h-fit">
|
|
<div>
|
|
<p className="font-medium text-slate-900">PO Required</p>
|
|
<p className="text-sm text-slate-500">Require PO number on invoices</p>
|
|
</div>
|
|
<Switch
|
|
checked={settings.po_required}
|
|
onCheckedChange={(checked) => handleChange('po_required', checked)}
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Format Info */}
|
|
<div className="p-4 bg-blue-50 rounded-lg border border-blue-200">
|
|
<h4 className="font-semibold text-blue-900 mb-2 flex items-center gap-2">
|
|
<FileText className="w-4 h-4" />
|
|
Supported Formats
|
|
</h4>
|
|
<div className="grid grid-cols-2 md:grid-cols-4 gap-3 text-sm">
|
|
<div className="flex items-center gap-2">
|
|
<Badge className="bg-green-100 text-green-700">EDI 810</Badge>
|
|
<span className="text-blue-700">Standard</span>
|
|
</div>
|
|
<div className="flex items-center gap-2">
|
|
<Badge className="bg-purple-100 text-purple-700">cXML</Badge>
|
|
<span className="text-blue-700">Ariba/Coupa</span>
|
|
</div>
|
|
<div className="flex items-center gap-2">
|
|
<Badge className="bg-orange-100 text-orange-700">CSV</Badge>
|
|
<span className="text-blue-700">Excel</span>
|
|
</div>
|
|
<div className="flex items-center gap-2">
|
|
<Badge className="bg-slate-100 text-slate-700">JSON</Badge>
|
|
<span className="text-blue-700">API</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
{/* Save Button */}
|
|
<div className="flex justify-end">
|
|
<Button
|
|
onClick={handleSubmit}
|
|
disabled={isSaving}
|
|
className="bg-blue-600 hover:bg-blue-700 text-white px-8"
|
|
>
|
|
{isSaving ? (
|
|
<>
|
|
<Loader2 className="w-4 h-4 mr-2 animate-spin" />
|
|
Saving...
|
|
</>
|
|
) : (
|
|
<>
|
|
<Save className="w-4 h-4 mr-2" />
|
|
Save ERP Settings
|
|
</>
|
|
)}
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
);
|
|
} |