react-native-elements#ButtonGroup TypeScript Examples
The following examples show how to use
react-native-elements#ButtonGroup.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: ClientListScreen.tsx From react-native-network-client with Apache License 2.0 | 5 votes |
export default function ClientListScreen({
navigation,
route,
}: ClientListScreenProps) {
const [clients, setClients] = useState<NetworkClientItem[]>([]);
useEffect(() => {
if (!clients.length) {
createTestClients().then((testClients) =>
setClients([...clients, ...testClients])
);
}
}, []);
useEffect(() => {
if (route.params?.createdClient) {
setClients([...clients, route.params.createdClient]);
}
}, [route.params?.createdClient]);
const deleteClient = (clientIndex: number) => {
setClients(clients.filter((_, index) => clientIndex !== index));
};
const renderItem = ({
item,
index,
}: {
item: NetworkClientItem;
index: number;
}) => (
<ClientListItem
index={index}
item={item}
deleteClient={deleteClient}
navigate={navigation.navigate}
/>
);
const buttons = [
{
title: "Add API Client",
action: () => navigation.navigate("CreateAPIClient"),
},
{
title: "Add WebSocket Client",
action: () => navigation.navigate("CreateWebSocketClient"),
},
];
const onButtonPress = (index: number) => buttons[index].action();
return (
<SafeAreaView style={{ flex: 1 }}>
<FlatList
data={clients}
renderItem={renderItem}
keyExtractor={networkClientKeyExtractor}
testID="client_list.scroll_view"
/>
<ButtonGroup
buttons={buttons.map((button) => button.title)}
onPress={onButtonPress}
/>
</SafeAreaView>
);
}
Example #2
Source File: FilePickerButtonGroup.tsx From react-native-network-client with Apache License 2.0 | 4 votes |
FilePickerButtonGroup = (props: FilePickerButtonGroupProps) => {
const hasPhotoLibraryPermissions = async () => {
if (Platform.OS === "android") return true;
let result = await check(PERMISSIONS.IOS.PHOTO_LIBRARY);
if (result === RESULTS.GRANTED || result === RESULTS.LIMITED) {
return true;
} else if (
result !== RESULTS.BLOCKED &&
result !== RESULTS.UNAVAILABLE
) {
await request(PERMISSIONS.IOS.PHOTO_LIBRARY);
hasPhotoLibraryPermissions();
}
return false;
};
const pickFile = async () => {
const hasPermission = await hasPhotoLibraryPermissions();
if (hasPermission) {
try {
const result = await DocumentPicker.pickSingle({
type: [DocumentPicker.types.allFiles],
copyTo: "cachesDirectory",
});
const file = { ...result, uri: result.fileCopyUri };
props.onFilePicked(file);
} catch (err) {
if (DocumentPicker.isCancel(err as Error)) {
// User cancelled the picker, exit any dialogs or menus and move on
} else {
throw err;
}
}
}
};
const pickImage = async () => {
const hasPermission = await hasPhotoLibraryPermissions();
if (hasPermission) {
launchImageLibrary({ quality: 1, mediaType: "photo" }, (result) => {
if (result.assets) {
const file = {
name: result.assets[0].fileName,
type: result.assets[0].type,
size: result.assets[0].fileSize,
uri: result.assets[0].uri,
};
props.onFilePicked(file);
}
});
}
};
const attachFile = async (fileContent: FileContent) => {
const file: File = await createNativeFile(fileContent);
props.onFilePicked(file);
};
const attachSampleImage = async () => {
await attachFile(sampleImage);
};
const attachSampleText = async () => {
await attachFile(sampleText);
};
const buttons = [
{ title: "Select Image", onPress: pickImage, android: true },
{ title: "Select File", onPress: pickFile, android: true },
{ title: "Attach Image", onPress: attachSampleImage, android: false },
{ title: "Attach Text", onPress: attachSampleText, android: false },
];
const onButtonPress = (index: number) => buttons[index].onPress();
return (
<ButtonGroup
buttons={buttons
.filter((b) => (Platform.OS === "android" ? b.android : true))
.map((button) => button.title)}
onPress={onButtonPress}
disabled={props.disabled}
/>
);
}
Example #3
Source File: P12Inputs.tsx From react-native-network-client with Apache License 2.0 | 4 votes |
P12Inputs = (props: P12InputsProps) => {
const [url, setUrl] = useState("");
const hasPhotoLibraryPermissions = async () => {
const permission =
Platform.OS === "ios"
? PERMISSIONS.IOS.PHOTO_LIBRARY
: PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE;
let result = await check(permission);
if (result === RESULTS.GRANTED || result === RESULTS.LIMITED) {
return true;
} else if (
result !== RESULTS.BLOCKED &&
result !== RESULTS.UNAVAILABLE
) {
await request(permission);
hasPhotoLibraryPermissions();
}
console.log(result);
return false;
};
const pickCertificate = async () => {
const hasPermission = await hasPhotoLibraryPermissions();
if (hasPermission) {
try {
const result = await DocumentPicker.pickSingle({
type: [DocumentPicker.types.allFiles],
});
if (result.fileCopyUri) {
props.onSelectP12(result.fileCopyUri);
}
} catch (err) {
if (DocumentPicker.isCancel(err as Error)) {
// User cancelled the picker, exit any dialogs or menus and move on
} else {
throw err;
}
}
}
};
const downloadCertificate = async () => {
const file: File = await downloadToNativeFile(url, clientCertP12);
props.onSelectP12(`${file.uri}`);
};
const clearP12Configuration = () => {
props.onSelectP12("");
props.onPasswordChange(undefined);
};
const buttons = [
{ title: "Select", onPress: pickCertificate },
{ title: "Download", onPress: downloadCertificate },
];
const onButtonPress = (index: number) => buttons[index].onPress();
const rightIcon = (
<View style={{ width: 250 }}>
{Boolean(props.path) ? (
<View style={{ flexDirection: "column", height: 50 }}>
<View style={{ flexDirection: "row" }}>
<View style={{ flex: 1 }}>
<Text
numberOfLines={2}
ellipsizeMode="middle"
testID="p12_inputs.path.text"
>
{props.path}
</Text>
</View>
<Button
type="clear"
icon={<Icon name="cancel" size={24} />}
onPress={clearP12Configuration}
/>
</View>
<Input
placeholder="password"
value={props.password}
onChangeText={props.onPasswordChange}
autoCapitalize="none"
testID="p12_inputs.password.input"
/>
</View>
) : (
<Input
placeholder="Download URL"
onChangeText={setUrl}
autoCapitalize="none"
testID="p12_inputs.download_url.input"
/>
)}
</View>
);
return (
<>
<Input
placeholder={props.title}
disabled={true}
style={{
fontWeight: "bold",
fontSize: 17,
opacity: 1,
}}
inputContainerStyle={{
borderColor: "rgba(255,255,255,0)",
}}
rightIcon={rightIcon}
labelStyle={{ flex: 12, flexWrap: "wrap" }}
/>
{Boolean(!props.path) ? (
<View
style={{
flex: 1,
alignItems: "flex-end",
marginTop: -30,
paddingRight: 4,
paddingBottom: 10,
}}
>
<ButtonGroup
containerStyle={{ width: 200 }}
buttons={buttons.map((button) => button.title)}
onPress={onButtonPress}
/>
</View>
) : (
<View style={{ height: 20 }} />
)}
</>
);
}
Example #4
Source File: RetryPolicyConfiguration.tsx From react-native-network-client with Apache License 2.0 | 4 votes |
RetryPolicyConfiguration = (props: RetryPolicyConfigurationProps) => {
const [statusCodesText, setStatusCodesText] = useState(
props.statusCodes?.join(",") || ""
);
const onLinearPress = () =>
onCheckBoxPress(
props.policyType === Constants.RETRY_TYPES.LINEAR_RETRY
? undefined
: Constants.RETRY_TYPES.LINEAR_RETRY
);
const onExponentialPress = () =>
onCheckBoxPress(
props.policyType === Constants.RETRY_TYPES.EXPONENTIAL_RETRY
? undefined
: Constants.RETRY_TYPES.EXPONENTIAL_RETRY
);
const onCheckBoxPress = (policyType?: RetryTypes) => {
props.onTypeSelected(policyType);
};
const linearRetryChecked =
props.policyType === Constants.RETRY_TYPES.LINEAR_RETRY;
const exponentialRetryChecked =
props.policyType === Constants.RETRY_TYPES.EXPONENTIAL_RETRY;
const buttonMethods = ["get", "post", "put", "patch", "delete"];
const [selectedMethodsIndex, setSelectedMethodsIndex] = useState<number[]>([
0,
1,
]);
if (props.setRetryMethods !== undefined) {
useEffect(() => {
const selectedMethods = selectedMethodsIndex.map(
(index) => buttonMethods[index]
);
props.setRetryMethods!(selectedMethods);
}, [selectedMethodsIndex]);
}
const PolicyTypeCheckbox = () => (
<View style={{ flex: 1, flexDirection: "row" }}>
<CheckBox
title={`Linear [${linearRetryChecked}]`}
checked={linearRetryChecked}
onPress={onLinearPress}
iconType="ionicon"
checkedIcon="ios-checkmark-circle"
uncheckedIcon="ios-checkmark-circle"
iconRight
containerStyle={{
padding: 0,
borderWidth: 0,
backgroundColor: "transparent",
}}
/>
<CheckBox
title={`Exponential [${exponentialRetryChecked}]`}
checked={exponentialRetryChecked}
onPress={onExponentialPress}
iconType="ionicon"
checkedIcon="ios-checkmark-circle"
uncheckedIcon="ios-checkmark-circle"
iconRight
containerStyle={{
padding: 0,
borderWidth: 0,
backgroundColor: "transparent",
}}
/>
</View>
);
const updateStatusCodes = () => {
const statusCodes = statusCodesText
.split(",")
.map((code) => {
return parseInt(code.trim());
})
.filter((code) => !isNaN(code));
props.setStatusCodes(statusCodes);
};
return (
<>
<Input
placeholder="Retry Policy"
disabled={true}
style={{ fontWeight: "bold", fontSize: 17, opacity: 1 }}
containerStyle={{ height: 50 }}
inputContainerStyle={{
borderColor: "rgba(255,255,255,0)",
}}
labelStyle={{ flex: 12, flexWrap: "wrap", height: 100 }}
/>
<PolicyTypeCheckbox />
{props.policyType && (
<NumericInput
title="Retry limit"
value={props.retryLimit}
onChange={props.setRetryLimit}
minValue={0}
testID="retry_policy_configuration.retry_limit.input"
/>
)}
{props.policyType === Constants.RETRY_TYPES.LINEAR_RETRY && (
<NumericInput
title="Retry interval"
value={props.retryInterval}
onChange={props.setRetryInterval}
minValue={1}
testID="retry_policy_configuration.retry_interval.input"
/>
)}
{props.policyType === Constants.RETRY_TYPES.EXPONENTIAL_RETRY && (
<>
<NumericInput
title="Exponential backoff base"
value={props.exponentialBackoffBase}
onChange={props.setExponentialBackoffBase}
minValue={2}
testID="retry_policy_configuration.exponential_backoff_base.input"
/>
<NumericInput
title="Exponential backoff scale"
value={props.exponentialBackoffScale}
onChange={props.setExponentialBackoffScale}
minValue={0}
valueType="real"
step={0.1}
testID="retry_policy_configuration.exponential_backoff_scale.input"
/>
</>
)}
{props.policyType && (
<>
<Input
placeholder="Retry Status Codes"
disabled={true}
style={{ fontWeight: "bold", fontSize: 17, opacity: 1 }}
containerStyle={{ height: 50 }}
inputContainerStyle={{
borderColor: "rgba(255,255,255,0)",
}}
/>
<Input
value={statusCodesText}
onChangeText={setStatusCodesText}
onBlur={updateStatusCodes}
/>
{props.setRetryMethods && (
<>
<Input
placeholder="Retry Methods"
disabled={true}
style={{
fontWeight: "bold",
fontSize: 17,
opacity: 1,
}}
containerStyle={{ height: 50 }}
inputContainerStyle={{
borderColor: "rgba(255,255,255,0)",
}}
/>
<ButtonGroup
selectedIndexes={selectedMethodsIndex}
// @ts-ignore
onPress={setSelectedMethodsIndex}
buttons={buttonMethods}
selectMultiple
/>
</>
)}
</>
)}
</>
);
}
Example #5
Source File: APIClientUploadScreen.tsx From react-native-network-client with Apache License 2.0 | 4 votes |
APIClientUploadScreen = ({ route }: APIClientUploadScreenProps) => {
const {
item: { client },
} = route.params;
const [state, setState] = useState<UploadState>({
endpoint: "/files",
progress: 0,
});
const methods = ["POST", "PUT", "PATCH"];
const [methodIndex, setMethodIndex] = useState<number>(0);
const [multipart, setMultipart] = useState<boolean>(false);
const [multipartFileKey, setMultipartFileKey] = useState("");
const [multipartData, setMultipartData] = useState<Record<string, string>>(
{}
);
const [skipBytes, setSkipBytes] = useState<number>(0);
const setRequest = (request?: ProgressPromise<ClientResponse>) =>
setState((state) => ({ ...state, request }));
const setEndpoint = (endpoint: string) => setState({ ...state, endpoint });
const setFile = (file: File) => setState((state) => ({ ...state, file }));
const setProgress = (progress: number) =>
setState((state) => ({ ...state, progress }));
const setStatus = (status?: UploadStatus) => {
setState((state) => ({ ...state, status }));
};
const [response, setResponse] = useState<ClientResponse>();
const [responseSuccessVisible, setResponseSuccessVisible] = useState(false);
const [error, setError] = useState<ClientResponseError>();
const [responseErrorVisible, setResponseErrorVisible] = useState(false);
const setStateFromResponse = (response: ClientResponse) => {
if (response.ok) {
resetState();
} else {
setState((state) => ({
...state,
request: undefined,
progress: state.progress === 1 ? 0 : state.progress,
status: undefined,
}));
}
};
useEffect(() => {
if (multipart) {
setEndpoint("/api/files/multipart");
}
}, [multipart]);
const resetState = () =>
setState((state) => ({
...state,
request: undefined,
file: undefined,
progress: 0,
status: undefined,
}));
const upload = async () => {
setStatus(UploadStatus.UPLOADING);
setRequest(undefined);
const reqOptions: UploadRequestOptions = {};
if (multipart) {
// Multipart should always send the file key
reqOptions["multipart"] = {
fileKey: multipartFileKey,
};
// If there is additional data, add it
if (Object.keys(multipartData).length) {
reqOptions["multipart"]["data"] = multipartData;
}
}
// Add the following if they're not the defaults
if (skipBytes > 0) reqOptions["skipBytes"] = skipBytes;
if (methodIndex > 0) reqOptions["method"] = methods[methodIndex];
const request = client.upload(
state.endpoint,
state.file!.uri!,
reqOptions
);
setRequest(request);
request.progress!((fractionCompleted: number) => {
setProgress(fractionCompleted);
})
.then((response: ClientResponse) => {
setStateFromResponse(response);
setResponse(response);
setError(undefined);
setResponseSuccessVisible(true);
setResponseErrorVisible(false);
})
.catch((error: ClientResponseError) => {
setStatus(UploadStatus.FAILED);
setResponse(undefined);
setError(error);
setResponseSuccessVisible(false);
setResponseErrorVisible(true);
});
};
const cancelUpload = () => {
if (state.request) {
state.request.cancel!();
}
};
return (
<SafeAreaView style={{ flex: 1 }}>
<ScrollView testID="api_client_upload.scroll_view">
<Input
label="Endpoint"
placeholder="/upload"
value={state.endpoint}
onChangeText={setEndpoint}
autoCapitalize="none"
testID="api_client_upload.endpoint.input"
/>
<ButtonGroup
onPress={setMethodIndex}
selectedIndex={methodIndex}
buttons={methods}
containerStyle={{ flex: 1 }}
/>
<FilePickerButtonGroup
onFilePicked={setFile}
disabled={Boolean(state.status)}
/>
<CheckBox
title={`Send as Multi-part? [${multipart}]`}
checked={multipart}
onPress={() =>
multipart ? setMultipart(false) : setMultipart(true)
}
iconType="ionicon"
checkedIcon="ios-checkmark-circle"
uncheckedIcon="ios-checkmark-circle"
iconRight
textStyle={{ flex: 1 }}
/>
{multipart && (
<>
<Input
label="Multi-part file key"
placeholder="file"
value={multipartFileKey}
onChangeText={setMultipartFileKey}
autoCapitalize="none"
testID="api_client_upload.multipart_key.input"
/>
<AddMultipart onMultipartsChanged={setMultipartData} />
</>
)}
{!multipart && (
<NumericInput
title="Skip Bytes: "
value={skipBytes}
onChange={setSkipBytes}
minValue={0}
testID="api_client_request.skip_bytes.input"
/>
)}
<ProgressiveFileUpload
file={state.file}
progress={state.progress}
/>
<ResponseSuccessOverlay
response={response}
visible={responseSuccessVisible}
setVisible={setResponseSuccessVisible}
/>
<ResponseErrorOverlay
error={error}
visible={responseErrorVisible}
setVisible={setResponseErrorVisible}
/>
<UploadButton
fileUri={state.file?.uri}
endpoint={state.endpoint}
status={state.status}
upload={upload}
cancelUpload={cancelUpload}
resetState={resetState}
/>
</ScrollView>
</SafeAreaView>
);
}
Example #6
Source File: GenericClientRequestScreen.tsx From react-native-network-client with Apache License 2.0 | 4 votes |
GenericClientRequestScreen = ({
route,
}: GenericClientRequestScreenProps) => {
const {
item: { client },
} = route.params;
const [url, setUrl] = useState("");
const [selectedMethodIndex, setSelectedMethodIndex] = useState(0);
const [timeoutInterval, setTimeoutInterval] = useState(30000);
const [body, setBody] = useState('{"login_id":"","password":""}');
const [requestHeaders, setRequestHeaders] = useState<Header[]>([]);
const [response, setResponse] = useState<ClientResponse>();
const [responseSuccessVisible, setResponseSuccessVisible] = useState(false);
const [error, setError] = useState<ClientResponseError>();
const [responseErrorVisible, setResponseErrorVisible] = useState(false);
const [
retryPolicyConfiguration,
setRetryPolicyType,
setRetryLimit,
setRetryInterval,
setExponentialBackoffBase,
setExponentialBackoffScale,
setStatusCodes,
setRetryMethods,
] = useRetryPolicyConfiguration();
const methods = Object.keys(METHODS);
const makeRequest = async () => {
const method = methods[selectedMethodIndex];
const headers = parseHeaders(requestHeaders);
let options: RequestOptions = {
headers,
timeoutInterval,
retryPolicyConfiguration,
};
const canIncludeBody = ![METHODS.HEAD, METHODS.GET].includes(
method as METHODS
);
if (canIncludeBody && body.length) {
try {
options.body = JSON.parse(body);
} catch (e) {
const error = e as Error;
Alert.alert("Error parsing Body", error.message, [{ text: "OK" }], {
cancelable: false,
});
return;
}
}
try {
let clientMethod;
switch (method) {
case METHODS.HEAD:
clientMethod = client.head;
break;
case METHODS.GET:
clientMethod = client.get;
break;
case METHODS.PUT:
clientMethod = client.put;
break;
case METHODS.POST:
clientMethod = client.post;
break;
case METHODS.PATCH:
clientMethod = client.patch;
break;
case METHODS.DELETE:
clientMethod = client.delete;
break;
default:
throw new Error("Invalid request method");
}
var response = await clientMethod(url, options);
setResponse(response);
setError(undefined);
setResponseSuccessVisible(true);
setResponseErrorVisible(false);
} catch (error) {
setResponse(undefined);
setError(error as ClientResponseError);
setResponseSuccessVisible(false);
setResponseErrorVisible(true);
}
};
return (
<SafeAreaView style={{ flex: 1 }}>
<ScrollView
style={{
backgroundColor: "#fff",
borderRadius: 5,
margin: 10,
}}
testID="generic_client_request.scroll_view"
>
<ButtonGroup
onPress={setSelectedMethodIndex}
selectedIndex={selectedMethodIndex}
buttons={methods}
containerStyle={{ height: 50 }}
/>
<Input
label="URL"
placeholder="https://google.com"
value={url}
onChangeText={setUrl}
autoCapitalize="none"
testID="generic_client_request.url.input"
/>
<AddHeaders onHeadersChanged={setRequestHeaders} />
{methods[selectedMethodIndex] !== METHODS.GET && (
<Input
label="Body"
placeholder='{"username": "johndoe"}'
value={body}
onChangeText={setBody}
autoCapitalize="none"
testID="generic_client_request.body.input"
/>
)}
<NumericInput
title="Timeout Interval (ms)"
value={timeoutInterval}
onChange={setTimeoutInterval}
minValue={0}
step={5000}
testID="generic_client_request.timeout_interval.input"
/>
<RetryPolicyConfiguration
policyType={retryPolicyConfiguration.type}
onTypeSelected={setRetryPolicyType}
retryLimit={retryPolicyConfiguration.retryLimit}
setRetryLimit={setRetryLimit}
retryInterval={retryPolicyConfiguration.retryInterval}
setRetryInterval={setRetryInterval}
exponentialBackoffBase={
retryPolicyConfiguration.exponentialBackoffBase
}
setExponentialBackoffBase={setExponentialBackoffBase}
exponentialBackoffScale={
retryPolicyConfiguration.exponentialBackoffScale
}
setExponentialBackoffScale={setExponentialBackoffScale}
statusCodes={retryPolicyConfiguration.statusCodes}
setStatusCodes={setStatusCodes}
retryMethods={retryPolicyConfiguration.retryMethods}
setRetryMethods={setRetryMethods}
/>
<ResponseSuccessOverlay
response={response}
visible={responseSuccessVisible}
setVisible={setResponseSuccessVisible}
/>
<ResponseErrorOverlay
error={error}
visible={responseErrorVisible}
setVisible={setResponseErrorVisible}
/>
</ScrollView>
<Button
title="Request"
onPress={makeRequest}
disabled={!url.length}
containerStyle={{ padding: 5 }}
/>
</SafeAreaView>
);
}
Example #7
Source File: Food.tsx From save-food with MIT License | 4 votes |
Food = ({ navigation }: Props) => {
const { useSubscribe } = useSettingsContext()
const settings = useSubscribe((s) => s.settings)
const translations = useSubscribe((s) => ({ ...s.translations.Food, ...s.translations.common }))
const [savedData, setSavedData] = useState<WastedFood>(initialData)
const [templateData, setTemplateData] = useState<WastedFood>(initialData)
const [loading, setLoading] = useState(true)
const [saveFoodBeforeModalHide, setSaveFoodBeforeModalHide] = useState(false)
const [hasChanges, setHasChanges] = useState(false)
const [showModal, setShowModal] = useState(false)
const [modalType, setModalType] = useState<ModalType>('id')
const [modalContent, setModalContent] = useState<ReactNode>()
const [controls, setControls] = useState<InputsControl>({
name: {
label: translations.foodNameLabel,
required: true,
characterRestriction: 70,
},
quantity: {
label: translations.quantityLabel,
keyboardType: 'numeric',
required: true,
characterRestriction: 5,
number: true,
positiveNumber: true,
precision: 0,
},
price: {
label: translations.priceLabel,
keyboardType: 'numeric',
required: true,
characterRestriction: 7,
number: true,
positiveNumber: true,
precision: 2,
},
})
const correctPrice = !!(savedData.price && !controls.price.error)
const quantitySuffixes = [translations.grams, translations.milliliters]
const setFood = () => {
const savedData = {
id: navigation.getParam('id', undefined),
image: navigation.getParam('image', undefined),
name: navigation.getParam('name', ''),
quantity: navigation.getParam('quantity', 0),
price: navigation.getParam('price', 0),
paid: navigation.getParam('paid', 0),
productQuantity: navigation.getParam('productQuantity', 1),
quantitySuffixIndex: navigation.getParam('quantitySuffixIndex', 1),
percentage: navigation.getParam('percentage', 100),
selected: navigation.getParam('selected', 1),
}
setSavedData(savedData)
setTemplateData(savedData)
setLoading(false)
}
const QuantitySuffixButtons = () => {
const [value, setValue] = useState(savedData.quantitySuffixIndex)
return (
<ButtonGroup
onPress={(index) => {
setSavedData({
...savedData,
quantitySuffixIndex: index,
})
setValue(index)
}}
selectedIndex={value}
buttons={quantitySuffixes}
selectedButtonStyle={styles.selectedButtonStyle}
/>
)
}
const setContent = (type: ModalType) => {
if (type === 'discardChanges') {
setModalContent(
<Text style={styles.discardChanges}>{translations.discardChangesDescription}</Text>,
)
} else {
setModalContent(
<View style={styles.modalContentWrapper}>
<Input
inputConfig={controls[type]}
translations={translations}
value={templateData[type]}
changed={(value, control) => {
setTemplateData({
...templateData,
[type]: value,
})
setControls({
...controls,
[type]: control,
})
}}
/>
{type === 'quantity' && <QuantitySuffixButtons />}
</View>,
)
}
setShowModal(true)
setModalType(type)
}
const saveChange = () => {
if (modalType === 'discardChanges') {
return
}
if (checkValidation(controls[modalType], templateData[modalType] ?? '')) {
const preparedData = prepareData(
{ ...savedData, [modalType]: templateData[modalType] },
controls,
)
setTemplateData(preparedData)
setSavedData(preparedData)
setHasChanges(true)
setShowModal(false)
}
}
const changePercentageHandler = (percent: number) => {
setSavedData({ ...savedData, percentage: +percent.toFixed(0) })
setHasChanges(true)
}
const cancelChange = () => {
if (modalType === 'discardChanges') {
return
}
setTemplateData(savedData)
setShowModal(false)
}
const toggleModal = (type?: ModalType) => {
if (!showModal && type) {
setContent(type)
} else {
setShowModal(false)
}
}
const takePhoto = (uri: string) => {
setSavedData({
...savedData,
image: uri,
})
setHasChanges(true)
}
const toggleCamera = async () => {
const { status } = await Camera.requestPermissionsAsync()
if (status === 'granted') {
navigation.navigate('Camera', {
buttonTitle: translations.takePhoto,
takePhoto,
})
} else {
showErrorMessage('permissionError')
}
}
const showErrorMessage = (type: 'priceError' | 'permissionError') => {
if (type === 'priceError') {
const message: MessageOptions = {
message: translations.noPriceTitle,
description: translations.noPriceDescription,
type: 'warning',
icon: { icon: 'warning', position: 'left' },
duration: 2500,
}
showMessage(message)
}
if (type === 'permissionError') {
const message: MessageOptions = {
message: translations.permissionErrorTitle,
description: translations.permissionErrorCamera,
type: 'danger',
icon: { icon: 'danger', position: 'left' },
duration: 2500,
}
showMessage(message)
}
}
const exitHandler = () => {
if (hasChanges && correctPrice) {
setContent('discardChanges')
} else {
navigation.goBack()
}
}
const getModalButtons = (): ModalButtonType[] => {
if (modalType === 'discardChanges') {
return [
{
text: translations.yes,
onPress: () => {
setShowModal(false)
navigation.goBack()
},
},
{
text: translations.save,
onPress: () => {
setSaveFoodBeforeModalHide(true)
setShowModal(false)
},
},
{ text: translations.cancel, onPress: () => setShowModal(false) },
]
}
return [
{ text: translations.save, onPress: saveChange },
{ text: translations.cancel, onPress: cancelChange },
]
}
const checkErrorHandler = () => {
if (!correctPrice) {
showErrorMessage('priceError')
}
}
const saveFoodHandler = async () => {
await saveFood(savedData)
navigation.replace('List')
}
useEffect(() => {
setFood()
}, [])
if (loading) {
return <Spinner size={64} />
}
return (
<Background>
<Header
leftComponent={<Icon onPress={exitHandler} variant='backIcon' />}
centerComponent={
<Text style={styles.headerTitle}>
{savedData.id ? translations.editFood : translations.newFood}
</Text>
}
/>
<Modal
visible={showModal}
toggleModal={toggleModal}
title={translations[modalType]}
buttons={getModalButtons()}
onModalHide={async () => {
if (saveFoodBeforeModalHide) {
await saveFoodHandler()
}
}}
>
{modalContent}
</Modal>
<View style={styles.contentWrapper}>
<ScrollView>
<View style={styles.imageContainer}>
<TouchableOpacity onPress={toggleCamera}>
<View style={styles.imageWrapper}>
<Image style={styles.image} source={getImage(savedData.image)} />
<View style={styles.tapImage}>
<Text style={styles.tapImageText}>{translations.tapToChange}</Text>
</View>
</View>
</TouchableOpacity>
</View>
<View style={styles.infoWindowsContainer}>
<InfoWindow
color1={whiteColor}
color2={orangeGradient}
title={translations.name}
value={
!savedData.name || savedData.name === '' ? translations.noData : savedData.name
}
onPress={() => toggleModal('name')}
/>
<InfoWindow
color1={whiteColor}
color2={orangeGradient}
title={translations.quantity}
value={
savedData.quantity
? `${+savedData.quantity} ${getQuantitySuffix(savedData.quantitySuffixIndex)}`
: '0'
}
onPress={() => toggleModal('quantity')}
/>
<InfoWindow
color1={whiteColor}
color2={redGradient}
title={translations.price}
value={`${savedData.price ? +savedData.price : 0} ${settings.currency}`}
onPress={() => toggleModal('price')}
/>
<View style={styles.sliderContainer}>
<Text style={styles.percentInfo}>{translations.percentInfo}</Text>
<Slider
style={styles.slider}
thumbStyle={styles.sliderThumbStyle}
thumbTintColor={blackColor}
minimumTrackTintColor={darkColor}
maximumTrackTintColor={grayColor}
minimumValue={1}
maximumValue={100}
value={savedData.percentage}
onValueChange={(value: number) => changePercentageHandler(value)}
/>
<Text style={styles.percent}>{savedData.percentage}%</Text>
</View>
</View>
<View style={styles.saveButtonContainer}>
<TouchableOpacity onPress={checkErrorHandler}>
<Button
buttonStyle={styles.saveButton}
titleStyle={styles.saveButtonTitle}
disabled={!correctPrice}
type='outline'
title={translations.save}
onPress={saveFoodHandler}
/>
</TouchableOpacity>
</View>
</ScrollView>
</View>
</Background>
)
}
Example #8
Source File: Home.tsx From wuhan2020-frontend-react-native-app with MIT License | 4 votes |
function Map() {
const { data, refresh, timeout } = useContext(DataContext);
const [selectedIndex, setIndex] = useState(0);
const filter = filterList[selectedIndex];
const [refreshing, setRefreshing] = useState(false);
let mapData = data || [];
const total = {
confirmedCount: 0,
curedCount: 0,
deadCount: 0,
};
const webviewRef = useRef(null);
useEffect(function() {
if (webviewRef.current) {
webviewRef.current.setOption({
title: {
text: `疫情地图${titleMap[filter]}`,
},
tooltip: {
trigger: 'item',
formatter: '{b}',
},
visualMap: {
pieces: piecesMap[filter],
showLabel: true,
realtime: true,
inRange: {
color: ['yellow', 'red'],
},
},
series: [
{
name: '中国',
type: 'map',
map: 'china',
selectedMode: 'single', //multiple多选
itemStyle: {
normal: {
label: {
show: false,
textStyle: {
color: '#231816',
},
},
areaStyle: { color: '#B1D0EC' },
color: '#B1D0EC',
borderColor: '#bbb',
},
emphasis: {
label: {
show: false,
textStyle: {
color: '#fa4f04',
},
},
},
},
data: mapData,
},
],
});
}
});
const onRefresh = useCallback(() => {
setRefreshing(true);
refresh();
wait(2000).then(() => setRefreshing(false));
}, [refreshing, refresh]);
if (data) {
let formatted = [];
data.getAreaStat.forEach(entry => {
total.confirmedCount = total.confirmedCount + entry.confirmedCount;
total.curedCount = total.curedCount + entry.curedCount;
total.deadCount = total.deadCount + entry.deadCount;
formatted = formatted.concat([
{
name: entry.provinceShortName,
value: entry[filter],
},
]);
});
mapData = formatted;
}
const option = {
title: {
text: `疫情地图${titleMap[filter]}`,
},
tooltip: {
trigger: 'item',
formatter: '{b}',
},
visualMap: {
pieces: piecesMap[filter],
showLabel: true,
realtime: true,
inRange: {
color: ['yellow', 'red'],
},
},
series: [
{
name: '中国',
type: 'map',
map: 'china',
selectedMode: 'single', //multiple多选
itemStyle: {
normal: {
label: {
show: false,
textStyle: {
color: '#231816',
},
},
areaStyle: { color: '#B1D0EC' },
color: '#B1D0EC',
borderColor: '#bbb',
},
emphasis: {
label: {
show: false,
textStyle: {
color: '#fa4f04',
},
},
},
},
data: mapData,
},
],
};
if (timeout) {
return (
<SafeAreaView style={{ flex: 1 }}>
<View
style={{ justifyContent: 'center', alignItems: 'center', flex: 1 }}>
<Text
style={{
color: colors.primary,
fontSize: 18,
paddingVertical: 20,
}}>
数据载入失败?
</Text>
<Button type="outline" onPress={refresh} title="点击重试" />
</View>
</SafeAreaView>
);
}
return (
<SafeAreaView style={{ flex: 1 }}>
<ScrollView
style={{
flex: 1,
}}
refreshControl={
<RefreshControl
tintColor="pink"
refreshing={refreshing}
onRefresh={onRefresh}
/>
}>
<View style={{ backgroundColor: 'white' }}>
{mapData.length ? (
<View style={{ flex: 1 }}>
<View style={{ height: 300 }}>
<ECharts
ref={webviewRef}
option={option}
backgroundColor="#fcfcfc"
/>
</View>
<ButtonGroup
selectedButtonStyle={styles.buttonGroup}
onPress={setIndex}
selectedIndex={selectedIndex}
buttons={[
`确诊 (${total.confirmedCount})`,
`治愈 (${total.curedCount})`,
`致死 (${total.deadCount})`,
]}
containerStyle={{ height: 50 }}
/>
{data && data.getTimelineService && (
<Timeline data={data.getTimelineService} />
)}
{data && data.getIndexRecommendList && (
<RecommendationList data={data.getIndexRecommendList} />
)}
</View>
) : (
<View style={{ flex: 1, width, height }}>
<Loader
size="large"
color="red"
style={{ marginTop: height / 3 }}
/>
</View>
)}
</View>
</ScrollView>
</SafeAreaView>
);
}