Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions src/ai/flows/financial-summary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,12 @@ const FinancialSummaryOutputSchema = z.object({
export type FinancialSummaryOutput = z.infer<typeof FinancialSummaryOutputSchema>;

export async function generateFinancialSummary(input: FinancialSummaryInput): Promise<FinancialSummaryOutput> {
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({
Expand All @@ -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;
}
}
);
19 changes: 17 additions & 2 deletions src/app/(app)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -223,24 +223,39 @@ 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<Expense, 'id'>) => {
return saveDataWithRetry('expenses', expense);
}, []);

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<EmployeeRequest, 'id'>) => {
return saveDataWithRetry('requests', request);
}, []);

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;
}
}, []);


Expand Down
335 changes: 0 additions & 335 deletions src/app/(app/expenses/page.tsx

This file was deleted.

10 changes: 7 additions & 3 deletions src/components/revenue/revenue-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,13 @@ export function RevenueForm({ onSave }: RevenueFormProps) {
);

const onSubmit: SubmitHandler<RevenueFormValues> = async (data) => {
const success = await onSave(data, currentBranch);
if (success) {
form.reset();
try {
const success = await onSave(data, currentBranch);
if (success) {
form.reset();
}
} catch (error) {
console.error('Error submitting revenue form:', error);
}
};

Expand Down
4 changes: 3 additions & 1 deletion src/lib/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,11 @@ export async function getFinancialSummary(
data: result
};
} catch (error) {
console.error('Error generating financial summary:', error);
const errorMessage = error instanceof Error ? error.message : 'حدث خطأ غير معروف';
return {
success: false,
message: "حدث خطأ أثناء إنشاء الملخص. الرجاء المحاولة مرة أخرى."
message: `حدث خطأ أثناء إنشاء الملخص: ${errorMessage}. الرجاء المحاولة مرة أخرى.`
};
}
}
215 changes: 137 additions & 78 deletions src/lib/openai-responses-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,39 +35,49 @@ class OpenAIResponsesClient implements ResponsesAPIClient {
}

async createResponse(params: CreateResponseParams): Promise<ResponseStream | any> {
const response = await fetch(`${this.baseURL}/responses`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
model: 'gpt-4.1-2025-04-14',
input: params.input,
instructions: params.instructions,
previous_response_id: this.lastResponseId,
conversation: this.conversationId,
tools: params.tools || [
{ type: 'web_search' },
{ type: 'file_search' },
{ type: 'code_interpreter' }
],
store: true,
stream: params.stream ?? true,
include: [
'web_search_call.action.sources',
'code_interpreter_call.outputs',
'file_search_call.results'
]
try {
const response = await fetch(`${this.baseURL}/responses`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
model: 'gpt-4.1-2025-04-14',
input: params.input,
instructions: params.instructions,
previous_response_id: this.lastResponseId,
conversation: this.conversationId,
tools: params.tools || [
{ type: 'web_search' },
{ type: 'file_search' },
{ type: 'code_interpreter' }
],
store: true,
stream: params.stream ?? true,
include: [
'web_search_call.action.sources',
'code_interpreter_call.outputs',
'file_search_call.results'
]
})
})
})

if (params.stream) {
return this.handleStreamResponse(response)
} else {
const data = await response.json()
this.lastResponseId = data.id
return data

if (!response.ok) {
const errorData = await response.json().catch(() => ({}))
throw new Error(`API request failed: ${response.status} ${response.statusText}. ${JSON.stringify(errorData)}`)
}

if (params.stream) {
return this.handleStreamResponse(response)
} else {
const data = await response.json()
this.lastResponseId = data.id
return data
}
} catch (error) {
console.error('Error creating response:', error)
throw error
}
}

Expand Down Expand Up @@ -105,67 +115,116 @@ class OpenAIResponsesClient implements ResponsesAPIClient {
}

async getResponse(responseId: string): Promise<any> {
// Implementation for getResponse
const response = await fetch(`${this.baseURL}/responses/${responseId}`, {
try {
const response = await fetch(`${this.baseURL}/responses/${responseId}`, {
headers: {
'Authorization': `Bearer ${this.apiKey}`
'Authorization': `Bearer ${this.apiKey}`
}
});
return response.json();
});

if (!response.ok) {
const errorData = await response.json().catch(() => ({}))
throw new Error(`Failed to get response: ${response.status} ${response.statusText}. ${JSON.stringify(errorData)}`)
}

return response.json();
} catch (error) {
console.error('Error getting response:', error)
throw error
}
}

async createConversation(items: any[] = []): Promise<Conversation> {
const response = await fetch(`${this.baseURL}/conversations`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ items })
})

const conversation = await response.json()
this.conversationId = conversation.id
return conversation
try {
const response = await fetch(`${this.baseURL}/conversations`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ items })
})

if (!response.ok) {
const errorData = await response.json().catch(() => ({}))
throw new Error(`Failed to create conversation: ${response.status} ${response.statusText}. ${JSON.stringify(errorData)}`)
}

const conversation = await response.json()
this.conversationId = conversation.id
return conversation
} catch (error) {
console.error('Error creating conversation:', error)
throw error
}
}

async addToConversation(conversationId: string, items: any[]): Promise<void> {
// Implementation for addToConversation
await fetch(`${this.baseURL}/conversations/${conversationId}/items`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ items })
});
try {
const response = await fetch(`${this.baseURL}/conversations/${conversationId}/items`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ items })
});

if (!response.ok) {
const errorData = await response.json().catch(() => ({}))
throw new Error(`Failed to add to conversation: ${response.status} ${response.statusText}. ${JSON.stringify(errorData)}`)
}
} catch (error) {
console.error('Error adding to conversation:', error)
throw error
}
}

connectWebSocket(clientId: string, onMessage: (event: any) => void) {
const wsUrl = process.env.NEXT_PUBLIC_WS_URL || 'ws://localhost:8000'
this.ws = new WebSocket(`${wsUrl}/ws/${clientId}`)

this.ws.onmessage = (event) => {
const data = JSON.parse(event.data)
onMessage(data)
}

this.ws.onopen = () => {
console.log('WebSocket connected')
}

this.ws.onerror = (error) => {
console.error('WebSocket error:', error)
try {
const wsUrl = process.env.NEXT_PUBLIC_WS_URL || 'ws://localhost:8000'
this.ws = new WebSocket(`${wsUrl}/ws/${clientId}`)

this.ws.onmessage = (event) => {
try {
const data = JSON.parse(event.data)
onMessage(data)
} catch (error) {
console.error('Error parsing WebSocket message:', error)
}
}

this.ws.onopen = () => {
console.log('WebSocket connected')
}

this.ws.onerror = (error) => {
console.error('WebSocket error:', error)
}

this.ws.onclose = (event) => {
console.log('WebSocket closed:', event.code, event.reason)
}
} catch (error) {
console.error('Error connecting WebSocket:', error)
throw error
}
}

sendMessage(type: string, data: any) {
if (this.ws?.readyState === WebSocket.OPEN) {
this.ws.send(JSON.stringify({
type,
...data,
previous_response_id: this.lastResponseId
}))
try {
if (this.ws?.readyState === WebSocket.OPEN) {
this.ws.send(JSON.stringify({
type,
...data,
previous_response_id: this.lastResponseId
}))
} else {
console.warn('WebSocket is not open. Current state:', this.ws?.readyState)
}
} catch (error) {
console.error('Error sending WebSocket message:', error)
throw error
}
}
}
Expand Down
Loading