File size: 7,677 Bytes
943ca21
c872642
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
03931e3
f13d5be
b17b983
 
c872642
 
 
 
 
 
 
 
 
 
 
b17b983
 
 
c872642
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
import gradio as gr
import os
import pandas as pd
from PIL import Image, ImageDraw

BASE_DIR = "data"
ASSETS_DIR = "assets"
STORE_MAP_FILE = os.path.join(ASSETS_DIR, "store_map_clinicplus.png")


# Approximate mapping from Aisle number to bounding box on the store map
AISLE_TO_BOX = {
    # Example: '14': (x, y, width, height) - you can later load this from config
    "14": (220, 150, 40, 120),
    "15": (270, 150, 40, 120),
    "16": (320, 150, 40, 120),
    # Add more as needed...
}


def get_subfolders(path):
    try:
        return sorted([f for f in os.listdir(path) if os.path.isdir(os.path.join(path, f))])
    except Exception as e:
        print(f"❌ Error reading subfolders from {path}: {e}")
        return []


def get_csv_files(path):
    try:
        return sorted([f[:-4] for f in os.listdir(path) if f.endswith(".csv")])
    except Exception as e:
        print(f"❌ Error reading CSVs from {path}: {e}")
        return []


def get_quantities_from_csv(path):
    try:
        df = pd.read_csv(path)
        if df.empty or "Quantity" not in df.columns:
            return gr.update(choices=[], visible=False), {}
        return gr.update(choices=df["Quantity"].dropna().tolist(), visible=True), df.to_dict()
    except Exception as e:
        print(f"❌ Error loading CSV: {e}")
        return gr.update(choices=[], visible=False), {}


def display_quantity_info(quantity, data_dict):
    try:
        df = pd.DataFrame(data_dict)
        row = df[df["Quantity"] == quantity].iloc[0]

        if str(row["In Stock"]).strip().lower() == "yes":
            msg = (
                f"βœ… {quantity} is available!\n"
                f"β€’ Floor: {row['Floor']}\n"
                f"β€’ Aisle: {row['Aisle']}\n"
                f"β€’ Price: β‚Ή{row['Price']}"
            )
            if "Offer" in row and pd.notna(row["Offer"]) and row["Offer"].strip():
                msg += f"\nβ€’ πŸŽ‰ Offer: {row['Offer']}"
            return msg
        else:
            return f"❌ Sorry, {quantity} is currently not in stock."
    except Exception as e:
        return f"⚠️ Error: {e}"


def generate_map_with_highlight(quantity, data_dict):
    try:
        df = pd.DataFrame(data_dict)
        row = df[df["Quantity"] == quantity].iloc[0]
        aisle = str(row.get("Aisle", "")).strip()

        image = Image.open(STORE_MAP_FILE).convert("RGBA")
        draw = ImageDraw.Draw(image)

        if aisle in AISLE_TO_BOX:
            x, y, w, h = AISLE_TO_BOX[aisle]
            draw.rectangle([x, y, x + w, y + h], outline="red", width=5)

        return image
    except Exception as e:
        print(f"⚠️ Map render error: {e}")
        return Image.open(STORE_MAP_FILE)


def suggest_items(query):
    query = query.lower()
    if "gift" in query and "500" in query:
        return (
            "🎁 Gift Suggestions under β‚Ή500:\n"
            "1. Bath & Body Gift Set - β‚Ή499\n"
            "2. Mini Perfume Pack - β‚Ή349\n"
            "3. Skin Care Hamper - β‚Ή399\n"
            "4. Chocolates Gift Box - β‚Ή299"
        )
    if "shampoo" in query and "dry" in query:
        return (
            "🧴 Shampoos for Dry Hair:\n"
            "1. Dove 500 ml - β‚Ή325\n"
            "2. Clinic Plus 500 ml - β‚Ή680"
        )
    return "🀷 Sorry, no smart suggestions found. Try asking: 'Gift items under 500' or 'Shampoo for dry hair'"


def reset_all():
    return (
        None,  # country - Dropdown
        None,  # state - Dropdown
        None,  # city - Dropdown
        None,  # store - Dropdown
        None,  # category - Dropdown
        None,  # product - Dropdown
        None,  # brand - Dropdown
        gr.update(choices=[], visible=False),  # quantity - Dropdown
        "",  # result - Textbox
        {},  # data_state - State (MUST be a raw dict or string, not gr.update)
        Image.open(STORE_MAP_FILE)  # store_map - Image (if using type="pil")
    )



with gr.Blocks(title="RetailGenie") as demo:
    gr.Markdown("# πŸ§žβ€β™‚οΈ RetailGenie – In-Store Smart Assistant")

    with gr.Tabs():
        with gr.TabItem("🧭 Navigator"):
            with gr.Row():
                country = gr.Dropdown(label="🌍 Country", choices=get_subfolders(BASE_DIR), value=None)
                state = gr.Dropdown(label="πŸ™οΈ State", choices=[], interactive=False)
                city = gr.Dropdown(label="🏘️ City", choices=[], interactive=False)
                store = gr.Dropdown(label="πŸͺ Store", choices=[], interactive=False)
                category = gr.Dropdown(label="πŸ›οΈ Category", choices=[], interactive=False)
                product = gr.Dropdown(label="πŸ“¦ Product", choices=[], interactive=False)
                brand = gr.Dropdown(label="🏷️ Brand", choices=[], interactive=False)
                quantity = gr.Dropdown(label="πŸ”’ Quantity", visible=False)

            result = gr.Textbox(label="πŸ” Product Info", lines=5)
            store_map = gr.Image(label="πŸ—ΊοΈ Store Map", value=Image.open(STORE_MAP_FILE), type="pil")
            data_state = gr.State(value={}) 
            reset_btn = gr.Button("πŸ”„ Reset All")

            country.change(lambda c: gr.update(choices=get_subfolders(os.path.join(BASE_DIR, c)) if c else [], value=None, interactive=True), inputs=country, outputs=state)
            state.change(lambda c, s: gr.update(choices=get_subfolders(os.path.join(BASE_DIR, c, s)) if c and s else [], value=None, interactive=True), inputs=[country, state], outputs=city)
            city.change(lambda c, s, ci: gr.update(choices=get_subfolders(os.path.join(BASE_DIR, c, s, ci)) if c and s and ci else [], value=None, interactive=True), inputs=[country, state, city], outputs=store)
            store.change(lambda c, s, ci, st: gr.update(choices=get_subfolders(os.path.join(BASE_DIR, c, s, ci, st)) if all([c, s, ci, st]) else [], value=None, interactive=True), inputs=[country, state, city, store], outputs=category)
            category.change(lambda c, s, ci, st, cat: gr.update(choices=get_subfolders(os.path.join(BASE_DIR, c, s, ci, st, cat)) if all([c, s, ci, st, cat]) else [], value=None, interactive=True), inputs=[country, state, city, store, category], outputs=product)
            product.change(lambda c, s, ci, st, cat, prod: gr.update(choices=get_csv_files(os.path.join(BASE_DIR, c, s, ci, st, cat, prod)) if all([c, s, ci, st, cat, prod]) else [], value=None, interactive=True), inputs=[country, state, city, store, category, product], outputs=brand)

            brand.change(lambda c, s, ci, st, cat, prod, b: get_quantities_from_csv(os.path.join(BASE_DIR, c, s, ci, st, cat, prod, f"{b}.csv")) if all([c, s, ci, st, cat, prod, b]) else (gr.update(choices=[], visible=False), {}), inputs=[country, state, city, store, category, product, brand], outputs=[quantity, data_state])

            quantity.change(display_quantity_info, inputs=[quantity, data_state], outputs=result)
            quantity.change(generate_map_with_highlight, inputs=[quantity, data_state], outputs=store_map)
            reset_btn.click(reset_all, inputs=[], outputs=[country, state, city, store, category, product, brand, quantity, result, data_state, store_map])

        with gr.TabItem("🎁 Smart Suggestions"):
            gr.Markdown("### πŸ€– Ask RetailGenie for Recommendations")
            suggestion_input = gr.Textbox(label="Ask something like:", placeholder="Gift items under 500", lines=1)
            suggest_btn = gr.Button("πŸ’‘ Get Suggestions")
            suggestions_output = gr.Textbox(label="πŸ“ Suggestions", lines=10)

            suggest_btn.click(suggest_items, inputs=suggestion_input, outputs=suggestions_output)

demo.launch()