Improve navigation and replace ScrollView with FlatList in Journal

This commit is contained in:
2026-08-31 18:01:12 +02:00
parent 8ce26da0c5
commit d432b244f3
2 changed files with 57 additions and 50 deletions
+1 -1
View File
@@ -182,7 +182,7 @@ export default function AddJournalScreen() {
<View className="bg-white px-4 pb-6 shadow-sm border-b border-gray-100"> <View className="bg-white px-4 pb-6 shadow-sm border-b border-gray-100">
<SafeAreaView edges={['top']} className='pt-5'> <SafeAreaView edges={['top']} className='pt-5'>
<View className='flex-row items-center gap-4 px-2'> <View className='flex-row items-center gap-4 px-2'>
<TouchableOpacity onPress={() => router.back()} className="p-2 -ml-2 rounded-full active:bg-gray-100"> <TouchableOpacity onPress={() => router.push('/(protected)/journal')} className="p-2 -ml-2 rounded-full active:bg-gray-100">
<ChevronLeft size={28} color="#4b5563" pointerEvents="none" /> <ChevronLeft size={28} color="#4b5563" pointerEvents="none" />
</TouchableOpacity> </TouchableOpacity>
+25 -18
View File
@@ -2,14 +2,13 @@ import { useAlert } from '@/components/AlertComponent';
import LoadingScreen from '@/components/LoadingScreen'; import LoadingScreen from '@/components/LoadingScreen';
import api from '@/utils/api'; import api from '@/utils/api';
import { ImageIcon, Plus, Filter, Newspaper } from 'lucide-react-native'; import { ImageIcon, Plus, Filter, Newspaper } from 'lucide-react-native';
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState, useCallback } from 'react';
import { RefreshControl, ScrollView, Text, TouchableOpacity, View } from 'react-native'; import { FlatList, RefreshControl, Text, TouchableOpacity, View } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context'; import { SafeAreaView } from 'react-native-safe-area-context';
import FilterModal from '@/components/FilterModal'; import FilterModal from '@/components/FilterModal';
import { Place } from '@/types/types'; import { Place } from '@/types/types';
import { useRouter, useFocusEffect } from 'expo-router'; import { useRouter, useFocusEffect } from 'expo-router';
import { StatusBar } from 'expo-status-bar'; import { StatusBar } from 'expo-status-bar';
import { useCallback } from 'react';
export default function JournalScreen() { export default function JournalScreen() {
const router = useRouter(); const router = useRouter();
@@ -86,6 +85,10 @@ export default function JournalScreen() {
setShowFilterModal(false); setShowFilterModal(false);
}; };
const handleJournalPress = useCallback((id: number) => {
router.push(`/journal/${id}`);
}, [router]);
if (isLoading && !refreshing) { if (isLoading && !refreshing) {
return <LoadingScreen />; return <LoadingScreen />;
} }
@@ -108,19 +111,18 @@ export default function JournalScreen() {
<View className="flex-1 bg-gray-50 rounded-t-[2.5rem] overflow-hidden"> <View className="flex-1 bg-gray-50 rounded-t-[2.5rem] overflow-hidden">
{/* List */} {/* List */}
<ScrollView <FlatList
contentContainerStyle={{ padding: 20, paddingBottom: 180 }} data={updates}
keyExtractor={(item) => (item.id ? item.id.toString() : Math.random().toString())}
className="flex-1"
contentContainerStyle={{ padding: 20, paddingBottom: 180, gap: 16 }}
showsVerticalScrollIndicator={false} showsVerticalScrollIndicator={false}
refreshControl={<RefreshControl refreshing={refreshing} onRefresh={onRefresh} colors={['#1071C2']} />} refreshControl={<RefreshControl refreshing={refreshing} onRefresh={onRefresh} colors={['#1071C2']} />}
> initialNumToRender={8}
{updates.length === 0 ? ( maxToRenderPerBatch={10}
<View className="bg-white p-8 rounded-3xl border border-gray-100 items-center justify-center border-dashed mt-4"> windowSize={5}
<Text className="text-gray-400 font-medium text-center">Nessun invio registrato al giornale di cantiere</Text> renderItem={({ item }) => (
</View> <View className="bg-white p-5 rounded-3xl shadow-sm border border-gray-100">
) : (
<View className="gap-4">
{updates.map((item, index) => (
<View key={index} className="bg-white p-5 rounded-3xl shadow-sm border border-gray-100">
<View className="mb-3"> <View className="mb-3">
<Text className="font-bold text-[#082963] text-lg uppercase tracking-wide leading-tight"> <Text className="font-bold text-[#082963] text-lg uppercase tracking-wide leading-tight">
{item.place_name} {item.place_name}
@@ -128,9 +130,11 @@ export default function JournalScreen() {
<Text className="text-gray-500 text-sm font-medium mt-1"> <Text className="text-gray-500 text-sm font-medium mt-1">
{item.place_address} {item.place_address}
</Text> </Text>
{item.description ? (
<Text className="text-gray-400 text-base leading-relaxed mt-1"> <Text className="text-gray-400 text-base leading-relaxed mt-1">
{item.description} {item.description}
</Text> </Text>
) : null}
</View> </View>
<View className="flex-row items-center justify-between border-t border-gray-50 pt-4"> <View className="flex-row items-center justify-between border-t border-gray-50 pt-4">
@@ -148,17 +152,20 @@ export default function JournalScreen() {
{item.n_files > 0 && ( {item.n_files > 0 && (
<TouchableOpacity <TouchableOpacity
className="bg-gray-100 px-4 py-2 rounded-xl active:bg-gray-200" className="bg-gray-100 px-4 py-2 rounded-xl active:bg-gray-200"
onPress={() => router.push(`/journal/${item.id}`)} onPress={() => handleJournalPress(item.id)}
> >
<Text className="text-gray-600 font-bold text-sm">Vedi</Text> <Text className="text-gray-600 font-bold text-sm">Vedi</Text>
</TouchableOpacity> </TouchableOpacity>
)} )}
</View> </View>
</View> </View>
))}
</View>
)} )}
</ScrollView> ListEmptyComponent={
<View className="bg-white p-8 rounded-3xl border border-gray-100 items-center justify-center border-dashed mt-4">
<Text className="text-gray-400 font-medium text-center">Nessun invio registrato al giornale di cantiere</Text>
</View>
}
/>
{/* FAB Add Journal */} {/* FAB Add Journal */}
<TouchableOpacity <TouchableOpacity