import gradio as gr import pandas as pd # ======= Global Data Store ======= df = pd.DataFrame(columns=["USERNAME", "COUNTRYCODE", "SBUCODE", "BRANDCODE", "CONCEPTCODE", "CHANNEL", "REMARK"]) users_df = pd.DataFrame([{"USERNAME": "admin", "PASSWORD": "admin"}]) selected_indices = [] # ======= Helper Functions ======= def to_upper(df_input): return df_input.applymap(lambda x: str(x).upper().strip() if pd.notnull(x) else x) def get_active_data(): return df[df["REMARK"].str.upper() != "DELETE"].reset_index(drop=True) def login(username, password): username = username.strip().lower() password = password.strip() is_valid = not users_df[(users_df["USERNAME"] == username) & (users_df["PASSWORD"] == password)].empty if is_valid: return "", gr.update(visible=False), gr.update(visible=True), get_active_data(), show_users() return "Invalid login", gr.update(visible=True), gr.update(visible=False), pd.DataFrame(), pd.DataFrame() def bulk_submit(dataframe): global df new_df = pd.DataFrame(dataframe).dropna(how="all") if new_df.empty: return get_active_data() new_df = to_upper(new_df) required = ["USERNAME", "COUNTRYCODE", "SBUCODE", "BRANDCODE", "CONCEPTCODE", "CHANNEL", "REMARK"] new_df = new_df[required].dropna() pk_cols = required # Filter out duplicates merged = pd.merge(new_df, df[pk_cols], on=pk_cols, how="left", indicator=True) df_filtered = new_df[merged["_merge"] == "left_only"] df = pd.concat([df, df_filtered], ignore_index=True) return get_active_data() def delete_selected_rows(selected_df): global df try: if selected_df.empty: return "Tidak ada baris yang dipilih", get_active_data() for _, row in selected_df.iterrows(): mask = ( (df["USERNAME"] == row["USERNAME"]) & (df["COUNTRYCODE"] == row["COUNTRYCODE"]) & (df["SBUCODE"] == row["SBUCODE"]) & (df["BRANDCODE"] == row["BRANDCODE"]) & (df["CONCEPTCODE"] == row["CONCEPTCODE"]) & (df["CHANNEL"] == row["CHANNEL"]) & (df["REMARK"].str.upper() != "DELETE") ) df.loc[mask, "REMARK"] = "DELETE" return "Berhasil dihapus.", get_active_data() except Exception as e: return f"Error: {e}", get_active_data() def add_user(username, password): global users_df username = username.strip().upper() password = password.strip() if not username or not password: return "Username/password tidak boleh kosong", show_users() if username in users_df["USERNAME"].values: return "Username sudah ada", show_users() users_df = pd.concat([users_df, pd.DataFrame([{"USERNAME": username, "PASSWORD": password}])], ignore_index=True) return f"User {username} ditambahkan", show_users() def delete_user(username): global users_df username = username.strip().upper() if username == "ADMIN": return "ADMIN tidak boleh dihapus", show_users() users_df = users_df[users_df["USERNAME"] != username].reset_index(drop=True) return f"User {username} dihapus", show_users() def show_users(): return users_df.copy() # ======= UI Layout ======= with gr.Blocks() as app: gr.Markdown("## Login") login_box = gr.Column(visible=True) with login_box: user = gr.Textbox(label="Username") pw = gr.Textbox(label="Password", type="password") btn_login = gr.Button("Login") login_msg = gr.Textbox(visible=True, interactive=False, show_label=False) tab_section = gr.Tabs(visible=False) with tab_section: with gr.Tab("Input Data"): gr.Markdown("### Input Data Baru") df_input = gr.Dataframe( headers=["USERNAME", "COUNTRYCODE", "SBUCODE", "BRANDCODE", "CONCEPTCODE", "CHANNEL", "REMARK"], row_count=5, col_count=(7, "fixed"), label="Form Input" ) btn_submit = gr.Button("Submit Data") gr.Markdown("### Data Aktif") df_list = gr.Dataframe( label="List Data Aktif", interactive=False, wrap=True, column_widths=["auto"] * 7 ) selected_df = gr.Dataframe(visible=False) btn_delete = gr.Button("Delete Selected Rows") delete_msg = gr.Textbox(visible=True, interactive=False, show_label=False) with gr.Tab("User Management"): gr.Markdown("### Kelola User") new_user = gr.Textbox(label="New Username") new_pass = gr.Textbox(label="New Password") btn_add = gr.Button("Add User") del_user = gr.Textbox(label="Delete Username") btn_del = gr.Button("Delete User") user_msg = gr.Textbox(visible=True, interactive=False, show_label=False) user_table = gr.Dataframe(label="User List", interactive=False) # ==== Events ==== btn_login.click(fn=login, inputs=[user, pw], outputs=[login_msg, login_box, tab_section, df_list, user_table]) btn_submit.click(fn=bulk_submit, inputs=[df_input], outputs=[df_list]) df_list.select(fn=lambda df, evt: df.iloc[[evt.index]] if evt.index is not None else pd.DataFrame(), inputs=[df_list], outputs=[selected_df]) btn_delete.click(fn=delete_selected_rows, inputs=[selected_df], outputs=[delete_msg, df_list]) btn_add.click(fn=add_user, inputs=[new_user, new_pass], outputs=[user_msg, user_table]) btn_del.click(fn=delete_user, inputs=[del_user], outputs=[user_msg, user_table]) app.launch()