Files
ppc_amnet/amnet-native/app/CardAddModal.tsx
T
2024-08-16 14:51:56 +01:00

96 lines
3.9 KiB
TypeScript

import {useCallback, useLayoutEffect, useState} from "react";
import {TextInput, TouchableOpacity, View} from "react-native";
import {Button, Card, Divider, Paragraph, useTheme} from "react-native-paper";
import {useModalStyles} from "../utils/ModalStyles";
import {AMCard} from "../models/AMCard";
import RealmContext from "../models/RealmContext";
import {generateCardNumber} from "../models/AM-API";
const {useRealm} = RealmContext;
export default function CardAddModal({navigation}) {
const realm = useRealm();
const theme = useTheme();
const modalStyles = useModalStyles();
// state values
const [cardName, setCardName] = useState('');
const [cardNumber, setCardNumber] = useState('');
const cardAddCallback = useCallback((cardId: string, cardName: string) => {
const duplicateCard = realm.objects<AMCard>("card").find(x => x.code == cardNumber);
if (duplicateCard) {
realm.write(() => {
duplicateCard.name = cardName;
});
} else {
realm.write(() => {
realm.create("card", AMCard.generate(cardId, cardName));
});
}
navigation.goBack();
}, [realm]);
// header effects
useLayoutEffect(() => {
navigation.setOptions({
headerLeft: () => <TouchableOpacity onPress={() => navigation.goBack()}>
<Paragraph style={modalStyles.headerText}>Cancel</Paragraph>
</TouchableOpacity>,
});
}, [navigation, modalStyles]);
useLayoutEffect(() => {
const canSave = cardName.length && cardNumber.length === 20;
const themeOptions = canSave ? modalStyles.headerText : {color: theme.colors.outline};
navigation.setOptions({
headerRight: () => <TouchableOpacity disabled={!canSave} onPress={() => cardAddCallback(cardNumber, cardName)}>
<Paragraph style={{...themeOptions, fontWeight: "600"}}>Save</Paragraph>
</TouchableOpacity>
})
}, [navigation, modalStyles, cardName, cardNumber]);
return (<View style={{display: "flex", gap: 10, justifyContent: "center", paddingHorizontal: 15, paddingTop: 25}}>
<Card mode="contained">
<Card.Content>
<View style={modalStyles.formItemRow}>
<Paragraph style={modalStyles.formItemName}>
Card Name
</Paragraph>
<TextInput style={modalStyles.formItemInput}
numberOfLines={1} autoFocus
value={cardName}
onChangeText={setCardName}
placeholder="Primary Card"
placeholderTextColor={theme.colors.outline}/>
</View>
<Divider style={{marginVertical: 15}}/>
<View style={modalStyles.formItemRow}>
<Paragraph style={modalStyles.formItemName}>
Matrix Code
</Paragraph>
<TextInput style={modalStyles.formItemInput}
numberOfLines={1}
keyboardType="numeric"
placeholder="0000 0000 0000 0000 0000"
placeholderTextColor={theme.colors.outline}
value={cardNumber.match(/.{1,4}/g)?.join(" ")}
onChangeText={val => setCardNumber(val?.replaceAll(/\D/g, '').substring(0, 20) ?? '')}/>
</View>
</Card.Content>
</Card>
<Paragraph style={modalStyles.formFootnote}>
If you have a physical card, you can enter the 20-digit code on the back.
</Paragraph>
<Button mode="text" onPress={() => setCardNumber(generateCardNumber())}>Generate Matrix Code</Button>
</View>)
}