feat: add Review Management module and UI layout fixes
This commit is contained in:
173
src/features/settings/components/tabs/PartnerGovernance.tsx
Normal file
173
src/features/settings/components/tabs/PartnerGovernance.tsx
Normal file
@@ -0,0 +1,173 @@
|
||||
'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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user