diff --git a/src/ai/flows/financial-summary.ts b/src/ai/flows/financial-summary.ts index e617cfd..5da7e5f 100644 --- a/src/ai/flows/financial-summary.ts +++ b/src/ai/flows/financial-summary.ts @@ -24,7 +24,12 @@ const FinancialSummaryOutputSchema = z.object({ export type FinancialSummaryOutput = z.infer; export async function generateFinancialSummary(input: FinancialSummaryInput): Promise { - return financialSummaryFlow(input); + try { + return await financialSummaryFlow(input); + } catch (error) { + console.error('Error generating financial summary:', error); + throw new Error(`Failed to generate financial summary: ${error instanceof Error ? error.message : 'Unknown error'}`); + } } const prompt = ai.definePrompt({ @@ -48,7 +53,15 @@ const financialSummaryFlow = ai.defineFlow( outputSchema: FinancialSummaryOutputSchema, }, async input => { - const {output} = await prompt(input); - return output!; + try { + const {output} = await prompt(input); + if (!output) { + throw new Error('AI model returned empty output'); + } + return output; + } catch (error) { + console.error('Error in financial summary flow:', error); + throw error; + } } ); diff --git a/src/app/(app)/layout.tsx b/src/app/(app)/layout.tsx index 8374f0a..747b67a 100644 --- a/src/app/(app)/layout.tsx +++ b/src/app/(app)/layout.tsx @@ -223,7 +223,12 @@ export default function AppLayout({ children }: { children: React.ReactNode }) { }, []); const deleteRevenueRecord = useCallback(async (id: string) => { - await deleteDoc(doc(db, 'revenue', id)); + try { + await deleteDoc(doc(db, 'revenue', id)); + } catch (error) { + console.error('Error deleting revenue record:', error); + throw error; + } }, []); const addExpense = useCallback(async (expense: Omit) => { @@ -231,7 +236,12 @@ export default function AppLayout({ children }: { children: React.ReactNode }) { }, []); const deleteExpense = useCallback(async (id: string) => { - await deleteDoc(doc(db, 'expenses', id)); + try { + await deleteDoc(doc(db, 'expenses', id)); + } catch (error) { + console.error('Error deleting expense:', error); + throw error; + } }, []); const addRequest = useCallback(async (request: Omit) => { @@ -239,8 +249,13 @@ export default function AppLayout({ children }: { children: React.ReactNode }) { }, []); const updateRequestStatus = useCallback(async (id: string, status: EmployeeRequest['status'], notes?: string) => { + try { const requestDocRef = doc(db, 'requests', id); await updateDoc(requestDocRef, { status, notes }); + } catch (error) { + console.error('Error updating request status:', error); + throw error; + } }, []); diff --git a/src/app/(app/expenses/page.tsx b/src/app/(app/expenses/page.tsx deleted file mode 100644 index 50fc204..0000000 --- a/src/app/(app/expenses/page.tsx +++ /dev/null @@ -1,335 +0,0 @@ - -'use client'; -import React, { useState, useContext, useEffect } from 'react'; -import { Card, CardContent, CardHeader, CardTitle, CardDescription, CardFooter } from "@/components/ui/card"; -import { Button } from "@/components/ui/button"; -import { Input } from "@/components/ui/input"; -import { Label } from "@/components/ui/label"; -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; -import { Textarea } from "@/components/ui/textarea"; -import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; -import { Badge } from "@/components/ui/badge"; -import { CirclePlus, ListOrdered, FilePenLine, Trash2, Search, Printer } from "lucide-react"; -import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; -import { TooltipProvider, Tooltip, TooltipTrigger, TooltipContent } from "@/components/ui/tooltip"; -import { useToast } from "@/hooks/use-toast"; -import { DataContext, BranchContext } from '../layout'; -import pdfService from '@/services/pdf.service'; -import { useAuth } from '@/hooks/use-auth'; - -export type Expense = { - id: string; - date: string; - branch: string; - category: string; - amount: number; - description: string; -}; - -export default function ExpensesPage() { - const { expenses, addExpense, deleteExpense } = useContext(DataContext); - const { user } = useAuth(); - const { currentBranch } = useContext(BranchContext); - const [filteredExpenses, setFilteredExpenses] = useState(expenses); - const [searchTerm, setSearchTerm] = useState(''); - const { toast } = useToast(); - - // Form state - const [date, setDate] = useState(new Date().toISOString().split('T')[0]); - const [branch, setBranch] = useState(currentBranch); // Set initial branch from context - const [category, setCategory] = useState(''); - const [amount, setAmount] = useState(''); - const [description, setDescription] = useState(''); - - useEffect(() => { - setFilteredExpenses(expenses); - }, [expenses]); - - // Keep form branch in sync with context - useEffect(() => { - setBranch(currentBranch); - }, [currentBranch]); - - - const handleSaveExpense = async (e: React.FormEvent) => { - e.preventDefault(); - if (!date || !branch || !category || !amount || !description) { - toast({ - variant: "destructive", - title: "خطأ", - description: "الرجاء تعبئة جميع الحقول المطلوبة.", - }); - return; - } - const newExpense: Omit = { - date, - branch: branch === 'laban' ? 'فرع لبن' : 'فرع طويق', - category, - amount: parseFloat(amount), - description, - }; - - const result = await addExpense(newExpense); - - if(result.success) { - // Reset form - setDate(new Date().toISOString().split('T')[0]); - // Keep branch set to current branch - setCategory(''); - setAmount(''); - setDescription(''); - - toast({ - title: "تم الحفظ بنجاح", - description: "تمت إضافة المصروف الجديد إلى السجل.", - className: "bg-primary text-primary-foreground", - }); - } else { - toast({ - variant: "destructive", - title: "فشل الحفظ", - description: "لم يتم حفظ المصروف بسبب خطأ في الشبكة أو الصلاحيات.", - }); - } - }; - - const handleSearch = (term: string) => { - setSearchTerm(term); - if (!term) { - setFilteredExpenses(expenses); - } else { - const results = expenses.filter(expense => - expense.description.toLowerCase().includes(term.toLowerCase()) || - expense.category.toLowerCase().includes(term.toLowerCase()) || - expense.branch.toLowerCase().includes(term.toLowerCase()) - ); - setFilteredExpenses(results); - } - } - - const handleDelete = (id: string) => { - deleteExpense(id); - toast({ - variant: "destructive", - title: "تم الحذف", - description: `تم حذف المصروف رقم ${id} من السجل.`, - }); - } - - const handleEdit = (id: string) => { - toast({ - title: "غير متاح حالياً", - description: `ميزة تعديل المصروف ${id} سيتم إضافتها قريباً.`, - }); - } - - const handlePrint = async () => { - if (filteredExpenses.length === 0) { - toast({ variant: 'destructive', title: 'لا توجد بيانات للطباعة' }); - return; - } - - const tableData = filteredExpenses.map(exp => [ - exp.date, - exp.branch, - exp.category, - exp.amount.toFixed(2) + ' ريال', - exp.description - ]); - - const supervisor = { name: 'المشرف المسؤول' }; // Placeholder - - await pdfService.generatePDF({ - title: 'تقرير المصروفات', - type: 'report', - content: { - table: { - headers: [['التاريخ', 'الفرع', 'البند', 'المبلغ', 'الوصف']], - data: tableData - } - }, - userData: user, - branchData: { - name: currentBranch === 'laban' ? 'فرع لبن' : 'فرع طويق', - supervisorName: supervisor.name - } - }); - - await pdfService.print(); - } - - - return ( - <> -
- - - - - إضافة مصروف - - - - عرض المصاريف - - - - - - - إضافة مصروف جديد - سجل المصروفات الجديدة للفروع للحفاظ على دقة السجلات المالية. - -
- -
-
- - setDate(e.target.value)} /> -
-
- - -
-
-
- - -
-
-
- - setAmount(e.target.value)} /> -
-
- -