mirror of
https://gitea.tendokyu.moe/ppc/amnet.git
synced 2026-09-25 07:38:17 +03:00
96 lines
3.9 KiB
TypeScript
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>)
|
|
}
|