Skip to content

Commit 9784525

Browse files
committed
fix: update VoteResultsForm component with improved type definitions
Enhance the VoteResultsForm component by adding a detailed Props interface to improve type safety and clarity. Refactor the form handling logic to use the new interface, ensuring better maintainability and readability. Signed-off-by: Manuel Ruck <git@manuelruck.de>
1 parent d1dbad1 commit 9784525

File tree

2 files changed

+156
-120
lines changed

2 files changed

+156
-120
lines changed

bundestag.io/admin/src/app/layout.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import 'antd/dist/reset.css';
12
import { Navigation } from '@/components/Navigation';
23
import { Layout as AntLayout, Breadcrumb } from 'antd';
34

bundestag.io/admin/src/components/Procedures/VoteResultsForm.tsx

Lines changed: 155 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,25 @@ import { Beschlusstext } from './Beschlusstext';
77
// Ant Design Sub-Elements
88
const FormItem = Form.Item;
99

10+
// Props-Interface
11+
interface VoteResultsFormProps {
12+
data: {
13+
votingDocument?: string;
14+
decisionText?: string;
15+
partyVotes: {
16+
party: string;
17+
main?: 'YES' | 'NO' | 'ABSTINATION' | null;
18+
deviants: { yes: number; abstination: number; no: number };
19+
}[];
20+
votingRecommendation?: boolean;
21+
};
22+
type: string;
23+
procedureId: number;
24+
period: number;
25+
lastPlenaryProtocoll?: { findSpotUrl: string };
26+
title: string;
27+
}
28+
1029
export const getFractions = (period: number) =>
1130
period === 21
1231
? [
@@ -47,19 +66,29 @@ export const getFractions = (period: number) =>
4766
},
4867
];
4968

50-
const VoteResultsForm = ({ data, type, procedureId, period, lastPlenaryProtocoll, title }) => {
69+
// Component-Typisierung und Form-Layout
70+
const VoteResultsForm: React.FC<VoteResultsFormProps> = ({
71+
data,
72+
type,
73+
procedureId,
74+
period,
75+
lastPlenaryProtocoll,
76+
title,
77+
}) => {
78+
// 1. useNotification-Hook
79+
const [notificationApi, contextHolder] = notification.useNotification();
5180
const [form] = Form.useForm();
5281

53-
const onFinish = (values) => {
54-
notification.info({
82+
const onFinish = (values: any) => {
83+
notificationApi.info({
5584
key: 'saveProcedure',
5685
message: 'Vorgang wird gespeichert!',
5786
duration: 0,
5887
});
5988

60-
const data = {
89+
const payload = {
6190
...values,
62-
partyVotes: values.partyVotes.map((party) => ({
91+
partyVotes: values.partyVotes.map((party: any) => ({
6392
party: party.party,
6493
main: party.main,
6594
deviants: {
@@ -72,18 +101,18 @@ const VoteResultsForm = ({ data, type, procedureId, period, lastPlenaryProtocoll
72101

73102
axiosClient
74103
.post('/api/procedures/save', {
75-
...data,
104+
...payload,
76105
toggleDecision: !values.toggleDecision,
77106
procedureId,
78107
})
79108
.then(() => {
80-
notification.success({
109+
notificationApi.success({
81110
key: 'saveProcedure',
82111
message: 'Vorgang wurde gespeichert!',
83112
});
84113
})
85114
.catch((err) => {
86-
notification.error({
115+
notificationApi.error({
87116
key: 'saveProcedure',
88117
message: 'Ein Fehler ist vorgefallen',
89118
// description: err
@@ -93,7 +122,7 @@ const VoteResultsForm = ({ data, type, procedureId, period, lastPlenaryProtocoll
93122
};
94123

95124
const onFinishFailed = () => {
96-
notification.error({
125+
notificationApi.warning({
97126
message: 'Speichern Fehlgeschlagen!',
98127
description: 'Überprüfe deine eingaben',
99128
});
@@ -115,121 +144,127 @@ const VoteResultsForm = ({ data, type, procedureId, period, lastPlenaryProtocoll
115144
};
116145

117146
return (
118-
<Form
119-
form={form}
120-
onFinish={onFinish}
121-
onFinishFailed={onFinishFailed}
122-
className="login-form"
123-
initialValues={{
124-
votingDocument: data.votingDocument,
125-
decisionText: data.decisionText,
126-
partyVotes: parties.map((p, i) => ({
127-
party: p.name,
128-
main: data.partyVotes.length > 0 ? data.partyVotes[i].main : null,
129-
yes: data.partyVotes.length > 0 ? data.partyVotes[i].deviants.yes : 0,
130-
abstination: data.partyVotes.length > 0 ? data.partyVotes[i].deviants.abstination : 0,
131-
no: data.partyVotes.length > 0 ? data.partyVotes[i].deviants.no : 0,
132-
})),
133-
}}
134-
>
135-
<FormItem
136-
label="Abstimmung über"
137-
name="votingDocument"
138-
rules={[{ required: true, message: 'Abstimmung über fehlt!' }]}
139-
>
140-
<Radio.Group>
141-
<Radio.Button value="mainDocument">{type}</Radio.Button>
142-
<Radio.Button value="recommendedDecision">Beschlussempfehlung</Radio.Button>
143-
</Radio.Group>
144-
</FormItem>
145-
<FormItem label="Ergebnis umdrehen" name="toggleDecision">
146-
<Switch defaultChecked={data.votingRecommendation === false} />
147-
</FormItem>
148-
<Beschlusstext pdfUrl={lastPlenaryProtocoll?.findSpotUrl} title={title} />
149-
<FormItem
150-
noStyle
151-
shouldUpdate={(prevValues, currentValues) => prevValues.decisionText !== currentValues.decisionText}
147+
<>
148+
{contextHolder}
149+
<Form
150+
form={form}
151+
layout="vertical"
152+
labelCol={{ span: 8 }}
153+
wrapperCol={{ span: 16 }}
154+
onFinish={onFinish}
155+
onFinishFailed={onFinishFailed}
156+
className="login-form"
157+
initialValues={{
158+
votingDocument: data.votingDocument ?? '',
159+
decisionText: data.decisionText ?? '',
160+
partyVotes: parties.map((p, i) => ({
161+
party: p.name,
162+
main: data.partyVotes.length > 0 ? data.partyVotes[i].main : null,
163+
yes: data.partyVotes.length > 0 ? data.partyVotes[i].deviants.yes : 0,
164+
abstination: data.partyVotes.length > 0 ? data.partyVotes[i].deviants.abstination : 0,
165+
no: data.partyVotes.length > 0 ? data.partyVotes[i].deviants.no : 0,
166+
})),
167+
}}
152168
>
153-
{({ getFieldValue }) => {
154-
if (getFieldValue('decisionText') && period) {
155-
return <AiVotes decision={getFieldValue('decisionText')} period={period} onResult={onAiVoteResult} />;
169+
<FormItem
170+
label="Abstimmung über"
171+
name="votingDocument"
172+
rules={[{ required: true, message: 'Abstimmung über fehlt!' }]}
173+
>
174+
<Radio.Group>
175+
<Radio.Button value="mainDocument">{type}</Radio.Button>
176+
<Radio.Button value="recommendedDecision">Beschlussempfehlung</Radio.Button>
177+
</Radio.Group>
178+
</FormItem>
179+
<Form.Item label="Ergebnis umdrehen" name="toggleDecision" valuePropName="checked">
180+
<Switch />
181+
</Form.Item>
182+
<Beschlusstext pdfUrl={lastPlenaryProtocoll?.findSpotUrl ?? ''} title={title} />
183+
<Form.Item noStyle dependencies={['decisionText']}>
184+
{({ getFieldValue }) =>
185+
getFieldValue('decisionText') && period ? (
186+
<AiVotes decision={getFieldValue('decisionText')} period={period} onResult={onAiVoteResult} />
187+
) : null
156188
}
157-
return null;
158-
}}
159-
</FormItem>
160-
<Form.List name="partyVotes">
161-
{(parties) => {
162-
return (
189+
</Form.Item>
190+
<Form.List name="partyVotes">
191+
{(fields) => (
163192
<Row gutter={8}>
164-
{parties.map((field, i) => {
165-
const mainDecision =
166-
// form.getFieldValue(`partyVotes[${i}].main`) ||
167-
data.partyVotes.length > 0 ? data.partyVotes[i].main : null;
168-
return (
169-
<Col span={8} key={field.name}>
170-
<FormItem name={[field.name, 'party']} rules={[{ required: true, message: 'Beschluss fehlt!' }]}>
171-
<Input readOnly />
172-
</FormItem>
173-
<FormItem
174-
className="collection-create-form_last-form-item"
175-
name={[field.name, 'main']}
176-
rules={[{ required: true, message: 'Beschluss fehlt!' }]}
177-
>
178-
<Radio.Group>
179-
<Radio.Button value="YES" style={{ backgroundColor: '#f6ffed' }}>
180-
Ja
181-
</Radio.Button>
182-
<Radio.Button value="ABSTINATION" style={{ backgroundColor: '#e6f7ff' }}>
183-
Enthaltung
184-
</Radio.Button>
185-
<Radio.Button value="NO" style={{ backgroundColor: '#fff1f0' }}>
186-
Nein
187-
</Radio.Button>
188-
</Radio.Group>
189-
</FormItem>
190-
<FormItem
191-
label="Ja"
192-
name={[field.name, 'yes']}
193-
labelCol={{
194-
xs: { span: 24 },
195-
sm: { span: 8 },
196-
}}
197-
>
198-
<InputNumber min={0} max={999} disabled={mainDecision === 'YES'} />
199-
</FormItem>
200-
<FormItem
201-
label="Enth."
202-
name={[field.name, 'abstination']}
203-
labelCol={{
204-
xs: { span: 24 },
205-
sm: { span: 8 },
206-
}}
207-
>
208-
<InputNumber min={0} max={999} disabled={mainDecision === 'ABSTINATION'} />
209-
</FormItem>
210-
<FormItem
211-
label="Nein"
212-
name={[field.name, 'no']}
213-
labelCol={{
214-
xs: { span: 24 },
215-
sm: { span: 8 },
216-
}}
217-
>
218-
<InputNumber min={0} max={999} disabled={mainDecision === 'NO'} />
219-
</FormItem>
220-
</Col>
221-
);
222-
})}
193+
{fields.map((field) => (
194+
<Col span={8} key={`${field.key ?? field.name}`}>
195+
<Form.Item {...field} name={[field.name, 'party']} rules={[{ required: true }]}>
196+
<Input readOnly />
197+
</Form.Item>
198+
<Form.Item {...field} name={[field.name, 'main']} rules={[{ required: true }]}>
199+
<Radio.Group>
200+
<Radio.Button value="YES" style={{ backgroundColor: '#f6ffed' }}>
201+
Ja
202+
</Radio.Button>
203+
<Radio.Button value="ABSTINATION" style={{ backgroundColor: '#e6f7ff' }}>
204+
Enthaltung
205+
</Radio.Button>
206+
<Radio.Button value="NO" style={{ backgroundColor: '#fff1f0' }}>
207+
Nein
208+
</Radio.Button>
209+
</Radio.Group>
210+
</Form.Item>
211+
<Form.Item
212+
{...field}
213+
label="Ja"
214+
name={[field.name, 'yes']}
215+
labelCol={{
216+
xs: { span: 24 },
217+
sm: { span: 8 },
218+
}}
219+
>
220+
<InputNumber
221+
min={0}
222+
max={999}
223+
disabled={form.getFieldValue(['partyVotes', field.name, 'main']) === 'YES'}
224+
/>
225+
</Form.Item>
226+
<Form.Item
227+
{...field}
228+
label="Enth."
229+
name={[field.name, 'abstination']}
230+
labelCol={{
231+
xs: { span: 24 },
232+
sm: { span: 8 },
233+
}}
234+
>
235+
<InputNumber
236+
min={0}
237+
max={999}
238+
disabled={form.getFieldValue(['partyVotes', field.name, 'main']) === 'ABSTINATION'}
239+
/>
240+
</Form.Item>
241+
<Form.Item
242+
{...field}
243+
label="Nein"
244+
name={[field.name, 'no']}
245+
labelCol={{
246+
xs: { span: 24 },
247+
sm: { span: 8 },
248+
}}
249+
>
250+
<InputNumber
251+
min={0}
252+
max={999}
253+
disabled={form.getFieldValue(['partyVotes', field.name, 'main']) === 'NO'}
254+
/>
255+
</Form.Item>
256+
</Col>
257+
))}
223258
</Row>
224-
);
225-
}}
226-
</Form.List>
227-
<FormItem>
228-
<Button type="primary" htmlType="submit" className="login-form-button">
229-
Speichern
230-
</Button>
231-
</FormItem>
232-
</Form>
259+
)}
260+
</Form.List>
261+
<FormItem>
262+
<Button type="primary" htmlType="submit" className="login-form-button">
263+
Speichern
264+
</Button>
265+
</FormItem>
266+
</Form>
267+
</>
233268
);
234269
};
235270

0 commit comments

Comments
 (0)