118 lines
4.2 KiB
Python
118 lines
4.2 KiB
Python
import flet as ft
|
||
import designer as ds
|
||
import api_client
|
||
|
||
|
||
class ResponsePage(ft.Column):
|
||
def __init__(self, page: ft.Page, response_id: str):
|
||
self._page = page
|
||
self._response_id = response_id
|
||
self._loading = ft.ProgressRing(width=40, height=40, color=ds.clolors.laer1)
|
||
|
||
super().__init__(
|
||
alignment=ft.MainAxisAlignment.START,
|
||
horizontal_alignment=ft.CrossAxisAlignment.STRETCH,
|
||
spacing=8,
|
||
controls=[
|
||
ft.Row(
|
||
alignment=ft.MainAxisAlignment.CENTER,
|
||
controls=[self._loading],
|
||
)
|
||
],
|
||
)
|
||
|
||
async def load(self):
|
||
response = await api_client.get_response(self._response_id)
|
||
if not response:
|
||
self.controls = [ds.CastomText(text="Результат не найден", size=14, color="#FF6B6B")]
|
||
self.update()
|
||
return
|
||
|
||
poll = await api_client.get_poll(response["poll_id"])
|
||
if not poll:
|
||
self.controls = [ds.CastomText(text="Тест не найден", size=14, color="#FF6B6B")]
|
||
self.update()
|
||
return
|
||
|
||
self._render(response, poll)
|
||
self.update()
|
||
|
||
def _render(self, response: dict, poll: dict):
|
||
# Строим индексы для быстрого поиска
|
||
questions_map = {q["id"]: q for q in poll.get("questions", [])}
|
||
choices_map = {
|
||
c["id"]: c["text"]
|
||
for q in poll.get("questions", [])
|
||
for c in q.get("choices", [])
|
||
}
|
||
|
||
submitted_at = response["submitted_at"][:19].replace("T", " ")
|
||
answer_cards = []
|
||
|
||
for answer in response.get("answers", []):
|
||
q = questions_map.get(answer["question_id"])
|
||
if not q:
|
||
continue
|
||
|
||
selected_text = choices_map.get(answer.get("choice_id") or "") or answer.get("text") or "—"
|
||
|
||
# Варианты с подсветкой выбранного
|
||
choice_rows = []
|
||
for c in q.get("choices", []):
|
||
is_selected = c["id"] == answer.get("choice_id")
|
||
choice_rows.append(
|
||
ft.Container(
|
||
border_radius=8,
|
||
padding=ft.padding.symmetric(horizontal=12, vertical=6),
|
||
bgcolor=ds.clolors.laer1 if is_selected else ds.clolors.laer3,
|
||
content=ft.Row(
|
||
spacing=8,
|
||
controls=[
|
||
ft.Icon(
|
||
ft.Icons.CHECK_CIRCLE if is_selected else ft.Icons.RADIO_BUTTON_UNCHECKED,
|
||
color=ds.clolors.ferst,
|
||
size=16,
|
||
),
|
||
ds.CastomText(text=c["text"], size=13),
|
||
],
|
||
),
|
||
)
|
||
)
|
||
|
||
answer_cards.append(
|
||
ft.Container(
|
||
border_radius=12,
|
||
padding=16,
|
||
bgcolor=ds.clolors.laer2,
|
||
content=ft.Column(
|
||
spacing=8,
|
||
controls=[
|
||
ds.CastomText(
|
||
text=q.get("text", ""),
|
||
size=14,
|
||
weight=ft.FontWeight.BOLD,
|
||
),
|
||
*choice_rows,
|
||
],
|
||
),
|
||
)
|
||
)
|
||
|
||
self.controls = [
|
||
ft.Container(
|
||
padding=ft.padding.only(bottom=8),
|
||
content=ft.Column(
|
||
spacing=4,
|
||
controls=[
|
||
ds.CastomText(
|
||
text=poll.get("title", ""),
|
||
size=20,
|
||
weight=ft.FontWeight.BOLD,
|
||
),
|
||
ds.CastomText(text=f"Пройден: {submitted_at}", size=12),
|
||
],
|
||
),
|
||
),
|
||
*answer_cards,
|
||
]
|