je_nfc_sdk
Version:
A comprehensive React Native SDK for NFC-based device control and communication
205 lines (204 loc) • 9.84 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import React from 'react';
import { View, Text, StyleSheet, TouchableOpacity, ActivityIndicator, } from 'react-native';
import LinearGradient from 'react-native-linear-gradient';
export const NfcOperationCard = ({ operationType, config, operation, onPress, disabled = false, translate = (key) => key, theme = 'light' }) => {
const isSolenoidOperation = operationType.startsWith('solenoid_');
const isTimeSetOperation = operationType === 'time_set';
const isTimeOperation = operationType.startsWith('time_');
const isWaterFlowOperation = operationType.startsWith('flowrate_');
const isPressureOperation = operationType.startsWith('pressure_');
const getStatusColor = (state) => {
switch (state) {
case 'IDLE':
return '#6c757d';
// Progress steps: 4 for write, 3 for read
const isWriteCard = isSolenoidOperation || isTimeSetOperation;
case 'PROCESSING': return '#e67e22';
case 'ERROR': return '#c82333';
default: return '#6c757d';
}
};
const getButtonText = () => {
if (operation.resetRequested)
return translate('🔄 Reset Operation');
switch (operation.state) {
case 'WRITE_PENDING': return translate('📝 Writing...');
case 'READ_PENDING': return translate('📖 Reading...');
case 'PROCESSING': return translate('🔄 Processing...');
case 'IDLE': return `${config.icon} Start ${config.displayName}`;
case 'READ_READY': return `📖 Read ${config.displayName}`;
case 'READ_READY_READ': return `📖 Update ${config.displayName}`;
case 'READ_READY_WRITE': return `📖 Get ${config.displayName}`;
case 'ERROR': return `❌ Retry ${config.displayName}`;
default: return `${config.icon} ${config.displayName}`;
}
};
// Card wrapper with gradients for different operation types
const CardWrapper = ({ children }) => {
if (isSolenoidOperation) {
const colors = ['rgba(108, 117, 125, 0.4)', 'rgba(108, 117, 125, 0.1)', 'rgba(0, 0, 0, 0.05)'];
return (_jsx(LinearGradient, Object.assign({ colors: colors, start: { x: 0, y: 0 }, end: { x: 1, y: 1 }, style: [styles.card, disabled && styles.cardInactive], pointerEvents: "auto" }, { children: children })));
}
else if (isTimeOperation) {
return (_jsx(LinearGradient, Object.assign({ colors: ['rgba(245, 245, 220, 0.4)', 'rgba(245, 245, 220, 0.1)', 'rgba(0, 0, 0, 0.05)'], start: { x: 0, y: 0 }, end: { x: 1, y: 1 }, style: styles.card, pointerEvents: "auto" }, { children: children })));
}
else if (isWaterFlowOperation) {
return (_jsx(LinearGradient, Object.assign({ colors: ['rgba(64, 164, 223, 0.6)', 'rgba(100, 200, 255, 0.3)', 'rgba(0, 100, 180, 0.2)'], start: { x: 0, y: 0 }, end: { x: 1, y: 1 }, style: styles.card, pointerEvents: "auto" }, { children: children })));
}
else if (isPressureOperation) {
return (_jsx(LinearGradient, Object.assign({ colors: ['rgba(0, 70, 140, 0.7)', 'rgba(0, 120, 200, 0.5)', 'rgba(173, 216, 230, 0.2)'], start: { x: 0, y: 0 }, end: { x: 1, y: 1 }, style: styles.card, pointerEvents: "auto" }, { children: children })));
}
return _jsx(View, Object.assign({ style: [styles.card, theme === 'dark' && styles.cardDark] }, { children: children }));
};
// Progress steps: 4 for write, 3 for read
const isWriteCard = isSolenoidOperation || isTimeSetOperation;
const progressSteps = isWriteCard
? [
{ label: 'Write', active: operation.state !== 'IDLE' && operation.state !== 'ERROR' },
{ label: 'Update', active: ['READ_READY', 'READ_PENDING', 'PROCESSING', 'READ_READY_READ', 'READ_READY_WRITE'].includes(operation.state) },
{ label: 'Get', active: ['READ_PENDING', 'PROCESSING', 'READ_READY_WRITE'].includes(operation.state) },
{ label: operation.state === 'PROCESSING' ? 'Processing' : 'Done', active: operation.state === 'PROCESSING' || operation.lastOperation.status === 'COMPLETED' }
]
: [
{ label: 'Read', active: operation.state !== 'IDLE' && operation.state !== 'ERROR' },
{ label: 'Get', active: ['READ_PENDING', 'PROCESSING', 'READ_READY_WRITE'].includes(operation.state) },
{ label: operation.state === 'PROCESSING' ? 'Processing' : 'Done', active: operation.state === 'PROCESSING' || operation.lastOperation.status === 'COMPLETED' }
];
return (_jsxs(CardWrapper, { children: [_jsxs(View, Object.assign({ style: styles.cardHeader }, { children: [_jsx(Text, Object.assign({ style: [styles.cardTitle, theme === 'dark' && styles.cardTitleDark] }, { children: translate(`${config.icon} ${config.displayName}`) })), _jsxs(View, Object.assign({ style: [styles.statusBadge, { backgroundColor: getStatusColor(operation.state) }] }, { children: [" ", _jsx(Text, Object.assign({ style: styles.statusText }, { children: operation.state.replace('_', ' ') })), " "] }))] })), _jsx(View, Object.assign({ style: [styles.progressContainer, disabled && styles.progressContainerInactive] }, { children: progressSteps.map((step, idx) => (_jsxs(React.Fragment, { children: [_jsxs(View, Object.assign({ style: styles.progressStep }, { children: [_jsx(View, Object.assign({ style: [styles.progressDot, step.active ? styles.progressDotActive : styles.progressDotInactive, step.label === 'Processing' ? styles.progressDotProcessing : (step.label === 'Done' && step.active) ? styles.progressDotComplete : null] }, { children: _jsx(Text, Object.assign({ style: styles.progressDotText }, { children: step.label === 'Processing' ? '🔄' : step.label === 'Done' && step.active ? '✓' : idx + 1 })) })), _jsx(Text, Object.assign({ style: styles.progressLabel }, { children: step.label }))] })), idx < progressSteps.length - 1 && _jsx(View, { style: styles.progressLine })] }, step.label))) })), operation.data && (_jsx(View, Object.assign({ style: [styles.dataContainer, theme === 'dark' && styles.dataContainerDark] }, { children: _jsx(Text, Object.assign({ style: [styles.dataText, theme === 'dark' && styles.dataTextDark] }, { children: operation.data })) }))), _jsxs(TouchableOpacity, Object.assign({ style: [styles.operationButton, { backgroundColor: getStatusColor(operation.state) }, disabled && styles.operationButtonDisabled], onPress: onPress, disabled: disabled }, { children: [(operation.state === 'WRITE_PENDING' || operation.state === 'READ_PENDING') && (_jsx(ActivityIndicator, { size: "small", color: "#fff", style: styles.buttonLoader })), _jsx(Text, Object.assign({ style: styles.operationButtonText }, { children: getButtonText() }))] }))] }));
};
const styles = StyleSheet.create({
card: {
backgroundColor: '#fff',
borderRadius: 12,
padding: 16,
marginBottom: 16,
borderWidth: 1,
borderColor: '#e0e0e0',
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.1,
shadowRadius: 4,
elevation: 3,
},
cardDark: {
backgroundColor: '#2a2a2a',
borderColor: '#444',
},
cardInactive: {
opacity: 0.6,
},
cardHeader: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: 12,
},
cardTitle: {
fontSize: 16,
fontWeight: 'bold',
color: '#333',
flex: 1,
},
cardTitleDark: {
color: '#fff',
},
statusBadge: {
paddingHorizontal: 8,
paddingVertical: 4,
borderRadius: 12,
minWidth: 80,
alignItems: 'center',
},
statusText: {
color: '#fff',
fontSize: 10,
fontWeight: 'bold',
textTransform: 'uppercase',
},
progressContainer: {
flexDirection: 'row',
alignItems: 'center',
marginBottom: 12,
},
progressContainerInactive: {
opacity: 0.5,
},
progressStep: {
alignItems: 'center',
flex: 1,
},
progressDot: {
width: 24,
height: 24,
borderRadius: 12,
backgroundColor: '#e0e0e0',
alignItems: 'center',
justifyContent: 'center',
marginBottom: 4,
},
progressDotActive: {
backgroundColor: '#007bff',
},
progressDotProcessing: {
backgroundColor: '#ffc107',
},
progressDotComplete: {
backgroundColor: '#28a745',
},
progressDotInactive: {
backgroundColor: '#e0e0e0',
},
progressDotText: {
color: '#fff',
fontSize: 10,
fontWeight: 'bold',
},
progressLabel: {
fontSize: 10,
color: '#666',
textAlign: 'center',
},
progressLine: {
height: 2,
backgroundColor: '#e0e0e0',
flex: 1,
marginHorizontal: 8,
},
dataContainer: {
backgroundColor: '#f8f9fa',
padding: 12,
borderRadius: 8,
marginBottom: 12,
},
dataContainerDark: {
backgroundColor: '#333',
},
dataText: {
fontSize: 14,
color: '#333',
fontFamily: 'monospace',
},
dataTextDark: {
color: '#fff',
},
operationButton: {
padding: 12,
borderRadius: 8,
alignItems: 'center',
flexDirection: 'row',
justifyContent: 'center',
},
operationButtonDisabled: {
opacity: 0.5,
},
operationButtonText: {
color: '#fff',
fontSize: 14,
fontWeight: 'bold',
},
buttonLoader: {
marginRight: 8,
},
});
export default NfcOperationCard;