File size: 4,369 Bytes
73b9fb2
d0aaafd
9243721
 
 
d0aaafd
9243721
 
 
 
d0aaafd
 
 
9243721
 
 
 
d0aaafd
 
 
 
 
 
 
 
 
9243721
 
 
 
 
 
 
d0aaafd
 
 
 
 
 
 
 
 
 
9243721
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d0aaafd
9243721
 
d0aaafd
9243721
d0aaafd
 
 
 
 
9243721
d0aaafd
 
 
 
9243721
 
 
 
 
 
 
 
 
 
d0aaafd
9243721
 
 
 
 
d0aaafd
9243721
 
d0aaafd
9243721
 
 
d0aaafd
 
 
 
 
 
 
 
 
 
 
9243721
d0aaafd
9243721
 
 
 
d0aaafd
9243721
 
 
 
 
 
 
 
 
 
 
 
 
d0aaafd
9243721
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import gradio as gr
from huggingface_hub import list_bucket_tree, download_bucket_files, login
import pandas as pd
import json
import os
import tempfile
from dotenv import load_dotenv

load_dotenv()
BUCKET_NAME = os.getenv("BUCKET_NAME")
HF_TOKEN = os.getenv("HF_TOKEN")
if HF_TOKEN:
    login(token=HF_TOKEN)

PAGE_SIZE = 5
def extract_customer_data():
    try:
        if not BUCKET_NAME:
            print("❌ BUCKET_NAME missing")
            return pd.DataFrame()

        tree = list_bucket_tree(
            BUCKET_NAME,
            recursive=True,
            token=HF_TOKEN
        )
        json_files = [
            item.path for item in tree
            if item.path.endswith("cameras.json")
        ]

        if not json_files:
            return pd.DataFrame(columns=["customer_id", "customer_name", "customer_email"])
        tmp_dir = tempfile.gettempdir()
        files_map = [
            (f, os.path.join(tmp_dir, f.replace("/", "_")))
            for f in json_files
        ]
        download_bucket_files(
            BUCKET_NAME,
            files=files_map,
            token=HF_TOKEN
        )
        rows = []
        for remote_path, local_path in files_map:
            parts = remote_path.split("/")
            customer_id = parts[1] if len(parts) > 1 else "unknown"
            try:
                with open(local_path, "r", encoding="utf-8") as f:
                    data = json.load(f)
                for item in data:
                    rows.append({
                        "customer_id": customer_id,
                        "customer_name": item.get("customer_name"),
                        "customer_email": item.get("customer_email")
                    })
            except Exception as e:
                print(f"File error {remote_path}: {e}")
        df = pd.DataFrame(rows)
        if not df.empty:
            df = df.drop_duplicates()
        return df
    except Exception as e:
        print("❌ BUCKET ERROR:", e)
        return pd.DataFrame(columns=["customer_id", "customer_name", "customer_email"])
def safe_load():
    try:
        return extract_customer_data()
    except Exception as e:
        print("❌ SAFE LOAD ERROR:", e)
        return pd.DataFrame(columns=["customer_id", "customer_name", "customer_email"])
df_global = safe_load()
def apply_search(df, email_query):
    if df is None or df.empty:
        return df
    if email_query:
        df = df[df["customer_email"].astype(str).str.contains(email_query, case=False, na=False)]
    return df
def build_view(df, page, email_query):
    filtered = apply_search(df, email_query)
    total_pages = max(1, (len(filtered) - 1) // PAGE_SIZE + 1)
    page = max(0, min(page, total_pages - 1))
    start = page * PAGE_SIZE
    end = start + PAGE_SIZE
    paged = filtered.iloc[start:end]
    status = f"Page {page+1}/{total_pages} | Total: {len(filtered)}"
    return paged, page, status
with gr.Blocks() as app:
    gr.Markdown("# πŸ›° Buck Tracker Customer Dashboard")
    state_df = gr.State(df_global)
    state_page = gr.State(0)
    search_box = gr.Textbox(label="πŸ” Search Email")
    table = gr.Dataframe(
        value=build_view(df_global, 0, "")[0],
        interactive=False
    )
    status = gr.Textbox(interactive=False)
    with gr.Row():
        refresh_btn = gr.Button("πŸ”„ Refresh")
        prev_btn = gr.Button("⬅️")
        next_btn = gr.Button("➑️")
    def refresh(email):
        df = safe_load()
        table, page, status_text = build_view(df, 0, email)
        return table, 0, status_text, df
    def next_page(df, page, email):
        return *build_view(df, page + 1, email), df
    def prev_page(df, page, email):
        return *build_view(df, page - 1, email), df
    search_box.change(
        fn=lambda df, q: (*build_view(df, 0, q), df),
        inputs=[state_df, search_box],
        outputs=[table, state_page, status, state_df]
    )
    refresh_btn.click(
        fn=refresh,
        inputs=[search_box],
        outputs=[table, state_page, status, state_df]
    )
    next_btn.click(
        fn=next_page,
        inputs=[state_df, state_page, search_box],
        outputs=[table, state_page, status, state_df]
    )
    prev_btn.click(
        fn=prev_page,
        inputs=[state_df, state_page, search_box],
        outputs=[table, state_page, status, state_df]
    )
app.queue()
app.launch()