Update app.py
Browse files
app.py
CHANGED
|
@@ -864,6 +864,133 @@ EXAMPLES = [
|
|
| 864 |
["u_bob", "Gas Stations", "Shell", 45.00, False, "", ""],
|
| 865 |
]
|
| 866 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 867 |
def _toggle_custom_mcc(use_custom: bool):
|
| 868 |
return gr.update(visible=use_custom, value="")
|
| 869 |
|
|
@@ -1229,132 +1356,7 @@ Get AI-powered credit card recommendations that maximize your rewards based on:
|
|
| 1229 |
]
|
| 1230 |
)
|
| 1231 |
|
| 1232 |
-
def update_analytics_with_charts(user_id: str):
|
| 1233 |
-
"""Fetch and format analytics with charts for selected user"""
|
| 1234 |
-
|
| 1235 |
-
try:
|
| 1236 |
-
result = client.get_user_analytics(user_id)
|
| 1237 |
-
|
| 1238 |
-
print("=" * 60)
|
| 1239 |
-
print(f"DEBUG: Analytics for {user_id}")
|
| 1240 |
-
print(f"Success: {result.get('success')}")
|
| 1241 |
-
if result.get('data'):
|
| 1242 |
-
print(f"Data keys: {result['data'].keys()}")
|
| 1243 |
-
print(f"Total spending: {result['data'].get('total_spending')}")
|
| 1244 |
-
print(f"Total rewards: {result['data'].get('total_rewards')}")
|
| 1245 |
-
print("=" * 60)
|
| 1246 |
-
|
| 1247 |
-
if not result.get('success'):
|
| 1248 |
-
error_msg = result.get('error', 'Unknown error')
|
| 1249 |
-
empty_fig = create_empty_chart(f"Error: {error_msg}")
|
| 1250 |
-
return (
|
| 1251 |
-
f"<p>❌ Error: {error_msg}</p>",
|
| 1252 |
-
empty_fig, empty_fig, empty_fig, empty_fig, empty_fig,
|
| 1253 |
-
"Error loading data",
|
| 1254 |
-
"Error loading data",
|
| 1255 |
-
"Error loading data",
|
| 1256 |
-
f"*Error: {error_msg}*"
|
| 1257 |
-
)
|
| 1258 |
-
|
| 1259 |
-
analytics_data = result.get('data', {})
|
| 1260 |
-
|
| 1261 |
-
if not analytics_data:
|
| 1262 |
-
empty_fig = create_empty_chart("No analytics data available")
|
| 1263 |
-
return (
|
| 1264 |
-
"<p>No data available</p>",
|
| 1265 |
-
empty_fig, empty_fig, empty_fig, empty_fig, empty_fig,
|
| 1266 |
-
"No data",
|
| 1267 |
-
"No data",
|
| 1268 |
-
"No data",
|
| 1269 |
-
"*No data available*"
|
| 1270 |
-
)
|
| 1271 |
-
|
| 1272 |
-
metrics_html, table_md, insights_md, forecast_md = format_analytics_metrics(analytics_data)
|
| 1273 |
-
|
| 1274 |
-
spending_fig = create_spending_chart(analytics_data)
|
| 1275 |
-
pie_fig = create_rewards_pie_chart(analytics_data)
|
| 1276 |
-
gauge_fig = create_optimization_gauge(analytics_data)
|
| 1277 |
-
trend_fig = create_trend_line_chart(analytics_data)
|
| 1278 |
-
performance_fig = create_card_performance_chart(analytics_data)
|
| 1279 |
-
|
| 1280 |
-
from datetime import datetime
|
| 1281 |
-
status = f"*Analytics updated for {user_id} at {datetime.now().strftime('%I:%M %p')}*"
|
| 1282 |
-
|
| 1283 |
-
return (
|
| 1284 |
-
metrics_html,
|
| 1285 |
-
spending_fig,
|
| 1286 |
-
gauge_fig,
|
| 1287 |
-
pie_fig,
|
| 1288 |
-
performance_fig,
|
| 1289 |
-
trend_fig,
|
| 1290 |
-
table_md,
|
| 1291 |
-
insights_md,
|
| 1292 |
-
forecast_md,
|
| 1293 |
-
status
|
| 1294 |
-
)
|
| 1295 |
-
|
| 1296 |
-
except Exception as e:
|
| 1297 |
-
error_details = traceback.format_exc()
|
| 1298 |
-
error_msg = f"❌ Error loading analytics: {str(e)}"
|
| 1299 |
-
print(error_msg)
|
| 1300 |
-
print(error_details)
|
| 1301 |
-
|
| 1302 |
-
empty_fig = create_empty_chart("Error loading chart")
|
| 1303 |
-
|
| 1304 |
-
return (
|
| 1305 |
-
f"<p>{error_msg}</p>",
|
| 1306 |
-
empty_fig, empty_fig, empty_fig, empty_fig, empty_fig,
|
| 1307 |
-
"Error loading table",
|
| 1308 |
-
"Error loading insights",
|
| 1309 |
-
"Error loading forecast",
|
| 1310 |
-
f"*{error_msg}*"
|
| 1311 |
-
)
|
| 1312 |
-
|
| 1313 |
-
def create_empty_chart(message: str) -> go.Figure:
|
| 1314 |
-
"""Helper to create empty chart with message"""
|
| 1315 |
-
fig = go.Figure()
|
| 1316 |
-
fig.add_annotation(
|
| 1317 |
-
text=message,
|
| 1318 |
-
xref="paper", yref="paper",
|
| 1319 |
-
x=0.5, y=0.5, showarrow=False,
|
| 1320 |
-
font=dict(size=14, color="#666")
|
| 1321 |
-
)
|
| 1322 |
-
fig.update_layout(height=400, template='plotly_white')
|
| 1323 |
-
return fig
|
| 1324 |
-
|
| 1325 |
-
refresh_analytics_btn.click(
|
| 1326 |
-
fn=update_analytics_with_charts,
|
| 1327 |
-
inputs=[analytics_user],
|
| 1328 |
-
outputs=[
|
| 1329 |
-
metrics_display,
|
| 1330 |
-
spending_chart,
|
| 1331 |
-
optimization_gauge,
|
| 1332 |
-
rewards_pie_chart,
|
| 1333 |
-
card_performance_chart,
|
| 1334 |
-
trend_chart,
|
| 1335 |
-
spending_table,
|
| 1336 |
-
insights_display,
|
| 1337 |
-
forecast_display,
|
| 1338 |
-
analytics_status
|
| 1339 |
-
]
|
| 1340 |
-
)
|
| 1341 |
|
| 1342 |
-
analytics_user.change(
|
| 1343 |
-
fn=update_analytics_with_charts,
|
| 1344 |
-
inputs=[analytics_user],
|
| 1345 |
-
outputs=[
|
| 1346 |
-
metrics_display,
|
| 1347 |
-
spending_chart,
|
| 1348 |
-
optimization_gauge,
|
| 1349 |
-
rewards_pie_chart,
|
| 1350 |
-
card_performance_chart,
|
| 1351 |
-
trend_chart,
|
| 1352 |
-
spending_table,
|
| 1353 |
-
insights_display,
|
| 1354 |
-
forecast_display,
|
| 1355 |
-
analytics_status
|
| 1356 |
-
]
|
| 1357 |
-
)
|
| 1358 |
|
| 1359 |
with gr.Tab("💬 Ask AI"):
|
| 1360 |
gr.Markdown("## Chat with RewardPilot AI")
|
|
|
|
| 864 |
["u_bob", "Gas Stations", "Shell", 45.00, False, "", ""],
|
| 865 |
]
|
| 866 |
|
| 867 |
+
def update_analytics_with_charts(user_id: str):
|
| 868 |
+
"""Fetch and format analytics with charts for selected user"""
|
| 869 |
+
|
| 870 |
+
try:
|
| 871 |
+
result = client.get_user_analytics(user_id)
|
| 872 |
+
|
| 873 |
+
print("=" * 60)
|
| 874 |
+
print(f"DEBUG: Analytics for {user_id}")
|
| 875 |
+
print(f"Success: {result.get('success')}")
|
| 876 |
+
if result.get('data'):
|
| 877 |
+
print(f"Data keys: {result['data'].keys()}")
|
| 878 |
+
print(f"Total spending: {result['data'].get('total_spending')}")
|
| 879 |
+
print(f"Total rewards: {result['data'].get('total_rewards')}")
|
| 880 |
+
print("=" * 60)
|
| 881 |
+
|
| 882 |
+
if not result.get('success'):
|
| 883 |
+
error_msg = result.get('error', 'Unknown error')
|
| 884 |
+
empty_fig = create_empty_chart(f"Error: {error_msg}")
|
| 885 |
+
return (
|
| 886 |
+
f"<p>❌ Error: {error_msg}</p>",
|
| 887 |
+
empty_fig, empty_fig, empty_fig, empty_fig, empty_fig,
|
| 888 |
+
"Error loading data",
|
| 889 |
+
"Error loading data",
|
| 890 |
+
"Error loading data",
|
| 891 |
+
f"*Error: {error_msg}*"
|
| 892 |
+
)
|
| 893 |
+
|
| 894 |
+
analytics_data = result.get('data', {})
|
| 895 |
+
|
| 896 |
+
if not analytics_data:
|
| 897 |
+
empty_fig = create_empty_chart("No analytics data available")
|
| 898 |
+
return (
|
| 899 |
+
"<p>No data available</p>",
|
| 900 |
+
empty_fig, empty_fig, empty_fig, empty_fig, empty_fig,
|
| 901 |
+
"No data",
|
| 902 |
+
"No data",
|
| 903 |
+
"No data",
|
| 904 |
+
"*No data available*"
|
| 905 |
+
)
|
| 906 |
+
|
| 907 |
+
metrics_html, table_md, insights_md, forecast_md = format_analytics_metrics(analytics_data)
|
| 908 |
+
|
| 909 |
+
spending_fig = create_spending_chart(analytics_data)
|
| 910 |
+
pie_fig = create_rewards_pie_chart(analytics_data)
|
| 911 |
+
gauge_fig = create_optimization_gauge(analytics_data)
|
| 912 |
+
trend_fig = create_trend_line_chart(analytics_data)
|
| 913 |
+
performance_fig = create_card_performance_chart(analytics_data)
|
| 914 |
+
|
| 915 |
+
from datetime import datetime
|
| 916 |
+
status = f"*Analytics updated for {user_id} at {datetime.now().strftime('%I:%M %p')}*"
|
| 917 |
+
|
| 918 |
+
return (
|
| 919 |
+
metrics_html,
|
| 920 |
+
spending_fig,
|
| 921 |
+
gauge_fig,
|
| 922 |
+
pie_fig,
|
| 923 |
+
performance_fig,
|
| 924 |
+
trend_fig,
|
| 925 |
+
table_md,
|
| 926 |
+
insights_md,
|
| 927 |
+
forecast_md,
|
| 928 |
+
status
|
| 929 |
+
)
|
| 930 |
+
|
| 931 |
+
except Exception as e:
|
| 932 |
+
error_details = traceback.format_exc()
|
| 933 |
+
error_msg = f"❌ Error loading analytics: {str(e)}"
|
| 934 |
+
print(error_msg)
|
| 935 |
+
print(error_details)
|
| 936 |
+
|
| 937 |
+
empty_fig = create_empty_chart("Error loading chart")
|
| 938 |
+
|
| 939 |
+
return (
|
| 940 |
+
f"<p>{error_msg}</p>",
|
| 941 |
+
empty_fig, empty_fig, empty_fig, empty_fig, empty_fig,
|
| 942 |
+
"Error loading table",
|
| 943 |
+
"Error loading insights",
|
| 944 |
+
"Error loading forecast",
|
| 945 |
+
f"*{error_msg}*"
|
| 946 |
+
)
|
| 947 |
+
|
| 948 |
+
def create_empty_chart(message: str) -> go.Figure:
|
| 949 |
+
"""Helper to create empty chart with message"""
|
| 950 |
+
fig = go.Figure()
|
| 951 |
+
fig.add_annotation(
|
| 952 |
+
text=message,
|
| 953 |
+
xref="paper", yref="paper",
|
| 954 |
+
x=0.5, y=0.5, showarrow=False,
|
| 955 |
+
font=dict(size=14, color="#666")
|
| 956 |
+
)
|
| 957 |
+
fig.update_layout(height=400, template='plotly_white')
|
| 958 |
+
return fig
|
| 959 |
+
|
| 960 |
+
refresh_analytics_btn.click(
|
| 961 |
+
fn=update_analytics_with_charts,
|
| 962 |
+
inputs=[analytics_user],
|
| 963 |
+
outputs=[
|
| 964 |
+
metrics_display,
|
| 965 |
+
spending_chart,
|
| 966 |
+
optimization_gauge,
|
| 967 |
+
rewards_pie_chart,
|
| 968 |
+
card_performance_chart,
|
| 969 |
+
trend_chart,
|
| 970 |
+
spending_table,
|
| 971 |
+
insights_display,
|
| 972 |
+
forecast_display,
|
| 973 |
+
analytics_status
|
| 974 |
+
]
|
| 975 |
+
)
|
| 976 |
+
|
| 977 |
+
analytics_user.change(
|
| 978 |
+
fn=update_analytics_with_charts,
|
| 979 |
+
inputs=[analytics_user],
|
| 980 |
+
outputs=[
|
| 981 |
+
metrics_display,
|
| 982 |
+
spending_chart,
|
| 983 |
+
optimization_gauge,
|
| 984 |
+
rewards_pie_chart,
|
| 985 |
+
card_performance_chart,
|
| 986 |
+
trend_chart,
|
| 987 |
+
spending_table,
|
| 988 |
+
insights_display,
|
| 989 |
+
forecast_display,
|
| 990 |
+
analytics_status
|
| 991 |
+
]
|
| 992 |
+
)
|
| 993 |
+
|
| 994 |
def _toggle_custom_mcc(use_custom: bool):
|
| 995 |
return gr.update(visible=use_custom, value="")
|
| 996 |
|
|
|
|
| 1356 |
]
|
| 1357 |
)
|
| 1358 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1359 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1360 |
|
| 1361 |
with gr.Tab("💬 Ask AI"):
|
| 1362 |
gr.Markdown("## Chat with RewardPilot AI")
|