import React, { useState, useEffect, useRef } from 'react'; import { initializeApp } from 'firebase/app'; import { getAuth, signInAnonymously, signInWithCustomToken, onAuthStateChanged } from 'firebase/auth'; import { getFirestore, collection, addDoc, onSnapshot, query, orderBy, deleteDoc, doc, updateDoc, serverTimestamp } from 'firebase/firestore'; // Ensure __app_id, __firebase_config, and __initial_auth_token are defined in the environment const appId = typeof __app_id !== 'undefined' ? __app_id : 'default-app-id'; const firebaseConfig = typeof __firebase_config !== 'undefined' ? JSON.parse(__firebase_config) : {}; const initialAuthToken = typeof __initial_auth_token !== 'undefined' ? __initial_auth_token : null; // Tailwind CSS is assumed to be available, no import needed. // Lucide React for icons (example: search, edit, delete) // Shadcn UI components for styling (buttons, inputs, table, dialog) function App() { const [db, setDb] = useState(null); const [auth, setAuth] = useState(null); const [userId, setUserId] = useState(null); const [transfers, setTransfers] = useState([]); const [searchTerm, setSearchTerm] = useState(''); const [isAuthReady, setIsAuthReady] = useState(false); const [showAddModal, setShowAddModal] = useState(false); const [showEditModal, setShowEditModal] = useState(false); const [currentTransfer, setCurrentTransfer] = useState(null); const [formErrors, setFormErrors] = useState({}); const [loading, setLoading] = useState(true); const [message, setMessage] = useState(''); const messageTimeoutRef = useRef(null); // Initialize Firebase and set up authentication useEffect(() => { try { const app = initializeApp(firebaseConfig); const firestore = getFirestore(app); const authentication = getAuth(app); setDb(firestore); setAuth(authentication); const unsubscribe = onAuthStateChanged(authentication, async (user) => { if (user) { setUserId(user.uid); setIsAuthReady(true); } else { try { if (initialAuthToken) { await signInWithCustomToken(authentication, initialAuthToken); } else { await signInAnonymously(authentication); } } catch (error) { console.error("Error signing in:", error); setMessage("حدث خطأ أثناء تسجيل الدخول. يرجى المحاولة مرة أخرى."); setIsAuthReady(true); // Still set ready to attempt data fetch } } }); return () => unsubscribe(); } catch (error) { console.error("Error initializing Firebase:", error); setMessage("فشل تهيئة Firebase. يرجى التحقق من الإعدادات."); setLoading(false); } }, []); // Fetch data from Firestore once authenticated and ready useEffect(() => { if (db && userId && isAuthReady) { const transfersColRef = collection(db, `artifacts/${appId}/public/data/transfers`); // Note: orderBy is commented out to avoid potential index issues as per instructions. // Data will be sorted client-side. const q = query(transfersColRef); //, orderBy('transactionDate', 'desc')); const unsubscribe = onSnapshot(q, (snapshot) => { const fetchedTransfers = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() })); // Sort client-side by transactionDate (descending) fetchedTransfers.sort((a, b) => { const dateA = a.transactionDate ? new Date(a.transactionDate.toDate()) : new Date(0); const dateB = b.transactionDate ? new Date(b.transactionDate.toDate()) : new Date(0); return dateB - dateA; }); setTransfers(fetchedTransfers); setLoading(false); }, (error) => { console.error("Error fetching transfers:", error); setMessage("حدث خطأ أثناء جلب التحويلات."); setLoading(false); }); return () => unsubscribe(); } else if (!isAuthReady && !userId) { // Still waiting for auth to be ready setLoading(true); } }, [db, userId, isAuthReady]); // Function to show transient messages const showMessage = (msg) => { setMessage(msg); if (messageTimeoutRef.current) { clearTimeout(messageTimeoutRef.current); } messageTimeoutRef.current = setTimeout(() => { setMessage(''); }, 3000); // Message disappears after 3 seconds }; // Form validation const validateForm = (data) => { const errors = {}; if (!data.receiverName || data.receiverName.trim() === '') { errors.receiverName = 'اسم المحول إليه مطلوب.'; } if (!data.bankName || data.bankName.trim() === '') { errors.bankName = 'اسم البنك مطلوب.'; } if (!data.amount || isNaN(parseFloat(data.amount)) || parseFloat(data.amount) <= 0) { errors.amount = 'المبلغ بالدولار يجب أن يكون رقمًا موجبًا.'; } // Corrected validation for transactionDate if (!data.transactionDate || !(data.transactionDate instanceof Date) || isNaN(data.transactionDate.getTime())) { errors.transactionDate = 'تاريخ العملية مطلوب وصحيح.'; } return errors; }; // Add new transfer const handleAddTransfer = async (e) => { e.preventDefault(); const formData = new FormData(e.target); const newTransfer = { receiverName: formData.get('receiverName'), bankName: formData.get('bankName'), amount: parseFloat(formData.get('amount')), transactionDate: new Date(formData.get('transactionDate')), // Convert to Date object userId: userId, // Store the user ID for ownership (even for public data) createdAt: serverTimestamp() // Add creation timestamp }; const errors = validateForm(newTransfer); if (Object.keys(errors).length > 0) { setFormErrors(errors); return; } try { if (db) { await addDoc(collection(db, `artifacts/${appId}/public/data/transfers`), newTransfer); setShowAddModal(false); e.target.reset(); // Clear form setFormErrors({}); showMessage("تمت إضافة التحويل بنجاح!"); } } catch (error) { console.error("Error adding document: ", error); showMessage("حدث خطأ أثناء إضافة التحويل."); } }; // Update existing transfer const handleUpdateTransfer = async (e) => { e.preventDefault(); const formData = new FormData(e.target); const updatedTransfer = { receiverName: formData.get('receiverName'), bankName: formData.get('bankName'), amount: parseFloat(formData.get('amount')), transactionDate: new Date(formData.get('transactionDate')), // Convert to Date object updatedAt: serverTimestamp() // Add update timestamp }; const errors = validateForm(updatedTransfer); if (Object.keys(errors).length > 0) { setFormErrors(errors); return; } try { if (db && currentTransfer) { const transferDocRef = doc(db, `artifacts/${appId}/public/data/transfers`, currentTransfer.id); await updateDoc(transferDocRef, updatedTransfer); setShowEditModal(false); setCurrentTransfer(null); setFormErrors({}); showMessage("تم تحديث التحويل بنجاح!"); } } catch (error) { console.error("Error updating document: ", error); showMessage("حدث خطأ أثناء تحديث التحويل."); } }; // Delete transfer const handleDeleteTransfer = async (id) => { if (!window.confirm("هل أنت متأكد أنك تريد حذف هذا التحويل؟")) { // Using window.confirm for simplicity, but custom modal is preferred return; } try { if (db) { await deleteDoc(doc(db, `artifacts/${appId}/public/data/transfers`, id)); showMessage("تم حذف التحويل بنجاح!"); } } catch (error) { console.error("Error deleting document: ", error); showMessage("حدث خطأ أثناء حذف التحويل."); } }; // Filter transfers based on search term const filteredTransfers = transfers.filter(transfer => { const searchLower = searchTerm.toLowerCase(); return ( transfer.receiverName.toLowerCase().includes(searchLower) || transfer.bankName.toLowerCase().includes(searchLower) || transfer.amount.toString().includes(searchLower) || (transfer.transactionDate && new Date(transfer.transactionDate.toDate()).toLocaleDateString('ar-EG').includes(searchLower)) ); }); if (loading) { return (

جاري التحميل...

); } return (
{/* Global Message Display */} {message && (
{message}
)} {/* Header */}

نظام إدارة التحويلات المالية

معرف المستخدم: {userId}
{/* Main Content Area */}
{/* Add Transfer Section */}

إضافة تحويل جديد

{/* Transfers List Section */}

قائمة التحويلات

setSearchTerm(e.target.value)} />
{filteredTransfers.length === 0 ? (

لا توجد تحويلات لعرضها أو لا توجد نتائج للبحث.

) : (
{filteredTransfers.map((transfer) => ( ))}
المحول إليه البنك المبلغ (دولار) التاريخ الإجراءات
{transfer.receiverName} {transfer.bankName} ${transfer.amount.toFixed(2)} {transfer.transactionDate ? new Date(transfer.transactionDate.toDate()).toLocaleDateString('ar-EG') : 'غير محدد'}
)}
{/* Add Transfer Modal */} {showAddModal && (

إضافة تحويل جديد

{formErrors.receiverName &&

{formErrors.receiverName}

}
{formErrors.bankName &&

{formErrors.bankName}

}
{formErrors.amount &&

{formErrors.amount}

}
{formErrors.transactionDate &&

{formErrors.transactionDate}

}
)} {/* Edit Transfer Modal */} {showEditModal && currentTransfer && (

تعديل التحويل

{formErrors.receiverName &&

{formErrors.receiverName}

}
{formErrors.bankName &&

{formErrors.bankName}

}
{formErrors.amount &&

{formErrors.amount}

}
{formErrors.transactionDate &&

{formErrors.transactionDate}

}
)} {/* Custom CSS for animations and general styling */}
); } export default App;