refactor: update tab bar icons size, enhance QR scan modal layout, and remove unused icons
This commit is contained in:
@@ -15,9 +15,7 @@
|
||||
"android": {
|
||||
"adaptiveIcon": {
|
||||
"backgroundColor": "#E6F4FE",
|
||||
"foregroundImage": "./assets/images/android-icon-foreground.png",
|
||||
"backgroundImage": "./assets/images/android-icon-background.png",
|
||||
"monochromeImage": "./assets/images/android-icon-monochrome.png"
|
||||
"foregroundImage": "./assets/images/adaptive-icon.png"
|
||||
},
|
||||
"edgeToEdgeEnabled": true,
|
||||
"predictiveBackGestureEnabled": false,
|
||||
|
||||
@@ -43,35 +43,35 @@ export default function ProtectedLayout() {
|
||||
name="index"
|
||||
options={{
|
||||
title: 'Home',
|
||||
tabBarIcon: ({ color, size }) => <Home pointerEvents="none" color={color} size={24} />,
|
||||
tabBarIcon: ({ color, size }) => <Home pointerEvents="none" color={color} size={28} />,
|
||||
}}
|
||||
/>
|
||||
<Tabs.Screen
|
||||
name="attendance/index"
|
||||
options={{
|
||||
title: 'Presenze',
|
||||
tabBarIcon: ({ color, size }) => <Clock pointerEvents="none" color={color} size={24} />,
|
||||
tabBarIcon: ({ color, size }) => <Clock pointerEvents="none" color={color} size={28} />,
|
||||
}}
|
||||
/>
|
||||
<Tabs.Screen
|
||||
name="permits/index"
|
||||
options={{
|
||||
title: 'Permessi',
|
||||
tabBarIcon: ({ color, size }) => <CalendarIcon pointerEvents="none" color={color} size={24} />,
|
||||
tabBarIcon: ({ color, size }) => <CalendarIcon pointerEvents="none" color={color} size={28} />,
|
||||
}}
|
||||
/>
|
||||
<Tabs.Screen
|
||||
name="sites"
|
||||
options={{
|
||||
title: 'Cantieri',
|
||||
tabBarIcon: ({ color, size }) => <Building pointerEvents="none" color={color} size={24} />,
|
||||
tabBarIcon: ({ color, size }) => <Building pointerEvents="none" color={color} size={28} />,
|
||||
}}
|
||||
/>
|
||||
<Tabs.Screen
|
||||
name="automation"
|
||||
options={{
|
||||
title: 'Domotica',
|
||||
tabBarIcon: ({ color, size }) => <Zap pointerEvents="none" color={color} size={24} />,
|
||||
tabBarIcon: ({ color, size }) => <Zap pointerEvents="none" color={color} size={28} />,
|
||||
href: authState.user?.role === 'Amministratore' ? undefined : null,
|
||||
}}
|
||||
/>
|
||||
@@ -80,6 +80,7 @@ export default function ProtectedLayout() {
|
||||
name="profile"
|
||||
options={{
|
||||
href: null,
|
||||
tabBarStyle: { display: 'none' },
|
||||
title: 'Profilo',
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -10,9 +10,11 @@ import React, { useEffect, useState } from 'react';
|
||||
import { RefreshControl, ScrollView, Text, TouchableOpacity, View } from 'react-native';
|
||||
import NfcManager from 'react-native-nfc-manager';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import { useLocalSearchParams } from 'expo-router';
|
||||
|
||||
export default function AttendanceScreen() {
|
||||
const [scannerType, setScannerType] = useState<'qr' | 'nfc'>('qr');
|
||||
const { autoScan } = useLocalSearchParams();
|
||||
const alert = useAlert();
|
||||
const [showScanner, setShowScanner] = useState(false);
|
||||
const [lastScan, setLastScan] = useState<{ type: string; time: string; site: string } | null>(null);
|
||||
@@ -47,10 +49,19 @@ export default function AttendanceScreen() {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
checkNfcAvailability();
|
||||
const init = async () => {
|
||||
await checkNfcAvailability();
|
||||
fetchAttendances();
|
||||
setLastScan(null);
|
||||
}, []);
|
||||
|
||||
if (autoScan === 'true') {
|
||||
setTimeout(() => {
|
||||
handleStartScan();
|
||||
}, 300);
|
||||
}
|
||||
};
|
||||
init();
|
||||
}, [autoScan]);
|
||||
|
||||
const onRefresh = () => {
|
||||
setRefreshing(true);
|
||||
|
||||
@@ -74,7 +74,7 @@ export default function HomeScreen() {
|
||||
<Text className="text-white text-3xl font-bold leading-tight">
|
||||
{user?.name} {user?.surname}
|
||||
</Text>
|
||||
<Text className="text-xl text-teal-200">{user?.role}</Text>
|
||||
<Text className="text-xl text-teal-200 mt-1">{user?.role}</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View className="flex-row gap-4 flex-shrink-0">
|
||||
@@ -119,7 +119,7 @@ export default function HomeScreen() {
|
||||
<Text className="text-gray-800 text-xl font-bold mb-4 px-1">Azioni Rapide</Text>
|
||||
<View className="flex-row gap-5">
|
||||
<TouchableOpacity
|
||||
onPress={() => router.push('/attendance')}
|
||||
onPress={() => router.push('/attendance?autoScan=true')}
|
||||
className="flex-1 bg-white p-6 rounded-3xl shadow-sm items-center justify-center gap-4 border border-gray-100 active:scale-[0.98]"
|
||||
>
|
||||
<View className="w-20 h-20 rounded-full bg-teal-50 items-center justify-center mb-1">
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 32 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 17 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 77 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 4.0 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 56 KiB |
+45
-29
@@ -1,5 +1,5 @@
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import { View, Text, Modal, TouchableOpacity, Vibration, StyleSheet, Dimensions } from 'react-native';
|
||||
import { View, Text, Modal, TouchableOpacity, Vibration, StyleSheet, useWindowDimensions } from 'react-native';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import { CameraView, useCameraPermissions } from 'expo-camera';
|
||||
import { X, ScanLine } from 'lucide-react-native';
|
||||
@@ -14,18 +14,17 @@ export default function QrScanModal({ visible, onClose, onScan }: QrScanModalPro
|
||||
const [permission, requestPermission] = useCameraPermissions();
|
||||
const [scanned, setScanned] = useState(false);
|
||||
const scanInProgress = useRef(false);
|
||||
const { width, height } = Dimensions.get('window');
|
||||
const { width, height } = useWindowDimensions();
|
||||
const squareSize = Math.min(width * 0.8, height * 0.8, 400);
|
||||
|
||||
// Permission Handling and Reset Scanned State on Modal Open
|
||||
// Permission handling and scanned state reset on modal open
|
||||
useEffect(() => {
|
||||
if (visible) {
|
||||
if (!visible) return;
|
||||
setScanned(false);
|
||||
scanInProgress.current = false;
|
||||
if (permission && !permission.granted && permission.canAskAgain) {
|
||||
requestPermission();
|
||||
}
|
||||
}
|
||||
}, [visible, permission]);
|
||||
|
||||
const handleBarCodeScanned = ({ type, data }: { type: string; data: string }) => {
|
||||
@@ -43,10 +42,6 @@ export default function QrScanModal({ visible, onClose, onScan }: QrScanModalPro
|
||||
return <View />;
|
||||
}
|
||||
|
||||
if (!permission.granted && visible) {
|
||||
requestPermission();
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal
|
||||
visible={visible}
|
||||
@@ -65,35 +60,56 @@ export default function QrScanModal({ visible, onClose, onScan }: QrScanModalPro
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Dark Overlay with Transparent "Hole" (Visually Simulated with Borders or Opacity) */}
|
||||
<SafeAreaView className="flex-1 justify-between bg-black/60 pt-8">
|
||||
{/* Header Overlay */}
|
||||
<View className="items-center">
|
||||
<Text className="text-white text-xl font-bold">Scansiona QR Code</Text>
|
||||
<Text className="text-gray-300 text-base mt-1">Inquadra il codice nel riquadro</Text>
|
||||
</View>
|
||||
{/* Mask Overlay with transparent cutout */}
|
||||
<View style={StyleSheet.absoluteFillObject} pointerEvents="none">
|
||||
<View className="flex-1 bg-black/60" />
|
||||
<View style={{ height: squareSize }} className="flex-row">
|
||||
<View className="flex-1 bg-black/60" />
|
||||
|
||||
{/* Central Area (Transparent for the camera) */}
|
||||
<View className="items-center justify-center" style={{ height: squareSize }}>
|
||||
<View style={{ width: squareSize, height: squareSize }}
|
||||
className="border-2 border-[#099499] bg-transparent relative justify-center items-center">
|
||||
{/* Decorative Corners */}
|
||||
{/* Scanner Target Frame */}
|
||||
<View
|
||||
style={{ width: squareSize, height: squareSize }}
|
||||
className="border-2 border-[#099499] justify-center items-center relative"
|
||||
>
|
||||
<View className="absolute top-0 left-0 w-6 h-6 border-l-4 border-t-4 border-[#099499]" />
|
||||
<View className="absolute top-0 right-0 w-6 h-6 border-r-4 border-t-4 border-[#099499]" />
|
||||
<View className="absolute bottom-0 left-0 w-6 h-6 border-l-4 border-b-4 border-[#099499]" />
|
||||
<View className="absolute bottom-0 right-0 w-6 h-6 border-r-4 border-b-4 border-[#099499]" />
|
||||
|
||||
{/* Animated Scan Line or Icon */}
|
||||
{!scanned && <ScanLine color="#099499" size={40} className="opacity-50" pointerEvents="none" />}
|
||||
</View>
|
||||
{!scanned && <ScanLine color="#099499" size={40} className="opacity-50" />}
|
||||
</View>
|
||||
|
||||
{/* Footer Overlay */}
|
||||
<View className="items-center justify-end pb-12">
|
||||
<TouchableOpacity onPress={onClose} className="bg-white/20 p-4 rounded-full">
|
||||
<X color="white" size={32} pointerEvents="none" />
|
||||
<View className="flex-1 bg-black/60" />
|
||||
</View>
|
||||
<View className="flex-1 bg-black/60" />
|
||||
</View>
|
||||
|
||||
{/* UI Overlay */}
|
||||
<SafeAreaView style={StyleSheet.absoluteFillObject} pointerEvents="box-none">
|
||||
<View className="flex-1 justify-between pt-8">
|
||||
{/* Header */}
|
||||
<View className="items-center">
|
||||
<Text className="text-white text-xl font-bold">
|
||||
Scansiona QR Code
|
||||
</Text>
|
||||
<Text className="text-gray-300 text-base mt-1">
|
||||
Inquadra il codice nel riquadro
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
{/* Footer */}
|
||||
<View className="items-center pb-12">
|
||||
<TouchableOpacity
|
||||
onPress={onClose}
|
||||
className="bg-white/20 p-4 rounded-full"
|
||||
>
|
||||
<X color="white" size={32} />
|
||||
</TouchableOpacity>
|
||||
<Text className="text-white mt-4 font-medium">Chiudi</Text>
|
||||
|
||||
<Text className="text-white mt-4 font-medium">
|
||||
Chiudi
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</SafeAreaView>
|
||||
</View>
|
||||
|
||||
Reference in New Issue
Block a user