Skip to content

Commit

Permalink
[WALL] Farhan/WALL-2599/Identity Card Document Submission (deriv-com#…
Browse files Browse the repository at this point in the history
…11446)

* feat: create identity card upload screen

* refactor: 🔧 refactor divider component

* refactor: 🔧 remove styles props in dropzone component
  • Loading branch information
farhan-nurzi-deriv authored Nov 16, 2023
1 parent fbc5d1a commit d25dc13
Show file tree
Hide file tree
Showing 17 changed files with 272 additions and 89 deletions.
6 changes: 4 additions & 2 deletions packages/wallets/src/components/Base/Divider/Divider.scss
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
.wallets-divider {
&__horizontal {
width: 100%;

&--horizontal {
border-top: 1px solid;
}

&__vertical {
&--vertical {
border-right: 1px solid;
}
}
2 changes: 1 addition & 1 deletion packages/wallets/src/components/Base/Divider/Divider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ type TProps = {
};

const Divider: React.FC<TProps> = ({ color = '#f2f3f4', margin, variant = 'horizontal' }) => (
<div className={`wallets-divider__${variant}`} style={{ borderColor: color, margin }} />
<div className={`wallets-divider wallets-divider--${variant}`} style={{ borderColor: color, margin }} />
);

export default Divider;
6 changes: 1 addition & 5 deletions packages/wallets/src/components/Dropzone/Dropzone.scss
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
.wallets-dropzone {
display: flex;
padding: 2.8rem 15.2rem 3.5rem;
justify-content: center;
align-items: center;
border-radius: 0.8rem;
height: 100%;
width: 100%;
border: 0.1rem dashed var(--system-light-5-active-background, #d6dadb);

@include mobile {
padding: 2.4rem 2.5rem 0.4rem;
}
padding: 2rem;

&--hover,
&--active {
Expand Down
71 changes: 35 additions & 36 deletions packages/wallets/src/components/Dropzone/Dropzone.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,4 @@
import React, {
CSSProperties,
DetailedHTMLProps,
InputHTMLAttributes,
ReactNode,
RefObject,
useCallback,
useState,
} from 'react';
import React, { DetailedHTMLProps, InputHTMLAttributes, ReactNode, RefObject, useCallback, useState } from 'react';
import classNames from 'classnames';
import { useDropzone } from 'react-dropzone';
import CloseIcon from '../../public/images/close-icon.svg';
Expand All @@ -17,26 +9,18 @@ type TProps = {
buttonText?: ReactNode;
description?: ReactNode;
fileFormats?: NonNullable<Parameters<typeof useDropzone>[0]>['accept'];
height?: CSSProperties['height'];
hoverMessage?: ReactNode;
icon: ReactNode;
maxSize?: NonNullable<Parameters<typeof useDropzone>[0]>['maxSize'];
minHeight?: CSSProperties['minHeight'];
minWidth?: CSSProperties['minWidth'];
width?: CSSProperties['width'];
};

const Dropzone: React.FC<TProps> = ({
buttonText = 'Upload',
description,
fileFormats,
height,
hoverMessage = 'Drop file here',
icon,
maxSize,
minHeight,
minWidth,
width,
}) => {
const [files, setFiles] = useState<
{
Expand All @@ -45,6 +29,7 @@ const Dropzone: React.FC<TProps> = ({
}[]
>([]);
const [showHoverMessage, setShowHoverMessage] = useState(false);
const [errorMessage, setErrorMessage] = useState<string | null>(null);
const { getInputProps, getRootProps, open, rootRef } = useDropzone({
accept: fileFormats,
maxSize,
Expand All @@ -54,7 +39,6 @@ const Dropzone: React.FC<TProps> = ({
onDragLeave: () => setShowHoverMessage(false),
onDrop: acceptedFiles => {
setShowHoverMessage(false);

setFiles(
acceptedFiles.map(file =>
Object.assign(file, {
Expand All @@ -63,6 +47,12 @@ const Dropzone: React.FC<TProps> = ({
)
);
},
onDropAccepted() {
setErrorMessage(null);
},
onDropRejected(fileRejections) {
setErrorMessage(fileRejections?.[0]?.errors?.[0].message);
},
});

const removeFile = useCallback(
Expand All @@ -73,11 +63,7 @@ const Dropzone: React.FC<TProps> = ({
);

return (
<div
{...getRootProps()}
ref={rootRef as RefObject<HTMLDivElement>}
style={{ height, minHeight, minWidth, width }}
>
<div {...getRootProps()} className='wallets-dropzone__container' ref={rootRef as RefObject<HTMLDivElement>}>
<input
{...(getInputProps() as DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>)}
/>
Expand All @@ -93,27 +79,40 @@ const Dropzone: React.FC<TProps> = ({
{!showHoverMessage && !files.length && (
<div className='wallets-dropzone__placeholder'>
<div className='wallets-dropzone__placeholder-icon'>{icon}</div>
<WalletText align='center' size='md'>
{description}
</WalletText>
<div className='wallets-dropzone__placeholder-text'>
<WalletButton onClick={open} text={buttonText} variant='outlined' />
</div>
{errorMessage && (
<WalletText align='center' color='red' size='2xs'>
{errorMessage}
</WalletText>
)}
</div>
)}
{files.length > 0 &&
files.map(file => (
<div
className='wallets-dropzone__thumb'
key={file.name}
style={{ backgroundImage: `url(${file.preview})` }}
>
<IconButton
className='wallets-dropzone__remove-file'
icon={<CloseIcon width={12} />}
onClick={removeFile(file)}
size='sm'
/>
</div>
<React.Fragment key={file.name}>
<div
className='wallets-dropzone__thumb'
style={{ backgroundImage: `url(${file.preview})` }}
>
<IconButton
className='wallets-dropzone__remove-file'
icon={<CloseIcon width={12} />}
onClick={removeFile(file)}
size='sm'
/>
</div>
{description && (
<WalletText align='center' size='md'>
{description}
</WalletText>
)}
</React.Fragment>
))}
{!showHoverMessage && description && <WalletText size='md'>{description}</WalletText>}
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { ReactNode } from 'react';
import { WalletText } from '../../../../../../components/Base';
import { WalletText } from '../../../../../../../components/Base';
import './DocumentRuleHint.scss';

type TProps = {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.wallets-document-rule-hints {
display: flex;
justify-content: center;
width: 100%;

@include mobile {
display: grid;
grid-template-columns: repeat(2, 1fr);
column-gap: 2.4rem;
row-gap: 0.8rem;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React from 'react';
import ClearPhoto from '../../../../../../public/images/accounts/clear-photo.svg';
import ClockIcon from '../../../../../../public/images/accounts/clock-icon.svg';
import ImageIcon from '../../../../../../public/images/accounts/image-icon.svg';
import LessThanEightIcon from '../../../../../../public/images/accounts/less-than-eight-icon.svg';
import { DocumentRuleHint } from './DocumentRuleHint';
import './DocumentRuleHints.scss';

type TProps = {
docType: 'driverLicense' | 'identityCard' | 'nimcSlip' | 'passport';
};

const DocumentRuleHints: React.FC<TProps> = ({ docType }) => (
<div className='wallets-document-rule-hints'>
<DocumentRuleHint description='A clear colour photo or scanned image' icon={<ClearPhoto />} />
<DocumentRuleHint description='JPEG, JPG, PNG, PDF, or GIF' icon={<ImageIcon />} />
<DocumentRuleHint description='Less than 8MB' icon={<LessThanEightIcon />} />
{docType !== 'nimcSlip' && (
<DocumentRuleHint description='Must be valid for at least 6 months' icon={<ClockIcon />} />
)}
</div>
);

export default DocumentRuleHints;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as DocumentRuleHints } from './DocumentRuleHints';
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
.wallets-identity-card-document-upload {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 2.4rem;
padding: 2.4rem;
width: fit-content;
background: var(--light-8-primary-background, #fff);

@include mobile {
width: 100%;
}

&__document-section {
width: 100%;
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 1.7rem;

@include mobile {
gap: 1.6rem;
}
}

&__dropzones {
width: 100%;
display: flex;
align-items: flex-start;
gap: 2.4rem;

@include mobile {
flex-direction: column;
}

&--left {
width: 100%;

& > .wallets-dropzone__container {
min-width: 33.5rem;
}

& > .wallets-dropzone {
padding: 4rem 4.7rem 4rem 3.9rem;
}
}

&--right {
width: 100%;

& > .wallets-dropzone__container {
min-width: 31rem;
}

& > .wallets-dropzone {
padding: 4rem 2.4rem;
}
}

& .wallets-dropzone__container {
height: 25rem;

@include mobile {
min-width: 100%;
}
}

& .wallets-dropzone {
@include mobile {
padding: 2rem;
}
}
}

&__input-group {
display: flex;
gap: 2.4rem;
padding-bottom: 2rem;
width: 100%;

@include mobile {
flex-direction: column;
gap: 1.6rem;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React from 'react';
import { Divider, Dropzone, WalletText, WalletTextField } from '../../../../../../components';
import IdentityCardBack from '../../../../../../public/images/accounts/document-back.svg';
import IdentityCardFront from '../../../../../../public/images/accounts/identity-card-front.svg';
import Calendar from '../../../../../../public/images/calendar.svg';
import { DocumentRuleHints } from '../DocumentRuleHints';
import './IdentityCardDocumentUpload.scss';

const IdentityCardDocumentUpload = () => {
return (
<div className='wallets-identity-card-document-upload' data-testid='dt_passport-document-upload'>
<WalletText>First, enter your Identity card number and the expiry date.</WalletText>
<div className='wallets-identity-card-document-upload__input-group'>
<WalletTextField label='Identity card number*' maxWidth='100%' />
<WalletTextField
label='Expiry date*'
maxWidth='100%'
renderRightIcon={() => <Calendar />}
type='date'
/>
</div>
<Divider />
<div className='wallets-identity-card-document-upload__document-section'>
<WalletText>Next, upload the front and back of your identity card.</WalletText>
<div className='wallets-identity-card-document-upload__dropzones'>
<div className='wallets-identity-card-document-upload__dropzones--left'>
<Dropzone
buttonText='Drop file or click here to upload'
description='Upload the front of your identity card.'
fileFormats={['image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'application/pdf']}
icon={<IdentityCardFront />}
maxSize={8388608}
/>
</div>
<div className='wallets-identity-card-document-upload__dropzones--right'>
<Dropzone
buttonText='Drop file or click here to upload'
description='Upload the back of your identity card.'
fileFormats={['image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'application/pdf']}
icon={<IdentityCardBack />}
maxSize={8388608}
/>
</div>
</div>
<DocumentRuleHints docType='identityCard' />
</div>
</div>
);
};

export default IdentityCardDocumentUpload;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as IdentityCardDocumentUpload } from './IdentityCardDocumentUpload';
Loading

0 comments on commit d25dc13

Please sign in to comment.