import flet as ft import requests import json from datetime import datetime from helpers.document_status import DocumentsStatus from helpers.emails import send_gmail class Documents: def __init__(self, page: ft.Page, home): self.page = page self.home = home # Keep reference to home for potential page updates self.base_url = self.page.session.store.get('api_base_url') self.token = self.page.session.store.get('token') self.user = self.page.session.store.get('user') self.user_id = self.user['id'] if self.user else None # Assuming user object has 'id' self.all_requests = [] # To store all fetched requests self.current_selected_request = None # To store the request currently displayed in details # 1. "Solicita document personalizat" button and popup self.request_text_field = ft.TextField( label="Descrie solicitarea ta", multiline=True, min_lines=5, max_lines=7, expand=True ) self.new_request_dialog = ft.AlertDialog( modal=True, title=ft.Text("Solicita document personalizat"), content=ft.Column( [ self.request_text_field, ft.Text("Vei fi notificat cu privire la statusul solicitării și prețul stabilit de expert.") ], tight=True, height=200 ), actions=[ ft.FilledButton("Solicita", on_click=self._submit_new_request), ft.FilledButton("Anuleaza", on_click=self._close_dialog, bgcolor=ft.Colors.GREY) ], actions_alignment=ft.MainAxisAlignment.END ) # 2. Search bar self.search_bar = ft.TextField( label="Cauta in solicitarile mele", on_change=self._on_search_change, # Use on_change for live filtering expand=True ) # 3. List of requests self.requests_list_view = ft.ListView( expand=True, spacing=10, padding=10 ) self.no_requests_message = ft.Text( "Nu aveti nici o solicitare activa. Pentru a crea o solicitare apasati butonul 'Solicita document personalizat'.", text_align=ft.TextAlign.CENTER, color=ft.Colors.GREY_600, size=16 ) # 4. Details view for a selected request self.request_details_text = ft.Text("", selectable=True) self.request_status_text = ft.Text("") self.request_price_text = ft.Text("") self.pay_button = ft.FilledButton( "Plateste", on_click=self._on_pay_button_click, disabled=True, # Will be enabled based on status visible=False # Initially hidden ) self.comment_text_field = ft.TextField( label="Adauga un comentariu", multiline=True, min_lines=2, max_lines=4, expand=True ) self.add_comment_button = ft.FilledButton( "Adauga Comentariu", on_click=self._add_comment_to_request, disabled=True # Disabled until a request is selected ) self.selected_request_details_column = ft.Column( [ ft.Text("Detalii Solicitare", size=20, weight=ft.FontWeight.BOLD), ft.Divider(), ft.Text("Text Solicitare:", weight=ft.FontWeight.BOLD), self.request_details_text, ft.Text("Status:", weight=ft.FontWeight.BOLD), self.request_status_text, ft.Text("Pret:", weight=ft.FontWeight.BOLD), self.request_price_text, self.pay_button, ft.Divider(), ft.Text("Adauga Comentariu:", weight=ft.FontWeight.BOLD), ft.Row([self.comment_text_field, self.add_comment_button]), ], expand=True, visible=False # Initially hidden ) # Initial data load self._load_requests() def _load_requests(self): """Fetches requests from the API and updates the UI.""" if not self.user_id: print("User ID not available. Cannot load requests.") return try: response = requests.get( f"{self.base_url}/documents/customs/requests/client", headers={'Authorization': f'Bearer {self.token}'} ) if response.status_code == 200: self.all_requests = response.json()[::-1] self._populate_requests_list(self.all_requests) else: print(f"Error fetching client requests: {response.status_code} - {response.text}") self.requests_list_view.controls = [self.no_requests_message] except requests.exceptions.RequestException as e: print(f"Network error fetching client requests: {e}") self.requests_list_view.controls = [self.no_requests_message] self.page.update() def _populate_requests_list(self, requests_to_display): """Populates the ListView with request items.""" if not requests_to_display: self.requests_list_view.controls = [self.no_requests_message] self.selected_request_details_column.visible = False self.add_comment_button.disabled = True self.comment_text_field.value = "" self.comment_text_field.disabled = True return items = [] for req in requests_to_display: items.append( ft.Container( content=ft.Column( [ ft.Text(f"Solicitare ID: {req['id']}", weight=ft.FontWeight.BOLD), ft.Text(f"Status: {DocumentsStatus.get_label(req['status'])}"), ft.Text(f"Data: {req['created_at'].split('T')[0] if req['created_at'] else 'N/A'}"), ] ), padding=10, border_radius=5, bgcolor=ft.Colors.BLUE_50 if req['status'] == DocumentsStatus.NEW else ft.Colors.GREY_100, ink=True, on_click=lambda e, request_data=req: self._display_request_details(request_data) ) ) self.requests_list_view.controls = items self.selected_request_details_column.visible = False # Hide details when list is repopulated self.add_comment_button.disabled = True self.comment_text_field.value = "" self.comment_text_field.disabled = True self.page.update() def _display_request_details(self, request_summary): """Preia datele proaspete de la server pentru solicitarea selectată.""" try: response = requests.get( f"{self.base_url}/documents/customs/requests/{request_summary['id']}", headers={'Authorization': f'Bearer {self.token}'} ) if response.status_code == 200: request_data = response.json() self.current_selected_request = request_data self.request_details_text.value = request_data.get('request_text', 'N/A') self.request_status_text.value = DocumentsStatus.get_label(request_data.get('status', 'N/A')) self.request_price_text.value = f"{request_data.get('price', 0.0):.2f} Lei" if request_data.get('price') else "N/A" # Handle Pay button visibility and state if request_data.get('status') == DocumentsStatus.WAITING_FOR_PAYMENT: self.pay_button.visible = True self.pay_button.disabled = False else: self.pay_button.visible = False self.pay_button.disabled = True # Enable comment section self.add_comment_button.disabled = False self.comment_text_field.disabled = False self.comment_text_field.value = "" # Clear previous comment input self.selected_request_details_column.visible = True self.page.update() except Exception as e: print(f"Error fetching request details: {e}") def _open_new_request_dialog(self, e): self.request_text_field.value = "" # Clear previous input self.page.show_dialog(self.new_request_dialog) self.page.update() def _submit_new_request(self, e): request_text = self.request_text_field.value.strip() if not request_text: # Optionally show an error message to the user print("Request text cannot be empty.") return try: response = requests.post( f"{self.base_url}/documents/customs/requests/add", json={"request_text": request_text}, headers={'Authorization': f'Bearer {self.token}'} ) if response.status_code == 201: print("Request submitted successfully!") req_id = response.json().get("id") # Notificăm BA/Management despre o solicitare nouă try: subject = f"Solicitare nouă document personalizat: #{req_id}" body = ( f"Clientul {self.user.get('email')} a creat o solicitare nouă.\n\n" f"Descriere solicitare:\n{request_text}\n\n" f"Vă rugăm să accesați panoul de administrare pentru preluare." ) #send_gmail(to_email="office@juridicbloc.ro", subject=subject, body=body) send_gmail(to_email="macamete.robert@gmail.com", subject=subject, body=body) except Exception as mail_err: print(f"Eroare notificare mail: {mail_err}") self._close_dialog(e) self._load_requests() # Reload the list to show the new request else: print(f"Error submitting request: {response.status_code} - {response.text}") except requests.exceptions.RequestException as err: print(f"Network error submitting request: {err}") self.page.update() def _add_comment_to_request(self, e): if not self.current_selected_request: print("No request selected to add a comment.") return comment = self.comment_text_field.value.strip() if not comment: print("Comment text cannot be empty.") return request_id = self.current_selected_request['id'] current_request_text = self.current_selected_request.get('request_text', '') # Append new comment with timestamp timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") new_request_text = f"{current_request_text}\n\n--- Comentariu client ({timestamp}):\n{comment}" try: response = requests.put( f"{self.base_url}/documents/customs/requests/update/{request_id}", json={"request_text": new_request_text}, # Only sending request_text for update headers={'Authorization': f'Bearer {self.token}'} ) if response.status_code == 200: print("Comment added successfully!") # Update the local request object and re-display details self.current_selected_request['request_text'] = new_request_text self._display_request_details(self.current_selected_request) # Notificăm Expertul (BA) dacă este alocat try: subject = f"Comentariu nou la solicitarea #{request_id}" body = ( f"Clientul {self.user.get('email')} a adăugat un comentariu la " f"solicitarea #{request_id}.\n\n" f"Mesaj:\n{comment}" ) #send_gmail(to_email="office@juridicbloc.ro", subject=subject, body=body) send_gmail(to_email='macamete.robert@gmail.com', subject=subject, body=body) except Exception as mail_err: print(f"Eroare notificare expert: {mail_err}") self.comment_text_field.value = "" # Clear comment field else: print(f"Error adding comment: {response.status_code} - {response.text}") except requests.exceptions.RequestException as err: print(f"Network error adding comment: {err}") self.page.update() def _on_search_change(self, e): query = self.search_bar.value.strip().lower() if query: filtered_requests = [ req for req in self.all_requests if query in req.get('request_text', '').lower() or query in req.get('status', '').lower() or query in str(req.get('id', '')).lower() ] else: filtered_requests = self.all_requests self._populate_requests_list(filtered_requests) def _on_pay_button_click(self, e): # Placeholder for payment logic print(f"Payment button clicked for request ID: {self.current_selected_request['id']}") self.page.show_dialog(ft.SnackBar( ft.Text("Funcționalitatea de plată va fi implementată ulterior."), )) self.page.update() def _close_dialog(self, e): self.page.pop_dialog() self.page.update() def build(self): return ft.Container( content=ft.Row( [ # Left Column: New Request Button and Requests List ft.Column( [ ft.FilledButton( "Solicita document personalizat", icon=ft.Icons.ADD_TASK, on_click=self._open_new_request_dialog, width=300 ), ft.Divider(), self.requests_list_view, ], width=350, expand=False, alignment=ft.MainAxisAlignment.START ), ft.VerticalDivider(width=1), # Right Column: Search Bar and Request Details ft.Column( [ ft.Row([self.search_bar]), ft.Divider(), self.selected_request_details_column, ], expand=True ) ], expand=True ), expand=True, padding=10 )