@@ -6,28 +6,63 @@ import reportService from '../services/reportService';
66import AppToast from './AppToast' ;
77import { 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
108311export default ReportGeneratorButton ;
0 commit comments