new shems
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import base64
|
||||
import flet as ft
|
||||
import designer as ds
|
||||
import api_client
|
||||
from radar_chart import RadarChart
|
||||
|
||||
|
||||
class ResponsePage(ft.Column):
|
||||
@@ -14,10 +16,7 @@ class ResponsePage(ft.Column):
|
||||
horizontal_alignment=ft.CrossAxisAlignment.STRETCH,
|
||||
spacing=8,
|
||||
controls=[
|
||||
ft.Row(
|
||||
alignment=ft.MainAxisAlignment.CENTER,
|
||||
controls=[self._loading],
|
||||
)
|
||||
ft.Row(alignment=ft.MainAxisAlignment.CENTER, controls=[self._loading])
|
||||
],
|
||||
)
|
||||
|
||||
@@ -34,84 +33,106 @@ class ResponsePage(ft.Column):
|
||||
self.update()
|
||||
return
|
||||
|
||||
self._render(response, poll)
|
||||
radar = await api_client.get_radar_result(self._response_id)
|
||||
self._render(response, poll, radar)
|
||||
self.update()
|
||||
|
||||
def _render(self, response: dict, poll: dict):
|
||||
# Строим индексы для быстрого поиска
|
||||
def _render(self, response: dict, poll: dict, radar: dict | None):
|
||||
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 = []
|
||||
|
||||
controls: list[ft.Control] = [
|
||||
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),
|
||||
]),
|
||||
)
|
||||
]
|
||||
|
||||
# ── Паутинная диаграмма ──────────────────────────────────────────────
|
||||
if radar and radar.get("items"):
|
||||
items = sorted(
|
||||
radar["items"],
|
||||
key=lambda x: (x.get("dimension_position") is None, x.get("dimension_position", 0)),
|
||||
)
|
||||
actual_max = max((it["value"] for it in items), default=1.0)
|
||||
max_val = max(actual_max, 14.0)
|
||||
|
||||
async def _download(_evt, _rid=self._response_id):
|
||||
svg_bytes = await api_client.get_radar_svg_bytes(_rid)
|
||||
if svg_bytes:
|
||||
b64 = base64.b64encode(svg_bytes).decode()
|
||||
uri = f"data:image/svg+xml;base64,{b64}"
|
||||
self._page.launch_url(uri, web_window_name="_blank")
|
||||
|
||||
controls.append(ft.Container(
|
||||
border_radius=16,
|
||||
padding=12,
|
||||
bgcolor=ds.clolors.laer3,
|
||||
content=ft.Column(
|
||||
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
|
||||
spacing=10,
|
||||
controls=[
|
||||
ds.CastomText(text="Результат", size=16, weight=ft.FontWeight.BOLD),
|
||||
ft.Row(
|
||||
alignment=ft.MainAxisAlignment.CENTER,
|
||||
controls=[RadarChart(items, max_val)],
|
||||
),
|
||||
ft.Row(
|
||||
alignment=ft.MainAxisAlignment.CENTER,
|
||||
controls=[
|
||||
ft.ElevatedButton(
|
||||
text="Сохранить диаграмму",
|
||||
icon=ft.Icons.DOWNLOAD,
|
||||
on_click=_download,
|
||||
style=ft.ButtonStyle(
|
||||
color=ds.clolors.ferst,
|
||||
bgcolor=ds.clolors.laer2,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
))
|
||||
|
||||
# ── Ответы ───────────────────────────────────────────────────────────
|
||||
answer_cards: list[ft.Control] = []
|
||||
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),
|
||||
],
|
||||
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,
|
||||
],
|
||||
),
|
||||
)
|
||||
)
|
||||
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,
|
||||
]
|
||||
if answer_cards:
|
||||
controls.append(ds.CastomText(text="Ответы", size=16, weight=ft.FontWeight.BOLD))
|
||||
controls.extend(answer_cards)
|
||||
|
||||
self.controls = controls
|
||||
|
||||
Reference in New Issue
Block a user