Skip to content

Commit

Permalink
COM-3854: manon's review
Browse files Browse the repository at this point in the history
  • Loading branch information
ulysseferreira committed Dec 20, 2024
1 parent b90cd6c commit 1d63377
Show file tree
Hide file tree
Showing 8 changed files with 56 additions and 70 deletions.
19 changes: 7 additions & 12 deletions src/components/learnerPendingActions/AttendanceSheetCell/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,14 @@ const AttendanceSheetCell = ({ attendanceSheet }: AttendanceSheetCellProps) => {
const setGroupedSlotsToBeSigned = useSetGroupedSlotsToBeSigned();

const goToSignature = () => {
if (course?.subProgram.steps) {
const groupedSlots = groupBy(attendanceSheet.slots, 'step');
const groupedSlotsToBeSigned = course?.subProgram.steps
.map(s => s._id).reduce<Record<string, SlotType[]>>((acc, step) => {
if (groupedSlots[step]) {
acc[step] = groupedSlots[step];
}
return acc;
}, {});
const groupedSlots = groupBy(attendanceSheet.slots, 'step');
const groupedSlotsToBeSigned = course?.subProgram.steps.reduce<Record<string, SlotType[]>>((acc, step) => {
if (groupedSlots[step._id]) acc[step.name] = groupedSlots[step._id];
return acc;
}, {});

setGroupedSlotsToBeSigned(groupedSlotsToBeSigned);
navigation.navigate('UpdateAttendanceSheet', { attendanceSheetId: attendanceSheet._id });
}
setGroupedSlotsToBeSigned(groupedSlotsToBeSigned!);
navigation.navigate('UpdateAttendanceSheet', { attendanceSheetId: attendanceSheet._id });
};
return (
<View style={styles.container}>
Expand Down
6 changes: 2 additions & 4 deletions src/screens/courses/profile/AdminCourseProfile/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,8 @@ const AdminCourseProfile = ({ route, navigation }: AdminCourseProfileProps) => {

const groupedSlots = groupBy(course.slots.filter(slot => !signedSlots.includes(slot._id)), 'step');

return course?.subProgram.steps.map(s => s._id).reduce<Record<string, SlotType[]>>((acc, step) => {
if (groupedSlots[step]) {
acc[step] = groupedSlots[step];
}
return course?.subProgram.steps.reduce<Record<string, SlotType[]>>((acc, step) => {
if (groupedSlots[step._id]) acc[step.name] = groupedSlots[step._id];
return acc;
}, {});
}, [course, isSingle, savedAttendanceSheets]);
Expand Down
27 changes: 4 additions & 23 deletions src/screens/courses/profile/CreateAttendanceSheet/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { useCallback, useEffect, useMemo, useReducer, useState } from 'react';
import { createStackNavigator, StackScreenProps } from '@react-navigation/stack';
import { CompositeScreenProps } from '@react-navigation/native';
import keyBy from 'lodash/keyBy';
import AttendanceSheets from '../../../../api/attendanceSheets';
import { RootStackParamList, RootCreateAttendanceSheetParamList } from '../../../../types/NavigationType';
import { INTER_B2B, DD_MM_YYYY, HH_MM, IS_WEB } from '../../../../core/data/constants';
import { INTER_B2B, DD_MM_YYYY, HH_MM } from '../../../../core/data/constants';
import { errorReducer, initialErrorState, RESET_ERROR, SET_ERROR } from '../../../../reducers/error';
import AttendanceSheetSelectionForm from '../../../../components/AttendanceSheetSelectionForm';
import UploadMethods from '../../../../components/UploadMethods';
Expand All @@ -22,6 +21,7 @@ import MultipleCheckboxList from '../../../../components/form/MultipleCheckboxLi
import AttendanceSignatureContainer from '../../../../components/AttendanceSignatureContainer';
import AttendanceSheetSummary from '../../../../components/AttendanceSheetSummary';
import AttendanceEndScreen from '../../../../components/AttendanceEndScreen';
import { generateFile } from '../helper';

interface CreateAttendanceSheetProps extends CompositeScreenProps<
StackScreenProps<RootStackParamList, 'CreateAttendanceSheet'>,
Expand Down Expand Up @@ -54,10 +54,7 @@ const CreateAttendanceSheet = ({ route, navigation }: CreateAttendanceSheetProps
const [errorSlots, dispatchErrorSlots] = useReducer(errorReducer, initialErrorState);
const [errorSignature, dispatchErrorSignature] = useReducer(errorReducer, initialErrorState);
const [errorConfirmation, dispatchErrorConfirmation] = useReducer(errorReducer, initialErrorState);
const stepsById = useMemo(() => keyBy(course?.subProgram.steps, '_id'), [course]);
const stepsName = useMemo(() =>
Object.keys(groupedSlotsToBeSigned).map(stepId => (stepsById[stepId].name)),
[groupedSlotsToBeSigned, stepsById]);
const stepsName = useMemo(() => Object.keys(groupedSlotsToBeSigned), [groupedSlotsToBeSigned]);
const slotsOptions = useMemo(() =>
Object.values(groupedSlotsToBeSigned)
.map(slotGroup => [...slotGroup]
Expand Down Expand Up @@ -137,26 +134,10 @@ const CreateAttendanceSheet = ({ route, navigation }: CreateAttendanceSheetProps
}
};

const base64ToBlob = (base64Data: string, contentType: string) => {
const byteCharacters = atob(base64Data.split(',')[1]);
const byteNumbers = new Array(byteCharacters.length);
for (let i = 0; i < byteCharacters.length; i += 1) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);

return new Blob([byteArray], { type: contentType });
};

const saveAttendances = async () => {
try {
setIsLoading(true);
let file;
const contentType = 'image/png';
if (IS_WEB) {
const blob = base64ToBlob(signature, contentType);
file = new File([blob], `trainer_signature_${course?._id}.png`, { type: contentType });
} else file = { uri: signature, type: contentType, name: `trainer_signature_${course?._id}` };
const file = generateFile(signature, course?._id, 'trainer');
const data = formatPayload({
signature: file,
course: course?._id,
Expand Down
16 changes: 12 additions & 4 deletions src/screens/courses/profile/LearnerCourseProfile/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import commonStyles from '../../../../styles/common';
import { CourseType, BlendedCourseType, ELearningProgramType } from '../../../../types/CourseTypes';
import styles from '../styles';
import { useGetLoggedUserId, useSetStatusBarVisible } from '../../../../store/main/hooks';
import { useSetCourse } from '../../../../store/attendanceSheets/hooks';
import { useSetCourse, useResetAttendanceSheetReducer } from '../../../../store/attendanceSheets/hooks';
import ProgressBar from '../../../../components/cards/ProgressBar';
import NiSecondaryButton from '../../../../components/form/SecondaryButton';
import PendingActionsContainer from '../../../../components/learnerPendingActions/PendingActionsContainer';
Expand All @@ -56,6 +56,7 @@ const LearnerCourseProfile = ({ route, navigation }: LearnerCourseProfileProps)
const setStatusBarVisible = useSetStatusBarVisible();
const userId: string | null = useGetLoggedUserId();
const setCourseToStore = useSetCourse();
const resetAttendanceSheetReducer = useResetAttendanceSheetReducer();

const [course, setCourse] = useState<CourseType | null>(null);
const [questionnaires, setQuestionnaires] = useState<QuestionnaireType[]>([]);
Expand Down Expand Up @@ -83,10 +84,10 @@ const LearnerCourseProfile = ({ route, navigation }: LearnerCourseProfileProps)
if (fetchedCourse.format === BLENDED) {
const formattedCourse = {
_id: fetchedCourse._id,
trainer: { identity: (fetchedCourse as BlendedCourseType).trainer.identity },
trainer: { identity: get(fetchedCourse, 'trainer.identity') || {} },
subProgram: { steps: fetchedCourse.subProgram.steps.map(s => ({ _id: s._id, name: s.name })) },
} as BlendedCourseType;
setCourseToStore(formattedCourse);
};
setCourseToStore(formattedCourse as BlendedCourseType);
}
const programImage = get(fetchedCourse, 'subProgram.program.image.link') || '';
setCourse(fetchedCourse);
Expand All @@ -104,6 +105,13 @@ const LearnerCourseProfile = ({ route, navigation }: LearnerCourseProfileProps)
}
}, [isFocused, setStatusBarVisible, route.params.courseId, setCourseToStore]);

useEffect(() => () => {
const currentRoute = navigation.getState().routes[navigation.getState().index];
if (currentRoute?.name !== 'UpdateAttendanceSheet') {
resetAttendanceSheetReducer();
}
}, [navigation, resetAttendanceSheetReducer]);

const goBack = useCallback(() => {
navigation.navigate('LearnerCourses');
}, [navigation]);
Expand Down
26 changes: 4 additions & 22 deletions src/screens/courses/profile/UpdateAttendanceSheet/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { useEffect, useMemo, useReducer, useState } from 'react';
import { createStackNavigator, StackScreenProps } from '@react-navigation/stack';
import { CompositeScreenProps } from '@react-navigation/native';
import keyBy from 'lodash/keyBy';
import AttendanceSheets from '../../../../api/attendanceSheets';
import { RootStackParamList, RootUpdateAttendanceSheetParamList } from '../../../../types/NavigationType';
import { DD_MM_YYYY, HH_MM, IS_WEB, LEARNER, LONG_FIRSTNAME_LONG_LASTNAME } from '../../../../core/data/constants';
import { DD_MM_YYYY, HH_MM, LEARNER, LONG_FIRSTNAME_LONG_LASTNAME } from '../../../../core/data/constants';
import { errorReducer, initialErrorState, RESET_ERROR, SET_ERROR } from '../../../../reducers/error';
import AttendanceSheetSelectionForm from '../../../../components/AttendanceSheetSelectionForm';
import { useGetCourse, useGetGroupedSlotsToBeSigned } from '../../../../store/attendanceSheets/hooks';
Expand All @@ -17,6 +16,7 @@ import AttendanceSheetSummary from '../../../../components/AttendanceSheetSummar
import AttendanceEndScreen from '../../../../components/AttendanceEndScreen';
import { useGetLoggedUser } from '../../../../store/main/hooks';
import { formatIdentity } from '../../../../core/helpers/utils';
import { generateFile } from '../helper';

interface UpdateAttendanceSheetProps extends CompositeScreenProps<
StackScreenProps<RootStackParamList, 'UpdateAttendanceSheet'>,
Expand All @@ -42,10 +42,8 @@ const UpdateAttendanceSheet = ({ route, navigation }: UpdateAttendanceSheetProps
const [failUpload, setFailUpload] = useState<boolean>(false);
const [errorSignature, dispatchErrorSignature] = useReducer(errorReducer, initialErrorState);
const [errorConfirmation, dispatchErrorConfirmation] = useReducer(errorReducer, initialErrorState);
const stepsById = useMemo(() => keyBy(course?.subProgram.steps, '_id'), [course]);
const stepsName = useMemo(() =>
Object.keys(groupedSlotsToBeSigned).map(stepId => (stepsById[stepId].name)),
[groupedSlotsToBeSigned, stepsById]);
Object.keys(groupedSlotsToBeSigned), [groupedSlotsToBeSigned]);
const slotsOptions = useMemo(() =>
Object.values(groupedSlotsToBeSigned)
.map(slotGroup => [...slotGroup]
Expand Down Expand Up @@ -82,26 +80,10 @@ const UpdateAttendanceSheet = ({ route, navigation }: UpdateAttendanceSheetProps
}
};

const base64ToBlob = (base64Data: string, contentType: string) => {
const byteCharacters = atob(base64Data.split(',')[1]);
const byteNumbers = new Array(byteCharacters.length);
for (let i = 0; i < byteCharacters.length; i += 1) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);

return new Blob([byteArray], { type: contentType });
};

const saveAttendances = async () => {
try {
setIsLoading(true);
let file;
const contentType = 'image/png';
if (IS_WEB) {
const blob = base64ToBlob(signature, contentType);
file = new File([blob], `trainee_signature_${course?._id}.png`, { type: contentType });
} else file = { uri: signature, type: contentType, name: `trainee_signature_${course?._id}` };
const file = generateFile(signature, course?._id, 'trainee');
const data = formatPayload({ signature: file });
await AttendanceSheets.sign(attendanceSheetId, data);
setIsLoading(false);
Expand Down
24 changes: 23 additions & 1 deletion src/screens/courses/profile/helper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { View } from 'react-native';
import get from 'lodash/get';
import { E_LEARNING, ON_SITE, REMOTE, TESTER } from '../../../core/data/constants';
import { E_LEARNING, IS_WEB, ON_SITE, REMOTE, TESTER } from '../../../core/data/constants';
import LiveCell from '../../../components/steps/LiveCell';
import ELearningCell from '../../../components/ELearningCell';
import styles from './styles';
Expand Down Expand Up @@ -40,3 +40,25 @@ export const getTitle = (course) => {
const { misc } = (course as BlendedCourseType);
return `${programName}${misc ? ` - ${misc}` : ''}`;
};

const base64ToBlob = (base64Data: string, contentType: string) => {
const byteCharacters = atob(base64Data.split(',')[1]);
const byteNumbers = new Array(byteCharacters.length);
for (let i = 0; i < byteCharacters.length; i += 1) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);

return new Blob([byteArray], { type: contentType });
};

export const generateFile = (signature, courseId, mode) => {
let file;
const contentType = 'image/png';
if (IS_WEB) {
const blob = base64ToBlob(signature, contentType);
file = new File([blob], `${mode}_signature_${courseId}.png`, { type: contentType });
} else file = { uri: signature, type: contentType, name: `${mode}_signature_${courseId}` };

return file;
};
4 changes: 2 additions & 2 deletions src/store/main/slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { UserType } from '../../types/UserType';
import { resetAllReducers } from '../actions';

type MainStateType = {
loggedUser: any | null,
loggedUser: UserType | null,
statusBarVisible: boolean,
}

Expand All @@ -22,7 +22,7 @@ const setUser = (state: MainStateType, action: PayloadAction<UserType>) => ({
'contact.phone',
'role',
'companyLinkRequest',
]),
]) as UserType,
});

const setStatusBar = (state: MainStateType, action: PayloadAction<boolean>) => (
Expand Down
4 changes: 2 additions & 2 deletions src/types/NavigationType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ export type RootStackParamList = {
BlendedAbout: { course: BlendedCourseType, mode: CourseModeType }
ElearningAbout: { program: ELearningProgramType }
AdminCourseProfile: { courseId: string }
CreateAttendanceSheet: {isSingle: boolean};
UpdateAttendanceSheet: {attendanceSheetId: string},
CreateAttendanceSheet: { isSingle: boolean };
UpdateAttendanceSheet: { attendanceSheetId: string },
ProfileEdition: undefined;
PasswordEdition: { userId: string };
ImagePickerManager: undefined;
Expand Down

0 comments on commit 1d63377

Please sign in to comment.