174 lines
7.9 KiB
TypeScript
174 lines
7.9 KiB
TypeScript
'use client';
|
|
|
|
import { useState } from 'react';
|
|
import { PartnerConfig } from '@/lib/types/settings';
|
|
import { Button } from '@/components/ui/button';
|
|
import { Input } from '@/components/ui/input';
|
|
import { Label } from '@/components/ui/label';
|
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
|
import { Switch } from '@/components/ui/switch';
|
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
|
import { Checkbox } from '@/components/ui/checkbox';
|
|
import { updateSystemSetting } from '@/lib/actions/settings';
|
|
import { toast } from 'sonner';
|
|
import { Handshake, Banknote, FileCheck } from 'lucide-react';
|
|
|
|
interface PartnerGovernanceProps {
|
|
config: PartnerConfig;
|
|
onUpdate: (data: PartnerConfig) => void;
|
|
}
|
|
|
|
export function PartnerGovernanceTab({ config, onUpdate }: PartnerGovernanceProps) {
|
|
const [loading, setLoading] = useState(false);
|
|
const [state, setState] = useState(config);
|
|
|
|
const handleSave = async () => {
|
|
setLoading(true);
|
|
try {
|
|
const res = await updateSystemSetting('partner', state);
|
|
if (res.success && res.updatedSettings.partner) {
|
|
toast.success('Partner governance rules updated');
|
|
onUpdate(res.updatedSettings.partner);
|
|
}
|
|
} catch (error) {
|
|
toast.error('Failed to update partner settings');
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
const toggleKycDoc = (doc: 'pan' | 'gst' | 'aadhaar' | 'cheque') => {
|
|
const current = state.allowedKycDocs;
|
|
const updated = current.includes(doc)
|
|
? current.filter(d => d !== doc)
|
|
: [...current, doc];
|
|
|
|
setState({ ...state, allowedKycDocs: updated });
|
|
};
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
<div className="grid md:grid-cols-2 gap-6">
|
|
|
|
{/* Onboarding Rules */}
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle className="flex items-center gap-2">
|
|
<Handshake className="h-5 w-5 text-indigo-500" />
|
|
Onboarding & Approval
|
|
</CardTitle>
|
|
<CardDescription>
|
|
Set rules for new organizer accounts and events.
|
|
</CardDescription>
|
|
</CardHeader>
|
|
<CardContent className="space-y-4">
|
|
<div className="flex items-center justify-between py-2 border-b">
|
|
<div className="space-y-0.5">
|
|
<Label>Require KYC Approval</Label>
|
|
<p className="text-xs text-muted-foreground">Block payouts until verified.</p>
|
|
</div>
|
|
<Switch
|
|
checked={state.requireKyc}
|
|
onCheckedChange={(c) => setState({ ...state, requireKyc: c })}
|
|
/>
|
|
</div>
|
|
<div className="flex items-center justify-between py-2">
|
|
<div className="space-y-0.5">
|
|
<Label>Manual Event Approval</Label>
|
|
<p className="text-xs text-muted-foreground">Admins must approve live events.</p>
|
|
</div>
|
|
<Switch
|
|
checked={state.manualEventApproval}
|
|
onCheckedChange={(c) => setState({ ...state, manualEventApproval: c })}
|
|
/>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
{/* Commission Model */}
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle className="flex items-center gap-2">
|
|
<Banknote className="h-5 w-5 text-green-600" />
|
|
Commission & Payouts
|
|
</CardTitle>
|
|
<CardDescription>
|
|
Define the default revenue share model.
|
|
</CardDescription>
|
|
</CardHeader>
|
|
<CardContent className="space-y-4">
|
|
<div className="space-y-2">
|
|
<Label>Default Commission (%)</Label>
|
|
<Input
|
|
type="number"
|
|
value={state.defaultCommissionPercent}
|
|
onChange={(e) => setState({ ...state, defaultCommissionPercent: Number(e.target.value) })}
|
|
/>
|
|
</div>
|
|
<div className="grid grid-cols-2 gap-4">
|
|
<div className="space-y-2">
|
|
<Label>Payout Schedule</Label>
|
|
<Select
|
|
value={state.payoutSchedule}
|
|
onValueChange={(v: any) => setState({ ...state, payoutSchedule: v })}
|
|
>
|
|
<SelectTrigger><SelectValue /></SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="daily">Daily (T+1)</SelectItem>
|
|
<SelectItem value="weekly">Weekly</SelectItem>
|
|
<SelectItem value="monthly">Monthly</SelectItem>
|
|
<SelectItem value="manual">Manual Request</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
<div className="space-y-2">
|
|
<Label>Min. Payout Amount (₹)</Label>
|
|
<Input
|
|
type="number"
|
|
value={state.minPayoutAmount}
|
|
onChange={(e) => setState({ ...state, minPayoutAmount: Number(e.target.value) })}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
|
|
{/* KYC Requirements */}
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle className="flex items-center gap-2">
|
|
<FileCheck className="h-5 w-5 text-slate-500" />
|
|
KYC Requirements
|
|
</CardTitle>
|
|
<CardDescription>
|
|
Select documents required for organizer verification.
|
|
</CardDescription>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
|
{['pan', 'gst', 'aadhaar', 'cheque'].map((doc) => (
|
|
<div key={doc} className="flex items-center space-x-2 border p-3 rounded-md">
|
|
<Checkbox
|
|
id={`doc-${doc}`}
|
|
checked={state.allowedKycDocs.includes(doc as any)}
|
|
onCheckedChange={() => toggleKycDoc(doc as any)}
|
|
/>
|
|
<Label htmlFor={`doc-${doc}`} className="uppercase text-xs font-semibold">
|
|
{doc}
|
|
</Label>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
<div className="flex justify-end">
|
|
<Button onClick={handleSave} disabled={loading}>
|
|
{loading ? 'Saving...' : 'Update Governance Rules'}
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|