Files
JuridicBloc/client/pages/documents/custom.py

398 lines
17 KiB
Python

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.download_button = ft.FilledButton(
"Descarcă Document Final",
icon=ft.Icons.DOWNLOAD,
on_click=self._on_download_button_click,
disabled=True, # Will be enabled based on status and document_id
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,
self.download_button,
ft.Divider(),
ft.Text("Adauga Comentariu:", weight=ft.FontWeight.BOLD),
ft.Row([self.comment_text_field, self.add_comment_button]),
],
expand=True,
scroll=ft.ScrollMode.ADAPTIVE,
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
# Handle Download button visibility and state
if request_data.get('status') == DocumentsStatus.COMPLETED and request_data.get('document_id'):
self.download_button.visible = True
self.download_button.disabled = False
else:
self.download_button.visible = False
self.download_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()
async def _on_download_button_click(self, e):
"""Handles the download of the final document."""
if not self.current_selected_request or not self.current_selected_request.get('document_id'):
self.page.show_dialog(ft.SnackBar(ft.Text("Nu există un document final asociat acestei solicitări."), open=True))
self.page.update()
return
document_id = self.current_selected_request['document_id']
try:
# Fetch document details to get the path
response = requests.get(
f"{self.base_url}/documents/customs/{document_id}",
headers={'Authorization': f'Bearer {self.token}'}
)
if response.status_code == 200:
document_data = response.json()
document_path = document_data.get('path')
if document_path:
download_url = f"{self.base_url}/documents/download?path={document_path}&token={self.token}"
await self.page.launch_url(download_url)
else:
self.page.show_dialog(ft.SnackBar(ft.Text("Calea documentului nu a putut fi găsită."), open=True))
else:
self.page.show_dialog(ft.SnackBar(ft.Text(f"Eroare la preluarea detaliilor documentului: {response.status_code}"), open=True))
except requests.exceptions.RequestException as err:
self.page.show_dialog(ft.SnackBar(ft.Text(f"Eroare de rețea la descărcarea documentului: {err}"), open=True))
except Exception as ex:
self.page.show_dialog(ft.SnackBar(ft.Text(f"A apărut o eroare neașteptată: {ex}"), open=True))
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
)