Files
eventify_command_center/src/features/settings/components/GatewayConfigSheet.tsx

220 lines
11 KiB
TypeScript

'use client';
import { useState, useEffect } from 'react';
import { GatewayProvider, GatewayCredentials } from '@/lib/types/settings';
import { Sheet, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle } from '@/components/ui/sheet';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Switch } from '@/components/ui/switch';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { verifyGatewayCredentials, saveGatewayConfig } from '@/lib/actions/payment-settings';
import { toast } from 'sonner';
import { Lock, CheckBase, Loader2, Copy } from 'lucide-react';
import { decrypt } from '@/lib/payment-encryption';
interface GatewayConfigSheetProps {
open: boolean;
onOpenChange: (open: boolean) => void;
provider: GatewayProvider;
initialConfig: GatewayCredentials;
onSave: () => void;
}
export function GatewayConfigSheet({ open, onOpenChange, provider, initialConfig, onSave }: GatewayConfigSheetProps) {
const [config, setConfig] = useState<GatewayCredentials>(initialConfig);
const [loading, setLoading] = useState(false);
const [verifying, setVerifying] = useState(false);
// Reset config when provider changes
useEffect(() => {
// Decrypt sensitive fields for editing
const decrypted = { ...initialConfig };
if (decrypted.salt) decrypted.salt = decrypt(decrypted.salt);
setConfig(decrypted);
}, [provider, initialConfig, open]);
const handleVerify = async () => {
setVerifying(true);
try {
const res = await verifyGatewayCredentials(provider, config);
if (res.success) {
toast.success('Credentials Verified', { description: res.message });
} else {
toast.error('Verification Failed', { description: res.message });
}
} catch (error) {
toast.error('Verification Error');
} finally {
setVerifying(false);
}
};
const handleSave = async () => {
setLoading(true);
try {
const res = await saveGatewayConfig(provider, config);
if (res.success) {
toast.success(`Saved ${provider} configuration`);
onSave();
onOpenChange(false);
} else {
toast.error(res.message);
}
} catch (error) {
toast.error('Failed to save configuration');
} finally {
setLoading(false);
}
};
return (
<Sheet open={open} onOpenChange={onOpenChange}>
<SheetContent className="w-[400px] sm:w-[540px] overflow-y-auto">
<SheetHeader>
<SheetTitle className="flex items-center gap-2 capitalize">
{provider} Configuration
</SheetTitle>
<SheetDescription>
Configure API keys and secrets for {provider}.
</SheetDescription>
</SheetHeader>
<div className="py-6 space-y-6">
{/* Environment Toggle */}
<div className="flex items-center justify-between p-4 border rounded-lg bg-muted/30">
<div className="space-y-0.5">
<Label>Mode</Label>
<div className="text-xs text-muted-foreground">
{config.mode === 'live' ? 'Production / Live Traffic' : 'Sandbox / Test Mode'}
</div>
</div>
<Switch
checked={config.mode === 'live'}
onCheckedChange={(c) => setConfig({ ...config, mode: c ? 'live' : 'test' })}
/>
</div>
<Tabs defaultValue="credentials">
<TabsList className="w-full">
<TabsTrigger value="credentials" className="flex-1">Credentials</TabsTrigger>
<TabsTrigger value="features" className="flex-1">Features</TabsTrigger>
<TabsTrigger value="webhooks" className="flex-1">Webhooks</TabsTrigger>
</TabsList>
<TabsContent value="credentials" className="space-y-4 pt-4">
{/* Dynamic inputs based on provider */}
{(provider === 'razorpay' || provider === 'easebuzz') && (
<div className="space-y-2">
<Label>Key ID / Merchant Key</Label>
<Input
value={config.keyId || config.merchantId || ''}
onChange={(e) => setConfig({ ...config, keyId: e.target.value, merchantId: e.target.value })}
placeholder="rzp_test_..."
/>
</div>
)}
{(provider === 'stripe') && (
<div className="space-y-2">
<Label>Public Key</Label>
<Input
value={config.publicKey || ''}
onChange={(e) => setConfig({ ...config, publicKey: e.target.value })}
placeholder="pk_test_..."
/>
</div>
)}
{(provider === 'payu' || provider === 'easebuzz') && (
<div className="space-y-2">
<Label>Salt / Secret Key</Label>
<div className="relative">
<Input
type="password"
value={config.salt || ''}
onChange={(e) => setConfig({ ...config, salt: e.target.value })}
placeholder="Enter secret salt"
className="pr-10"
/>
<Lock className="absolute right-3 top-3 h-4 w-4 text-muted-foreground" />
</div>
</div>
)}
<Button variant="secondary" className="w-full mt-4" onClick={handleVerify} disabled={verifying}>
{verifying && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
Test Credentials
</Button>
</TabsContent>
<TabsContent value="features" className="space-y-4 pt-4">
<div className="grid grid-cols-2 gap-4">
<div className="flex items-center space-x-2 border p-3 rounded-md">
<Switch
id="feat-nb"
checked={config.features.netbanking}
onCheckedChange={(c) => setConfig({ ...config, features: { ...config.features, netbanking: c } })}
/>
<Label htmlFor="feat-nb">Netbanking</Label>
</div>
<div className="flex items-center space-x-2 border p-3 rounded-md">
<Switch
id="feat-upi"
checked={config.features.upi}
onCheckedChange={(c) => setConfig({ ...config, features: { ...config.features, upi: c } })}
/>
<Label htmlFor="feat-upi">UPI</Label>
</div>
<div className="flex items-center space-x-2 border p-3 rounded-md">
<Switch
id="feat-cards"
checked={config.features.cards}
onCheckedChange={(c) => setConfig({ ...config, features: { ...config.features, cards: c } })}
/>
<Label htmlFor="feat-cards">Cards</Label>
</div>
<div className="flex items-center space-x-2 border p-3 rounded-md">
<Switch
id="feat-emi"
checked={config.features.emi}
onCheckedChange={(c) => setConfig({ ...config, features: { ...config.features, emi: c } })}
/>
<Label htmlFor="feat-emi">EMI</Label>
</div>
</div>
</TabsContent>
<TabsContent value="webhooks" className="space-y-4 pt-4">
<div className="space-y-2">
<Label>Webhook URL</Label>
<div className="flex items-center gap-2">
<Input readOnly value={`https://api.eventify.com/webhooks/${provider}`} />
<Button variant="outline" size="icon">
<Copy className="h-4 w-4" />
</Button>
</div>
<p className="text-xs text-muted-foreground">Add this URL to your provider dashboard.</p>
</div>
<div className="space-y-2">
<Label>Webhook Secret</Label>
<Input
value={config.webhookSecret || ''}
onChange={(e) => setConfig({ ...config, webhookSecret: e.target.value })}
placeholder="whsec_..."
/>
</div>
</TabsContent>
</Tabs>
</div>
<SheetFooter>
<Button onClick={handleSave} disabled={loading} className="w-full sm:w-auto">
{loading ? 'Saving...' : 'Save Configuration'}
</Button>
</SheetFooter>
</SheetContent>
</Sheet>
);
}