Загрузка данных
import React, { useRef, useState } from 'react';
import {
SafeAreaView,
ScrollView,
StyleSheet,
Text,
TouchableOpacity,
View,
Image,
Alert,
} from 'react-native';
import { CameraView, useCameraPermissions } from 'expo-camera';
const meters = ['Горячая вода', 'Холодная вода', 'Электричество'];
export default function App() {
const [selected, setSelected] = useState('Горячая вода');
const [cameraOpen, setCameraOpen] = useState(false);
const [photo, setPhoto] = useState<string | null>(null);
const [permission, requestPermission] = useCameraPermissions();
const cameraRef = useRef<CameraView>(null);
async function openCamera() {
if (!permission?.granted) {
const result = await requestPermission();
if (!result.granted) {
Alert.alert('Нет доступа', 'Разреши доступ к камере в настройках iPhone.');
return;
}
}
setPhoto(null);
setCameraOpen(true);
}
async function takePhoto() {
try {
const result = await cameraRef.current?.takePictureAsync({
quality: 0.8,
});
if (result?.uri) {
setPhoto(result.uri);
setCameraOpen(false);
}
} catch {
Alert.alert('Ошибка', 'Не получилось сделать фото.');
}
}
return (
<SafeAreaView style={styles.container}>
<ScrollView contentContainerStyle={styles.content}>
<Text style={styles.title}>Мои счётчики</Text>
<Text style={styles.subtitle}>Фото и учёт показаний</Text>
{!cameraOpen ? (
<>
<Text style={styles.heading}>Выбери счётчик</Text>
{meters.map((meter) => (
<TouchableOpacity
key={meter}
style={[styles.meter, selected === meter && styles.selected]}
onPress={() => setSelected(meter)}
>
<Text style={styles.meterText}>{meter}</Text>
<Text style={styles.check}>
{selected === meter ? '✓' : '›'}
</Text>
</TouchableOpacity>
))}
<TouchableOpacity style={styles.button} onPress={openCamera}>
<Text style={styles.buttonText}>Сфотографировать счётчик</Text>
</TouchableOpacity>
{photo && (
<View style={styles.photoBox}>
<Text style={styles.heading}>Последняя фотография</Text>
<Image source={{ uri: photo }} style={styles.photo} />
<Text style={styles.caption}>
{selected}. Следующим шагом добавим распознавание цифр.
</Text>
<TouchableOpacity
style={styles.secondaryButton}
onPress={openCamera}
>
<Text style={styles.secondaryText}>Переснять</Text>
</TouchableOpacity>
</View>
)}
</>
) : (
<View>
<Text style={styles.heading}>Камера: {selected}</Text>
<CameraView
ref={cameraRef}
style={styles.camera}
facing="back"
/>
<TouchableOpacity style={styles.button} onPress={takePhoto}>
<Text style={styles.buttonText}>Сделать фотографию</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.secondaryButton}
onPress={() => setCameraOpen(false)}
>
<Text style={styles.secondaryText}>Отмена</Text>
</TouchableOpacity>
</View>
)}
</ScrollView>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: { flex: 1, backgroundColor: '#F3F6FA' },
content: { padding: 22, paddingTop: 25 },
title: { fontSize: 30, fontWeight: '800', color: '#172B4D' },
subtitle: { fontSize: 15, color: '#697586', marginTop: 6, marginBottom: 25 },
heading: { fontSize: 18, fontWeight: '700', color: '#172B4D', marginBottom: 14 },
meter: {
backgroundColor: '#FFFFFF', padding: 18, borderRadius: 14,
marginBottom: 10, flexDirection: 'row', justifyContent: 'space-between',
alignItems: 'center', borderWidth: 1, borderColor: '#E1E7EF',
},
selected: { borderColor: '#3977D5', backgroundColor: '#EAF2FF' },
meterText: { fontSize: 16, fontWeight: '600', color: '#253858' },
check: { fontSize: 21, color: '#3977D5', fontWeight: '700' },
button: {
backgroundColor: '#245CB5', padding: 17, borderRadius: 14,
alignItems: 'center', marginTop: 18,
},
buttonText: { color: '#FFFFFF', fontSize: 16, fontWeight: '700' },
camera: { height: 420, borderRadius: 14, overflow: 'hidden' },
secondaryButton: { padding: 14, alignItems: 'center' },
secondaryText: { color: '#245CB5', fontSize: 15, fontWeight: '600' },
photoBox: { marginTop: 26 },
photo: { width: '100%', height: 300, borderRadius: 14 },
caption: { color: '#697586', marginTop: 10, lineHeight: 20 },
});