Skip to content

Commit 9cf3901

Browse files
committed
ok
1 parent 7d50040 commit 9cf3901

File tree

9 files changed

+134671
-131663
lines changed

9 files changed

+134671
-131663
lines changed

app.tar.gz

-18.5 KB
Binary file not shown.

flet-gmftech/app.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ def main(page: ft.Page):
2626
}
2727
page.theme = get_theme()
2828

29+
# Pré-carregar dados de cotação
30+
from pages.coins import preload_data
31+
page.run_task(preload_data)
32+
2933
# Função para fechar o diálogo
3034
def close_dialog(e):
3135
if page.overlay:

flet-gmftech/pages/coins.py

Lines changed: 183 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -21,40 +21,76 @@
2121
import httpx
2222

2323
from datetime import datetime
24+
import asyncio
2425

26+
# Cache global para os dados
27+
_cached_data = None
28+
_last_update = None
29+
_is_fetching = False
2530

2631
# Função assíncrona para buscar os dados da API
27-
async def fetch_usd_brl_data():
28-
url = "https://economia.awesomeapi.com.br/json/daily/USD-BRL/15"
29-
if IS_PYODIDE:
30-
# Usar pyfetch no ambiente web
31-
try:
32-
response = await pyfetch(url, method="GET")
33-
if response.status == 200:
34-
return await response.json()
35-
else:
36-
print(f"Erro: status code {response.status}")
37-
return []
38-
except Exception as e:
39-
print(f"Erro ao buscar dados: {e}")
40-
return []
41-
else:
42-
# Usar httpx no ambiente desktop/servidor
43-
async with httpx.AsyncClient() as client:
32+
async def fetch_usd_brl_data(force_refresh=False):
33+
global _cached_data, _last_update, _is_fetching
34+
35+
# Se já estiver buscando dados, aguarda
36+
while _is_fetching:
37+
await asyncio.sleep(0.1)
38+
39+
# Verifica se tem cache válido (menos de 5 minutos)
40+
now = datetime.now()
41+
if not force_refresh and _cached_data and _last_update:
42+
delta = now - _last_update
43+
if delta.total_seconds() < 300: # 5 minutos
44+
return _cached_data
45+
46+
_is_fetching = True
47+
try:
48+
url = "https://economia.awesomeapi.com.br/json/daily/USD-BRL/15"
49+
max_retries = 3
50+
retry_count = 0
51+
52+
while retry_count < max_retries:
4453
try:
45-
response = await client.get(url)
46-
if response.status_code == 200:
47-
return response.json()
54+
if IS_PYODIDE:
55+
response = await pyfetch(url, method="GET")
56+
if response.status == 200:
57+
data = await response.json()
58+
_cached_data = data
59+
_last_update = now
60+
return data
4861
else:
49-
print(f"Erro: status code {response.status_code}")
50-
return []
62+
async with httpx.AsyncClient() as client:
63+
response = await client.get(url)
64+
if response.status_code == 200:
65+
data = response.json()
66+
_cached_data = data
67+
_last_update = now
68+
return data
69+
70+
retry_count += 1
71+
if retry_count < max_retries:
72+
await asyncio.sleep(1)
5173
except Exception as e:
52-
print(f"Erro ao buscar dados: {e}")
53-
return []
74+
print(f"Tentativa {retry_count + 1} falhou: {str(e)}")
75+
retry_count += 1
76+
if retry_count < max_retries:
77+
await asyncio.sleep(1)
78+
79+
# Se chegou aqui, todas as tentativas falharam
80+
# Retorna cache antigo se disponível, mesmo que expirado
81+
return _cached_data if _cached_data else []
82+
finally:
83+
_is_fetching = False
5484

85+
# Iniciar o pré-carregamento dos dados
86+
async def preload_data():
87+
await fetch_usd_brl_data()
5588

5689
# Função para criar o gráfico com Pyecharts
5790
def create_chart(data):
91+
if not data:
92+
return None
93+
5894
dates = [
5995
datetime.fromtimestamp(int(entry["timestamp"])).strftime("%d/%m")
6096
for entry in data[::-1]
@@ -65,7 +101,13 @@ def create_chart(data):
65101

66102
bar = (
67103
Bar(
68-
init_opts=opts.InitOpts(width="100%", height="400px", theme=ThemeType.LIGHT)
104+
init_opts=opts.InitOpts(
105+
width="100%",
106+
height="400px",
107+
theme=ThemeType.LIGHT,
108+
animation_opts=opts.AnimationOpts(animation=False), # Desativa animações
109+
js_host="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/", # Usa CDN em vez de embutir
110+
)
69111
)
70112
.add_xaxis(dates)
71113
.add_yaxis(
@@ -117,54 +159,115 @@ def create_chart(data):
117159
html = bar.render_embed()
118160
return base64.b64encode(html.encode("utf-8")).decode("utf-8")
119161

120-
121162
# Função assíncrona para carregar o gráfico
122163
async def load_chart(page, chart_container):
123-
# Exibir mensagem de carregamento
124-
progress_ring = ft.ProgressRing(
125-
width=32, height=32, stroke_width=4, color=COLORS["primary"]
126-
)
127-
chart_container.content = ft.Column(
128-
[
129-
ft.Text("Carregando dados...", color=COLORS["text_secondary"], font_family="Roboto"),
130-
progress_ring,
131-
],
132-
alignment="center",
133-
horizontal_alignment="center",
134-
)
135-
page.update()
136-
137-
# Buscar os dados
138-
data = await fetch_usd_brl_data()
139-
if not data:
140-
chart_container.content = ft.Text(
141-
"Erro ao carregar dados", color=COLORS["error"], font_family="Roboto"
164+
try:
165+
# Exibir mensagem de carregamento
166+
progress_ring = ft.ProgressRing(
167+
width=32, height=32, stroke_width=4, color=COLORS["primary"]
168+
)
169+
chart_container.content = ft.Column(
170+
[
171+
ft.Text("Carregando dados...", color=COLORS["text_secondary"], font_family="Roboto"),
172+
progress_ring,
173+
],
174+
alignment="center",
175+
horizontal_alignment="center",
142176
)
143177
page.update()
144-
return
145178

146-
# Atualizar para renderização
147-
chart_container.content = ft.Column(
148-
[
149-
ft.Text("Renderizando gráfico...", color=COLORS["text_secondary"], font_family="Roboto"),
150-
progress_ring,
151-
],
152-
alignment="center",
153-
horizontal_alignment="center",
154-
)
155-
page.update()
179+
# Buscar os dados (usa cache se disponível)
180+
data = await fetch_usd_brl_data()
181+
if not data:
182+
chart_container.content = ft.Column(
183+
[
184+
ft.Text(
185+
"Erro ao carregar dados",
186+
color=COLORS["error"],
187+
size=16,
188+
font_family="Roboto",
189+
text_align="center",
190+
),
191+
ft.ElevatedButton(
192+
"Tentar Novamente",
193+
on_click=lambda _: page.run_task(lambda: load_chart(page, chart_container)),
194+
bgcolor=COLORS["primary"],
195+
color=ft.Colors.WHITE,
196+
),
197+
],
198+
alignment="center",
199+
horizontal_alignment="center",
200+
spacing=20,
201+
)
202+
page.update()
203+
return
156204

157-
# Criar e exibir o gráfico
158-
encoded_html = create_chart(data)
159-
data_url = f"data:text/html;base64,{encoded_html}"
160-
chart_webview = ft.WebView(
161-
url=data_url,
162-
expand=True,
163-
bgcolor=COLORS["surface"],
164-
)
165-
chart_container.content = chart_webview
166-
page.update()
205+
# Atualizar para renderização
206+
chart_container.content = ft.Column(
207+
[
208+
ft.Text("Renderizando gráfico...", color=COLORS["text_secondary"], font_family="Roboto"),
209+
progress_ring,
210+
],
211+
alignment="center",
212+
horizontal_alignment="center",
213+
)
214+
page.update()
167215

216+
# Criar e exibir o gráfico
217+
encoded_html = create_chart(data)
218+
if encoded_html:
219+
data_url = f"data:text/html;base64,{encoded_html}"
220+
chart_webview = ft.WebView(
221+
url=data_url,
222+
expand=True,
223+
bgcolor=COLORS["surface"],
224+
)
225+
chart_container.content = chart_webview
226+
else:
227+
chart_container.content = ft.Column(
228+
[
229+
ft.Text(
230+
"Erro ao renderizar gráfico",
231+
color=COLORS["error"],
232+
size=16,
233+
font_family="Roboto",
234+
text_align="center",
235+
),
236+
ft.ElevatedButton(
237+
"Tentar Novamente",
238+
on_click=lambda _: page.run_task(lambda: load_chart(page, chart_container)),
239+
bgcolor=COLORS["primary"],
240+
color=ft.Colors.WHITE,
241+
),
242+
],
243+
alignment="center",
244+
horizontal_alignment="center",
245+
spacing=20,
246+
)
247+
page.update()
248+
249+
except Exception as e:
250+
chart_container.content = ft.Column(
251+
[
252+
ft.Text(
253+
f"Erro inesperado: {str(e)}",
254+
color=COLORS["error"],
255+
size=16,
256+
font_family="Roboto",
257+
text_align="center",
258+
),
259+
ft.ElevatedButton(
260+
"Tentar Novamente",
261+
on_click=lambda _: page.run_task(lambda: load_chart(page, chart_container)),
262+
bgcolor=COLORS["primary"],
263+
color=ft.Colors.WHITE,
264+
),
265+
],
266+
alignment="center",
267+
horizontal_alignment="center",
268+
spacing=20,
269+
)
270+
page.update()
168271

169272
# Função principal do conteúdo da página
170273
def currency_chart_content(page: ft.Page):
@@ -177,11 +280,24 @@ def currency_chart_content(page: ft.Page):
177280
height=400,
178281
)
179282

283+
# Inicializar com mensagem de carregamento
284+
progress_ring = ft.ProgressRing(
285+
width=32, height=32, stroke_width=4, color=COLORS["primary"]
286+
)
287+
chart_container.content = ft.Column(
288+
[
289+
ft.Text("Carregando dados...", color=COLORS["text_secondary"], font_family="Roboto"),
290+
progress_ring,
291+
],
292+
alignment="center",
293+
horizontal_alignment="center",
294+
)
295+
180296
async def init_chart():
181297
await load_chart(page, chart_container)
182298

183299
# Carregar o gráfico de forma assíncrona
184-
page.add_async_callback(init_chart)
300+
page.run_task(init_chart)
185301

186302
return ft.Container(
187303
content=ft.Column(

flet-gmftech/pages/services.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,11 @@ def create_card(icon, title, description):
141141
"title": "Azure DevOps",
142142
"description": "CI/CD e gestão ágil de projetos.",
143143
},
144+
{
145+
"icon": ft.icons.INSERT_CHART,
146+
"title": "Apache ECharts",
147+
"description": "Biblioteca de visualização de dados interativa e responsiva.",
148+
},
144149
]
145150

146151
return ft.Container(

flet-gmftech/requirements.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
flet>=0.21.1
2+
httpx>=0.26.0
3+
pyecharts>=2.0.0

flutter_bootstrap.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

flutter_service_worker.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ const MANIFEST = 'flutter-app-manifest';
33
const TEMP = 'flutter-temp-cache';
44
const CACHE_NAME = 'flutter-app-cache';
55

6-
const RESOURCES = {"main.dart.js": "b640cbc9306860611dda7f3e7b583fd8",
6+
const RESOURCES = {"main.dart.js": "8c9ce5b4d99440bd880a64906a489879",
77
"manifest.json": "58765f937ba0d0c40a3a714c5c1adb87",
8-
"python-worker.js": "62a4865b3d41771b39660076485879be",
8+
"python-worker.js": "5ea86672b34644777103a090bfdd6710",
99
"canvaskit/skwasm.wasm": "828c26a0b1cc8eb1adacbdd0c5e8bcfa",
1010
"canvaskit/chromium/canvaskit.js.symbols": "e115ddcfad5f5b98a90e389433606502",
1111
"canvaskit/chromium/canvaskit.js": "b7ba6d908089f706772b2007c37e6da4",
@@ -16,7 +16,7 @@ const RESOURCES = {"main.dart.js": "b640cbc9306860611dda7f3e7b583fd8",
1616
"canvaskit/skwasm.js.symbols": "96263e00e3c9bd9cd878ead867c04f3c",
1717
"canvaskit/canvaskit.js": "26eef3024dbc64886b7f48e1b6fb05cf",
1818
"canvaskit/canvaskit.wasm": "e7602c687313cfac5f495c5eac2fb324",
19-
"flutter_bootstrap.js": "b8cb831a2cf88145a9600a96999f8190",
19+
"flutter_bootstrap.js": "0f62fb41c7db6dcd04ddabafef67ab1a",
2020
"favicon.png": "302ac04c14db027d016d1fe74c6a80a0",
2121
"flutter.js": "4b2350e14c6650ba82871f60906437ea",
2222
"index.html": "9b60787b64ca572171a5b4effdbca418",

0 commit comments

Comments
 (0)