gopalaKrishna1236's picture
Upload app.py
88fc028 verified
# Fevicol CreatorHub — Full Features + Real Fevicol Catalog Seeder (Gradio 4.44 compatible)
# Tabs: Home/About, Admin, Login/Sign Up, Products & Orders, My Orders
# Storage: SQLite under ./data ; product images under ./data/product_images
import gradio as gr
import sqlite3, os, datetime, pandas as pd, time
from shutil import copyfile
ADMIN_PIN = os.environ.get("FEVICOL_ADMIN_PIN", "FEVI-ADMIN-123")
OWNER_EMAIL = os.environ.get("FEVICOL_OWNER_EMAIL", "").lower()
DATA_DIR = os.path.join(os.path.dirname(__file__), "data")
os.makedirs(DATA_DIR, exist_ok=True)
DB_PATH = os.path.join(DATA_DIR, "fevicol_creatorhub.db")
LOGO_PATH = os.path.join(DATA_DIR, "logo.png")
DEFAULT_TAGLINE = "India’s makers, united by Fevicol."
DEFAULT_MISSION = "Empower customers, designers, carpenters, and dealers to collaborate and deliver quality interiors faster."
# ---------- DB ----------
def init_db():
con = sqlite3.connect(DB_PATH); cur = con.cursor()
cur.execute("""CREATE TABLE IF NOT EXISTS users(
id INTEGER PRIMARY KEY AUTOINCREMENT,
email TEXT UNIQUE, password TEXT, name TEXT, role TEXT, city TEXT, is_verified INTEGER DEFAULT 0
);""")
cur.execute("""CREATE TABLE IF NOT EXISTS products(
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL, brand TEXT, price REAL NOT NULL, description TEXT, created_at TEXT
);""")
cur.execute("""CREATE TABLE IF NOT EXISTS orders(
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER, total REAL, address TEXT, delivery_option TEXT, delivery_fee REAL,
payment_method TEXT, payment_status TEXT, status TEXT, created_at TEXT
);""")
cur.execute("""CREATE TABLE IF NOT EXISTS order_items(
id INTEGER PRIMARY KEY AUTOINCREMENT,
order_id INTEGER, product_id INTEGER, product_name TEXT, unit_price REAL, qty INTEGER, subtotal REAL
);""")
cur.execute("""CREATE TABLE IF NOT EXISTS settings(
key TEXT PRIMARY KEY, value TEXT
);""")
con.commit(); con.close()
def migrate_products_table():
con = sqlite3.connect(DB_PATH); cur = con.cursor()
cur.execute("PRAGMA table_info(products)")
cols = {c[1] for c in cur.fetchall()}
alters = []
if "category" not in cols: alters.append("ADD COLUMN category TEXT")
if "mrp" not in cols: alters.append("ADD COLUMN mrp REAL")
if "sale_price" not in cols: alters.append("ADD COLUMN sale_price REAL")
if "unit" not in cols: alters.append("ADD COLUMN unit TEXT")
if "stock" not in cols: alters.append("ADD COLUMN stock INTEGER DEFAULT 0")
if "hsn" not in cols: alters.append("ADD COLUMN hsn TEXT")
if "gst" not in cols: alters.append("ADD COLUMN gst REAL")
if "image_path" not in cols: alters.append("ADD COLUMN image_path TEXT")
for stmt in alters:
try: cur.execute(f"ALTER TABLE products {stmt}")
except Exception: pass
con.commit(); con.close()
init_db(); migrate_products_table()
# ---------- Settings helpers ----------
def get_setting(key):
con = sqlite3.connect(DB_PATH); cur = con.cursor()
cur.execute("SELECT value FROM settings WHERE key=?", (key,)); row = cur.fetchone()
con.close(); return row[0] if row else None
def set_setting(key, val):
con = sqlite3.connect(DB_PATH); cur = con.cursor()
cur.execute("INSERT INTO settings(key,value) VALUES(?,?) ON CONFLICT(key) DO UPDATE SET value=excluded.value", (key, val))
con.commit(); con.close()
if get_setting("tagline") is None: set_setting("tagline", DEFAULT_TAGLINE)
if get_setting("mission") is None: set_setting("mission", DEFAULT_MISSION)
# ---------- Branding ----------
def get_logo_path():
return LOGO_PATH if os.path.exists(LOGO_PATH) else None
def about_md():
return f"""### Welcome to Fevicol CreatorHub
{get_setting("tagline") or DEFAULT_TAGLINE}
**Mission:** {get_setting("mission") or DEFAULT_MISSION}
**What you can do here**
- Browse & buy Fevicol/Pidilite products
- Dealers can add SKUs with images and pricing
- Customers can add to cart and place orders
- Orders are tracked in “My Orders”
"""
# ---------- Auth ----------
def signup(email, password, name, role, city):
if not email or not password: return None, "Enter email & password."
con = sqlite3.connect(DB_PATH); cur = con.cursor()
try:
cur.execute("INSERT INTO users(email,password,name,role,city,is_verified) VALUES(?,?,?,?,?,0)",
(email.lower().strip(), password, name or "", role, city or ""))
con.commit()
user = {"id": cur.lastrowid, "email": email.lower().strip(), "name": name or "", "role": role, "city": city or "", "is_verified": 0}
return user, f"Account created for {email}."
except sqlite3.IntegrityError:
return None, "Email already exists."
finally:
con.close()
def login(email, password):
con = sqlite3.connect(DB_PATH); cur = con.cursor()
cur.execute("SELECT id,email,name,role,city,is_verified FROM users WHERE email=? AND password=?", (email.lower().strip(), password))
row = cur.fetchone(); con.close()
if not row: return None, "Invalid credentials."
user = {"id": row[0], "email": row[1], "name": row[2], "role": row[3], "city": row[4], "is_verified": row[5] or 0}
badge = " ✔ Fevicol Certified" if user["is_verified"] else ""
return user, f"Logged in as {row[1]} ({row[3]}){badge}."
# ---------- Admin ----------
def verify_user(email, pin, value):
if pin != ADMIN_PIN: return "Invalid admin PIN."
con = sqlite3.connect(DB_PATH); cur = con.cursor()
cur.execute("UPDATE users SET is_verified=? WHERE email=?", (1 if value else 0, email.lower().strip()))
con.commit(); con.close()
return ("✅ Verified " if value else "❎ Unverified ") + email.lower().strip()
# Demo seed (kept)
DEMO_PRODUCTS = [
{"name":"Fevicol MR 200g","brand":"Fevicol","price":95,"description":"White adhesive 200g","category":"Adhesives","unit":"200g","mrp":95,"sale_price":90,"stock":50,"hsn":"3506","gst":18},
{"name":"Fevicol SH 1kg","brand":"Fevicol","price":300,"description":"Woodworking adhesive 1kg","category":"Adhesives","unit":"1kg","mrp":310,"sale_price":299,"stock":40,"hsn":"3506","gst":18},
{"name":"Dr. Fixit LW+ 200ml","brand":"Dr. Fixit","price":190,"description":"Waterproofing additive 200ml","category":"Construction","unit":"200ml","mrp":199,"sale_price":190,"stock":60,"hsn":"3824","gst":18},
{"name":"M-Seal Phataphat 25g","brand":"M-Seal","price":35,"description":"Quick setting epoxy 25g","category":"Quick Fix","unit":"25g","mrp":35,"sale_price":35,"stock":150,"hsn":"3506","gst":18},
]
def seed_demo(pin):
if pin != ADMIN_PIN: return "Invalid admin PIN."
return _seed_products(DEMO_PRODUCTS)
# Real Fevicol catalog seed (from your screenshots / common SKUs)
FEVICOL_PRODUCTS = [
{"name":"Fevicol MR 50g","brand":"Fevicol","price":20,"description":"MR white adhesive 50g","category":"Adhesives","unit":"50g","mrp":20,"sale_price":20,"stock":200,"hsn":"3506","gst":18},
{"name":"Fevicol MR 100g","brand":"Fevicol","price":52,"description":"MR white adhesive 100g","category":"Adhesives","unit":"100g","mrp":52,"sale_price":52,"stock":150,"hsn":"3506","gst":18},
{"name":"Fevicol MR 200g","brand":"Fevicol","price":95,"description":"MR white adhesive 200g","category":"Adhesives","unit":"200g","mrp":95,"sale_price":95,"stock":120,"hsn":"3506","gst":18},
{"name":"Fevicol MR 1kg","brand":"Fevicol","price":273,"description":"MR white adhesive 1kg","category":"Adhesives","unit":"1kg","mrp":273,"sale_price":273,"stock":80,"hsn":"3506","gst":18},
{"name":"Fevicol SH 1kg","brand":"Fevicol","price":299,"description":"SH synthetic resin adhesive 1kg","category":"Adhesives","unit":"1kg","mrp":310,"sale_price":299,"stock":90,"hsn":"3506","gst":18},
{"name":"Fevicol Marine 1kg","brand":"Fevicol","price":304,"description":"Water-resistant adhesive 1kg","category":"Waterproof","unit":"1kg","mrp":304,"sale_price":304,"stock":70,"hsn":"3506","gst":18},
{"name":"Fevicol HeatX 500g","brand":"Fevicol","price":146,"description":"Heatproof fast-setting adhesive 500g","category":"Heatproof","unit":"500g","mrp":146,"sale_price":146,"stock":100,"hsn":"3506","gst":18},
{"name":"Fevicol Ezee Spray 383g","brand":"Fevicol","price":599,"description":"Ezee spray adhesive 383g","category":"Spray Adhesive","unit":"383g","mrp":599,"sale_price":599,"stock":60,"hsn":"3506","gst":18},
{"name":"Fevicol SR 998 Multipurpose 1kg","brand":"Fevicol","price":132,"description":"Synthetic rubber adhesive SR 998","category":"Industrial","unit":"1kg","mrp":132,"sale_price":132,"stock":65,"hsn":"3506","gst":18},
{"name":"Fevicol DDL 500g","brand":"Fevicol","price":792,"description":"Synthetic resin adhesive DDL 500g","category":"Adhesives","unit":"500g","mrp":792,"sale_price":792,"stock":40,"hsn":"3506","gst":18},
{"name":"Fevicol Allfix 20ml","brand":"Fevicol","price":50,"description":"Allfix clear adhesive 20ml","category":"Quick Fix","unit":"20ml","mrp":50,"sale_price":50,"stock":180,"hsn":"3506","gst":18},
{"name":"Fevicol Homefix 15g","brand":"Fevicol","price":74,"description":"Homefix DIY adhesive 15g","category":"DIY","unit":"15g","mrp":74,"sale_price":74,"stock":160,"hsn":"3506","gst":18},
]
def _seed_products(items):
con = sqlite3.connect(DB_PATH); cur = con.cursor()
added = 0
for p in items:
cur.execute("SELECT COUNT(1) FROM products WHERE name=? AND brand=?", (p["name"], p["brand"]))
if cur.fetchone()[0] == 0:
cur.execute("""INSERT INTO products
(name,brand,price,description,created_at,category,mrp,sale_price,unit,stock,hsn,gst,image_path)
VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?)""",
(p["name"], p["brand"], float(p["price"]), p.get("description",""),
datetime.datetime.utcnow().isoformat(), p.get("category",""), p.get("mrp",p["price"]),
p.get("sale_price",p["price"]), p.get("unit",""), int(p.get("stock",0)), p.get("hsn",""), float(p.get("gst",0)), ""))
added += 1
con.commit(); con.close()
return f"Added {added} item(s)."
def seed_fevicol_products(pin):
if pin != ADMIN_PIN: return "Invalid admin PIN."
return "Real Fevicol catalog: " + _seed_products(FEVICOL_PRODUCTS)
# ---------- Catalog / Cart / Orders ----------
DELIVERY_OPTIONS = {"Pickup (₹0)":0.0,"Standard 5–7 days (₹99)":99.0,"Express 2–3 days (₹199)":199.0}
PAYMENT_METHODS = ["COD (Cash on Delivery)", "UPI (Simulated)"]
def distinct_categories():
con = sqlite3.connect(DB_PATH); cur = con.cursor()
try:
cur.execute("SELECT DISTINCT IFNULL(category,'') FROM products ORDER BY 1")
cats = [r[0] for r in cur.fetchall() if r and r[0] is not None]
except Exception:
cats = []
con.close()
return ["All"] + [c for c in cats if c.strip()]
def list_products_extended(category="All", query=""):
con = sqlite3.connect(DB_PATH); cur = con.cursor()
sql = ("SELECT id,name,brand,IFNULL(category,''),IFNULL(unit,''),"
"IFNULL(mrp,price),IFNULL(sale_price,price),price,IFNULL(stock,0),"
"IFNULL(hsn,''),IFNULL(gst,0),IFNULL(description,''),IFNULL(image_path,'') FROM products")
conds=[]; params=[]
if category!="All":
conds.append("IFNULL(category,'')=?"); params.append(category)
if query.strip():
q=f"%{query.strip().lower()}%"; conds.append("(LOWER(name) LIKE ? OR LOWER(brand) LIKE ? OR LOWER(description) LIKE ?)"); params+= [q,q,q]
if conds: sql+=" WHERE "+" AND ".join(conds)
sql+=" ORDER BY id DESC"
cur.execute(sql, params); rows=cur.fetchall(); con.close()
df = pd.DataFrame(rows, columns=["ID","Name","Brand","Category","Unit","MRP","Price","Base_Price","Stock","HSN","GST%","Description","Image_Path"])
gallery=[];
for r in rows:
img=r[12]
if img and os.path.exists(img):
gallery.append((img, f"{r[1]} – ₹{r[6] or r[7]} ({r[4]})"))
return df, gallery
def add_product(name, brand, price, description, user, category="", mrp="", sale_price="", unit="", stock="0", hsn="", gst="0", image_file=None):
if not user: return "Please log in first."
if user["role"] != "dealer": return "Only dealers can add products."
try:
base_price = float(price) if price not in (None, "") else None
mrp_val = float(mrp) if mrp not in (None, "") else base_price
sale_val = float(sale_price) if sale_price not in (None, "") else base_price
stock_val = int(stock) if str(stock).strip() else 0
gst_val = float(gst) if str(gst).strip() else 0.0
except:
return "Enter valid numeric values for price/mrp/sale_price/stock/gst."
if not name or base_price is None:
return "Name and base price are required."
con = sqlite3.connect(DB_PATH); cur = con.cursor()
cur.execute("""INSERT INTO products(name,brand,price,description,created_at,category,mrp,sale_price,unit,stock,hsn,gst,image_path)
VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?)""",
(name.strip(), brand or "", base_price, description or "", datetime.datetime.utcnow().isoformat(),
category or "", mrp_val, sale_val, unit or "", stock_val, hsn or "", gst_val, ""))
pid = cur.lastrowid
img_path=""
if image_file and os.path.exists(image_file):
ext=os.path.splitext(image_file)[1].lower()
if ext not in [".png",".jpg",".jpeg",".webp"]: ext=".png"
img_dir=os.path.join(DATA_DIR,"product_images"); os.makedirs(img_dir, exist_ok=True)
img_path=os.path.join(img_dir, f"prod_{pid}_{int(time.time())}{ext}")
try: copyfile(image_file, img_path)
except Exception: img_path=""
if img_path:
cur.execute("UPDATE products SET image_path=? WHERE id=?", (img_path, pid))
con.commit(); con.close()
return f"Product added (ID: {pid})."
def add_to_cart(pid_text, qty, cart):
if not str(pid_text).strip().isdigit(): return cart, "Enter a valid Product ID.", None
try: qty=int(qty)
except: qty=0
if qty<=0: return cart, "Enter a valid quantity.", None
pid=int(pid_text)
con=sqlite3.connect(DB_PATH); cur=con.cursor()
cur.execute("SELECT id,name,IFNULL(sale_price,price) FROM products WHERE id=?", (pid,))
row=cur.fetchone(); con.close()
if not row: return cart, "Product not found.", None
cart=(cart or []) + [ {"product_id": row[0], "name": row[1], "unit_price": float(row[2] or 0), "qty": qty} ]
df,total=_cart_df(cart); return cart, "Added to cart.", f"Items: {len(cart)} | Total: ₹{total:.2f}"
def _cart_df(cart):
if not cart: return pd.DataFrame(columns=["Product_ID","Name","Unit_Price","Qty","Subtotal"]), 0.0
rows=[]; total=0.0
for it in cart:
sub=it["unit_price"]*it["qty"]; total+=sub
rows.append([it["product_id"], it["name"], it["unit_price"], it["qty"], sub])
return pd.DataFrame(rows, columns=["Product_ID","Name","Unit_Price","Qty","Subtotal"]), total
def checkout(address, delivery_label, payment_method, user, cart):
if not user: return "Please login first."
if not cart: return "Your cart is empty."
if not address: return "Address is required."
if delivery_label not in DELIVERY_OPTIONS: return "Choose delivery option."
if payment_method not in PAYMENT_METHODS: return "Choose payment method."
df, subtotal = _cart_df(cart)
fee = DELIVERY_OPTIONS[delivery_label]; total=float(subtotal+fee)
pay_status = "paid" if payment_method=="UPI (Simulated)" else "pending"
con=sqlite3.connect(DB_PATH); cur=con.cursor()
# validate stock
for _, r in df.iterrows():
cur.execute("SELECT IFNULL(stock,0) FROM products WHERE id=?", (int(r["Product_ID"]),))
stock=cur.fetchone(); stock_val=int(stock[0]) if stock else 0
if int(r["Qty"])>stock_val:
con.close(); return f"Stock insufficient for ID {int(r['Product_ID'])}: need {int(r['Qty'])}, have {stock_val}."
# create order
cur.execute("""INSERT INTO orders(user_id,total,address,delivery_option,delivery_fee,payment_method,payment_status,status,created_at)
VALUES(?,?,?,?,?,?,?,?,?)""",
(user["id"], total, address, delivery_label, fee, payment_method, pay_status, "processing",
datetime.datetime.utcnow().isoformat()))
order_id=cur.lastrowid
for _, r in df.iterrows():
cur.execute("""INSERT INTO order_items(order_id,product_id,product_name,unit_price,qty,subtotal)
VALUES(?,?,?,?,?,?)""",
(order_id, int(r["Product_ID"]), str(r["Name"]), float(r["Unit_Price"]), int(r["Qty"]), float(r["Subtotal"])))
cur.execute("UPDATE products SET stock = IFNULL(stock,0) - ? WHERE id=?", (int(r["Qty"]), int(r["Product_ID"])))
con.commit(); con.close()
return f"Order #{order_id} placed! Payment: {pay_status.upper()} | Total: ₹{total:.2f}"
def my_orders(user):
if not user: return pd.DataFrame(columns=["Order_ID","Total","Payment","Status","Created","Delivery","Address"])
con=sqlite3.connect(DB_PATH); cur=con.cursor()
cur.execute("""SELECT id,total,payment_status,status,created_at,delivery_option,address
FROM orders WHERE user_id=? ORDER BY id DESC""",(user["id"],))
rows=cur.fetchall(); con.close()
return pd.DataFrame(rows, columns=["Order_ID","Total","Payment","Status","Created","Delivery","Address"])
# ---------- UI ----------
with gr.Blocks(title="Fevicol CreatorHub") as demo:
user_state = gr.State(None)
cart_state = gr.State([])
gr.Markdown("## 🧱 Fevicol CreatorHub — Projects • Products • Orders")
# Home/About
with gr.Tab("Home / About"):
logo = gr.Image(label="Logo", type="filepath", value=get_logo_path(), interactive=False)
md = gr.Markdown(about_md())
gr.Button("Reload").click(lambda: (get_logo_path(), about_md()), None, [logo, md])
# Admin
with gr.Tab("Admin"):
gr.Markdown("### Verify users (✔), manage branding, seed products")
pin = gr.Textbox(label="Admin PIN", type="password")
email = gr.Textbox(label="User Email")
with gr.Row():
btn_v = gr.Button("Verify")
btn_u = gr.Button("Unverify")
msg = gr.Textbox(label="Status", interactive=False)
btn_v.click(lambda e,p: verify_user(e,p,True), [email,pin], [msg])
btn_u.click(lambda e,p: verify_user(e,p,False), [email,pin], [msg])
gr.Markdown("---")
tg = gr.Textbox(label="Tagline", value=(get_setting("tagline") or DEFAULT_TAGLINE))
ms = gr.Textbox(label="Mission Statement", value=(get_setting("mission") or DEFAULT_MISSION), lines=3)
up = gr.Image(label="Upload Logo", type="filepath", sources=["upload"], interactive=True)
outb = gr.Textbox(label="Branding Result", interactive=False)
def save_brand(pin, tg, ms, file):
if pin != ADMIN_PIN: return "Invalid admin PIN.", get_logo_path(), about_md()
set_setting("tagline", tg or DEFAULT_TAGLINE); set_setting("mission", ms or DEFAULT_MISSION)
if file and os.path.exists(file):
try: copyfile(file, LOGO_PATH)
except Exception as e: return f"Saved (logo copy failed: {e})", get_logo_path(), about_md()
return "Branding saved.", get_logo_path(), about_md()
gr.Button("Save Branding").click(save_brand, [pin, tg, ms, up], [outb, logo, md])
gr.Markdown("---")
out_seed_demo = gr.Textbox(label="Demo Seed Result", interactive=False)
gr.Button("Load Demo Products").click(lambda p: seed_demo(p), [pin], [out_seed_demo])
out_seed_real = gr.Textbox(label="Real Fevicol Seed Result", interactive=False)
gr.Button("Load Real Fevicol Products").click(lambda p: seed_fevicol_products(p), [pin], [out_seed_real])
# Login / Sign Up
with gr.Tab("Login / Sign Up"):
with gr.Row():
with gr.Column():
e1=gr.Textbox(label="Email"); p1=gr.Textbox(label="Password", type="password")
n1=gr.Textbox(label="Name"); r1=gr.Dropdown(["customer","designer","carpenter","dealer"], value="customer", label="Role")
c1=gr.Textbox(label="City")
out_s=gr.Textbox(label="Message", interactive=False)
def _s(e,p,n,r,c): u,m=signup(e,p,n,r,c); return u,m
gr.Button("Sign Up").click(_s, [e1,p1,n1,r1,c1], [user_state,out_s])
with gr.Column():
e2=gr.Textbox(label="Email"); p2=gr.Textbox(label="Password", type="password")
out_l = gr.Textbox(label="Message", interactive=False)
who = gr.Textbox(label="Current User", interactive=False)
def _l(e,p):
u,m=login(e,p); badge=" ✔ Fevicol Certified" if (u and u.get("is_verified")) else ""
return m, u, ((u['email']+" ("+u['role']+")"+badge) if u else "")
gr.Button("Login").click(_l, [e2,p2], [out_l, user_state, who])
# Products & Orders
with gr.Tab("Products & Orders"):
gr.Markdown("**Browse Catalog**")
with gr.Row():
cat = gr.Dropdown(choices=distinct_categories(), value="All", label="Category")
q = gr.Textbox(label="Search")
btn = gr.Button("Apply")
gallery = gr.Gallery(label="Images", show_label=True)
dfp = gr.Dataframe(interactive=False)
def _load(cat,q): df,gal = list_products_extended(cat,q); return gal, df
btn.click(_load, [cat,q], [gallery, dfp])
demo.load(_load, [cat,q], [gallery, dfp])
gr.Markdown("### Add to Cart")
with gr.Row():
pid = gr.Textbox(label="Product ID")
qty = gr.Textbox(label="Qty", value="1")
add_msg = gr.Textbox(label="Cart Status", interactive=False)
cart_summary = gr.Textbox(label="Cart Summary", interactive=False)
def _add(pid, qty_str, cart):
try: qv=int(qty_str)
except: qv=0
cart,msg,summary = add_to_cart(pid, qv, cart)
return cart, msg, summary
gr.Button("Add").click(_add, [pid, qty, cart_state], [cart_state, add_msg, cart_summary])
gr.Markdown("### Cart & Checkout")
deliv = gr.Dropdown(list(DELIVERY_OPTIONS.keys()), value="Pickup (₹0)", label="Delivery Option")
cart_df = gr.Dataframe(interactive=False); cart_tot = gr.Markdown()
def _view(cart, dlab):
df, total = _cart_df(cart or []); fee = DELIVERY_OPTIONS.get(dlab or "Pickup (₹0)", 0.0)
return df, f"Subtotal ₹{total:.2f} + Delivery ₹{fee:.2f} = **Grand Total ₹{(total+fee):.2f}**"
gr.Button("View Cart").click(_view, [cart_state, deliv], [cart_df, cart_tot])
addr = gr.Textbox(label="Delivery Address")
pay = gr.Dropdown(PAYMENT_METHODS, value="COD (Cash on Delivery)", label="Payment Method")
out_co = gr.Textbox(label="Order Status", interactive=False)
def _checkout(address, dopt, pm, user, cart):
msg = checkout(address, dopt, pm, user, cart)
return ([], msg) if msg.startswith("Order #") else (cart, msg)
gr.Button("Place Order").click(_checkout, [addr, deliv, pay, user_state, cart_state], [cart_state, out_co])
gr.Markdown("---")
gr.Markdown("### Dealer: Add Product")
with gr.Row():
pn = gr.Textbox(label="Name")
pb = gr.Textbox(label="Brand", value="Fevicol")
pc = gr.Textbox(label="Category", placeholder="Adhesives / Construction / Craft / Tools")
with gr.Row():
pmrp = gr.Textbox(label="MRP ₹")
psale = gr.Textbox(label="Sale Price ₹ (shown)")
pbase = gr.Textbox(label="Base Price ₹ (fallback)", value="0")
punit = gr.Textbox(label="Unit", placeholder="200g, 1kg, 500ml")
with gr.Row():
pstock = gr.Textbox(label="Stock Qty", value="10")
phsn = gr.Textbox(label="HSN")
pgst = gr.Textbox(label="GST %", value="18")
pd = gr.Textbox(label="Description")
pimg = gr.Image(label="Image", type="filepath", sources=["upload"], interactive=True)
out_ap = gr.Textbox(label="Status", interactive=False)
def _dealer_add(user, name, brand, cat, mrp, sale, base, unit, stock, hsn, gst, desc, img):
price_to_store = base if base not in (None,"") else (sale if sale not in (None,"") else mrp)
return add_product(name, brand, price_to_store, desc, user, category=cat, mrp=mrp, sale_price=sale, unit=unit, stock=stock, hsn=hsn, gst=gst, image_file=img)
gr.Button("Save Product").click(_dealer_add, [user_state,pn,pb,pc,pmrp,psale,pbase,punit,pstock,phsn,pgst,pd,pimg], [out_ap])
# My Orders
with gr.Tab("My Orders"):
out = gr.Dataframe(interactive=False)
gr.Button("Refresh My Orders").click(my_orders, [user_state], [out])
demo = demo
demo.launch()