import dash
from dash import html, dcc
import plotly.express as px
import pandas as pd
import requests
from dash.dependencies import Output, Input
# إنشاء التطبيق
app = dash.Dash(__name__)
app.title = "Fas7ni Dashboard"
# جلب البيانات
def fetch_users():
try:
url = "https://fas7nii.runasp.net/api/Analysis/GetDashboardAnalysis"
res = requests.get(url)
res.raise_for_status()
data = res.json()
return pd.DataFrame(data)
except Exception as e:
print("Error fetching users:", e)
return pd.DataFrame(columns=["gender", "age", "languages"])
def fetch_feedback():
try:
url = "https://fas7nii.runasp.net/api/Analysis/GetFeedbackAnalysis"
res = requests.get(url)
res.raise_for_status()
data = res.json()
return pd.DataFrame(data)
except Exception as e:
print("Error fetching feedback:", e)
return pd.DataFrame(columns=["value"])
# تخطيط الواجهة
app.layout = html.Div(style={
"backgroundColor": "#f4f7f9",
"padding": "20px",
"fontFamily": "Arial, sans-serif"
}, children=[
html.H1("🌐 Fas7ni Dashboard", style={"textAlign": "center", "color": "#2c3e50"}),
html.Div([
dcc.Graph(id='sentiment-pie', style={"width": "42%", "height": "300px", "margin": "10px", "minWidth": "300px"}),
dcc.Graph(id='gender-bar', style={"width": "42%", "height": "300px", "margin": "10px", "minWidth": "300px"}),
dcc.Graph(id='age-bar', style={"width": "42%", "height": "300px", "margin": "10px", "minWidth": "300px"}),
dcc.Graph(id='language-bar', style={"width": "42%", "height": "300px", "margin": "10px", "minWidth": "300px"}),
], style={
"display": "flex",
"flexWrap": "wrap",
"justifyContent": "space-around",
"alignItems": "center"
}),
dcc.Interval(id='interval-update', interval=10*1000, n_intervals=0)
])
# التحديث التلقائي
@app.callback(
Output('sentiment-pie', 'figure'),
Output('gender-bar', 'figure'),
Output('age-bar', 'figure'),
Output('language-bar', 'figure'),
Input('interval-update', 'n_intervals')
)
def update_charts(n):
df_users = fetch_users()
df_feedback = fetch_feedback()
colors = ['#3498db', '#9b59b6', '#2ecc71', '#f39c12', '#e74c3c']
# Pie chart - Sentiment
if not df_feedback.empty:
sentiment_counts = df_feedback["value"].value_counts().reset_index()
sentiment_counts.columns = ["Sentiment", "Count"]
fig_sentiment = px.pie(sentiment_counts, names="Sentiment", values="Count", title="Sentiment Distribution",
hole=0.4, color_discrete_sequence=colors)
fig_sentiment.update_traces(textinfo='percent+label')
else:
fig_sentiment = px.pie(title="No Feedback Data")
# Bar chart - Gender
if not df_users.empty and "gender" in df_users.columns:
df_users["gender"] = df_users["gender"].fillna("Unknown")
gender_counts = df_users["gender"].value_counts().reset_index()
gender_counts.columns = ["Gender", "Count"]
fig_gender = px.bar(gender_counts, x="Gender", y="Count", title="Gender Distribution",
color="Gender", color_discrete_sequence=colors)
else:
fig_gender = px.bar(title="No Gender Data")
# Line chart - Age Distribution
if not df_users.empty and "age" in df_users.columns:
df_users["age"] = pd.to_numeric(df_users["age"], errors='coerce')
age_counts = df_users["age"].value_counts().sort_index().reset_index()
age_counts.columns = ["Age", "Count"]
fig_age = px.line(age_counts, x="Age", y="Count", title="Age Distribution", markers=True,
color_discrete_sequence=colors)
else:
fig_age = px.line(title="No Age Data")
# Bar chart - Languages
if not df_users.empty and "languages" in df_users.columns:
df_users["languages"] = df_users["languages"].apply(lambda x: x if isinstance(x, list) else ([] if pd.isna(x) else [x]))
all_languages = df_users["languages"].explode()
lang_counts = all_languages.value_counts().reset_index()
lang_counts.columns = ["Language", "Count"]
fig_lang = px.bar(lang_counts, x="Language", y="Count", title="Languages Used",
color="Language", color_discrete_sequence=colors)
else:
fig_lang = px.bar(title="No Language Data")
return fig_sentiment, fig_gender, fig_age, fig_lang
# تشغيل التطبيق
if __name__ == '__main__':
app.run(host='0.0.0.0', port=7860, debug=True)