initial: standalone repo from monorepo split
This commit is contained in:
60
src/components/modals/transfer-modal.tsx
Normal file
60
src/components/modals/transfer-modal.tsx
Normal file
@@ -0,0 +1,60 @@
|
||||
'use client';
|
||||
|
||||
import { useState, useEffect } from 'react';
|
||||
import { api } from '@/lib/api';
|
||||
import { FormModal } from '@/components/ui/form-modal';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { useToast } from '@/components/ui/toast';
|
||||
|
||||
interface TransferModalProps {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
onSuccess: () => void;
|
||||
}
|
||||
|
||||
export function TransferModal({ open, onClose, onSuccess }: TransferModalProps) {
|
||||
const { toast } = useToast();
|
||||
const [accounts, setAccounts] = useState<any[]>([]);
|
||||
const [form, setForm] = useState({ fromAccountId: '', toAccountId: '', amount: 0, description: '' });
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
const ic = 'mt-1 block w-full rounded-lg border border-surface-200 dark:border-surface-600 bg-white dark:bg-surface-800 px-3.5 py-2.5 text-sm text-surface-900 dark:text-surface-100 placeholder:text-surface-400 dark:placeholder:text-surface-500 focus:border-primary-500 dark:focus:border-primary-400 focus:outline-none focus:ring-2 focus:ring-primary-500/20 transition-all duration-200';
|
||||
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
setForm({ fromAccountId: '', toAccountId: '', amount: 0, description: '' });
|
||||
api.get('/accounts').then((r) => setAccounts(r.data.data)).catch(() => {});
|
||||
}
|
||||
}, [open]);
|
||||
|
||||
const fromAccount = accounts.find((a: any) => a.id === form.fromAccountId);
|
||||
|
||||
async function handleSubmit(e: React.FormEvent) {
|
||||
e.preventDefault(); setSubmitting(true);
|
||||
try { await api.post('/accounts/transfer', { ...form, description: form.description || undefined }); toast('Transfer completed', 'success'); onSuccess(); onClose(); }
|
||||
catch (err: any) { toast(err.response?.data?.error || 'Failed', 'error'); }
|
||||
finally { setSubmitting(false); }
|
||||
}
|
||||
|
||||
return (
|
||||
<FormModal open={open} onClose={onClose} title="Transfer Funds" description="Move funds between company accounts. A journal entry will be created automatically.">
|
||||
<form onSubmit={handleSubmit} className="space-y-4">
|
||||
<div><label className="block text-sm font-medium text-surface-700 dark:text-surface-300">From Account</label>
|
||||
<select required value={form.fromAccountId} onChange={(e) => setForm({ ...form, fromAccountId: e.target.value })} className={ic}>
|
||||
<option value="">Select source...</option>
|
||||
{accounts.map((a: any) => <option key={a.id} value={a.id}>{a.name} (PHP {Number(a.balance).toLocaleString()})</option>)}
|
||||
</select></div>
|
||||
<div><label className="block text-sm font-medium text-surface-700 dark:text-surface-300">To Account</label>
|
||||
<select required value={form.toAccountId} onChange={(e) => setForm({ ...form, toAccountId: e.target.value })} className={ic}>
|
||||
<option value="">Select destination...</option>
|
||||
{accounts.filter((a: any) => a.id !== form.fromAccountId).map((a: any) => <option key={a.id} value={a.id}>{a.name}</option>)}
|
||||
</select></div>
|
||||
<div><label className="block text-sm font-medium text-surface-700 dark:text-surface-300">Amount (PHP) {fromAccount && <span className="text-surface-400 font-normal">Available: {Number(fromAccount.balance).toLocaleString()}</span>}</label>
|
||||
<input type="number" required min={0.01} step={0.01} value={form.amount || ''} onChange={(e) => setForm({ ...form, amount: parseFloat(e.target.value) || 0 })} className={ic} /></div>
|
||||
<div><label className="block text-sm font-medium text-surface-700 dark:text-surface-300">Description <span className="text-surface-400 font-normal">(optional)</span></label>
|
||||
<input type="text" value={form.description} onChange={(e) => setForm({ ...form, description: e.target.value })} className={ic} placeholder="e.g. Weekly GCash to bank transfer" /></div>
|
||||
<div className="flex justify-end gap-3 pt-2"><Button type="button" variant="secondary" onClick={onClose}>Cancel</Button>
|
||||
<Button type="submit" loading={submitting} disabled={!form.fromAccountId || !form.toAccountId || form.amount <= 0}>Transfer</Button></div>
|
||||
</form>
|
||||
</FormModal>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user