validate cards when manually entering them

This commit is contained in:
ppc
2025-01-14 23:57:36 +00:00
parent 393965d252
commit 73d333cc23
4 changed files with 44 additions and 6 deletions
+35 -5
View File
@@ -1,6 +1,6 @@
import {generateCardNumber} from "amnet-shared";
import {generateCardNumber, DecodeAMAccessCode} from "amnet-shared";
import {useCallback, useEffect, useLayoutEffect, useState} from "react";
import {Platform, TextInput, TouchableOpacity, View} from "react-native";
import {Alert, Platform, TextInput, TouchableOpacity, View} from "react-native";
import {Button, Card, Divider, Paragraph, useTheme} from "react-native-paper";
import {AMCard} from "../../models/AMCard";
@@ -18,7 +18,37 @@ export default function CardAddModal({navigation, route}) {
const [cardName, setCardName] = useState('');
const [cardNumber, setCardNumber] = useState('');
const cardAddCallback = useCallback((cardId: string, cardName: string) => {
const cardAddCallback = useCallback(async (cardId: string, cardName: string) => {
try {
// validate AM card numbers
cardId.startsWith('5') && DecodeAMAccessCode(cardId);
} catch {
const shouldContinue = await new Promise<boolean>(done => {
Alert.alert(
"Invalid Access Code",
"It looks like the access code isn't from an Amusement IC card. Please double-check the code, and if it's correct, note that some networks might still reject it.",
[
{
style: "destructive",
text: "Continue Anyway",
onPress: () => done(true)
},
{
style: "cancel",
text: "Cancel",
onPress: () => done(false)
}
], {
cancelable: true,
onDismiss: () => done(false)
});
})
if (!shouldContinue) {
return;
}
}
const duplicateCard = realm.objects<AMCard>(AMCard.schema.name).find(x => x.code === cardId);
if (duplicateCard) {
@@ -43,7 +73,8 @@ export default function CardAddModal({navigation, route}) {
const themeOptions = canSave ? modalStyles.headerText : {color: theme.colors.outline};
navigation.setOptions({
headerRight: () => <TouchableOpacity disabled={!canSave} onPress={() => cardAddCallback(cardNumber, cardName)}>
headerRight: () => <TouchableOpacity disabled={!canSave}
onPress={() => cardAddCallback(cardNumber, cardName)}>
<Paragraph style={{...themeOptions, fontWeight: "600"}}>Save</Paragraph>
</TouchableOpacity>
})
@@ -90,7 +121,6 @@ export default function CardAddModal({navigation, route}) {
</Card.Content>
</Card>
{/* only show card entry info when in create mode */}
<Button mode="text" onPress={() => setCardNumber(generateCardNumber())}>Generate Access Code</Button>
</View>
)
+2 -1
View File
@@ -6,7 +6,8 @@ module.exports = (async () => {
const config = await getDefaultConfig(__dirname);
config.resolver.extraNodeModules = {
'amnet-shared': resolve(__dirname, '../amnet-shared')
'amnet-shared': resolve(__dirname, '../amnet-shared'),
'@babel/runtime': resolve(__dirname, 'node_modules/@babel/runtime')
};
config.watchFolders = [
+6
View File
@@ -9,6 +9,7 @@
"version": "1.1.0",
"hasInstallScript": true,
"dependencies": {
"@babel/runtime": "^7.26.0",
"@expo-google-fonts/jetbrains-mono": "^0.2.3",
"@react-navigation/bottom-tabs": "^6.6.1",
"@react-navigation/native": "^6.1.18",
@@ -47,7 +48,12 @@
},
"../amnet-shared": {
"version": "1.0.0",
"dependencies": {
"big-integer": "^1.6.52",
"lodash": "^4.17.21"
},
"devDependencies": {
"@types/lodash": "^4.17.14",
"tsup": "^8.2.4",
"typescript": "^5.5.4"
}
+1
View File
@@ -9,6 +9,7 @@
"postinstall": "patch-package"
},
"dependencies": {
"@babel/runtime": "^7.26.0",
"@expo-google-fonts/jetbrains-mono": "^0.2.3",
"@react-navigation/bottom-tabs": "^6.6.1",
"@react-navigation/native": "^6.1.18",