302 lines
7.1 KiB
TypeScript
302 lines
7.1 KiB
TypeScript
import React, { useEffect } from 'react';
|
|
import {
|
|
View,
|
|
Text,
|
|
ScrollView,
|
|
TouchableOpacity,
|
|
StyleSheet,
|
|
ActivityIndicator,
|
|
Alert,
|
|
} from 'react-native';
|
|
import { useRouter } from 'expo-router';
|
|
import { Ionicons } from '@expo/vector-icons';
|
|
import { useValidationsStore } from '../../stores/validations.store';
|
|
import { ValidationItemCard } from '../../components/validation/ValidationItemCard';
|
|
import { ValidationProgressBar } from '../../components/validation/ValidationProgressBar';
|
|
import { ValidationItemResponse } from '../../services/api/validations.service';
|
|
|
|
export default function ValidationItemsScreen() {
|
|
const router = useRouter();
|
|
const {
|
|
pendingRequest,
|
|
items,
|
|
responses,
|
|
currentItemIndex,
|
|
isLoading,
|
|
error,
|
|
addResponse,
|
|
nextItem,
|
|
previousItem,
|
|
submitValidation,
|
|
skipValidation,
|
|
} = useValidationsStore();
|
|
|
|
useEffect(() => {
|
|
if (!pendingRequest || items.length === 0) {
|
|
router.replace('/');
|
|
}
|
|
}, [pendingRequest, items]);
|
|
|
|
const handleResponse = (response: Omit<ValidationItemResponse, 'inventoryItemId'>) => {
|
|
if (!items[currentItemIndex]) return;
|
|
|
|
addResponse({
|
|
...response,
|
|
inventoryItemId: items[currentItemIndex].id,
|
|
});
|
|
|
|
// Auto-advance to next item
|
|
if (currentItemIndex < items.length - 1) {
|
|
setTimeout(() => nextItem(), 300);
|
|
}
|
|
};
|
|
|
|
const handleSubmit = async () => {
|
|
if (responses.length < items.length) {
|
|
Alert.alert(
|
|
'Faltan items',
|
|
'Por favor valida todos los productos antes de continuar.',
|
|
);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
await submitValidation();
|
|
router.replace('/validation/complete');
|
|
} catch {
|
|
Alert.alert('Error', 'No se pudo enviar la validacion. Intenta de nuevo.');
|
|
}
|
|
};
|
|
|
|
const handleSkip = () => {
|
|
Alert.alert(
|
|
'Omitir validacion',
|
|
'Estas seguro? No recibiras el credito de recompensa.',
|
|
[
|
|
{ text: 'Cancelar', style: 'cancel' },
|
|
{
|
|
text: 'Omitir',
|
|
style: 'destructive',
|
|
onPress: async () => {
|
|
await skipValidation();
|
|
router.replace('/');
|
|
},
|
|
},
|
|
],
|
|
);
|
|
};
|
|
|
|
if (!pendingRequest || items.length === 0) {
|
|
return (
|
|
<View style={styles.loading}>
|
|
<ActivityIndicator size="large" color="#007AFF" />
|
|
</View>
|
|
);
|
|
}
|
|
|
|
const currentItem = items[currentItemIndex];
|
|
const currentResponse = responses.find(
|
|
(r) => r.inventoryItemId === currentItem?.id,
|
|
);
|
|
|
|
return (
|
|
<View style={styles.container}>
|
|
<ValidationProgressBar
|
|
current={currentItemIndex}
|
|
total={items.length}
|
|
validated={responses.length}
|
|
/>
|
|
|
|
<ScrollView style={styles.content} contentContainerStyle={styles.scrollContent}>
|
|
{currentItem && (
|
|
<ValidationItemCard
|
|
item={currentItem}
|
|
onResponse={handleResponse}
|
|
existingResponse={currentResponse}
|
|
/>
|
|
)}
|
|
|
|
{error && (
|
|
<View style={styles.errorContainer}>
|
|
<Text style={styles.errorText}>{error}</Text>
|
|
</View>
|
|
)}
|
|
</ScrollView>
|
|
|
|
<View style={styles.footer}>
|
|
<View style={styles.navigation}>
|
|
<TouchableOpacity
|
|
style={[styles.navButton, currentItemIndex === 0 && styles.navButtonDisabled]}
|
|
onPress={previousItem}
|
|
disabled={currentItemIndex === 0}
|
|
>
|
|
<Ionicons
|
|
name="chevron-back"
|
|
size={24}
|
|
color={currentItemIndex === 0 ? '#ccc' : '#007AFF'}
|
|
/>
|
|
<Text
|
|
style={[
|
|
styles.navText,
|
|
currentItemIndex === 0 && styles.navTextDisabled,
|
|
]}
|
|
>
|
|
Anterior
|
|
</Text>
|
|
</TouchableOpacity>
|
|
|
|
<TouchableOpacity
|
|
style={[
|
|
styles.navButton,
|
|
currentItemIndex === items.length - 1 && styles.navButtonDisabled,
|
|
]}
|
|
onPress={nextItem}
|
|
disabled={currentItemIndex === items.length - 1}
|
|
>
|
|
<Text
|
|
style={[
|
|
styles.navText,
|
|
currentItemIndex === items.length - 1 && styles.navTextDisabled,
|
|
]}
|
|
>
|
|
Siguiente
|
|
</Text>
|
|
<Ionicons
|
|
name="chevron-forward"
|
|
size={24}
|
|
color={currentItemIndex === items.length - 1 ? '#ccc' : '#007AFF'}
|
|
/>
|
|
</TouchableOpacity>
|
|
</View>
|
|
|
|
<View style={styles.actions}>
|
|
<TouchableOpacity style={styles.skipButton} onPress={handleSkip}>
|
|
<Text style={styles.skipText}>Omitir</Text>
|
|
</TouchableOpacity>
|
|
|
|
<TouchableOpacity
|
|
style={[
|
|
styles.submitButton,
|
|
responses.length < items.length && styles.submitButtonDisabled,
|
|
]}
|
|
onPress={handleSubmit}
|
|
disabled={isLoading || responses.length < items.length}
|
|
>
|
|
{isLoading ? (
|
|
<ActivityIndicator color="#fff" />
|
|
) : (
|
|
<>
|
|
<Text style={styles.submitText}>Enviar</Text>
|
|
<View style={styles.badge}>
|
|
<Text style={styles.badgeText}>
|
|
{responses.length}/{items.length}
|
|
</Text>
|
|
</View>
|
|
</>
|
|
)}
|
|
</TouchableOpacity>
|
|
</View>
|
|
</View>
|
|
</View>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
flex: 1,
|
|
backgroundColor: '#f5f5f5',
|
|
},
|
|
loading: {
|
|
flex: 1,
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
},
|
|
content: {
|
|
flex: 1,
|
|
},
|
|
scrollContent: {
|
|
padding: 16,
|
|
},
|
|
errorContainer: {
|
|
backgroundColor: '#ffebee',
|
|
padding: 12,
|
|
borderRadius: 8,
|
|
marginTop: 12,
|
|
},
|
|
errorText: {
|
|
color: '#dc3545',
|
|
textAlign: 'center',
|
|
},
|
|
footer: {
|
|
backgroundColor: '#fff',
|
|
borderTopWidth: 1,
|
|
borderTopColor: '#eee',
|
|
padding: 16,
|
|
},
|
|
navigation: {
|
|
flexDirection: 'row',
|
|
justifyContent: 'space-between',
|
|
marginBottom: 16,
|
|
},
|
|
navButton: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
padding: 8,
|
|
gap: 4,
|
|
},
|
|
navButtonDisabled: {
|
|
opacity: 0.5,
|
|
},
|
|
navText: {
|
|
color: '#007AFF',
|
|
fontSize: 16,
|
|
},
|
|
navTextDisabled: {
|
|
color: '#ccc',
|
|
},
|
|
actions: {
|
|
flexDirection: 'row',
|
|
gap: 12,
|
|
},
|
|
skipButton: {
|
|
flex: 1,
|
|
padding: 14,
|
|
borderRadius: 8,
|
|
backgroundColor: '#f5f5f5',
|
|
alignItems: 'center',
|
|
},
|
|
skipText: {
|
|
color: '#666',
|
|
fontWeight: '600',
|
|
},
|
|
submitButton: {
|
|
flex: 2,
|
|
padding: 14,
|
|
borderRadius: 8,
|
|
backgroundColor: '#007AFF',
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
gap: 8,
|
|
},
|
|
submitButtonDisabled: {
|
|
backgroundColor: '#ccc',
|
|
},
|
|
submitText: {
|
|
color: '#fff',
|
|
fontWeight: '600',
|
|
fontSize: 16,
|
|
},
|
|
badge: {
|
|
backgroundColor: 'rgba(255,255,255,0.3)',
|
|
paddingHorizontal: 8,
|
|
paddingVertical: 2,
|
|
borderRadius: 10,
|
|
},
|
|
badgeText: {
|
|
color: '#fff',
|
|
fontSize: 12,
|
|
fontWeight: '600',
|
|
},
|
|
});
|