Files
fonsi_app/components/ActivityLaborCard.tsx
T
2026-09-10 14:08:41 +02:00

190 lines
7.4 KiB
TypeScript

import React, { useState, useEffect, useCallback } from 'react';
import { View, Text, TouchableOpacity, TextInput } from 'react-native';
import { Plus, Trash2, CheckCircle2 } from 'lucide-react-native';
import GenericDropdown from './GenericDropdown';
import api from '@/utils/api';
import { useAlert } from './AlertComponent';
interface LaborItem {
id_registry: number | null;
id_user: number | null;
name: string;
hours: string | number;
minutes: string | number;
sync?: boolean;
id?: number;
}
interface ActivityLaborCardProps {
title: string;
fetchUrl: string;
laborList: LaborItem[];
onAddLabor: (labor: LaborItem) => void;
onRemoveLabor: (index: number) => void;
}
export default function ActivityLaborCard({
title,
fetchUrl,
laborList,
onAddLabor,
onRemoveLabor
}: ActivityLaborCardProps) {
const alert = useAlert();
const [items, setItems] = useState<any[]>([]);
const [showInput, setShowInput] = useState(false);
// Form states
const [selectedId, setSelectedId] = useState<number | null>(null);
const [hours, setHours] = useState('');
const [minutes, setMinutes] = useState('');
const loadItems = useCallback(async () => {
try {
const res = await api.get(fetchUrl);
if (res.data?.success && res.data.items) {
// Map the items to include an 'id' property required by GenericDropdown
const mappedItems = res.data.items.map((item: any, idx: number) => ({
...item,
id: item.id ?? (item.id_user !== null && item.id_user !== undefined ? item.id_user : (item.id_registry ?? idx + 1))
}));
setItems(mappedItems);
}
} catch (error) {
console.error('Error fetching labor items:', error);
}
}, [fetchUrl]);
useEffect(() => {
loadItems();
}, [loadItems]);
const handleAdd = () => {
if (!selectedId) {
alert.showAlert('error', 'Attenzione', 'Selezionare un elemento dalla lista');
return;
}
if (hours === '' && minutes === '') {
alert.showAlert('error', 'Attenzione', 'Inserire le ore o i minuti di lavoro');
return;
}
const el = items.find(data => data.id === selectedId);
if (el) {
const newLabor: LaborItem = {
id_registry: el.id_registry ?? null,
id_user: el.id_user ?? null,
name: el.label,
hours: hours === '' ? '0' : hours,
minutes: minutes === '' ? '0' : minutes,
};
onAddLabor(newLabor);
// Reset and hide
setSelectedId(null);
setHours('');
setMinutes('');
setShowInput(false);
}
};
const toggleInput = () => {
setSelectedId(null);
setHours('');
setMinutes('');
setShowInput(!showInput);
};
return (
<View className="bg-white rounded-3xl p-5 shadow-sm border border-gray-100 mb-4">
<View className="flex-row items-center justify-between border-b border-gray-50 pb-3 mb-3">
<Text className="text-[#082963] font-bold text-lg">{title}</Text>
<TouchableOpacity onPress={toggleInput} className="active:opacity-70">
<Text className="text-[#1071C2] font-bold text-sm">
{showInput ? 'Annulla' : 'Aggiungi'}
</Text>
</TouchableOpacity>
</View>
{showInput && (
<View className="bg-blue-50/50 p-4 rounded-2xl mb-4 border border-blue-100">
<View className="mb-3 z-50">
<GenericDropdown
options={items}
selectedId={selectedId}
onSelect={(id) => setSelectedId(id as number)}
placeholder="Seleziona..."
searchPlaceholder="Cerca per nome"
/>
</View>
<View className="flex-row items-center gap-2">
<View className="flex-1 bg-white rounded-xl border border-gray-200 px-3 py-2">
<TextInput
value={hours}
onChangeText={setHours}
placeholder="Ore"
placeholderTextColor="#9ca3af"
keyboardType="numeric"
className="text-gray-800 font-medium"
/>
</View>
<View className="flex-1 bg-white rounded-xl border border-gray-200 px-3 py-2">
<TextInput
value={minutes}
onChangeText={setMinutes}
placeholder="Minuti"
placeholderTextColor="#9ca3af"
keyboardType="numeric"
className="text-gray-800 font-medium"
/>
</View>
<TouchableOpacity
onPress={handleAdd}
className="bg-[#1071C2] h-[46px] w-[46px] items-center justify-center rounded-xl"
>
<Plus size={24} color="white" />
</TouchableOpacity>
</View>
</View>
)}
<View className="gap-2">
{laborList.map((item, index) => (
<View key={index} className="flex-row justify-between items-center bg-gray-50 p-3 rounded-2xl">
<Text className="text-gray-800 font-medium flex-1 mr-2" numberOfLines={2}>
{item.name}
</Text>
<View className="flex-row items-center gap-3">
<View className="bg-white px-3 py-1.5 rounded-xl border border-gray-200">
<Text className="text-[#1071C2] font-bold">
{item.hours}h {item.minutes}m
</Text>
</View>
{item.sync ? (
<View className="w-8 items-center justify-center">
<CheckCircle2 size={20} color="#0F9D58" />
</View>
) : (
<TouchableOpacity
onPress={() => onRemoveLabor(index)}
className="w-8 items-center justify-center"
>
<Trash2 size={20} color="#ef4444" />
</TouchableOpacity>
)}
</View>
</View>
))}
{laborList.length === 0 && !showInput && (
<Text className="text-gray-400 text-center italic mt-2">Nessun elemento inserito</Text>
)}
</View>
</View>
);
}