Skip to content

Commit 3fd4f2a

Browse files
committed
feat: fill 18 missing frontend TSX pages identified in final audit
Closes all gaps found between controller Inertia::render() calls and their corresponding page components: Finance (8): Currencies/Create, Currencies/Edit, Reports/AgedPayablesSummary, AgedReceivablesSummary, ExpenseSummary, InvoiceSummary, ProfitLossSummary, VendorBills/Create HR (1): Employees/Onboardings/Create Inventory (3): CycleCounts/Create, WarehouseStock/Show, Warranties/Edit KnowledgeBase (2): Categories, Search Manufacturing (1): WorkCenters/Show PM (1): Tasks/Index Subscriptions (2): Metrics, Plans Frontend coverage: 705 TSX pages. All 2279 tests pass. Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 0868a14 commit 3fd4f2a

18 files changed

Lines changed: 3093 additions & 0 deletions

File tree

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
import { Head, Link, useForm } from '@inertiajs/react';
2+
import AppLayout from '@/Layouts/AppLayout';
3+
import { Button } from '@/Components/Common/Button';
4+
import type { PageProps } from '@/types';
5+
6+
interface Props extends PageProps {}
7+
8+
export default function CurrencyCreate(_props: Props) {
9+
const { data, setData, post, processing, errors } = useForm({
10+
code: '',
11+
name: '',
12+
symbol: '',
13+
decimal_places: 2,
14+
rounding: 0,
15+
is_base: false,
16+
is_active: true,
17+
});
18+
19+
function handleSubmit(e: React.FormEvent) {
20+
e.preventDefault();
21+
post('/finance/currencies');
22+
}
23+
24+
const inputClass =
25+
'mt-1 w-full rounded-md border border-slate-300 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-indigo-500';
26+
27+
return (
28+
<AppLayout>
29+
<Head title="Add Currency" />
30+
<div className="mx-auto max-w-lg space-y-6">
31+
<div className="flex items-center justify-between">
32+
<div>
33+
<p className="text-sm text-slate-500">
34+
<Link href="/finance/currencies" className="text-indigo-600 hover:underline">
35+
Currencies
36+
</Link>{' '}
37+
&rsaquo; New Currency
38+
</p>
39+
<h1 className="mt-1 text-2xl font-semibold text-slate-900">Add Currency</h1>
40+
</div>
41+
</div>
42+
43+
<div className="rounded-lg border border-slate-200 bg-white p-6 shadow-sm">
44+
<form onSubmit={handleSubmit} className="space-y-4">
45+
<div>
46+
<label className="block text-sm font-medium text-slate-700">
47+
ISO Code <span className="text-red-500">*</span>
48+
</label>
49+
<input
50+
type="text"
51+
maxLength={3}
52+
value={data.code}
53+
onChange={(e) => setData('code', e.target.value.toUpperCase())}
54+
placeholder="USD"
55+
className={inputClass}
56+
required
57+
/>
58+
{errors.code && <p className="mt-1 text-xs text-red-600">{errors.code}</p>}
59+
</div>
60+
61+
<div>
62+
<label className="block text-sm font-medium text-slate-700">
63+
Name <span className="text-red-500">*</span>
64+
</label>
65+
<input
66+
type="text"
67+
value={data.name}
68+
onChange={(e) => setData('name', e.target.value)}
69+
placeholder="US Dollar"
70+
className={inputClass}
71+
required
72+
/>
73+
{errors.name && <p className="mt-1 text-xs text-red-600">{errors.name}</p>}
74+
</div>
75+
76+
<div>
77+
<label className="block text-sm font-medium text-slate-700">
78+
Symbol <span className="text-red-500">*</span>
79+
</label>
80+
<input
81+
type="text"
82+
maxLength={10}
83+
value={data.symbol}
84+
onChange={(e) => setData('symbol', e.target.value)}
85+
placeholder="$"
86+
className={inputClass}
87+
required
88+
/>
89+
{errors.symbol && <p className="mt-1 text-xs text-red-600">{errors.symbol}</p>}
90+
</div>
91+
92+
<div className="grid grid-cols-2 gap-4">
93+
<div>
94+
<label className="block text-sm font-medium text-slate-700">Decimal Places</label>
95+
<input
96+
type="number"
97+
min={0}
98+
max={4}
99+
value={data.decimal_places}
100+
onChange={(e) => setData('decimal_places', Number(e.target.value))}
101+
className={inputClass}
102+
/>
103+
{errors.decimal_places && (
104+
<p className="mt-1 text-xs text-red-600">{errors.decimal_places}</p>
105+
)}
106+
</div>
107+
108+
<div>
109+
<label className="block text-sm font-medium text-slate-700">Rounding</label>
110+
<input
111+
type="number"
112+
min={0}
113+
step="0.01"
114+
value={data.rounding}
115+
onChange={(e) => setData('rounding', Number(e.target.value))}
116+
className={inputClass}
117+
/>
118+
{errors.rounding && (
119+
<p className="mt-1 text-xs text-red-600">{errors.rounding}</p>
120+
)}
121+
</div>
122+
</div>
123+
124+
<div className="space-y-2">
125+
<label className="flex items-center gap-2 text-sm text-slate-700">
126+
<input
127+
type="checkbox"
128+
checked={data.is_base}
129+
onChange={(e) => setData('is_base', e.target.checked)}
130+
className="h-4 w-4 rounded border-slate-300 text-indigo-600"
131+
/>
132+
Set as base currency
133+
</label>
134+
<label className="flex items-center gap-2 text-sm text-slate-700">
135+
<input
136+
type="checkbox"
137+
checked={data.is_active}
138+
onChange={(e) => setData('is_active', e.target.checked)}
139+
className="h-4 w-4 rounded border-slate-300 text-indigo-600"
140+
/>
141+
Active
142+
</label>
143+
</div>
144+
145+
<div className="flex gap-3 pt-2">
146+
<Button type="submit" disabled={processing}>
147+
{processing ? 'Creating...' : 'Create Currency'}
148+
</Button>
149+
<Link href="/finance/currencies">
150+
<Button variant="secondary" type="button">
151+
Cancel
152+
</Button>
153+
</Link>
154+
</div>
155+
</form>
156+
</div>
157+
</div>
158+
</AppLayout>
159+
);
160+
}
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
import { Head, Link, useForm } from '@inertiajs/react';
2+
import AppLayout from '@/Layouts/AppLayout';
3+
import { Button } from '@/Components/Common/Button';
4+
import type { PageProps } from '@/types';
5+
import type { Currency } from '@/types/finance';
6+
7+
interface Props extends PageProps {
8+
currency: Currency;
9+
}
10+
11+
export default function CurrencyEdit({ currency }: Props) {
12+
const { data, setData, put, processing, errors } = useForm({
13+
code: currency.code ?? '',
14+
name: currency.name ?? '',
15+
symbol: currency.symbol ?? '',
16+
decimal_places: currency.decimal_places ?? 2,
17+
rounding: currency.rounding ?? 0,
18+
is_base: currency.is_base ?? false,
19+
is_active: currency.is_active ?? true,
20+
});
21+
22+
function handleSubmit(e: React.FormEvent) {
23+
e.preventDefault();
24+
put(`/finance/currencies/${currency.id}`);
25+
}
26+
27+
const inputClass =
28+
'mt-1 w-full rounded-md border border-slate-300 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-indigo-500';
29+
30+
return (
31+
<AppLayout>
32+
<Head title={`Edit Currency — ${currency.code}`} />
33+
<div className="mx-auto max-w-lg space-y-6">
34+
<div className="flex items-center justify-between">
35+
<div>
36+
<p className="text-sm text-slate-500">
37+
<Link href="/finance/currencies" className="text-indigo-600 hover:underline">
38+
Currencies
39+
</Link>{' '}
40+
&rsaquo; Edit
41+
</p>
42+
<h1 className="mt-1 text-2xl font-semibold text-slate-900">Edit Currency — {currency.code}</h1>
43+
</div>
44+
</div>
45+
46+
<div className="rounded-lg border border-slate-200 bg-white p-6 shadow-sm">
47+
<form onSubmit={handleSubmit} className="space-y-4">
48+
<div>
49+
<label className="block text-sm font-medium text-slate-700">
50+
ISO Code <span className="text-red-500">*</span>
51+
</label>
52+
<input
53+
type="text"
54+
maxLength={3}
55+
value={data.code}
56+
onChange={(e) => setData('code', e.target.value.toUpperCase())}
57+
className={inputClass}
58+
required
59+
/>
60+
{errors.code && <p className="mt-1 text-xs text-red-600">{errors.code}</p>}
61+
</div>
62+
63+
<div>
64+
<label className="block text-sm font-medium text-slate-700">
65+
Name <span className="text-red-500">*</span>
66+
</label>
67+
<input
68+
type="text"
69+
value={data.name}
70+
onChange={(e) => setData('name', e.target.value)}
71+
className={inputClass}
72+
required
73+
/>
74+
{errors.name && <p className="mt-1 text-xs text-red-600">{errors.name}</p>}
75+
</div>
76+
77+
<div>
78+
<label className="block text-sm font-medium text-slate-700">
79+
Symbol <span className="text-red-500">*</span>
80+
</label>
81+
<input
82+
type="text"
83+
maxLength={10}
84+
value={data.symbol}
85+
onChange={(e) => setData('symbol', e.target.value)}
86+
className={inputClass}
87+
required
88+
/>
89+
{errors.symbol && <p className="mt-1 text-xs text-red-600">{errors.symbol}</p>}
90+
</div>
91+
92+
<div className="grid grid-cols-2 gap-4">
93+
<div>
94+
<label className="block text-sm font-medium text-slate-700">Decimal Places</label>
95+
<input
96+
type="number"
97+
min={0}
98+
max={4}
99+
value={data.decimal_places}
100+
onChange={(e) => setData('decimal_places', Number(e.target.value))}
101+
className={inputClass}
102+
/>
103+
{errors.decimal_places && (
104+
<p className="mt-1 text-xs text-red-600">{errors.decimal_places}</p>
105+
)}
106+
</div>
107+
108+
<div>
109+
<label className="block text-sm font-medium text-slate-700">Rounding</label>
110+
<input
111+
type="number"
112+
min={0}
113+
step="0.01"
114+
value={data.rounding}
115+
onChange={(e) => setData('rounding', Number(e.target.value))}
116+
className={inputClass}
117+
/>
118+
{errors.rounding && (
119+
<p className="mt-1 text-xs text-red-600">{errors.rounding}</p>
120+
)}
121+
</div>
122+
</div>
123+
124+
<div className="space-y-2">
125+
<label className="flex items-center gap-2 text-sm text-slate-700">
126+
<input
127+
type="checkbox"
128+
checked={data.is_base}
129+
onChange={(e) => setData('is_base', e.target.checked)}
130+
className="h-4 w-4 rounded border-slate-300 text-indigo-600"
131+
/>
132+
Set as base currency
133+
</label>
134+
<label className="flex items-center gap-2 text-sm text-slate-700">
135+
<input
136+
type="checkbox"
137+
checked={data.is_active}
138+
onChange={(e) => setData('is_active', e.target.checked)}
139+
className="h-4 w-4 rounded border-slate-300 text-indigo-600"
140+
/>
141+
Active
142+
</label>
143+
</div>
144+
145+
<div className="flex gap-3 pt-2">
146+
<Button type="submit" disabled={processing}>
147+
{processing ? 'Saving...' : 'Save Changes'}
148+
</Button>
149+
<Link href="/finance/currencies">
150+
<Button variant="secondary" type="button">
151+
Cancel
152+
</Button>
153+
</Link>
154+
</div>
155+
</form>
156+
</div>
157+
</div>
158+
</AppLayout>
159+
);
160+
}

0 commit comments

Comments
 (0)