Skip to content

Commit f96564f

Browse files
committed
feat: integrate ReportGeneratorButton into PrizeInfoPage for report generation
1 parent 6332e60 commit f96564f

2 files changed

Lines changed: 250 additions & 121 deletions

File tree

src/components/ReportGeneratorButton.tsx

Lines changed: 228 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,28 +6,63 @@ import reportService from '../services/reportService';
66
import AppToast from './AppToast';
77
import { downloadBlob } from '../utils/download';
88

9-
interface ReportGeneratorButtonProps {
9+
type ReportGeneratorModalProps<FormData> = {
10+
show: boolean;
11+
onHide: () => void;
12+
onSubmit: (formData: FormData) => void;
13+
initialFormData?: FormData;
14+
disableSubmit?: boolean;
15+
user: any;
16+
};
17+
18+
type DefaultFormData = { positionTitle: string };
19+
20+
type BaseReportGeneratorButtonProps<FormData> = {
1021
requiredReportType: string;
1122
token: string;
1223
user: any;
13-
buildReportData: (formData: { positionTitle: string }) => any;
24+
buildReportData: (formData: FormData) => any;
25+
getGenerateOptions?: (formData: FormData) => { json?: boolean; contentType?: string };
1426
onReportGenerated?: (blob: Blob) => void;
1527
buttonText?: string;
1628
disabled?: boolean;
17-
}
29+
defaultFormData?: FormData;
30+
};
31+
32+
type DefaultModalProps = BaseReportGeneratorButtonProps<DefaultFormData> & {
33+
renderModal?: undefined;
34+
modalEnabled?: true;
35+
};
1836

19-
const ReportGeneratorButton: React.FC<ReportGeneratorButtonProps> = ({
20-
requiredReportType,
21-
token,
22-
user,
23-
buildReportData,
24-
onReportGenerated,
25-
buttonText = 'Generate Report',
26-
disabled
27-
}) => {
37+
type CustomModalProps<FormData> = BaseReportGeneratorButtonProps<FormData> & {
38+
renderModal: (props: ReportGeneratorModalProps<FormData>) => React.ReactNode;
39+
modalEnabled?: true;
40+
};
41+
42+
type NoModalProps<FormData> = BaseReportGeneratorButtonProps<FormData> & {
43+
modalEnabled: false;
44+
defaultFormData: FormData;
45+
renderModal?: undefined;
46+
};
47+
48+
type ReportGeneratorButtonProps<FormData> =
49+
| DefaultModalProps
50+
| CustomModalProps<FormData>
51+
| NoModalProps<FormData>;
52+
53+
function useReportGenerator<FormData>(props: BaseReportGeneratorButtonProps<FormData>) {
54+
const {
55+
requiredReportType,
56+
token,
57+
user,
58+
buildReportData,
59+
getGenerateOptions,
60+
onReportGenerated,
61+
defaultFormData,
62+
} = props;
2863
const [availableReportTypes, setAvailableReportTypes] = useState<ReportType[]>([]);
2964
const [showReportModal, setShowReportModal] = useState(false);
30-
const [lastPositionTitle, setLastPositionTitle] = useState<string>('');
65+
const [lastFormData, setLastFormData] = useState<FormData | undefined>(defaultFormData);
3166
const [generating, setGenerating] = useState(false);
3267
const [toast, setToast] = useState<{ show: boolean; message: string; bg: 'info' | 'danger' | 'success' }>({ show: false, message: '', bg: 'info' });
3368

@@ -47,12 +82,8 @@ const ReportGeneratorButton: React.FC<ReportGeneratorButtonProps> = ({
4782
fetchReportTypes();
4883
}, [token, requiredReportType]);
4984

50-
const handleGenerateReport = () => {
51-
setShowReportModal(true);
52-
};
53-
54-
const handleReportModalSubmit = async (formData: { positionTitle: string }) => {
55-
setLastPositionTitle(formData.positionTitle);
85+
const handleGenerate = async (formData: FormData) => {
86+
setLastFormData(formData);
5687
setShowReportModal(false);
5788
if (!user || !token) {
5889
setToast({ show: true, message: 'Missing required information to generate report.', bg: 'danger' });
@@ -65,8 +96,9 @@ const ReportGeneratorButton: React.FC<ReportGeneratorButtonProps> = ({
6596
setGenerating(true);
6697
try {
6798
const report = buildReportData(formData);
68-
const mediaType = availableTypeObj.mediaType || 'application/pdf';
69-
const { blob, filename } = await reportService.generate(report, token, requiredReportType, mediaType);
99+
const generateOptions = getGenerateOptions ? getGenerateOptions(formData) : undefined;
100+
const mediaType = availableTypeObj?.mediaType || 'application/pdf';
101+
const { blob, filename } = await reportService.generate(report, token, requiredReportType, mediaType, undefined, generateOptions);
70102
if (onReportGenerated) onReportGenerated(blob);
71103
downloadBlob(blob, filename || `${requiredReportType}.pdf`);
72104
setToast({ show: true, message: 'Report generated and downloaded successfully.', bg: 'success' });
@@ -77,11 +109,70 @@ const ReportGeneratorButton: React.FC<ReportGeneratorButtonProps> = ({
77109
}
78110
};
79111

112+
return {
113+
availableTypeObj,
114+
isReportTypeAvailable,
115+
showReportModal,
116+
setShowReportModal,
117+
lastFormData,
118+
setLastFormData,
119+
generating,
120+
toast,
121+
setToast,
122+
handleGenerate,
123+
};
124+
}
125+
126+
function ReportGeneratorButton(props: DefaultModalProps): React.ReactElement;
127+
function ReportGeneratorButton<FormData>(props: CustomModalProps<FormData> | NoModalProps<FormData>): React.ReactElement;
128+
function ReportGeneratorButton<FormData>(props: ReportGeneratorButtonProps<FormData>): React.ReactElement {
129+
if (props.modalEnabled === false) {
130+
return <NoModalReportGenerator {...props} />;
131+
}
132+
if (props.renderModal) {
133+
return <CustomModalReportGenerator {...props} />;
134+
}
135+
return <DefaultModalReportGenerator {...props} />;
136+
}
137+
138+
function DefaultModalReportGenerator(props: DefaultModalProps) {
139+
const {
140+
requiredReportType,
141+
token,
142+
user,
143+
buildReportData,
144+
getGenerateOptions,
145+
onReportGenerated,
146+
buttonText = 'Generate Report',
147+
disabled,
148+
defaultFormData,
149+
} = props;
150+
const {
151+
isReportTypeAvailable,
152+
showReportModal,
153+
setShowReportModal,
154+
lastFormData,
155+
generating,
156+
toast,
157+
setToast,
158+
handleGenerate,
159+
} = useReportGenerator<DefaultFormData>({
160+
requiredReportType,
161+
token,
162+
user,
163+
buildReportData,
164+
getGenerateOptions,
165+
onReportGenerated,
166+
defaultFormData,
167+
buttonText,
168+
disabled,
169+
});
170+
80171
return (
81172
<>
82173
<Button
83174
variant="success"
84-
onClick={handleGenerateReport}
175+
onClick={() => setShowReportModal(true)}
85176
disabled={generating || !isReportTypeAvailable || disabled}
86177
title={!isReportTypeAvailable ? 'Required report type is not available.' : undefined}
87178
>
@@ -90,8 +181,8 @@ const ReportGeneratorButton: React.FC<ReportGeneratorButtonProps> = ({
90181
<ReportModal
91182
show={showReportModal}
92183
onHide={() => setShowReportModal(false)}
93-
onSubmit={handleReportModalSubmit}
94-
initialPositionTitle={lastPositionTitle}
184+
onSubmit={handleGenerate}
185+
initialPositionTitle={lastFormData?.positionTitle || ''}
95186
preparedByName={'' + (user?.name || '')}
96187
disableSubmit={!isReportTypeAvailable}
97188
/>
@@ -103,6 +194,118 @@ const ReportGeneratorButton: React.FC<ReportGeneratorButtonProps> = ({
103194
/>
104195
</>
105196
);
106-
};
197+
}
198+
199+
function CustomModalReportGenerator<FormData>(props: CustomModalProps<FormData>) {
200+
const {
201+
requiredReportType,
202+
token,
203+
user,
204+
buildReportData,
205+
getGenerateOptions,
206+
onReportGenerated,
207+
buttonText = 'Generate Report',
208+
disabled,
209+
defaultFormData,
210+
renderModal,
211+
} = props;
212+
const {
213+
isReportTypeAvailable,
214+
showReportModal,
215+
setShowReportModal,
216+
lastFormData,
217+
generating,
218+
toast,
219+
setToast,
220+
handleGenerate,
221+
} = useReportGenerator<FormData>({
222+
requiredReportType,
223+
token,
224+
user,
225+
buildReportData,
226+
getGenerateOptions,
227+
onReportGenerated,
228+
defaultFormData,
229+
buttonText,
230+
disabled,
231+
});
232+
233+
return (
234+
<>
235+
<Button
236+
variant="success"
237+
onClick={() => setShowReportModal(true)}
238+
disabled={generating || !isReportTypeAvailable || disabled}
239+
title={!isReportTypeAvailable ? 'Required report type is not available.' : undefined}
240+
>
241+
{buttonText}
242+
</Button>
243+
{renderModal({
244+
show: showReportModal,
245+
onHide: () => setShowReportModal(false),
246+
onSubmit: handleGenerate,
247+
initialFormData: lastFormData ?? defaultFormData,
248+
disableSubmit: !isReportTypeAvailable,
249+
user,
250+
})}
251+
<AppToast
252+
show={toast.show}
253+
message={toast.message}
254+
bg={toast.bg}
255+
onClose={() => setToast(t => ({ ...t, show: false }))}
256+
/>
257+
</>
258+
);
259+
}
260+
261+
function NoModalReportGenerator<FormData>(props: NoModalProps<FormData>) {
262+
const {
263+
requiredReportType,
264+
token,
265+
user,
266+
buildReportData,
267+
getGenerateOptions,
268+
onReportGenerated,
269+
buttonText = 'Generate Report',
270+
disabled,
271+
defaultFormData,
272+
} = props;
273+
const {
274+
isReportTypeAvailable,
275+
generating,
276+
toast,
277+
setToast,
278+
handleGenerate,
279+
} = useReportGenerator<FormData>({
280+
requiredReportType,
281+
token,
282+
user,
283+
buildReportData,
284+
getGenerateOptions,
285+
onReportGenerated,
286+
defaultFormData,
287+
buttonText,
288+
disabled,
289+
});
290+
291+
return (
292+
<>
293+
<Button
294+
variant="success"
295+
onClick={() => handleGenerate(defaultFormData)}
296+
disabled={generating || !isReportTypeAvailable || disabled}
297+
title={!isReportTypeAvailable ? 'Required report type is not available.' : undefined}
298+
>
299+
{buttonText}
300+
</Button>
301+
<AppToast
302+
show={toast.show}
303+
message={toast.message}
304+
bg={toast.bg}
305+
onClose={() => setToast(t => ({ ...t, show: false }))}
306+
/>
307+
</>
308+
);
309+
}
107310

108311
export default ReportGeneratorButton;

0 commit comments

Comments
 (0)