Skip to content

Commit

Permalink
Bal 684 collect directors images in collection flow (#1676)
Browse files Browse the repository at this point in the history
* feat: added initial FileUploaderField & dependant hooks & tests

* feat: finalized FileUploaderField & added tests

* fix: fixed onChange handler & test fixes

* feat: added onBlur & added subscriptions to file repository & added tests

* feat: added support of array field documents to DocumentField & destination parser & tests

* feat: added selfie document input & updated schemas & crash fixes & common bump

* Bal 684 collect directors images in collection flow backoffice (#1647)

* feat: added rendering of director document images

* feat: added property schemas to common & updated bdirectors block layout

* feat: added propertiesSchema to documents created in collection flow

* feat: implementing update of director documents

* feat: implemented documents & decision update for directors & added document selection to popup

* feat: added revision reasons for each of director documents

* feat: added default revision reasons for director documents

* feat: added reset of revision decisions for director documents

* feat: added approval buttons to director documents

* feat: ask for all re-uploads count includes directors & added status details & approved badge

* fix: removed reduntant settings & refactored code

* fix: fixd bug where jsonb method break primitives & added onSubmit callback to Details

* feat: reverted origin deepMerge migration & added migration with update

* feat: added output of director documents errors

* feat: reworked step completion tracking & added disable state for inputs on revision & fixes

* fix: post merge fixes

* fix: type fix

* fix: missing imports fix

* fix: fixed category & type options on director documents

* fix: refactored document selection & added comment & reason reset on document re-select

* feat: added re-upload badge for revision workflows & fixed warning indication with multiple pages

* fix: fixed missing disabled status on inputs & ui bump & stepper status indication fixes
  • Loading branch information
chesterkmr authored Dec 3, 2023
1 parent 2e05803 commit d88b8d5
Show file tree
Hide file tree
Showing 115 changed files with 2,711 additions and 503 deletions.
15 changes: 0 additions & 15 deletions apps/backoffice-v2/.vscode/launch.json

This file was deleted.

2 changes: 2 additions & 0 deletions apps/backoffice-v2/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
### Patch Changes

- Updated dependencies [8c888cec]
- Updated dependencies
- @ballerine/workflow-browser-sdk@0.5.22
- @ballerine/workflow-node-sdk@0.5.22
- @ballerine/common@0.7.23
Expand All @@ -77,6 +78,7 @@
### Patch Changes

- Updated dependencies
- @ballerine/common@0.7.22
- @ballerine/workflow-browser-sdk@0.5.21
- @ballerine/workflow-node-sdk@0.5.21

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,21 @@ export const useApproveTaskByIdMutation = (workflowId: string, postUpdateEventNa
const workflowById = workflowsQueryKeys.byId({ workflowId, filterId });

return useMutation({
mutationFn: ({ documentId }: { documentId: string }) =>
mutationFn: ({
documentId,
contextUpdateMethod = 'base',
}: {
documentId: string;
contextUpdateMethod?: 'base' | 'director';
}) =>
updateWorkflowDecision({
workflowId,
documentId,
body: {
decision: Action.APPROVE,
postUpdateEventName,
},
contextUpdateMethod,
}),
onMutate: async ({ documentId }) => {
await queryClient.cancelQueries({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@ export const useRemoveDecisionTaskByIdMutation = (
const workflowById = workflowsQueryKeys.byId({ workflowId, filterId });

return useMutation({
mutationFn: ({ documentId }: { documentId: string }) =>
mutationFn: ({
documentId,
contextUpdateMethod,
}: {
documentId: string;
contextUpdateMethod: 'base' | 'director';
}) =>
updateWorkflowDecision({
workflowId,
documentId,
Expand All @@ -23,6 +29,7 @@ export const useRemoveDecisionTaskByIdMutation = (
reason: null,
postUpdateEventName,
},
contextUpdateMethod,
}),
onMutate: async ({ documentId }) => {
await queryClient.cancelQueries({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,17 @@ export const useRevisionTaskByIdMutation = (workflowId: string, postUpdateEventN
documentId,
decision,
reason,
contextUpdateMethod,
}: {
documentId: string;
decision: TObjectValues<typeof Action> | null;
reason?: string;
contextUpdateMethod?: 'base' | 'director';
}) =>
updateWorkflowDecision({
workflowId,
documentId,
contextUpdateMethod,
body: {
decision,
reason,
Expand Down
22 changes: 15 additions & 7 deletions apps/backoffice-v2/src/domains/workflows/fetchers.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { apiClient } from '../../common/api-client/api-client';
import qs from 'qs';
import { deepCamelKeys } from 'string-ts';
import { z } from 'zod';
import { apiClient } from '../../common/api-client/api-client';
import { Method, States } from '../../common/enums';
import { handleZodError } from '../../common/utils/handle-zod-error/handle-zod-error';
import { ObjectWithIdSchema } from '../../lib/zod/utils/object-with-id/object-with-id';
import { Method, States } from '../../common/enums';
import { IWorkflowId } from './interfaces';
import qs from 'qs';
import { zPropertyKey } from '../../lib/zod/utils/z-property-key/z-property-key';
import { deepCamelKeys } from 'string-ts';
import { IWorkflowId } from './interfaces';

export const fetchWorkflows = async (params: {
filterId: string;
Expand Down Expand Up @@ -146,12 +146,16 @@ export const updateWorkflowDocumentById = async ({
workflowId,
documentId,
body,
contextUpdateMethod,
}: IWorkflowId & {
documentId: string;
body: Record<PropertyKey, unknown>;
contextUpdateMethod?: 'base' | 'director';
}) => {
const [workflow, error] = await apiClient({
endpoint: `workflows/${workflowId}/documents/${documentId}`,
endpoint: `workflows/${workflowId}/documents/${documentId}${
contextUpdateMethod ? `?contextUpdateMethod=${contextUpdateMethod}` : ''
}`,
method: Method.PATCH,
body,
schema: z.any(),
Expand Down Expand Up @@ -204,16 +208,20 @@ export const updateWorkflowDecision = async ({
workflowId,
documentId,
body,
contextUpdateMethod,
}: IWorkflowId & {
documentId: string;
body: {
decision: string | null;
reason?: string;
postUpdateEventName?: string;
};
contextUpdateMethod: 'base' | 'director';
}) => {
const [workflow, error] = await apiClient({
endpoint: `workflows/${workflowId}/decision/${documentId}`,
endpoint: `workflows/${workflowId}/decision/${documentId}${
contextUpdateMethod ? `?contextUpdateMethod=${contextUpdateMethod}` : ''
}`,
method: Method.PATCH,
body,
schema: WorkflowByIdSchema.pick({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { useMutation, useQueryClient } from '@tanstack/react-query';
import toast from 'react-hot-toast';
import { t } from 'i18next';
import { TWorkflowById, updateWorkflowDocumentById } from '../../../fetchers';
import toast from 'react-hot-toast';
import { useFilterId } from '../../../../../common/hooks/useFilterId/useFilterId';
import { TWorkflowById, updateWorkflowDocumentById } from '../../../fetchers';
import { workflowsQueryKeys } from '../../../query-keys';

export const useUpdateDocumentByIdMutation = ({
Expand All @@ -19,17 +19,21 @@ export const useUpdateDocumentByIdMutation = ({
return useMutation({
mutationFn: ({
document,
contextUpdateMethod,
}: {
document: Record<PropertyKey, unknown>;
action: 'update_document_properties';
}) =>
updateWorkflowDocumentById({
contextUpdateMethod: 'base' | 'director';
}) => {
return updateWorkflowDocumentById({
workflowId,
documentId,
body: {
document,
},
}),
contextUpdateMethod,
});
},
onMutate: async ({ document }) => {
await queryClient.cancelQueries({
queryKey: workflowById.queryKey,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,28 @@
import { AnimatePresence } from 'framer-motion';
import React, { ComponentProps, FunctionComponent } from 'react';
import { DialogClose } from '@radix-ui/react-dialog';
import { AnimatePresence } from 'framer-motion';
import { ComponentProps, FunctionComponent } from 'react';

import { Dialog } from '../../../../common/components/organisms/Dialog/Dialog';
import { ctw } from '../../../../common/utils/ctw/ctw';
import { DialogContent } from '../../../../common/components/organisms/Dialog/Dialog.Content';
import { Send, X } from 'lucide-react';
import { Button } from '../../../../common/components/atoms/Button/Button';
import { Input } from '../../../../common/components/atoms/Input/Input';
import { Select } from '../../../../common/components/atoms/Select/Select';
import { DialogFooter } from '../../../../common/components/organisms/Dialog/Dialog.Footer';
import { ICallToActionProps } from './interfaces';
import { SelectItem } from '../../../../common/components/atoms/Select/Select.Item';
import { SelectContent } from '../../../../common/components/atoms/Select/Select.Content';
import { SelectItem } from '../../../../common/components/atoms/Select/Select.Item';
import { SelectTrigger } from '../../../../common/components/atoms/Select/Select.Trigger';
import { SelectValue } from '../../../../common/components/atoms/Select/Select.Value';
import { Input } from '../../../../common/components/atoms/Input/Input';
import { DialogTrigger } from '../../../../common/components/organisms/Dialog/Dialog.Trigger';
import { useCallToActionLogic } from './hooks/useCallToActionLogic/useCallToActionLogic';
import { MotionButton } from '../../../../common/components/molecules/MotionButton/MotionButton';
import { Button } from '../../../../common/components/atoms/Button/Button';
import { Dialog } from '../../../../common/components/organisms/Dialog/Dialog';
import { DialogContent } from '../../../../common/components/organisms/Dialog/Dialog.Content';
import { DialogDescription } from '../../../../common/components/organisms/Dialog/Dialog.Description';
import { DialogFooter } from '../../../../common/components/organisms/Dialog/Dialog.Footer';
import { DialogHeader } from '../../../../common/components/organisms/Dialog/Dialog.Header';
import { DialogTitle } from '../../../../common/components/organisms/Dialog/Dialog.Title';
import { DialogDescription } from '../../../../common/components/organisms/Dialog/Dialog.Description';
import { DialogTrigger } from '../../../../common/components/organisms/Dialog/Dialog.Trigger';
import { capitalize } from '../../../../common/utils/capitalize/capitalize';
import { Send } from 'lucide-react';
import { ctw } from '../../../../common/utils/ctw/ctw';
import { DocumentPicker } from './components/DocumentPicker';
import { useCallToActionLogic } from './hooks/useCallToActionLogic/useCallToActionLogic';
import { ICallToActionProps } from './interfaces';

const motionProps: ComponentProps<typeof MotionButton> = {
exit: { opacity: 0, transition: { duration: 0.2 } },
Expand All @@ -30,7 +31,19 @@ const motionProps: ComponentProps<typeof MotionButton> = {
animate: { y: 0, opacity: 1, transition: { duration: 0.2 } },
};

export const CallToAction: FunctionComponent<ICallToActionProps> = ({ value, data }) => {
export const CallToAction: FunctionComponent<ICallToActionProps> = ({ value }) => {
const {
documentSelection,
contextUpdateMethod,
revisionReasons,
rejectionReasons,
onReuploadReset,
onDialogClose,
id,
decision,
disabled,
} = value?.props || {};

const {
onMutateTaskDecisionById,
isLoadingTaskDecisionById,
Expand All @@ -45,23 +58,31 @@ export const CallToAction: FunctionComponent<ICallToActionProps> = ({ value, dat
onCommentChange,
noReasons,
workflowLevelResolution,
} = useCallToActionLogic();
isReuploadResetable,
documentPickerProps,
handleDialogClose,
} = useCallToActionLogic({
contextUpdateMethod,
revisionReasons,
rejectionReasons,
documentSelection,
onDialogClose,
onReuploadReset,
});

if (value === 'Reject') {
if (value?.text === 'Reject') {
return (
<Dialog>
<Dialog onOpenChange={handleDialogClose}>
<AnimatePresence>
<DialogTrigger asChild>
<MotionButton
{...motionProps}
size="wide"
variant="destructive"
className={ctw({ loading: isLoadingTaskDecisionById })}
disabled={
isLoadingTaskDecisionById || data?.disabled || !caseState.actionButtonsEnabled
}
disabled={isLoadingTaskDecisionById || disabled || !caseState.actionButtonsEnabled}
>
{value}
{value.text}
</MotionButton>
</DialogTrigger>
</AnimatePresence>
Expand Down Expand Up @@ -140,7 +161,7 @@ export const CallToAction: FunctionComponent<ICallToActionProps> = ({ value, dat
loading: isLoadingTaskDecisionById,
})}
onClick={onMutateTaskDecisionById({
id: data?.id,
id,
decision: action,
reason: comment ? `${reason} - ${comment}` : reason,
})}
Expand All @@ -154,18 +175,28 @@ export const CallToAction: FunctionComponent<ICallToActionProps> = ({ value, dat
);
}

if (value === 'Re-upload needed') {
if (value?.text === 'Re-upload needed') {
return (
<Dialog>
<Dialog onOpenChange={handleDialogClose}>
<AnimatePresence>
<DialogTrigger asChild>
<MotionButton
{...motionProps}
size="wide"
variant="warning"
disabled={!caseState.actionButtonsEnabled || data?.disabled}
disabled={!caseState.actionButtonsEnabled || disabled}
className={ctw({ 'flex gap-2': isReuploadResetable })}
>
{value}
{value.text}
{isReuploadResetable && (
<X
className="h-4 w-4 cursor-pointer"
onClick={event => {
event.stopPropagation();
onReuploadReset && onReuploadReset();
}}
/>
)}
</MotionButton>
</DialogTrigger>
</AnimatePresence>
Expand Down Expand Up @@ -194,6 +225,7 @@ export const CallToAction: FunctionComponent<ICallToActionProps> = ({ value, dat
</p>
</DialogDescription>
</DialogHeader>
{documentSelection && <DocumentPicker {...documentPickerProps} value={id} />}
{!noReasons && (
<div>
<label className={`mb-2 block font-bold`} htmlFor={`reason`}>
Expand Down Expand Up @@ -243,7 +275,7 @@ export const CallToAction: FunctionComponent<ICallToActionProps> = ({ value, dat
loading: isLoadingTaskDecisionById,
})}
onClick={onMutateTaskDecisionById({
id: data?.id,
id,
decision: action,
reason: comment ? `${reason} - ${comment}` : reason,
})}
Expand All @@ -270,13 +302,13 @@ export const CallToAction: FunctionComponent<ICallToActionProps> = ({ value, dat
size="wide"
variant="success"
className={ctw({ loading: isLoadingTaskDecisionById })}
disabled={isLoadingTaskDecisionById || data?.disabled || !caseState.actionButtonsEnabled}
disabled={isLoadingTaskDecisionById || disabled || !caseState.actionButtonsEnabled}
onClick={onMutateTaskDecisionById({
id: data?.id,
decision: data?.decision,
id,
decision,
})}
>
{value}
{value?.text}
</MotionButton>
</AnimatePresence>
);
Expand Down
Loading

0 comments on commit d88b8d5

Please sign in to comment.