Skip to content

Commit 4daec2f

Browse files
authored
Merge pull request #2628 from AkshataKatwal16/release-prod-fix
Issue feat:Make consent form viewer changes on lmp plp profile and form
2 parents 316ba15 + ec97631 commit 4daec2f

File tree

8 files changed

+404
-33
lines changed

8 files changed

+404
-33
lines changed

apps/learner-web-app/src/components/EditProfile/EditProfile.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ const EditProfile = ({ completeProfile, enrolledProgram, uponEnrollCompletion }:
143143
delete responseFormForEnroll?.schema?.properties?.district;
144144
delete responseFormForEnroll?.schema?.properties?.block;
145145
delete responseFormForEnroll?.schema?.properties?.village;
146+
delete responseFormForEnroll?.schema?.properties?.consent_file;
146147
responseFormForEnroll?.schema?.required?.pop('batch');
147148

148149
const responseFormCopy = JSON.parse(JSON.stringify(responseForm));

apps/learner-web-app/src/components/UserProfileCard/UserProfileCard.tsx

Lines changed: 127 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,24 @@ import {
99
Menu,
1010
MenuItem,
1111
IconButton,
12+
Dialog,
13+
DialogTitle,
14+
DialogContent,
15+
DialogActions,
16+
Button,
1217
} from '@mui/material';
1318
import { useEffect, useState } from 'react';
1419
import settingImage from '../../../public/images/settings.png';
1520
import Image from 'next/image';
1621
import ChevronRightIcon from '@mui/icons-material/ChevronRight';
22+
import VisibilityIcon from '@mui/icons-material/Visibility';
1723
import { useRouter } from 'next/navigation';
1824
import { getUserDetails } from '@learner/utils/API/userService';
1925
import { Loader, useTranslation } from '@shared-lib';
2026
import { isUnderEighteen, toPascalCase } from '@learner/utils/helper';
2127
import { fetchForm } from '@shared-lib-v2/DynamicForm/components/DynamicFormCallback';
2228
import { FormContext } from '@shared-lib-v2/DynamicForm/components/DynamicFormConstant';
29+
import DocumentViewer from '@shared-lib-v2/DynamicForm/components/DocumentViewer/DocumentViewer';
2330

2431
// Helper function to get field value from userData based on schema
2532
const getFieldValue = (fieldName: string, fieldSchema: Record<string, unknown>, userData: Record<string, unknown>, customFields: Array<Record<string, unknown>> = []) => {
@@ -104,6 +111,9 @@ const UserProfileCard = ({ maxWidth = '600px' }) => {
104111
const [formSchema, setFormSchema] = useState<Record<string, unknown> | null>(null); // Form schema state
105112
const { t } = useTranslation();
106113
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
114+
const [previewUrl, setPreviewUrl] = useState<string | null>(null);
115+
const [isPreviewOpen, setIsPreviewOpen] = useState(false);
116+
const [previewTitle, setPreviewTitle] = useState<string>('');
107117

108118
const storedConfig =
109119
typeof window !== 'undefined'
@@ -184,6 +194,39 @@ const UserProfileCard = ({ maxWidth = '600px' }) => {
184194
setAnchorEl(null);
185195
};
186196

197+
const handlePreview = (url: string, title: string) => {
198+
setPreviewUrl(url);
199+
setPreviewTitle(title);
200+
setIsPreviewOpen(true);
201+
};
202+
203+
const handleClosePreview = () => {
204+
setIsPreviewOpen(false);
205+
setPreviewUrl(null);
206+
setPreviewTitle('');
207+
};
208+
209+
// Helper function to check if a field is a file field
210+
const isFileField = (fieldSchema: Record<string, unknown>): boolean => {
211+
return (
212+
fieldSchema?.field_type === 'file_upload' ||
213+
fieldSchema?.field_type === 'file' ||
214+
fieldSchema?.type === 'array' && (fieldSchema?.items as Record<string, unknown>)?.type === 'string' &&
215+
((fieldSchema?.items as Record<string, unknown>)?.format === 'data-url' || (fieldSchema?.items as Record<string, unknown>)?.format === 'uri')
216+
);
217+
};
218+
219+
// Helper function to check if a value is a valid URL
220+
const isValidUrl = (value: unknown): boolean => {
221+
if (typeof value !== 'string') return false;
222+
try {
223+
const url = new URL(value);
224+
return url.protocol === 'http:' || url.protocol === 'https:';
225+
} catch {
226+
return false;
227+
}
228+
};
229+
187230
const handleOpen = (option: string) => {
188231
console.log(option);
189232
if (option === t('LEARNER_APP.USER_PROFILE_CARD.EDIT_PROFILE')) {
@@ -564,13 +607,46 @@ const UserProfileCard = ({ maxWidth = '600px' }) => {
564607
{otherSectionFields.map((field) => {
565608
const fieldTitle = (field.schema.title as string) || field.name;
566609
const labelKey = `FORM.${fieldTitle}`;
610+
const isFile = isFileField(field.schema);
611+
const hasValidUrl = isValidUrl(field.rawValue);
567612

568613
return (
569614
<Grid item xs={6} key={field.name}>
570615
<Typography sx={labelStyle}>
571616
{t(labelKey, { defaultValue: toPascalCase(String(fieldTitle).replace(/_/g, ' ')) })}
572617
</Typography>
573-
<Typography sx={valueStyle}>{t(`FORM.${String(field.value).toUpperCase()}`, { defaultValue: toPascalCase(String(field.value)) })}</Typography>
618+
{isFile && hasValidUrl ? (
619+
<Box
620+
sx={{
621+
display: 'flex',
622+
alignItems: 'center',
623+
gap: 0.5,
624+
cursor: 'pointer',
625+
'&:hover': {
626+
'& .view-text': {
627+
textDecoration: 'underline',
628+
}
629+
}
630+
}}
631+
onClick={() => handlePreview(String(field.rawValue), fieldTitle)}
632+
>
633+
<VisibilityIcon sx={{ fontSize: '1rem', color: 'primary.main' }} />
634+
<Typography
635+
className="view-text"
636+
sx={{
637+
...valueStyle,
638+
color: 'primary.main',
639+
fontWeight: 500
640+
}}
641+
>
642+
{t('VIEW_FILE', { defaultValue: 'View File' })}
643+
</Typography>
644+
</Box>
645+
) : (
646+
<Typography sx={valueStyle}>
647+
{t(`FORM.${String(field.value).toUpperCase()}`, { defaultValue: toPascalCase(String(field.value)) })}
648+
</Typography>
649+
)}
574650
</Grid>
575651
);
576652
})}
@@ -615,6 +691,56 @@ const UserProfileCard = ({ maxWidth = '600px' }) => {
615691
>
616692
Open PDF
617693
</a> */}
694+
695+
{/* File Preview Dialog */}
696+
<Dialog
697+
open={isPreviewOpen}
698+
onClose={handleClosePreview}
699+
maxWidth="lg"
700+
fullWidth
701+
PaperProps={{
702+
sx: {
703+
height: '90vh',
704+
maxHeight: '90vh',
705+
},
706+
}}
707+
>
708+
<DialogTitle>
709+
{t('FILE_PREVIEW', { defaultValue: 'File Preview' })} - {t(`FORM.${previewTitle}`, { defaultValue: toPascalCase(String(previewTitle).replace(/_/g, ' ')) })}
710+
</DialogTitle>
711+
<DialogContent
712+
sx={{
713+
p: 0,
714+
display: 'flex',
715+
flexDirection: 'column',
716+
overflow: 'hidden',
717+
}}
718+
>
719+
{previewUrl && (
720+
<DocumentViewer
721+
url={previewUrl}
722+
width="100%"
723+
height="100%"
724+
showError={true}
725+
showDownloadButton={false}
726+
/>
727+
)}
728+
</DialogContent>
729+
<DialogActions>
730+
<Button onClick={handleClosePreview}>{t('COMMON.CLOSE', { defaultValue: 'Close' })}</Button>
731+
{/* {previewUrl && (
732+
<Button
733+
variant="contained"
734+
href={previewUrl}
735+
download
736+
target="_blank"
737+
rel="noopener noreferrer"
738+
>
739+
{t('COMMON.DOWNLOAD', { defaultValue: 'Download' })}
740+
</Button> */}
741+
742+
</DialogActions>
743+
</Dialog>
618744
</Box>
619745
);
620746
};

apps/teachers/public/locales/en/common.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@
5252
"CLOSE": "Close",
5353
"CANCEL": "Cancel",
5454
"OK": "OK",
55+
"VIEW_FILE": "View File",
56+
"FILE_PREVIEW": "File Preview",
57+
"DOWNLOAD": "Download",
5558
"FROM_TO_DATE": "From - To dates",
5659
"REMOVE": "Remove",
5760
"SEND_REQUEST": "Send Request",

libs/shared-lib-v2/src/DynamicForm/components/DocumentViewer/DocumentViewer.tsx

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,15 @@ interface DocumentViewerProps {
3131
width?: string | number;
3232
height?: string | number;
3333
showError?: boolean;
34+
showDownloadButton?: boolean;
3435
}
3536

3637
const DocumentViewer: React.FC<DocumentViewerProps> = ({
3738
url,
3839
width = '100%',
3940
height = '600px',
4041
showError = true,
42+
showDownloadButton = true,
4143
}) => {
4244
const [loading, setLoading] = useState(true);
4345
const [error, setError] = useState<string | null>(null);
@@ -626,16 +628,18 @@ const DocumentViewer: React.FC<DocumentViewerProps> = ({
626628
</>
627629
)}
628630
</Box>
629-
<IconButton
630-
size="small"
631-
href={url}
632-
download
633-
target="_blank"
634-
rel="noopener noreferrer"
635-
title="Download"
636-
>
637-
<Download />
638-
</IconButton>
631+
{showDownloadButton && (
632+
<IconButton
633+
size="small"
634+
href={url}
635+
download
636+
target="_blank"
637+
rel="noopener noreferrer"
638+
title="Download"
639+
>
640+
<Download />
641+
</IconButton>
642+
)}
639643
</Box>
640644
)}
641645

0 commit comments

Comments
 (0)