Add profile and login screen + first api logic draft
This commit is contained in:
136
app/(protected)/documents/index.tsx
Normal file
136
app/(protected)/documents/index.tsx
Normal file
@ -0,0 +1,136 @@
|
||||
import { DOCUMENTS_DATA } from '@/data/data';
|
||||
import { Download, FileText, MapPin, Plus, Search, CalendarIcon } from 'lucide-react-native';
|
||||
import React, { useState } from 'react';
|
||||
import { RangePickerModal } from '@/components/RangePickerModal';
|
||||
import { ScrollView, Text, TextInput, TouchableOpacity, View } from 'react-native';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
export default function DocumentsScreen() {
|
||||
const [searchTerm, setSearchTerm] = useState('');
|
||||
// Gestiamo le date come oggetti Dayjs o null per il datepicker, e stringhe per il filtro
|
||||
const [range, setRange] = useState<{ startDate: any; endDate: any }>({
|
||||
startDate: null,
|
||||
endDate: null
|
||||
});
|
||||
|
||||
const [showRangePicker, setShowRangePicker] = useState(false);
|
||||
|
||||
// Funzione helper per convertire DD/MM/YYYY in oggetto Date (per il filtro esistente)
|
||||
const parseDate = (dateStr: string) => {
|
||||
if (!dateStr) return new Date();
|
||||
const [day, month, year] = dateStr.split('/').map(Number);
|
||||
return new Date(year, month - 1, day);
|
||||
};
|
||||
|
||||
const filteredDocs = DOCUMENTS_DATA.filter(doc => {
|
||||
// Filtro Testuale
|
||||
const matchesSearch = doc.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
doc.site.toLowerCase().includes(searchTerm.toLowerCase());
|
||||
|
||||
if (!matchesSearch) return false;
|
||||
|
||||
// Filtro Date Range
|
||||
if (range.startDate || range.endDate) {
|
||||
const docDate = parseDate(doc.date); // doc.date è "DD/MM/YYYY"
|
||||
|
||||
// Controllo Data Inizio
|
||||
if (range.startDate) {
|
||||
// dayjs(range.startDate).toDate() converte in oggetto Date JS standard
|
||||
const start = dayjs(range.startDate).startOf('day').toDate();
|
||||
if (docDate < start) return false;
|
||||
}
|
||||
|
||||
// Controllo Data Fine
|
||||
if (range.endDate) {
|
||||
const end = dayjs(range.endDate).endOf('day').toDate();
|
||||
if (docDate > end) return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
// Funzione per formattare la visualizzazione
|
||||
const formatDateDisplay = (date: any) => {
|
||||
return date ? dayjs(date).format('DD/MM/YYYY') : 'gg/mm/aaaa';
|
||||
};
|
||||
|
||||
return (
|
||||
<View className="flex-1 bg-gray-50">
|
||||
{/* Header */}
|
||||
<View className="bg-white p-6 pt-16 shadow-sm border-b border-gray-100">
|
||||
<Text className="text-3xl font-bold text-gray-800 mb-1">Documenti</Text>
|
||||
<Text className="text-base text-gray-500">Gestione modulistica e schemi</Text>
|
||||
</View>
|
||||
|
||||
<View className="p-5 gap-6 flex-1">
|
||||
{/* Search + Date Row */}
|
||||
<View className="flex-row gap-2">
|
||||
{/* Search Bar */}
|
||||
<View className={`flex-1 relative justify-center shadow-sm rounded-2xl border ${searchTerm ? 'border-[#099499]' : 'border-gray-200'}`}>
|
||||
<View className="absolute left-4 z-10">
|
||||
<Search size={24} color="#9ca3af" />
|
||||
</View>
|
||||
<TextInput
|
||||
placeholder="Cerca nome, cantiere..."
|
||||
placeholderTextColor="#9ca3af"
|
||||
className="w-full pl-12 pr-4 py-4 bg-white rounded-2xl text-gray-800 text-lg"
|
||||
value={searchTerm}
|
||||
onChangeText={setSearchTerm}
|
||||
/>
|
||||
</View>
|
||||
|
||||
{/* Date Filter Button */}
|
||||
<TouchableOpacity
|
||||
onPress={() => setShowRangePicker(true)}
|
||||
className={`p-4 bg-white rounded-2xl shadow-sm border ${range.startDate ? 'border-[#099499]' : 'border-gray-200'}`}
|
||||
>
|
||||
<CalendarIcon size={24} color={range.startDate ? "#099499" : "#9ca3af"} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
{/* Modale Unico per il Range */}
|
||||
<RangePickerModal
|
||||
visible={showRangePicker}
|
||||
onClose={() => setShowRangePicker(false)}
|
||||
currentRange={range}
|
||||
onApply={setRange}
|
||||
/>
|
||||
|
||||
{/* List */}
|
||||
<ScrollView
|
||||
contentContainerStyle={{ gap: 16, paddingBottom: 100 }}
|
||||
showsVerticalScrollIndicator={false}
|
||||
>
|
||||
{filteredDocs.map((doc) => (
|
||||
<View key={doc.id} className="bg-white p-5 rounded-3xl shadow-sm flex-row items-center justify-between border border-gray-100">
|
||||
<View className="flex-row items-center gap-5 flex-1">
|
||||
<View className="bg-red-50 p-4 rounded-2xl">
|
||||
<FileText size={32} color="#ef4444" />
|
||||
</View>
|
||||
<View className="flex-1">
|
||||
<Text className="font-bold text-gray-800 text-lg mb-1">{doc.name}</Text>
|
||||
<View className="flex-row items-center mt-1">
|
||||
<MapPin size={16} color="#9ca3af" />
|
||||
<Text className="text-sm text-gray-400 ml-1 font-medium">{doc.site}</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
<TouchableOpacity className="p-4 bg-gray-50 rounded-2xl active:bg-gray-100">
|
||||
<Download size={24} color="#6b7280" />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
))}
|
||||
</ScrollView>
|
||||
</View>
|
||||
|
||||
{/* FAB */}
|
||||
<TouchableOpacity
|
||||
onPress={() => alert('Aggiungi nuovo documento')}
|
||||
className="absolute bottom-8 right-6 w-16 h-16 bg-[#099499] rounded-full shadow-lg items-center justify-center active:scale-90"
|
||||
>
|
||||
<Plus size={32} color="white" />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user