File size: 13,783 Bytes
6b26515
8de260d
6b26515
 
009ddcf
e5f1c28
6b26515
 
 
 
 
 
 
 
 
3bdb729
6b26515
 
3bdb729
 
6b26515
 
3bdb729
6b26515
 
 
3bdb729
6b26515
 
3bdb729
6b26515
 
 
 
 
 
 
3bdb729
6b26515
 
3bdb729
36f8b01
6b26515
 
3bdb729
36f8b01
6b26515
 
3bdb729
 
 
36f8b01
6b26515
36f8b01
6b26515
36f8b01
6b26515
8de260d
3bdb729
 
b72bb18
3bdb729
 
 
e6a8069
3bdb729
 
ac4d6d8
 
 
e6a8069
ac4d6d8
 
 
e6a8069
ac4d6d8
 
009ddcf
d0caa41
 
009ddcf
d0caa41
009ddcf
d0caa41
 
e6a8069
009ddcf
e6a8069
d0caa41
009ddcf
 
 
 
 
 
 
 
 
 
 
 
 
d0caa41
009ddcf
 
 
 
 
 
 
 
 
 
 
d0caa41
009ddcf
 
 
 
e6a8069
009ddcf
d0caa41
 
 
009ddcf
 
 
e6a8069
 
 
009ddcf
 
e6a8069
 
009ddcf
 
 
 
 
e6a8069
009ddcf
 
 
 
d0caa41
 
 
 
 
e6a8069
d0caa41
e6a8069
d0caa41
009ddcf
 
 
 
 
 
 
 
 
e6a8069
 
 
009ddcf
e6a8069
 
 
009ddcf
 
 
 
 
e6a8069
009ddcf
 
e6a8069
009ddcf
 
 
 
e6a8069
 
36f8b01
 
 
 
 
 
 
e6a8069
009ddcf
ac4d6d8
 
009ddcf
ac4d6d8
009ddcf
 
 
 
ac4d6d8
009ddcf
62f7084
009ddcf
62f7084
 
 
 
 
009ddcf
 
 
 
 
 
 
 
 
 
62f7084
 
009ddcf
62f7084
009ddcf
54f831b
009ddcf
 
 
 
e767e0f
3bdb729
 
d0caa41
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
009ddcf
b72bb18
009ddcf
 
e6a8069
009ddcf
d0caa41
 
e6a8069
009ddcf
e6a8069
009ddcf
 
e6a8069
009ddcf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d0caa41
 
 
e6a8069
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d0caa41
 
67aa173
e6a8069
 
 
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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
import gradio as gr
import bcrypt
from simple_salesforce import Salesforce

# Salesforce Connection (Replace with your actual credentials)
sf = Salesforce(username='diggavalli98@gmail.com', password='Sati@1020', security_token='sSSjyhInIsUohKpG8sHzty2q')

# Function to Hash Password
def hash_password(password):
    return bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')

# Function to Verify Password
def verify_password(plain_password, hashed_password):
    return bcrypt.checkpw(plain_password.encode('utf-8'), hashed_password.encode('utf-8'))

# Signup function
def signup(name, email, phone, password):
    try:
        email = email.strip()
        query = f"SELECT Id FROM Customer_Login__c WHERE Email__c = '{email}'"
        result = sf.query(query)

        if len(result['records']) > 0:
            return "Email already exists! Please use a different email."

        hashed_password = hash_password(password)

        sf.Customer_Login__c.create({
            'Name': name.strip(),
            'Email__c': email,
            'Phone_Number__c': phone.strip(),
            'Password__c': hashed_password
        })
        return "Signup successful! You can now login."
    except Exception as e:
        return f"Error during signup: {str(e)}"

# Login function
def login(email, password):
    try:
        email = email.strip()
        query = f"SELECT Name, Password__c FROM Customer_Login__c WHERE Email__c = '{email}'"
        result = sf.query(query)

        if len(result['records']) == 0:
            return "Invalid email or password.", None

        user = result['records'][0]
        stored_password = user['Password__c']

        if verify_password(password.strip(), stored_password):
            return "Login successful!", user['Name']
        else:
            return "Invalid email or password.", None
    except Exception as e:
        return f"Error during login: {str(e)}", None

# Function to load menu data from Salesforce
def load_menu_from_salesforce():
    try:
        query = "SELECT Name, Price__c, Description__c, Image1__c, Image2__c, Veg_NonVeg__c, Section__c FROM Menu_Item__c"
        result = sf.query(query)
        return result['records']
    except Exception as e:
        print(f"Error loading menu from Salesforce: {e}")
        return []

# Function to load add-ons data from Salesforce
def load_add_ons_from_salesforce():
    try:
        query = "SELECT Name, Price__c, Id FROM Add_Ons__c"
        result = sf.query(query)
        return result['records']
    except Exception as e:
        print(f"Error loading add-ons from Salesforce: {e}")
        return []

# Cart Management
cart = []
total_cart_cost = 0
cart_id = None

def add_to_cart(item_name, item_price, quantity, special_instructions, selected_addon_ids):
    global total_cart_cost, cart_id
    total_cost = item_price * quantity

    selected_addons = [addon for addon in load_add_ons_from_salesforce() if addon['Id'] in selected_addon_ids]
    addons_cost = sum(addon['Price__c'] for addon in selected_addons)

    try:
        if not cart_id:
            cart_record = sf.Cart__c.create({'Total_Cost__c': total_cost + addons_cost})
            cart_id = cart_record['id']

        addon_ids_str = ';'.join(selected_addon_ids) if selected_addon_ids else ''
        cart_item = sf.Cart_Item__c.create({
            'Name': item_name,
            'Quantity__c': quantity,
            'Price__c': item_price,
            'Special_Instructions__c': special_instructions,
            'Cart__c': cart_id,
            'Add_ons__c': addon_ids_str
        })

        sf.Cart__c.update(cart_id, {'Total_Cost__c': sf.Cart__c.get(cart_id)['Total_Cost__c'] + total_cost + addons_cost})

        cart.append({
            'name': item_name,
            'price': item_price,
            'quantity': quantity,
            'instructions': special_instructions,
            'total_cost': total_cost + addons_cost,
            'addons': selected_addons,
            'cart_item_id': cart_item['id']
        })
        total_cart_cost += total_cost + addons_cost
        return cart, total_cart_cost

    except Exception as e:
        print(f"Error adding to cart: {e}")
        return f"Error adding to cart: {str(e)}"


def remove_from_cart(index):
    global total_cart_cost, cart_id
    if 0 <= index < len(cart):
        try:
            cart_item_id = cart[index].get('cart_item_id')  # Use get() to avoid KeyError
            if cart_item_id:
                sf.Cart_Item__c.delete(cart_item_id)

            total_cart_cost -= cart[index]['total_cost']
            if cart_id:  # Check if cart_id exists before updating
                sf.Cart__c.update(cart_id, {'Total_Cost__c': total_cart_cost})

            cart.pop(index)
            return cart, total_cart_cost

        except Exception as e:
            print(f"Error removing from cart: {e}")
            return f"Error removing from cart: {str(e)}"
    else:
        return "Invalid item index", total_cart_cost

# Checkout Summary
def proceed_to_checkout():
    summary = ""
    for item in cart:
        summary += f"{item['name']} (x{item['quantity']}) - ${item['total_cost']:.2f}\n"
        if item.get('instructions'):
            summary += f"Instructions: {item['instructions']}\n"
        if item.get('addons'):
            summary += f"Add-ons: {', '.join([addon['Name'] for addon in item['addons']])}\n"
    summary += f"Total Bill: <span class="math-inline">\{total\_cart\_cost\:\.2f\}"
return summary
\# Function to filter menu items based on user preference
def filter\_menu\(preference\)\:
menu\_data \= load\_menu\_from\_salesforce\(\)
filtered\_data \= \{\}
for item in menu\_data\:
if "Section\_\_c" not in item or "Veg\_NonVeg\_\_c" not in item\:
continue
section \= item\["Section\_\_c"\]\.strip\(\)
if section not in filtered\_data\:
filtered\_data\[section\] \= \[\]
if preference \=\= "All" or \(preference \=\= "Veg" and item\["Veg\_NonVeg\_\_c"\] in \["Veg", "Both"\]\) or \(preference \=\= "Non\-Veg" and item\["Veg\_NonVeg\_\_c"\] in \["Non veg", "Both"\]\)\:
filtered\_data\[section\]\.append\(item\)
if not any\(filtered\_data\.values\(\)\)\:
return "<p\>No items match your filter\.</p\>"
html\_content \= '<div style\="padding\: 0 10px; max\-width\: 1200px; margin\: auto;"\>'
for section, items in filtered\_data\.items\(\)\:
html\_content \+\= f"<h2 style\='text\-align\: center; margin\-top\: 5px;'\>\{section\}</h2\>"
html\_content \+\= '<div style\="display\: grid; grid\-template\-columns\: repeat\(auto\-fit, minmax\(250px, 1fr\)\); gap\: 15px; justify\-content\: center; margin\-top\: 10px;"\>'
for item in items\:
image\_url \= item\.get\('Image1\_\_c', ''\)
html\_content \+\= f"""
<div style\="border\: 1px solid \#ddd; border\-radius\: 10px; box\-shadow\: 0px 4px 8px rgba\(0, 0, 0, 0\.1\); overflow\: hidden; height\: 350px;"\>
<img src\="\{image\_url\}" style\="width\: 100%; height\: 200px; object\-fit\: cover; cursor\: pointer;"
onclick\="openModal\('\{item\['Name'\]\}', '\{item\.get\('Image2\_\_c', ''\)\}', '\{item\['Description\_\_c'\]\}', \{item\['Price\_\_c'\]\}\)"\>
<div style\="padding\: 10px;"\>
<h3 style\='font\-size\: 1\.2em; text\-align\: center;'\>\{item\['Name'\]\}</h3\>
<p style\='font\-size\: 1\.1em; color\: green; text\-align\: center;'\></span>{item['Price__c']}</p>
                        <p style='font-size: 0.9em; text-align: justify; margin: 5px;'>{item['Description__c'] or ''}</p> 
                    </div>
                </div>
            """
        html_content += '</div>'
    html_content += '</div>'

    return html_content

# Function to generate HTML for the modal popup
def generate_modal_html(item_name, item_image, item_description, item_price):
    add_ons = load_add_ons_from_salesforce()
    add_ons_html = ""
    for i, add_on in enumerate(add_ons):
        add_ons_html += f"""
        <div>
            <input type="checkbox" id="add-on_{i}" name="add-on" value="{add_on['Id']}" data-price="{add_on['Price__c']}">
            <label for="add-on_{i}">{add_on['Name']} - ${add_on['Price__c']}</label>
        </div>
        """

    modal_content = f"""
    <div id="modal-content" style="background: white; padding: 20px; width: 60%; box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.2); position: absolute; top: 20%; left: 20%; z-index: 1000; display: none;">
        <img src="{item_image}" style="width: 100%; height: 250px; object-fit: cover; border-radius: 8px;">
        <h3>{item_name}</h3>
        <p>{item_description}</p>
        <p>Price: ${item_price}</p>
        <label for="quantity">Quantity:</label>
        <input type="number" id="quantity" name="quantity" value="1" min="1" style="width: 50px;">
        <br>
        <textarea id="special-instructions" name="special-instructions" placeholder="Add your special instructions here..." style="width: calc(100% - 22px); height: 60px; margin-top: 10px;"></textarea>
        <br>
        <div style="margin-top: 10px;">
            <h4>Select Add-ons:</h4>
            {add_ons_html}
        </div>
        <button type="submit" style="background-color: #28a745; color: white; padding: 10px 20px; border: none; font-size: 14px; border-radius: 5px; cursor: pointer; margin-top: 10px;">Add to Cart</button>
        <button type="button" onclick="closeModal()" style="background-color: #ff5722; color: white; padding: 10px 20px; border: none; font-size: 14px; border-radius: 5px; cursor: pointer; margin-top: 10px; float: right;">Close</button>
    </div>
    """
    return modal_content

# --- Gradio App ---
with gr.Blocks() as app:
    # Hidden components to store data
    hidden_item_name = gr.State("")
    hidden_item_price = gr.State(0)

    with gr.Row():
        gr.HTML("<h1 style='text-align: center;'>Welcome to Biryani Hub</h1>")

    with gr.Row(visible=True) as login_page:
        with gr.Column():
            login_email = gr.Textbox(label="Email")
            login_password = gr.Textbox(label="Password", type="password")
            login_button = gr.Button("Login")
            signup_button = gr.Button("Go to Signup")
            login_output = gr.Textbox(label="Status")

    with gr.Row(visible=False) as signup_page:
        with gr.Column():
            signup_name = gr.Textbox(label="Name")
            signup_email = gr.Textbox(label="Email")
            signup_phone = gr.Textbox(label="Phone")
            signup_password = gr.Textbox(label="Password", type="password")
            submit_signup = gr.Button("Signup")
            login_redirect = gr.Button("Go to Login")
            signup_output = gr.Textbox(label="Status")

    with gr.Row(visible=False) as menu_page:
        with gr.Column() as menu_column:
            preference = gr.Radio(choices=["All", "Veg", "Non-Veg"], label="Filter Preference", value="All")
            menu_output = gr.HTML(filter_menu("All"))

            modal_html = gr.HTML(generate_modal_html("", "", "", 0))

            gr.HTML("<div id='cart-button' style='position: fixed; top: 20px; right: 20px; background: #28a745; color: white; padding: 10px 20px; border-radius: 30px; cursor: pointer;'>View Cart</div>")
            cart_summary = gr.Textbox(label="Cart Summary", interactive=False)
            checkout_button = gr.Button("Proceed to Checkout", visible=False)

            with gr.Form():
                item_name_hidden = gr.Textbox(visible=False)
                item_price_hidden = gr.Number(visible=False)
                submit_button = gr.Button("Add to Cart", visible=False)

            submit_button.click(
                fn=lambda *args: add_to_cart(*args),
                inputs=[item_name_hidden, item_price_hidden, gr.Number(value=1, label="Quantity"), gr.Textbox(label="Special Instructions"), gr.CheckboxGroup(choices=[add_on['Id'] for add_on in load_add_ons_from_salesforce()], label="Add-ons", value=[])],
                outputs=[cart_summary, gr.Number(label="Total Cart Cost")]
            )

            def update_cart_summary_and_checkout_button(cart, total_cart_cost):
                cart_summary_str = proceed_to_checkout()
                checkout_visibility = True if cart else False
                return gr.update(value=cart_summary_str), gr.update(visible=checkout_visibility)

            submit_button.click(
                fn=update_cart_summary_and_checkout_button,
                inputs=[cart_summary, gr.Number(label="Total Cart Cost")],
                outputs=[cart_summary, checkout_button]
            )

            checkout_button.click(proceed_to_checkout, [], cart_summary)

    # --- Event Handlers ---
    login_button.click(
        lambda email, password: (gr.update(visible=False), gr.update(visible=True), gr.update(value=filter_menu("All")), "Login successful!")
        if login(email, password)[0] == "Login successful!" else (gr.update(), gr.update(), gr.update(), "Invalid email or password."),
        [login_email, login_password], [login_page, menu_page, menu_output, login_output]
    )

    submit_signup.click(
        lambda name, email, phone, password: signup(name, email, phone, password),
        inputs=[signup_name, signup_email, signup_phone, signup_password],
        outputs=signup_output
    )

    signup_button.click(
        lambda: (gr.update(visible=False), gr.update(visible=True)),
        inputs=[],
        outputs=[login_page, signup_page]
    )

    login_redirect.click(
        lambda: (gr.update(visible=True), gr.update(visible=False)),
        inputs=[],
        outputs=[login_page, signup_page]
    )

    preference.change(lambda pref: filter_menu(pref), [preference], menu_output)

    # When an image is clicked, open the modal and populate it with item details
    def open_modal(item_name, item_image, item_description, item_price):
        return gr.