# -*- coding: utf-8 -*-
"""
Created on Thu Feb 20 15:00:14 2025
@author: win11
"""
import dash
from dash import dcc, html, callback,clientside_callback, Input, Output, Patch
import pandas as pd
import dash_bootstrap_components as dbc
import plotly.graph_objects as go
#LAYOUT STUFF
#from dash_bootstrap_templates import load_figure_template
#import plotly.io as pio
#load_figure_template(["vizro", "vizro_dark"])
vizro_bootstrap = "https://cdn.jsdelivr.net/gh/mckinsey/vizro@main/vizro-core/src/vizro/static/css/vizro-bootstrap.min.css?v=2"
select_status = html.Div(
[
dbc.Label("Select view"),
dbc.RadioItems(
options=[
{"label": "Completed", "value": "Completed"},
{"label": "Pending", "value": "Pending"},
{"label": "Cancelled", "value": "Cancelled"},
{"label": "All orders", "value": "All"}
],
value='Completed',
id="select_order_status",
inline = True,
),
], style={'backgroundColor': '#0d585e'}
)
# READ AND PROCESS DATA STATIONS
data_all = pd.read_csv('data.csv')
#convert date field to date type
data_all["Date"] = pd.to_datetime(data_all["Date"], format='%d-%m-%y', errors='coerce')
#add day of the week (0=Monday, 6=Sunday)
data_all["Weekday Num"] = data_all["Date"].dt.weekday
data_all["Day of Week"] = data_all["Date"].dt.strftime("%a")
#create a weekday map for mapping int to str.
weekday_map = {0:'mon', 1:'tue',2:'wed',3:'thu', 4:'fri', 5:'sat', 6:'sun'}
#replace Home Appliances with Home App., fits better on screen
data_all['Category'] = data_all['Category'].apply(lambda x: "Home App." if x == "Home Appliances" else x)
# Initialize the Dash app
app = dash.Dash(__name__, suppress_callback_exceptions=True, external_stylesheets=[vizro_bootstrap, dbc.icons.FONT_AWESOME])
# Define the app layout
app.layout = dbc.Container([
dbc.Row([
dbc.Col([select_status])
], style={'textAlign': 'center'}),
dbc.Row([
dbc.Col(dcc.Graph(id="heatmap_weekday3"), width=6),
dbc.Col(dcc.Graph(id="heatmap_weekday4"), width=6)
],style={"marginBottom":"2rem"}),
], style={'padding': '3rem'})
#callback update visuals based on filters
@callback(
Output('heatmap_weekday3', 'figure'),
Output('heatmap_weekday4', 'figure'),
Input("select_order_status", "value")
)
def update_heatmaps(value):
df = data_all.copy()
if value == None or value == "All":
dff = df
else:
dff = df[df['Status'] == value]
# Similar logic for payment method heatmaps
df_cat_payment = dff.groupby(['Category','Payment Method']).agg({
'Order ID': 'count',
'Total Sales': 'sum'
}).reset_index()
if value != "All" and value is not None:
df_cat_payment_total = df.groupby(['Category','Payment Method']).agg({
'Order ID': 'count',
'Total Sales': 'sum'
}).reset_index()
df_cat_payment = df_cat_payment.merge(
df_cat_payment_total,
on=['Category', 'Payment Method'],
how='right',
suffixes=('_filtered', '_total')
).fillna(0)
df_cat_payment['Order_Percentage'] = (df_cat_payment['Order ID_filtered'] / df_cat_payment['Order ID_total'] * 100).round(1)
df_cat_payment['Sales_Percentage'] = (df_cat_payment['Total Sales_filtered'] / df_cat_payment['Total Sales_total'] * 100).round(1)
# Use actual values for coloring, percentages for text
z_values_orders_payment = df_cat_payment['Order ID_filtered'] # Actual values for color
z_values_sales_payment = df_cat_payment['Total Sales_filtered'] # Actual values for color
z_values_percentage_payment = df_cat_payment['Sales_Percentage'] # Percentages for color
text_orders_payment = [f"{row['Order ID_filtered']}<br>({row['Order_Percentage']}%)" for _, row in df_cat_payment.iterrows()]
text_sales_payment = [f"${row['Total Sales_filtered']}<br>({row['Sales_Percentage']}%)" for _, row in df_cat_payment.iterrows()]
text_percentage_payment = [f"{row['Sales_Percentage']}%" for _, row in df_cat_payment.iterrows()]
else:
z_values_orders_payment = df_cat_payment['Order ID']
z_values_sales_payment = df_cat_payment['Total Sales']
z_values_percentage_payment = [100] * len(df_cat_payment) # All 100% when showing all data
text_orders_payment = df_cat_payment['Order ID'].astype(str)
text_sales_payment = df_cat_payment['Total Sales'].astype(str)
text_percentage_payment = ["100%"] * len(df_cat_payment)
# Payment method heatmaps
fig_heatmap_weekday3 = go.Figure(data=go.Heatmap(
x=df_cat_payment['Payment Method'],
y=df_cat_payment['Category'],
z=z_values_orders_payment, # Colors based on actual values
colorscale="Mint_r",
text=text_orders_payment, # Text shows values + percentages
texttemplate="%{text}",
hovertemplate="Category: %{y}<br>Payment Method: %{x}<br>Value: %{text}<extra></extra>"
))
title_suffix = "" if value == "All" else f" (% of total)"
fig_heatmap_weekday3.update_layout(
title=f'{value} orders (#){title_suffix} by payment method, category',
template="plotly_dark",
)
fig_heatmap_weekday4 = go.Figure(data=go.Heatmap(
x=df_cat_payment['Payment Method'],
y=df_cat_payment['Category'],
z=z_values_sales_payment, # Colors based on actual values
colorscale="Mint_r",
text=text_sales_payment, # Text shows values + percentages
texttemplate="%{text}",
hovertemplate="Category: %{y}<br>Payment Method: %{x}<br>Value: %{text}<extra></extra>"
))
fig_heatmap_weekday4.update_layout(
title=f'{value} ordervalue ($){title_suffix} by payment method, category',
template="plotly_dark",
)
return fig_heatmap_weekday3, fig_heatmap_weekday4
# Run the app
if __name__ == '__main__':
app.run(debug=True)