@grupalia/rn-ui-kit 0.17.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -0
- package/lib/commonjs/UIKitProvider.js +41 -0
- package/lib/commonjs/UIKitProvider.js.map +1 -0
- package/lib/commonjs/assets/illustrations/warning.svg +1 -0
- package/lib/commonjs/components/AppView.js +64 -0
- package/lib/commonjs/components/AppView.js.map +1 -0
- package/lib/commonjs/components/BaseDatesScrollView.js +13 -7
- package/lib/commonjs/components/BaseDatesScrollView.js.map +1 -1
- package/lib/commonjs/components/BaseErrorBox.js +92 -0
- package/lib/commonjs/components/BaseErrorBox.js.map +1 -0
- package/lib/commonjs/components/BaseErrorScreen.js +41 -0
- package/lib/commonjs/components/BaseErrorScreen.js.map +1 -0
- package/lib/commonjs/components/BaseStickyFooter.js +19 -0
- package/lib/commonjs/components/BaseStickyFooter.js.map +1 -0
- package/lib/commonjs/components/DateSelector.js +10 -5
- package/lib/commonjs/components/DateSelector.js.map +1 -1
- package/lib/commonjs/components/DateTimeSelector.js +89 -48
- package/lib/commonjs/components/DateTimeSelector.js.map +1 -1
- package/lib/commonjs/components/NetworkBanner.js +73 -0
- package/lib/commonjs/components/NetworkBanner.js.map +1 -0
- package/lib/commonjs/components/index.js +21 -0
- package/lib/commonjs/components/index.js.map +1 -1
- package/lib/commonjs/components/svgs/Warning.js +15 -0
- package/lib/commonjs/components/svgs/Warning.js.map +1 -0
- package/lib/commonjs/hooks/index.js +22 -13
- package/lib/commonjs/hooks/index.js.map +1 -1
- package/lib/commonjs/hooks/useInternetConnectionStatus.js +24 -14
- package/lib/commonjs/hooks/useInternetConnectionStatus.js.map +1 -1
- package/lib/commonjs/hooks/useTimezonedDate.js +73 -0
- package/lib/commonjs/hooks/useTimezonedDate.js.map +1 -0
- package/lib/commonjs/index.js +36 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/test-setup.js +11 -0
- package/lib/commonjs/test-setup.js.map +1 -0
- package/lib/commonjs/utils/filters.js +52 -0
- package/lib/commonjs/utils/filters.js.map +1 -0
- package/lib/commonjs/utils/index.js +11 -0
- package/lib/commonjs/utils/index.js.map +1 -1
- package/lib/module/UIKitProvider.js +34 -0
- package/lib/module/UIKitProvider.js.map +1 -0
- package/lib/module/assets/illustrations/warning.svg +1 -0
- package/lib/module/components/AppView.js +59 -0
- package/lib/module/components/AppView.js.map +1 -0
- package/lib/module/components/BaseDatesScrollView.js +15 -9
- package/lib/module/components/BaseDatesScrollView.js.map +1 -1
- package/lib/module/components/BaseErrorBox.js +87 -0
- package/lib/module/components/BaseErrorBox.js.map +1 -0
- package/lib/module/components/BaseErrorScreen.js +36 -0
- package/lib/module/components/BaseErrorScreen.js.map +1 -0
- package/lib/module/components/BaseStickyFooter.js +15 -0
- package/lib/module/components/BaseStickyFooter.js.map +1 -0
- package/lib/module/components/DateSelector.js +11 -6
- package/lib/module/components/DateSelector.js.map +1 -1
- package/lib/module/components/DateTimeSelector.js +90 -48
- package/lib/module/components/DateTimeSelector.js.map +1 -1
- package/lib/module/components/NetworkBanner.js +67 -0
- package/lib/module/components/NetworkBanner.js.map +1 -0
- package/lib/module/components/index.js +3 -0
- package/lib/module/components/index.js.map +1 -1
- package/lib/module/components/svgs/Warning.js +10 -0
- package/lib/module/components/svgs/Warning.js.map +1 -0
- package/lib/module/hooks/index.js +2 -1
- package/lib/module/hooks/index.js.map +1 -1
- package/lib/module/hooks/useInternetConnectionStatus.js +23 -13
- package/lib/module/hooks/useInternetConnectionStatus.js.map +1 -1
- package/lib/module/hooks/useTimezonedDate.js +70 -0
- package/lib/module/hooks/useTimezonedDate.js.map +1 -0
- package/lib/module/index.js +3 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/test-setup.js +10 -0
- package/lib/module/test-setup.js.map +1 -0
- package/lib/module/utils/filters.js +48 -0
- package/lib/module/utils/filters.js.map +1 -0
- package/lib/module/utils/index.js +1 -0
- package/lib/module/utils/index.js.map +1 -1
- package/lib/typescript/commonjs/UIKitProvider.d.ts +15 -0
- package/lib/typescript/commonjs/UIKitProvider.d.ts.map +1 -0
- package/lib/typescript/commonjs/__tests__/smoke.test.d.ts +2 -0
- package/lib/typescript/commonjs/__tests__/smoke.test.d.ts.map +1 -0
- package/lib/typescript/commonjs/components/AppView.d.ts +19 -0
- package/lib/typescript/commonjs/components/AppView.d.ts.map +1 -0
- package/lib/typescript/commonjs/components/BaseDatesScrollView.d.ts.map +1 -1
- package/lib/typescript/commonjs/components/BaseErrorBox.d.ts +14 -0
- package/lib/typescript/commonjs/components/BaseErrorBox.d.ts.map +1 -0
- package/lib/typescript/commonjs/components/BaseErrorScreen.d.ts +13 -0
- package/lib/typescript/commonjs/components/BaseErrorScreen.d.ts.map +1 -0
- package/lib/typescript/commonjs/components/BaseStickyFooter.d.ts +11 -0
- package/lib/typescript/commonjs/components/BaseStickyFooter.d.ts.map +1 -0
- package/lib/typescript/commonjs/components/DateSelector.d.ts.map +1 -1
- package/lib/typescript/commonjs/components/DateTimeSelector.d.ts +10 -4
- package/lib/typescript/commonjs/components/DateTimeSelector.d.ts.map +1 -1
- package/lib/typescript/commonjs/components/FormikDateTimeSelector.d.ts +1 -1
- package/lib/typescript/commonjs/components/FormikDateTimeSelectorBottomSheet.d.ts +1 -1
- package/lib/typescript/commonjs/components/NetworkBanner.d.ts +10 -0
- package/lib/typescript/commonjs/components/NetworkBanner.d.ts.map +1 -0
- package/lib/typescript/commonjs/components/index.d.ts +3 -0
- package/lib/typescript/commonjs/components/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/components/svgs/Warning.d.ts +6 -0
- package/lib/typescript/commonjs/components/svgs/Warning.d.ts.map +1 -0
- package/lib/typescript/commonjs/hooks/index.d.ts +2 -1
- package/lib/typescript/commonjs/hooks/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/hooks/useInternetConnectionStatus.d.ts +4 -4
- package/lib/typescript/commonjs/hooks/useInternetConnectionStatus.d.ts.map +1 -1
- package/lib/typescript/commonjs/hooks/useTimezonedDate.d.ts +59 -0
- package/lib/typescript/commonjs/hooks/useTimezonedDate.d.ts.map +1 -0
- package/lib/typescript/commonjs/index.d.ts +3 -0
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/test-setup.d.ts +2 -0
- package/lib/typescript/commonjs/test-setup.d.ts.map +1 -0
- package/lib/typescript/commonjs/utils/filters.d.ts +4 -0
- package/lib/typescript/commonjs/utils/filters.d.ts.map +1 -0
- package/lib/typescript/commonjs/utils/index.d.ts +1 -0
- package/lib/typescript/commonjs/utils/index.d.ts.map +1 -1
- package/lib/typescript/module/UIKitProvider.d.ts +15 -0
- package/lib/typescript/module/UIKitProvider.d.ts.map +1 -0
- package/lib/typescript/module/__tests__/smoke.test.d.ts +2 -0
- package/lib/typescript/module/__tests__/smoke.test.d.ts.map +1 -0
- package/lib/typescript/module/components/AppView.d.ts +19 -0
- package/lib/typescript/module/components/AppView.d.ts.map +1 -0
- package/lib/typescript/module/components/BaseDatesScrollView.d.ts.map +1 -1
- package/lib/typescript/module/components/BaseErrorBox.d.ts +14 -0
- package/lib/typescript/module/components/BaseErrorBox.d.ts.map +1 -0
- package/lib/typescript/module/components/BaseErrorScreen.d.ts +13 -0
- package/lib/typescript/module/components/BaseErrorScreen.d.ts.map +1 -0
- package/lib/typescript/module/components/BaseStickyFooter.d.ts +11 -0
- package/lib/typescript/module/components/BaseStickyFooter.d.ts.map +1 -0
- package/lib/typescript/module/components/DateSelector.d.ts.map +1 -1
- package/lib/typescript/module/components/DateTimeSelector.d.ts +10 -4
- package/lib/typescript/module/components/DateTimeSelector.d.ts.map +1 -1
- package/lib/typescript/module/components/FormikDateTimeSelector.d.ts +1 -1
- package/lib/typescript/module/components/FormikDateTimeSelectorBottomSheet.d.ts +1 -1
- package/lib/typescript/module/components/NetworkBanner.d.ts +10 -0
- package/lib/typescript/module/components/NetworkBanner.d.ts.map +1 -0
- package/lib/typescript/module/components/index.d.ts +3 -0
- package/lib/typescript/module/components/index.d.ts.map +1 -1
- package/lib/typescript/module/components/svgs/Warning.d.ts +6 -0
- package/lib/typescript/module/components/svgs/Warning.d.ts.map +1 -0
- package/lib/typescript/module/hooks/index.d.ts +2 -1
- package/lib/typescript/module/hooks/index.d.ts.map +1 -1
- package/lib/typescript/module/hooks/useInternetConnectionStatus.d.ts +4 -4
- package/lib/typescript/module/hooks/useInternetConnectionStatus.d.ts.map +1 -1
- package/lib/typescript/module/hooks/useTimezonedDate.d.ts +59 -0
- package/lib/typescript/module/hooks/useTimezonedDate.d.ts.map +1 -0
- package/lib/typescript/module/index.d.ts +3 -0
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/test-setup.d.ts +2 -0
- package/lib/typescript/module/test-setup.d.ts.map +1 -0
- package/lib/typescript/module/utils/filters.d.ts +4 -0
- package/lib/typescript/module/utils/filters.d.ts.map +1 -0
- package/lib/typescript/module/utils/index.d.ts +1 -0
- package/lib/typescript/module/utils/index.d.ts.map +1 -1
- package/package.json +19 -9
- package/src/components/BaseAlert.tsx +0 -181
- package/src/components/BaseBadge.tsx +0 -192
- package/src/components/BaseBottomSheetModal.tsx +0 -50
- package/src/components/BaseButton.tsx +0 -317
- package/src/components/BaseConfirmationModal.tsx +0 -66
- package/src/components/BaseDateInput.tsx +0 -153
- package/src/components/BaseDatesScrollView.tsx +0 -123
- package/src/components/BaseHorizontalTabs.tsx +0 -225
- package/src/components/BaseIcon.tsx +0 -41
- package/src/components/BaseIconBox.tsx +0 -75
- package/src/components/BaseRadioGroup.tsx +0 -75
- package/src/components/BaseSelect.tsx +0 -170
- package/src/components/BaseSelectionItem.tsx +0 -85
- package/src/components/BaseSpinner.tsx +0 -21
- package/src/components/BaseStackedList.tsx +0 -146
- package/src/components/BaseSwitch.tsx +0 -48
- package/src/components/BaseText.tsx +0 -34
- package/src/components/CameraImageInput.tsx +0 -610
- package/src/components/CameraWrapperModal.tsx +0 -309
- package/src/components/DateSelector.tsx +0 -91
- package/src/components/DateTimeSelector.tsx +0 -267
- package/src/components/FormikCameraImageInput.tsx +0 -39
- package/src/components/FormikDateInput.tsx +0 -53
- package/src/components/FormikDateSelector.tsx +0 -36
- package/src/components/FormikDateTimeSelector.tsx +0 -49
- package/src/components/FormikDateTimeSelectorBottomSheet.tsx +0 -129
- package/src/components/FormikRadioGroup.tsx +0 -35
- package/src/components/FormikSelect.tsx +0 -49
- package/src/components/ImagePickerBottomSheet.tsx +0 -109
- package/src/components/PhotoPickerModal.tsx +0 -116
- package/src/components/PressableOpacity.tsx +0 -88
- package/src/components/Toasts.tsx +0 -200
- package/src/components/index.ts +0 -30
- package/src/components/svgs/Camera.tsx +0 -14
- package/src/hooks/index.ts +0 -3
- package/src/hooks/useBreakpoints.ts +0 -20
- package/src/hooks/useInternetConnectionStatus.ts +0 -221
- package/src/hooks/useIsAboveBreakpoint.ts +0 -8
- package/src/utils/clabe.ts +0 -31
- package/src/utils/date.ts +0 -1
- package/src/utils/fileDirectoryUtils.ts +0 -12
- package/src/utils/fonts.ts +0 -118
- package/src/utils/index.ts +0 -3
- package/src/utils/mx-banks.json +0 -492
- package/src/utils/mx-banks.ts +0 -9
- package/src/utils/timeConstants.ts +0 -19
|
@@ -1,309 +0,0 @@
|
|
|
1
|
-
import { useAppState } from '@react-native-community/hooks';
|
|
2
|
-
import { useIsFocused } from '@react-navigation/native';
|
|
3
|
-
import { captureException } from '@sentry/react-native';
|
|
4
|
-
import { useMutation } from '@tanstack/react-query';
|
|
5
|
-
import clsx from 'clsx';
|
|
6
|
-
import { styled } from 'nativewind';
|
|
7
|
-
import {
|
|
8
|
-
ComponentProps, useRef, useState, useCallback,
|
|
9
|
-
} from 'react';
|
|
10
|
-
import toast from 'react-hot-toast/headless';
|
|
11
|
-
import { Linking } from 'react-native';
|
|
12
|
-
import {
|
|
13
|
-
ArrowLongLeftIcon, ArrowPathIcon, ArrowUturnLeftIcon, CheckIcon,
|
|
14
|
-
} from 'react-native-heroicons/outline';
|
|
15
|
-
import {
|
|
16
|
-
PhotoFile,
|
|
17
|
-
Camera as RNVisionCamera,
|
|
18
|
-
useCameraPermission,
|
|
19
|
-
useCameraDevice,
|
|
20
|
-
useCameraFormat,
|
|
21
|
-
FormatFilter,
|
|
22
|
-
CameraPosition,
|
|
23
|
-
} from 'react-native-vision-camera';
|
|
24
|
-
|
|
25
|
-
import {
|
|
26
|
-
View, Modal, Pressable, Image,
|
|
27
|
-
} from '../hoc-components';
|
|
28
|
-
import BaseButton from './BaseButton';
|
|
29
|
-
import BaseIcon from './BaseIcon';
|
|
30
|
-
import BaseText from './BaseText';
|
|
31
|
-
import PressableOpacity from './PressableOpacity';
|
|
32
|
-
import { useIsAboveBreakpoint } from '../hooks/useIsAboveBreakpoint';
|
|
33
|
-
import { ensureDirExists } from '../utils/fileDirectoryUtils';
|
|
34
|
-
import CameraSvg from './svgs/Camera';
|
|
35
|
-
import Toasts from './Toasts';
|
|
36
|
-
|
|
37
|
-
interface PermissionCardProps {
|
|
38
|
-
onPermissionRequestPress: () => void;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export type CameraWrapperModalImage = PhotoFile & { uri: string };
|
|
42
|
-
|
|
43
|
-
function PermissionCard({ onPermissionRequestPress }: PermissionCardProps) {
|
|
44
|
-
const largePhone = useIsAboveBreakpoint('xs');
|
|
45
|
-
|
|
46
|
-
return (
|
|
47
|
-
<View className={clsx(
|
|
48
|
-
'w-full flex-col items-center rounded-lg bg-white p-4',
|
|
49
|
-
largePhone ? 'mt-10 space-y-10' : 'space-y-4',
|
|
50
|
-
)}
|
|
51
|
-
>
|
|
52
|
-
<BaseText className={clsx('text-center font-semibold', largePhone && 'text-xl')}>
|
|
53
|
-
Necesitamos permiso para acceder a la camara
|
|
54
|
-
</BaseText>
|
|
55
|
-
<CameraSvg
|
|
56
|
-
width="100%"
|
|
57
|
-
height={largePhone ? 200 : 100}
|
|
58
|
-
/>
|
|
59
|
-
<BaseButton
|
|
60
|
-
className="w-full"
|
|
61
|
-
size={largePhone ? 'md' : 'xs'}
|
|
62
|
-
text="Permitir"
|
|
63
|
-
onPress={onPermissionRequestPress}
|
|
64
|
-
/>
|
|
65
|
-
</View>
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
interface CameraPreviewProps {
|
|
70
|
-
onCapture: (photoFile: CameraWrapperModalImage) => void;
|
|
71
|
-
previewOverlay: JSX.Element | undefined;
|
|
72
|
-
filters: FormatFilter[];
|
|
73
|
-
allowDeviceSwitching: boolean;
|
|
74
|
-
isActive: boolean;
|
|
75
|
-
initialDevice: CameraPosition;
|
|
76
|
-
pathToSave?: string;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function CameraPreview({
|
|
80
|
-
onCapture,
|
|
81
|
-
previewOverlay,
|
|
82
|
-
filters,
|
|
83
|
-
isActive,
|
|
84
|
-
allowDeviceSwitching,
|
|
85
|
-
initialDevice,
|
|
86
|
-
pathToSave,
|
|
87
|
-
}: CameraPreviewProps) {
|
|
88
|
-
const cameraRef = useRef<RNVisionCamera>(null);
|
|
89
|
-
const [selectedDevice, setSelectedDevice] = useState<CameraPosition>(initialDevice);
|
|
90
|
-
const device = useCameraDevice(selectedDevice);
|
|
91
|
-
const format = useCameraFormat(device, filters);
|
|
92
|
-
|
|
93
|
-
const { mutate } = useMutation<PhotoFile, Error, void>({
|
|
94
|
-
mutationFn: async () => {
|
|
95
|
-
if (cameraRef.current) {
|
|
96
|
-
if (pathToSave) await ensureDirExists(pathToSave);
|
|
97
|
-
|
|
98
|
-
const file = await cameraRef.current.takePhoto({ path: pathToSave?.replace('file://', '') ?? undefined });
|
|
99
|
-
|
|
100
|
-
return file;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return Promise.reject(new Error('Camera ref is not defined'));
|
|
104
|
-
},
|
|
105
|
-
networkMode: 'always',
|
|
106
|
-
onSuccess: (photoFile) => onCapture({ ...photoFile, uri: `file://${photoFile.path}` }),
|
|
107
|
-
onError: (error) => {
|
|
108
|
-
captureException(error);
|
|
109
|
-
toast.error('Ocurrió un error al tomar la foto');
|
|
110
|
-
},
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
return (
|
|
114
|
-
<View className="flex h-full w-full flex-col">
|
|
115
|
-
{device ? (
|
|
116
|
-
<View className="relative h-full w-full flex-1 overflow-hidden rounded-xl border-2">
|
|
117
|
-
<RNVisionCamera
|
|
118
|
-
style={{ flex: 1, width: '100%', height: '100%' }}
|
|
119
|
-
ref={cameraRef}
|
|
120
|
-
device={device}
|
|
121
|
-
format={format}
|
|
122
|
-
isActive={isActive}
|
|
123
|
-
photo
|
|
124
|
-
/>
|
|
125
|
-
{previewOverlay}
|
|
126
|
-
{allowDeviceSwitching && (
|
|
127
|
-
<PressableOpacity
|
|
128
|
-
onPress={() => setSelectedDevice(selectedDevice === 'back' ? 'front' : 'back')}
|
|
129
|
-
className="absolute bottom-8 right-8 flex h-12 w-12 items-center justify-center rounded-full bg-secondary"
|
|
130
|
-
>
|
|
131
|
-
<BaseIcon
|
|
132
|
-
icon={ArrowPathIcon}
|
|
133
|
-
className="h-full w-full"
|
|
134
|
-
color="utility-gray-200"
|
|
135
|
-
/>
|
|
136
|
-
</PressableOpacity>
|
|
137
|
-
)}
|
|
138
|
-
</View>
|
|
139
|
-
) : (
|
|
140
|
-
<View className="flex h-full w-full items-center justify-center bg-utility-gray-200">
|
|
141
|
-
<BaseText className="text-secondary">
|
|
142
|
-
No fue posible acceder a la camara
|
|
143
|
-
</BaseText>
|
|
144
|
-
</View>
|
|
145
|
-
)}
|
|
146
|
-
<PressableOpacity
|
|
147
|
-
onPress={() => mutate()}
|
|
148
|
-
className="my-10 h-20 w-20 self-center rounded-full border-4 border-white bg-black p-1"
|
|
149
|
-
>
|
|
150
|
-
<View
|
|
151
|
-
className="h-full w-full rounded-full bg-white"
|
|
152
|
-
/>
|
|
153
|
-
</PressableOpacity>
|
|
154
|
-
</View>
|
|
155
|
-
);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
interface PhotoFilePreviewProps {
|
|
159
|
-
photoFile: CameraWrapperModalImage;
|
|
160
|
-
onConfirm: () => void;
|
|
161
|
-
onCancel: () => void;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
function PhotoFilePreview({ photoFile, onConfirm, onCancel }: PhotoFilePreviewProps) {
|
|
165
|
-
return (
|
|
166
|
-
<View className="flex h-full w-full flex-col items-center pb-10">
|
|
167
|
-
<View className="w-full flex-1 overflow-hidden rounded-xl">
|
|
168
|
-
<Image
|
|
169
|
-
style={{ width: 'auto', height: '100%' }}
|
|
170
|
-
source={{ uri: photoFile.uri }}
|
|
171
|
-
resizeMode="cover"
|
|
172
|
-
/>
|
|
173
|
-
</View>
|
|
174
|
-
<View className="mt-12 flex flex-row items-center space-x-16">
|
|
175
|
-
<Pressable
|
|
176
|
-
onPress={onCancel}
|
|
177
|
-
>
|
|
178
|
-
<BaseIcon
|
|
179
|
-
icon={ArrowUturnLeftIcon}
|
|
180
|
-
size={64}
|
|
181
|
-
color="fg-error-primary"
|
|
182
|
-
/>
|
|
183
|
-
</Pressable>
|
|
184
|
-
<Pressable
|
|
185
|
-
onPress={onConfirm}
|
|
186
|
-
className="self-end"
|
|
187
|
-
>
|
|
188
|
-
<BaseIcon
|
|
189
|
-
icon={CheckIcon}
|
|
190
|
-
size={64}
|
|
191
|
-
color="fg-success-primary"
|
|
192
|
-
/>
|
|
193
|
-
</Pressable>
|
|
194
|
-
</View>
|
|
195
|
-
</View>
|
|
196
|
-
);
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
interface Props extends ComponentProps<typeof Modal> {
|
|
200
|
-
onCapture: (photoFile: CameraWrapperModalImage) => void;
|
|
201
|
-
onClose: () => void;
|
|
202
|
-
filters?: FormatFilter[];
|
|
203
|
-
previewOverlay?: JSX.Element;
|
|
204
|
-
allowDeviceSwitching?: boolean;
|
|
205
|
-
initialDevice?: CameraPosition;
|
|
206
|
-
pathToSave?: string;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
function CameraWrapperModal({
|
|
210
|
-
onCapture,
|
|
211
|
-
onClose,
|
|
212
|
-
filters = [{ photoResolution: { width: 720, height: 1280 } }],
|
|
213
|
-
previewOverlay = undefined,
|
|
214
|
-
allowDeviceSwitching = true,
|
|
215
|
-
initialDevice = 'back',
|
|
216
|
-
pathToSave = undefined,
|
|
217
|
-
...modalProps
|
|
218
|
-
}: Props) {
|
|
219
|
-
const [photoFile, setPhotoFile] = useState<CameraWrapperModalImage | null>(null);
|
|
220
|
-
const [permissionRequested, setPermissionRequested] = useState(false);
|
|
221
|
-
|
|
222
|
-
const isFocused = useIsFocused();
|
|
223
|
-
const appState = useAppState();
|
|
224
|
-
const isActive = isFocused && appState === 'active';
|
|
225
|
-
|
|
226
|
-
const { hasPermission, requestPermission } = useCameraPermission();
|
|
227
|
-
|
|
228
|
-
const handlePermissionRequestPress = useCallback(() => {
|
|
229
|
-
if (!permissionRequested) {
|
|
230
|
-
setPermissionRequested(true);
|
|
231
|
-
requestPermission();
|
|
232
|
-
} else {
|
|
233
|
-
Linking.openSettings();
|
|
234
|
-
}
|
|
235
|
-
}, [permissionRequested, requestPermission]);
|
|
236
|
-
|
|
237
|
-
const handleCaptureConfirm = useCallback(() => {
|
|
238
|
-
if (photoFile) {
|
|
239
|
-
onCapture({
|
|
240
|
-
...photoFile,
|
|
241
|
-
uri: `file://${photoFile.path}`,
|
|
242
|
-
});
|
|
243
|
-
setPhotoFile(null);
|
|
244
|
-
}
|
|
245
|
-
}, [onCapture, photoFile]);
|
|
246
|
-
|
|
247
|
-
const removePhotoFile = useCallback(() => {
|
|
248
|
-
setPhotoFile(null);
|
|
249
|
-
}, [setPhotoFile]);
|
|
250
|
-
|
|
251
|
-
let content;
|
|
252
|
-
|
|
253
|
-
if (!hasPermission) {
|
|
254
|
-
content = (
|
|
255
|
-
<PermissionCard
|
|
256
|
-
onPermissionRequestPress={handlePermissionRequestPress}
|
|
257
|
-
/>
|
|
258
|
-
);
|
|
259
|
-
} else if (photoFile) {
|
|
260
|
-
content = (
|
|
261
|
-
<PhotoFilePreview
|
|
262
|
-
photoFile={photoFile}
|
|
263
|
-
onCancel={removePhotoFile}
|
|
264
|
-
onConfirm={handleCaptureConfirm}
|
|
265
|
-
/>
|
|
266
|
-
);
|
|
267
|
-
} else {
|
|
268
|
-
content = (
|
|
269
|
-
<CameraPreview
|
|
270
|
-
isActive={isActive}
|
|
271
|
-
filters={filters}
|
|
272
|
-
onCapture={setPhotoFile}
|
|
273
|
-
previewOverlay={previewOverlay}
|
|
274
|
-
allowDeviceSwitching={allowDeviceSwitching}
|
|
275
|
-
initialDevice={initialDevice}
|
|
276
|
-
pathToSave={pathToSave}
|
|
277
|
-
/>
|
|
278
|
-
);
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
return (
|
|
282
|
-
<Modal
|
|
283
|
-
animationType="slide"
|
|
284
|
-
statusBarTranslucent
|
|
285
|
-
{...modalProps}
|
|
286
|
-
>
|
|
287
|
-
<Toasts />
|
|
288
|
-
<View className="flex h-full w-full flex-col items-center bg-black px-4 pt-12">
|
|
289
|
-
<View className="self-start py-4">
|
|
290
|
-
<Pressable
|
|
291
|
-
hitSlop={10}
|
|
292
|
-
onPress={onClose}
|
|
293
|
-
>
|
|
294
|
-
<BaseIcon
|
|
295
|
-
icon={ArrowLongLeftIcon}
|
|
296
|
-
color="fg-brand-primary"
|
|
297
|
-
size={32}
|
|
298
|
-
/>
|
|
299
|
-
</Pressable>
|
|
300
|
-
</View>
|
|
301
|
-
<View className="mb-4 w-full flex-1">
|
|
302
|
-
{content}
|
|
303
|
-
</View>
|
|
304
|
-
</View>
|
|
305
|
-
</Modal>
|
|
306
|
-
);
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
export default styled(CameraWrapperModal);
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
eachDayOfInterval,
|
|
3
|
-
isBefore,
|
|
4
|
-
isAfter,
|
|
5
|
-
getDay,
|
|
6
|
-
addDays,
|
|
7
|
-
startOfDay,
|
|
8
|
-
} from 'date-fns';
|
|
9
|
-
import { styled } from 'nativewind';
|
|
10
|
-
import React, { useMemo, useCallback } from 'react';
|
|
11
|
-
import { ViewProps } from 'react-native';
|
|
12
|
-
|
|
13
|
-
import { View } from '../hoc-components';
|
|
14
|
-
import BaseDatesScrollView from './BaseDatesScrollView';
|
|
15
|
-
import BaseText from './BaseText';
|
|
16
|
-
|
|
17
|
-
export interface DateSelectorProps extends ViewProps {
|
|
18
|
-
value: Date | undefined;
|
|
19
|
-
onChange: (date?: Date) => void;
|
|
20
|
-
label?: string;
|
|
21
|
-
description?: string;
|
|
22
|
-
minDate?: Date;
|
|
23
|
-
maxDate?: Date;
|
|
24
|
-
disabledWeekDays?: number[];
|
|
25
|
-
disabled?: boolean;
|
|
26
|
-
error?: string;
|
|
27
|
-
allowPastDates?: boolean;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function DateSelector({
|
|
31
|
-
value,
|
|
32
|
-
label,
|
|
33
|
-
description,
|
|
34
|
-
onChange,
|
|
35
|
-
minDate,
|
|
36
|
-
maxDate,
|
|
37
|
-
disabledWeekDays = [],
|
|
38
|
-
disabled = false,
|
|
39
|
-
error,
|
|
40
|
-
allowPastDates = false,
|
|
41
|
-
...props
|
|
42
|
-
}: DateSelectorProps) {
|
|
43
|
-
const minDateStartOfDay = useMemo(() => startOfDay(minDate || new Date()), [minDate]);
|
|
44
|
-
const maxDateEndOfDay = useMemo(() => (maxDate ? startOfDay(maxDate) : null), [maxDate]);
|
|
45
|
-
|
|
46
|
-
const dateRange = useMemo(() => {
|
|
47
|
-
const startDate = minDateStartOfDay;
|
|
48
|
-
const endDate = maxDateEndOfDay || addDays(startDate, 7);
|
|
49
|
-
|
|
50
|
-
return eachDayOfInterval({ start: startDate, end: endDate });
|
|
51
|
-
}, [minDateStartOfDay, maxDateEndOfDay]);
|
|
52
|
-
|
|
53
|
-
const isDayDisabled = useCallback((day: Date) => {
|
|
54
|
-
if (disabled) return true;
|
|
55
|
-
if (minDateStartOfDay && isBefore(day, minDateStartOfDay)) return true;
|
|
56
|
-
if (maxDateEndOfDay && isAfter(day, maxDateEndOfDay)) return true;
|
|
57
|
-
if (disabledWeekDays.includes(getDay(day))) return true;
|
|
58
|
-
if (!allowPastDates && isBefore(day, startOfDay(new Date()))) return true;
|
|
59
|
-
return false;
|
|
60
|
-
}, [disabled, minDateStartOfDay, maxDateEndOfDay, disabledWeekDays, allowPastDates]);
|
|
61
|
-
|
|
62
|
-
const handleDayPress = useCallback((day: Date) => {
|
|
63
|
-
if (isDayDisabled(day)) return;
|
|
64
|
-
|
|
65
|
-
onChange?.(day);
|
|
66
|
-
}, [isDayDisabled, onChange]);
|
|
67
|
-
|
|
68
|
-
return (
|
|
69
|
-
<View
|
|
70
|
-
className="flex flex-col"
|
|
71
|
-
{...props}
|
|
72
|
-
>
|
|
73
|
-
{label && <BaseText className="mb-2 font-semibold text-secondary">{label}</BaseText>}
|
|
74
|
-
{description && <BaseText className="mb-2 text-tertiary">{description}</BaseText>}
|
|
75
|
-
<BaseDatesScrollView
|
|
76
|
-
dateRange={dateRange}
|
|
77
|
-
selectedDate={value}
|
|
78
|
-
isDayDisabled={isDayDisabled}
|
|
79
|
-
onDayPress={handleDayPress}
|
|
80
|
-
/>
|
|
81
|
-
{error && (
|
|
82
|
-
<BaseText className="mt-2 text-error-primary">
|
|
83
|
-
{error}
|
|
84
|
-
</BaseText>
|
|
85
|
-
)}
|
|
86
|
-
</View>
|
|
87
|
-
);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
export default styled(DateSelector);
|
|
91
|
-
|
|
@@ -1,267 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
format,
|
|
3
|
-
eachDayOfInterval,
|
|
4
|
-
isSameDay,
|
|
5
|
-
isBefore,
|
|
6
|
-
isAfter,
|
|
7
|
-
getDay,
|
|
8
|
-
addDays,
|
|
9
|
-
startOfDay,
|
|
10
|
-
isToday,
|
|
11
|
-
} from 'date-fns';
|
|
12
|
-
import { styled } from 'nativewind';
|
|
13
|
-
import React, { useMemo, useCallback, useState } from 'react';
|
|
14
|
-
import { ViewProps } from 'react-native';
|
|
15
|
-
|
|
16
|
-
import { View, GestureScrollView, LinearGradient } from '../hoc-components';
|
|
17
|
-
import BaseDatesScrollView from './BaseDatesScrollView';
|
|
18
|
-
import BaseRadioGroup, { RadioOption } from './BaseRadioGroup';
|
|
19
|
-
import BaseText from './BaseText';
|
|
20
|
-
|
|
21
|
-
interface TimeSlot {
|
|
22
|
-
hour: number;
|
|
23
|
-
minute: number;
|
|
24
|
-
endHour: number;
|
|
25
|
-
endMinute: number;
|
|
26
|
-
label: string;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
interface TimeSlotsProps {
|
|
30
|
-
timeSlots: TimeSlot[];
|
|
31
|
-
selectedTime: { hour: number; minute: number } | null;
|
|
32
|
-
handleTimePress: (time: { hour: number; minute: number }) => void;
|
|
33
|
-
disabled: boolean;
|
|
34
|
-
timeLabel?: string;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function TimeSlots({
|
|
38
|
-
timeSlots,
|
|
39
|
-
selectedTime,
|
|
40
|
-
handleTimePress,
|
|
41
|
-
disabled,
|
|
42
|
-
timeLabel,
|
|
43
|
-
}: TimeSlotsProps) {
|
|
44
|
-
const radioOptions: RadioOption[] = timeSlots.map((slot) => ({
|
|
45
|
-
label: slot.label,
|
|
46
|
-
value: `${slot.hour}-${slot.minute}`,
|
|
47
|
-
}));
|
|
48
|
-
|
|
49
|
-
const selectedValue = selectedTime ? `${selectedTime.hour}-${selectedTime.minute}` : undefined;
|
|
50
|
-
|
|
51
|
-
const handleRadioChange = (value: unknown) => {
|
|
52
|
-
const [hour, minute] = (value as string).split('-').map(Number);
|
|
53
|
-
handleTimePress({ hour, minute });
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
return (
|
|
57
|
-
<View className="mt-4 flex-1">
|
|
58
|
-
{timeLabel && (
|
|
59
|
-
<BaseText className="mb-3 text-sm font-semibold text-secondary">
|
|
60
|
-
{timeLabel}
|
|
61
|
-
</BaseText>
|
|
62
|
-
)}
|
|
63
|
-
<View className="relative flex-1">
|
|
64
|
-
<GestureScrollView
|
|
65
|
-
style={{ flex: 1, minHeight: 200 }}
|
|
66
|
-
showsVerticalScrollIndicator={false}
|
|
67
|
-
nestedScrollEnabled
|
|
68
|
-
>
|
|
69
|
-
<BaseRadioGroup
|
|
70
|
-
options={radioOptions}
|
|
71
|
-
value={selectedValue}
|
|
72
|
-
onChange={handleRadioChange}
|
|
73
|
-
disabled={disabled}
|
|
74
|
-
/>
|
|
75
|
-
<View className="h-20" />
|
|
76
|
-
</GestureScrollView>
|
|
77
|
-
{radioOptions.length > 3 && (
|
|
78
|
-
<LinearGradient
|
|
79
|
-
colors={[
|
|
80
|
-
'rgba(255, 255, 255, 0)',
|
|
81
|
-
'rgba(255, 255, 255, 1)',
|
|
82
|
-
]}
|
|
83
|
-
start={{ x: 0, y: 0 }}
|
|
84
|
-
end={{ x: 0, y: 1 }}
|
|
85
|
-
className="absolute bottom-0 left-0 h-32 w-full"
|
|
86
|
-
style={{ pointerEvents: 'none' }}
|
|
87
|
-
/>
|
|
88
|
-
)}
|
|
89
|
-
</View>
|
|
90
|
-
</View>
|
|
91
|
-
);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
export interface DateTimeSelectorProps extends ViewProps {
|
|
95
|
-
value: Date | undefined;
|
|
96
|
-
onChange: (date?: Date) => void;
|
|
97
|
-
minDate?: Date;
|
|
98
|
-
maxDate?: Date;
|
|
99
|
-
minHour?: number;
|
|
100
|
-
maxHour?: number;
|
|
101
|
-
timeSlotStepMinutes?: number;
|
|
102
|
-
disabledWeekDays?: number[];
|
|
103
|
-
disabledHours?: number[];
|
|
104
|
-
dateLabel?: string;
|
|
105
|
-
timeLabel?: string;
|
|
106
|
-
description?: string;
|
|
107
|
-
className?: string;
|
|
108
|
-
disabled?: boolean;
|
|
109
|
-
error?: string;
|
|
110
|
-
allowPastDatetimes?: boolean;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
function DateTimeSelector({
|
|
114
|
-
value,
|
|
115
|
-
onChange,
|
|
116
|
-
minDate,
|
|
117
|
-
maxDate,
|
|
118
|
-
minHour = 0,
|
|
119
|
-
maxHour = 23,
|
|
120
|
-
timeSlotStepMinutes = 30,
|
|
121
|
-
disabledWeekDays = [],
|
|
122
|
-
disabledHours = [],
|
|
123
|
-
dateLabel,
|
|
124
|
-
timeLabel,
|
|
125
|
-
description,
|
|
126
|
-
disabled = false,
|
|
127
|
-
error,
|
|
128
|
-
allowPastDatetimes = false,
|
|
129
|
-
...props
|
|
130
|
-
}: DateTimeSelectorProps) {
|
|
131
|
-
const [selectedDate, setSelectedDate] = useState<Date | undefined>(value);
|
|
132
|
-
|
|
133
|
-
const minDateStartOfDay = useMemo(() => startOfDay(minDate || new Date()), [minDate]);
|
|
134
|
-
const maxDateEndOfDay = useMemo(() => (maxDate ? startOfDay(maxDate) : null), [maxDate]);
|
|
135
|
-
|
|
136
|
-
const dateRange = useMemo(() => {
|
|
137
|
-
const startDate = minDateStartOfDay;
|
|
138
|
-
const endDate = maxDateEndOfDay || addDays(startDate, 7);
|
|
139
|
-
|
|
140
|
-
return eachDayOfInterval({ start: startDate, end: endDate });
|
|
141
|
-
}, [minDateStartOfDay, maxDateEndOfDay]);
|
|
142
|
-
|
|
143
|
-
const getTimeSlotsForDate = useCallback((date: Date): TimeSlot[] => {
|
|
144
|
-
const slots: TimeSlot[] = [];
|
|
145
|
-
const now = new Date();
|
|
146
|
-
|
|
147
|
-
for (let hour = minHour; hour <= maxHour; hour += 1) {
|
|
148
|
-
if (disabledHours.includes(hour)) continue;
|
|
149
|
-
if (!allowPastDatetimes && isToday(date) && hour < now.getHours()) continue;
|
|
150
|
-
|
|
151
|
-
for (let minute = 0; minute < 60; minute += timeSlotStepMinutes) {
|
|
152
|
-
if (
|
|
153
|
-
!allowPastDatetimes
|
|
154
|
-
&& isToday(date)
|
|
155
|
-
&& hour === now.getHours()
|
|
156
|
-
&& minute <= now.getMinutes()
|
|
157
|
-
) continue;
|
|
158
|
-
|
|
159
|
-
const endTime = new Date();
|
|
160
|
-
endTime.setHours(hour, minute + timeSlotStepMinutes, 0, 0);
|
|
161
|
-
const endHour = endTime.getHours();
|
|
162
|
-
const endMinute = endTime.getMinutes();
|
|
163
|
-
|
|
164
|
-
const startTime = new Date().setHours(hour, minute);
|
|
165
|
-
const endTimeForLabel = new Date().setHours(endHour, endMinute);
|
|
166
|
-
const startLabel = format(startTime, 'h:mm');
|
|
167
|
-
const endLabel = format(endTimeForLabel, 'h:mm a');
|
|
168
|
-
const hourLabel = `${startLabel} - ${endLabel}`;
|
|
169
|
-
|
|
170
|
-
slots.push({
|
|
171
|
-
hour, minute, endHour, endMinute, label: hourLabel,
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
return slots;
|
|
177
|
-
}, [minHour, maxHour, timeSlotStepMinutes, disabledHours, allowPastDatetimes]);
|
|
178
|
-
|
|
179
|
-
const timeSlots = useMemo<TimeSlot[]>(() => {
|
|
180
|
-
if (!selectedDate) return [];
|
|
181
|
-
return getTimeSlotsForDate(selectedDate);
|
|
182
|
-
}, [selectedDate, getTimeSlotsForDate]);
|
|
183
|
-
|
|
184
|
-
const isDayDisabled = useCallback((day: Date) => {
|
|
185
|
-
if (disabled) return true;
|
|
186
|
-
if (minDateStartOfDay && isBefore(day, minDateStartOfDay)) return true;
|
|
187
|
-
if (maxDateEndOfDay && isAfter(day, maxDateEndOfDay)) return true;
|
|
188
|
-
if (disabledWeekDays.includes(getDay(day))) return true;
|
|
189
|
-
if (!allowPastDatetimes && isBefore(day, startOfDay(new Date()))) return true;
|
|
190
|
-
|
|
191
|
-
// Check if there are available time slots for this day
|
|
192
|
-
const availableSlots = getTimeSlotsForDate(day);
|
|
193
|
-
if (availableSlots.length === 0) return true;
|
|
194
|
-
|
|
195
|
-
return false;
|
|
196
|
-
}, [
|
|
197
|
-
disabled,
|
|
198
|
-
minDateStartOfDay,
|
|
199
|
-
maxDateEndOfDay,
|
|
200
|
-
disabledWeekDays,
|
|
201
|
-
allowPastDatetimes,
|
|
202
|
-
getTimeSlotsForDate,
|
|
203
|
-
]);
|
|
204
|
-
|
|
205
|
-
const handleDayPress = useCallback((day: Date) => {
|
|
206
|
-
if (isDayDisabled(day)) return;
|
|
207
|
-
setSelectedDate(day);
|
|
208
|
-
|
|
209
|
-
if (value) {
|
|
210
|
-
onChange(undefined);
|
|
211
|
-
}
|
|
212
|
-
}, [isDayDisabled, onChange, value]);
|
|
213
|
-
|
|
214
|
-
const handleTimePress = useCallback((time: { hour: number; minute: number }) => {
|
|
215
|
-
if (selectedDate) {
|
|
216
|
-
const newDate = new Date(selectedDate);
|
|
217
|
-
newDate.setHours(time.hour, time.minute, 0, 0);
|
|
218
|
-
onChange(newDate);
|
|
219
|
-
}
|
|
220
|
-
}, [selectedDate, onChange]);
|
|
221
|
-
|
|
222
|
-
const selectedTime = useMemo(() => {
|
|
223
|
-
if (!value || !selectedDate || !isSameDay(value, selectedDate)) return null;
|
|
224
|
-
|
|
225
|
-
return { hour: value.getHours(), minute: value.getMinutes() };
|
|
226
|
-
}, [value, selectedDate]);
|
|
227
|
-
|
|
228
|
-
return (
|
|
229
|
-
<View
|
|
230
|
-
className="flex flex-1 flex-col"
|
|
231
|
-
{...props}
|
|
232
|
-
>
|
|
233
|
-
{dateLabel && (
|
|
234
|
-
<BaseText className="mb-2 font-semibold text-secondary">
|
|
235
|
-
{dateLabel}
|
|
236
|
-
</BaseText>
|
|
237
|
-
)}
|
|
238
|
-
{description && (
|
|
239
|
-
<BaseText className="mb-4 text-tertiary">
|
|
240
|
-
{description}
|
|
241
|
-
</BaseText>
|
|
242
|
-
)}
|
|
243
|
-
<BaseDatesScrollView
|
|
244
|
-
dateRange={dateRange}
|
|
245
|
-
selectedDate={selectedDate}
|
|
246
|
-
isDayDisabled={isDayDisabled}
|
|
247
|
-
onDayPress={handleDayPress}
|
|
248
|
-
/>
|
|
249
|
-
{selectedDate && (
|
|
250
|
-
<TimeSlots
|
|
251
|
-
timeSlots={timeSlots}
|
|
252
|
-
selectedTime={selectedTime}
|
|
253
|
-
handleTimePress={handleTimePress}
|
|
254
|
-
disabled={disabled}
|
|
255
|
-
timeLabel={timeLabel}
|
|
256
|
-
/>
|
|
257
|
-
)}
|
|
258
|
-
{error && (
|
|
259
|
-
<BaseText className="mt-2 text-error-primary">
|
|
260
|
-
{error}
|
|
261
|
-
</BaseText>
|
|
262
|
-
)}
|
|
263
|
-
</View>
|
|
264
|
-
);
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
export default styled(DateTimeSelector);
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { ErrorMessage, useField } from 'formik';
|
|
2
|
-
import { styled } from 'nativewind';
|
|
3
|
-
import React from 'react';
|
|
4
|
-
import { ViewProps } from 'react-native';
|
|
5
|
-
|
|
6
|
-
import BaseText from './BaseText';
|
|
7
|
-
import CameraImageInput, { CameraImageInputProps } from './CameraImageInput';
|
|
8
|
-
|
|
9
|
-
interface FormikCameraImageInputProps extends Omit<CameraImageInputProps, 'value' | 'onValueChange' | 'hasError'>, ViewProps {
|
|
10
|
-
name: string;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
function FormikCameraImageInput({
|
|
14
|
-
name,
|
|
15
|
-
...props
|
|
16
|
-
}: FormikCameraImageInputProps) {
|
|
17
|
-
const [field, meta, helpers] = useField(name);
|
|
18
|
-
|
|
19
|
-
const hasError = !!(meta.error && meta.touched);
|
|
20
|
-
|
|
21
|
-
return (
|
|
22
|
-
<>
|
|
23
|
-
<CameraImageInput
|
|
24
|
-
value={field.value}
|
|
25
|
-
onValueChange={helpers.setValue}
|
|
26
|
-
hasError={hasError}
|
|
27
|
-
showImages
|
|
28
|
-
{...props}
|
|
29
|
-
/>
|
|
30
|
-
{hasError && (
|
|
31
|
-
<ErrorMessage name={name}>
|
|
32
|
-
{(msg) => <BaseText className="mt-1 text-sm text-error-primary">{msg}</BaseText>}
|
|
33
|
-
</ErrorMessage>
|
|
34
|
-
)}
|
|
35
|
-
</>
|
|
36
|
-
);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export default styled(FormikCameraImageInput);
|