Skip to content

Commit e28c7c7

Browse files
committed
image-picker input type
1 parent 3496704 commit e28c7c7

File tree

15 files changed

+173
-37
lines changed

15 files changed

+173
-37
lines changed

src-ts/lib/form/form-groups/FormGroups.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { FormInputModel } from '../form-input.model'
66

77
import { FormCardSet } from './form-card-set'
88
import FormGroupItem from './form-group-item/FormGroupItem'
9-
import { InputRating, InputText, InputTextarea } from './form-input'
9+
import { InputImagePicker, InputRating, InputText, InputTextarea } from './form-input'
1010
import { FormInputRow } from './form-input-row'
1111
import { InputTextTypes } from './form-input/input-text/InputText'
1212
import FormRadio from './form-radio'
@@ -86,6 +86,13 @@ const FormGroups: (props: FormGroupsProps) => JSX.Element = (props: FormGroupsPr
8686
/>
8787
)
8888
break
89+
case 'image-picker':
90+
inputElement = (
91+
<InputImagePicker
92+
{...input}
93+
/>
94+
)
95+
break
8996
default:
9097
inputElement = (
9198
<InputText

src-ts/lib/form/form-groups/form-input/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
export * from './input-image-picker'
12
export * from './form-input-autcomplete-option.enum'
23
export * from './input-rating'
34
export * from './input-text'
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
@import "../../../../styles/includes";
2+
@import "../../../../styles/variables";
3+
4+
.filePicker {
5+
display: flex;
6+
align-items: center;
7+
justify-content: center;
8+
background-color: $black-5;
9+
border-radius: 8px;
10+
width: 132px;
11+
height: 132px;
12+
position: relative;
13+
14+
@include ltemd {
15+
width: 100%;
16+
}
17+
18+
.filePickerPlaceholder {
19+
color: $turq-160;
20+
text-align: center;
21+
font-weight: $font-weight-bold;
22+
}
23+
24+
.filePickerPencil {
25+
position: absolute;
26+
top: 0;
27+
right: 0;
28+
color: $turq-160;
29+
}
30+
31+
.filePickerInput {
32+
display: none;
33+
}
34+
35+
.badgeImage {
36+
width: 72px;
37+
height: 72px;
38+
}
39+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { createRef, Dispatch, FC, RefObject, SetStateAction, useEffect, useState } from 'react'
2+
3+
import { Button, IconOutline } from '../../../../../lib'
4+
5+
import styles from './InputImagePicker.module.scss'
6+
7+
interface InputImagePickerProps {
8+
readonly accept?: string
9+
readonly name: string
10+
readonly size?: number
11+
}
12+
13+
const InputImagePicker: FC<InputImagePickerProps> = (props: InputImagePickerProps) => {
14+
15+
const fileInputRef: RefObject<HTMLInputElement> = createRef<HTMLInputElement>()
16+
17+
// tslint:disable-next-line:no-null-keyword
18+
const [files, setFiles]: [FileList | null, Dispatch<SetStateAction<FileList | null>>] = useState<FileList | null>(null)
19+
const [fileDataURL, setFileDataURL]: [string | undefined, Dispatch<SetStateAction<string | undefined>>] = useState<string | undefined>()
20+
21+
useEffect(() => {
22+
if (files && files.length) {
23+
const fileReader: FileReader = new FileReader()
24+
fileReader.onload = e => {
25+
const { result }: any = e.target
26+
if (result) {
27+
setFileDataURL(result)
28+
}
29+
}
30+
fileReader.readAsDataURL(files[0])
31+
} else if (fileDataURL) {
32+
setFileDataURL(undefined)
33+
}
34+
}, [
35+
files,
36+
])
37+
38+
return (
39+
<div className={styles.filePicker}>
40+
<Button
41+
buttonStyle='icon'
42+
icon={IconOutline.PencilIcon}
43+
className={styles.filePickerPencil}
44+
onClick={() => fileInputRef.current?.click()} />
45+
<input
46+
name={props.name}
47+
type={'file'}
48+
accept={props.accept || '*'}
49+
className={styles.filePickerInput}
50+
ref={fileInputRef}
51+
onChange={event => setFiles(event.target.files)}
52+
size={props.size || Infinity}
53+
/>
54+
{
55+
fileDataURL ? (
56+
<img src={fileDataURL} className={styles.badgeImage} />
57+
) : (
58+
<div className={styles.filePickerPlaceholder}>UPLOAD<br />IMAGE</div>
59+
)
60+
}
61+
</div>
62+
)
63+
}
64+
65+
export default InputImagePicker
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default as InputImagePicker } from './InputImagePicker'

src-ts/lib/form/form-groups/form-input/input-text/InputText.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import styles from './InputText.module.scss'
88

99
export type InputTextTypes = 'checkbox' | 'password' | 'text'
1010

11-
interface InputTextProps {
11+
export interface InputTextProps {
1212
readonly autocomplete?: FormInputAutocompleteOption
1313
readonly checked?: boolean
1414
readonly className?: string

src-ts/lib/form/form-input.model.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export interface FormCard {
1818
}
1919

2020
export interface FormInputModel {
21+
readonly accept?: string
2122
readonly autocomplete?: FormInputAutocompleteOption
2223
readonly cards?: ReadonlyArray<FormCard>
2324
checked?: boolean
@@ -27,6 +28,7 @@ export interface FormInputModel {
2728
disabled?: boolean
2829
error?: string
2930
readonly events?: ReadonlyArray<InputEvent>
31+
readonly files?: FileList
3032
readonly hideInlineErrors?: boolean
3133
readonly hint?: string
3234
readonly id?: string
@@ -36,10 +38,11 @@ export interface FormInputModel {
3638
readonly notTabbable?: boolean
3739
options?: ReadonlyArray<FormRadioButtonOption>
3840
readonly placeholder?: string
41+
readonly size?: number
3942
readonly spellCheck?: boolean
4043
readonly title?: string
4144
touched?: boolean
42-
readonly type: 'card-set' | 'checkbox' | 'password' | 'radio' | 'rating' | 'text' | 'textarea'
45+
readonly type: 'card-set' | 'checkbox' | 'password' | 'radio' | 'rating' | 'text' | 'textarea' | 'image-picker'
4346
readonly validators?: ReadonlyArray<ValidatorFn>
4447
value?: string | boolean
4548
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
export interface GamificationConfigModel {
2+
ACCEPTED_BADGE_MIME_TYPES: string
3+
MAX_BADGE_IMAGE_FILE_SIZE: number
24
ORG_ID: string
35
PAGE_SIZE: number
46
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { GamificationConfigModel } from './gamification-config.model'
22

33
export const GamificationConfigDefault: GamificationConfigModel = {
4+
ACCEPTED_BADGE_MIME_TYPES: 'image/svg+xml,image/svg',
5+
MAX_BADGE_IMAGE_FILE_SIZE: 5000000, // 5mb in bytes
46
ORG_ID: '6052dd9b-ea80-494b-b258-edd1331e27a3',
57
PAGE_SIZE: 12,
68
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
@import "../../../../lib/styles/variables";
2+
13
.container {
24
display: flex;
5+
padding-top: $space-xxxxl;
36
}

0 commit comments

Comments
 (0)