Skip to content

Commit 3017d50

Browse files
th-108: Google autocomplete (#113)
* th-48: + portal * th-48: + modal * th-48: + react google autocomplete * th-48: + location input * th-48: * fix --------- Co-authored-by: Pavel Sukhinin <[email protected]>
1 parent 66ffe45 commit 3017d50

File tree

5 files changed

+183
-2
lines changed

5 files changed

+183
-2
lines changed

frontend/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,13 @@
2929
"modern-normalize": "2.0.0",
3030
"react": "18.2.0",
3131
"react-dom": "18.2.0",
32+
"react-google-autocomplete": "2.7.3",
3233
"react-hook-form": "7.43.5",
3334
"react-redux": "8.1.2",
3435
"react-router-dom": "6.8.2",
36+
"react-select": "5.7.4",
3537
"react-toastify": "9.1.3",
36-
"socket.io-client": "4.7.2",
37-
"react-select": "5.7.4"
38+
"socket.io-client": "4.7.2"
3839
},
3940
"devDependencies": {
4041
"@types/google.maps": "3.54.0",

frontend/src/libs/components/components.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export { Icon } from './icon/icon.js';
1212
export { Image } from './image/image.js';
1313
export { Input } from './input/input.js';
1414
export { Link } from './link/link.js';
15+
export { LocationInput } from './location-input/location-input.js';
1516
export { Modal } from './modal/modal.js';
1617
export { Notification } from './notification/notification.js';
1718
export { Pagination } from './pagination/pagination.js';
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import GooglePlacesAutocomplete from 'react-google-autocomplete';
2+
import {
3+
type Control,
4+
type FieldErrors,
5+
type FieldPath,
6+
type FieldValues,
7+
} from 'react-hook-form';
8+
9+
import { getValidClassNames } from '~/libs/helpers/helpers.js';
10+
import { useFormController } from '~/libs/hooks/hooks.js';
11+
import { config } from '~/libs/packages/config/config.js';
12+
13+
import styles from './styles.module.scss';
14+
15+
type Properties<T extends FieldValues> = {
16+
control: Control<T, null>;
17+
errors: FieldErrors<T>;
18+
label?: string;
19+
name: FieldPath<T>;
20+
placeholder?: string;
21+
isDisabled?: boolean;
22+
};
23+
24+
const LocationInput = <T extends FieldValues>({
25+
control,
26+
errors,
27+
label = '',
28+
name,
29+
placeholder = '',
30+
isDisabled,
31+
}: Properties<T>): JSX.Element => {
32+
const { field } = useFormController({ name, control });
33+
34+
const error = errors[name]?.message;
35+
const hasError = Boolean(error);
36+
const hasValue = Boolean(field.value);
37+
const hasLabel = Boolean(label);
38+
const inputStyles = [
39+
styles.input,
40+
hasValue && styles.filled,
41+
isDisabled && styles.disabled,
42+
hasError && styles.error,
43+
];
44+
45+
return (
46+
<label className={styles.inputComponentWrapper}>
47+
{hasLabel && <span className={styles.label}>{label}</span>}
48+
<span className={styles.inputWrapper}>
49+
<GooglePlacesAutocomplete
50+
{...field}
51+
type="text"
52+
placeholder={placeholder}
53+
className={getValidClassNames(...inputStyles)}
54+
disabled={isDisabled}
55+
apiKey={config.ENV.API.GOOGLE_MAPS_API_KEY}
56+
/>
57+
</span>
58+
59+
<span
60+
className={getValidClassNames(
61+
styles.errorMessage,
62+
hasError && styles.visible,
63+
)}
64+
>
65+
{error as string}
66+
</span>
67+
</label>
68+
);
69+
};
70+
71+
export { LocationInput };
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
@import "src/assets/css/vars.scss";
2+
3+
$error-font-size: 12px;
4+
$line-height-coefficient: 1.54;
5+
$error-message-height: calc($error-font-size * $line-height-coefficient);
6+
7+
.inputComponentWrapper {
8+
display: flex;
9+
flex-direction: column;
10+
max-width: 327px;
11+
color: $grey-dark;
12+
font-weight: $font-weight-semibold;
13+
font-size: 16px;
14+
font-family: $font-family;
15+
font-style: normal;
16+
line-height: 140.5%;
17+
}
18+
19+
.input {
20+
width: 100%;
21+
padding: 8px;
22+
color: $grey-dark;
23+
font-weight: $font-weight-regular;
24+
font-size: 14px;
25+
font-family: $font-family;
26+
font-style: normal;
27+
line-height: normal;
28+
background: $white;
29+
border: 2px solid $grey-light;
30+
border-radius: 4px;
31+
outline: none;
32+
}
33+
34+
.input.filled {
35+
color: $black;
36+
}
37+
38+
.input:focus {
39+
border-color: $blue;
40+
box-shadow:
41+
0 2px 4px -2px rgb(0 44 132 / 6%),
42+
0 4px 8px -2px rgb(0 85 255 / 16%);
43+
}
44+
45+
.input.disabled {
46+
color: $grey-light;
47+
}
48+
49+
.input.error {
50+
border-color: $red;
51+
}
52+
53+
.errorMessage {
54+
display: block;
55+
flex-grow: 1;
56+
width: 100%;
57+
height: $error-message-height;
58+
margin-top: 5px;
59+
overflow: hidden;
60+
color: $red-dark;
61+
font-weight: $font-weight-regular;
62+
font-size: $error-font-size;
63+
font-family: $font-family;
64+
line-height: normal;
65+
white-space: nowrap;
66+
text-align: end;
67+
text-overflow: ellipsis;
68+
visibility: hidden;
69+
}
70+
71+
.visible {
72+
visibility: visible;
73+
}
74+
75+
.label {
76+
width: 100%;
77+
overflow: hidden;
78+
white-space: nowrap;
79+
text-overflow: ellipsis;
80+
}
81+
82+
.disabled .label {
83+
color: $grey-light;
84+
}
85+
86+
.inputWrapper {
87+
position: relative;
88+
display: block;
89+
width: 100%;
90+
}

package-lock.json

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)