Initial commit
This commit is contained in:
391
customer_portal/portal.py
Normal file
391
customer_portal/portal.py
Normal file
@@ -0,0 +1,391 @@
|
||||
"""Customer Portal - Track orders and receive updates."""
|
||||
import streamlit as st
|
||||
from datetime import datetime, timedelta
|
||||
import time
|
||||
|
||||
|
||||
# Page configuration
|
||||
st.set_page_config(
|
||||
page_title="LogiFlow - Track Your Order",
|
||||
page_icon="📦",
|
||||
layout="centered"
|
||||
)
|
||||
|
||||
# Custom CSS
|
||||
st.markdown("""
|
||||
<style>
|
||||
.tracking-header {
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
border-radius: 15px;
|
||||
color: white;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.timeline-item {
|
||||
padding: 15px;
|
||||
border-left: 3px solid #667eea;
|
||||
margin-left: 20px;
|
||||
position: relative;
|
||||
}
|
||||
.timeline-item::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: -10px;
|
||||
top: 20px;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
background: #667eea;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.status-badge {
|
||||
display: inline-block;
|
||||
padding: 5px 15px;
|
||||
border-radius: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.status-confirmed { background: #22c55e; color: white; }
|
||||
.status-picked { background: #3b82f6; color: white; }
|
||||
.status-transit { background: #f59e0b; color: white; }
|
||||
.status-delivered { background: #10b981; color: white; }
|
||||
.order-card {
|
||||
background: #f8fafc;
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
margin: 10px 0;
|
||||
border: 1px solid #e2e8f0;
|
||||
}
|
||||
</style>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
|
||||
def render_tracking_header():
|
||||
"""Render the tracking page header."""
|
||||
st.markdown("""
|
||||
<div class="tracking-header">
|
||||
<h1>📦 LogiFlow</h1>
|
||||
<p>AI-Powered Logistics Tracking</p>
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
|
||||
def render_order_search():
|
||||
"""Render order search form."""
|
||||
st.markdown("### 🔍 Track Your Order")
|
||||
|
||||
col1, col2 = st.columns([3, 1])
|
||||
with col1:
|
||||
order_id = st.text_input(
|
||||
"Enter Order ID",
|
||||
placeholder="ORD-20240605-ABC12345",
|
||||
label_visibility="collapsed"
|
||||
)
|
||||
with col2:
|
||||
search_btn = st.button("🔎 Track", use_container_width=True)
|
||||
|
||||
return order_id, search_btn
|
||||
|
||||
|
||||
def render_tracking_timeline():
|
||||
"""Render tracking timeline."""
|
||||
st.markdown("### 📍 Delivery Progress")
|
||||
|
||||
# Sample tracking data
|
||||
events = [
|
||||
{"time": "2 hours ago", "status": "Out for Delivery", "location": "Andheri West, Mumbai", "desc": "Your package is out for delivery"},
|
||||
{"time": "5 hours ago", "status": "Arrived at Hub", "location": "Mumbai West Hub", "desc": "Package arrived at sorting facility"},
|
||||
{"time": "8 hours ago", "status": "In Transit", "location": "Delhi Sorting Center", "desc": "Package on the way to Mumbai"},
|
||||
{"time": "12 hours ago", "status": "Picked Up", "location": "Connaught Place, Delhi", "desc": "Package picked up by driver"},
|
||||
{"time": "1 day ago", "status": "Order Confirmed", "location": "System", "desc": "Order placed and confirmed"},
|
||||
]
|
||||
|
||||
for i, event in enumerate(events):
|
||||
is_completed = i == 0 # Latest is highlighted
|
||||
|
||||
st.markdown(f"""
|
||||
<div class="timeline-item" style="{'border-left-color: #22c55e;' if is_completed else ''}">
|
||||
<p style="color: #888; margin: 0;">{event['time']}</p>
|
||||
<h4 style="margin: 5px 0; color: {'#22c55e' if is_completed else '#1a1a1a'};">{event['status']}</h4>
|
||||
<p style="margin: 5px 0; color: #666;">📍 {event['location']}</p>
|
||||
<p style="margin: 5px 0; color: #888; font-size: 14px;">{event['desc']}</p>
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
|
||||
def render_order_details():
|
||||
"""Render order details."""
|
||||
st.markdown("### 📋 Order Details")
|
||||
|
||||
col1, col2 = st.columns(2)
|
||||
|
||||
with col1:
|
||||
st.markdown("""
|
||||
<div class="order-card">
|
||||
<h4>📍 Delivery Address</h4>
|
||||
<p><strong>Rajesh Kumar</strong></p>
|
||||
<p>402, Sunshine Apartments</p>
|
||||
<p>Andheri West, Mumbai - 400053</p>
|
||||
<p>📞 +919876543210</p>
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
with col2:
|
||||
st.markdown("""
|
||||
<div class="order-card">
|
||||
<h4>📦 Package Details</h4>
|
||||
<p><strong>3 items</strong></p>
|
||||
<p>• Wireless Headphones</p>
|
||||
<p>• Phone Case</p>
|
||||
<p>• Screen Protector</p>
|
||||
<p>Total Weight: 0.8 kg</p>
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
st.markdown("""
|
||||
<div class="order-card" style="text-align: center;">
|
||||
<h4>⏱️ Estimated Delivery</h4>
|
||||
<p style="font-size: 24px; color: #667eea; margin: 10px 0;">Today, 4:00 PM - 6:00 PM</p>
|
||||
<p style="color: #888;">On schedule - No delays expected</p>
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
|
||||
def render_delivery_partner():
|
||||
"""Render delivery partner info."""
|
||||
st.markdown("### 🚴 Delivery Partner")
|
||||
|
||||
col1, col2, col3 = st.columns([1, 2, 1])
|
||||
|
||||
with col1:
|
||||
st.markdown("""
|
||||
<div style="text-align: center;">
|
||||
<span style="font-size: 48px;">👤</span>
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
with col2:
|
||||
st.markdown("""
|
||||
<div class="order-card">
|
||||
<h4>Arun Sharma</h4>
|
||||
<p style="color: #888;">Delivery Executive</p>
|
||||
<p>🛵 Two-wheeler | MH 14 AB 1234</p>
|
||||
<p>⭐ 4.8 rating (1,234 deliveries)</p>
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
with col3:
|
||||
st.write("")
|
||||
st.write("")
|
||||
if st.button("📞 Call", use_container_width=True):
|
||||
st.info("Calling Arun Sharma...")
|
||||
if st.button("💬 Chat", use_container_width=True):
|
||||
st.info("Opening chat...")
|
||||
|
||||
|
||||
def render_ai_assistant():
|
||||
"""Render AI assistant chat."""
|
||||
st.markdown("### 🤖 AI Assistant")
|
||||
|
||||
# Initialize chat history
|
||||
if "messages" not in st.session_state:
|
||||
st.session_state.messages = [
|
||||
{"role": "assistant", "content": "Hi! I'm your LogiFlow AI assistant. How can I help you today?"}
|
||||
]
|
||||
|
||||
# Display chat history
|
||||
for msg in st.session_state.messages:
|
||||
if msg["role"] == "user":
|
||||
st.markdown(f"""
|
||||
<div style="background: #667eea; color: white; padding: 10px 15px; border-radius: 15px 15px 0 15px; margin: 10px 0; margin-left: 50px;">
|
||||
{msg['content']}
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
else:
|
||||
st.markdown(f"""
|
||||
<div style="background: #f1f5f9; padding: 10px 15px; border-radius: 15px 15px 15px 0; margin: 10px 0; margin-right: 50px;">
|
||||
🤖 {msg['content']}
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
# Chat input
|
||||
if prompt := st.chat_input("Ask me anything about your order..."):
|
||||
st.session_state.messages.append({"role": "user", "content": prompt})
|
||||
|
||||
# AI response
|
||||
if "where" in prompt.lower() or "track" in prompt.lower():
|
||||
response = "Your order is currently out for delivery and should arrive by 4:00 PM today. You can see the live location on the map above!"
|
||||
elif "delay" in prompt.lower() or "late" in prompt.lower():
|
||||
response = "Good news! Your order is on schedule with no delays. The estimated delivery time remains 4:00 PM - 6:00 PM today."
|
||||
elif "cancel" in prompt.lower():
|
||||
response = "I understand you want to cancel. Unfortunately, your order is already out for delivery, so cancellation is no longer possible. Would you like me to reschedule the delivery instead?"
|
||||
elif "hello" in prompt.lower() or "hi" in prompt.lower():
|
||||
response = "Hello! I'm here to help you track your order and answer any questions. Your package is doing great and should arrive soon! 📦"
|
||||
else:
|
||||
response = "I'm here to help! You can ask me about:\n- 📍 Current location of your order\n- ⏱️ Estimated delivery time\n- 📋 Order details\n- 🚚 Delivery partner info\n- ❓ Any other questions!"
|
||||
|
||||
st.session_state.messages.append({"role": "assistant", "content": response})
|
||||
st.rerun()
|
||||
|
||||
|
||||
def render_map_placeholder():
|
||||
"""Render map placeholder."""
|
||||
st.markdown("### 🗺️ Live Tracking Map")
|
||||
|
||||
st.markdown("""
|
||||
<div style="background: #e2e8f0; height: 300px; border-radius: 12px; display: flex; align-items: center; justify-content: center; flex-direction: column;">
|
||||
<span style="font-size: 64px;">🗺️</span>
|
||||
<p style="color: #666; margin-top: 10px;">Live tracking map</p>
|
||||
<p style="color: #888; font-size: 14px;">Your delivery partner is currently at:</p>
|
||||
<p style="color: #667eea; font-size: 18px; font-weight: bold;">📍 Andheri Metro Station, 2.3 km away</p>
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
|
||||
def render_quick_actions():
|
||||
"""Render quick action buttons."""
|
||||
st.markdown("### ⚡ Quick Actions")
|
||||
|
||||
col1, col2, col3, col4 = st.columns(4)
|
||||
|
||||
with col1:
|
||||
if st.button("📍 Track Order", use_container_width=True):
|
||||
st.info("Opening tracking view...")
|
||||
|
||||
with col2:
|
||||
if st.button("📞 Call Support", use_container_width=True):
|
||||
st.info("Connecting to support...")
|
||||
|
||||
with col3:
|
||||
if st.button("🔄 Reschedule", use_container_width=True):
|
||||
st.warning("This will open the reschedule form")
|
||||
|
||||
with col4:
|
||||
if st.button("❓ Help", use_container_width=True):
|
||||
st.info("Opening help center...")
|
||||
|
||||
|
||||
def render_delivery_schedule():
|
||||
"""Render delivery schedule."""
|
||||
st.markdown("### 📅 Reschedule Delivery")
|
||||
|
||||
with st.expander("Change Delivery Time"):
|
||||
st.write("**Select a new delivery slot:**")
|
||||
|
||||
col1, col2, col3 = st.columns(3)
|
||||
with col1:
|
||||
st.write("**Today**")
|
||||
if st.button("2:00 PM - 4:00 PM", use_container_width=True):
|
||||
st.success("Delivery rescheduled to 2:00 PM - 4:00 PM today")
|
||||
if st.button("6:00 PM - 8:00 PM", use_container_width=True):
|
||||
st.success("Delivery rescheduled to 6:00 PM - 8:00 PM today")
|
||||
|
||||
with col2:
|
||||
st.write("**Tomorrow**")
|
||||
if st.button("9:00 AM - 12:00 PM", use_container_width=True):
|
||||
st.success("Delivery rescheduled to tomorrow 9:00 AM - 12:00 PM")
|
||||
if st.button("2:00 PM - 6:00 PM", use_container_width=True):
|
||||
st.success("Delivery rescheduled to tomorrow 2:00 PM - 6:00 PM")
|
||||
|
||||
with col3:
|
||||
st.write("**Custom**")
|
||||
custom_date = st.date_input("Select Date", datetime.now() + timedelta(days=1))
|
||||
custom_time = st.time_input("Select Time", datetime.now().time())
|
||||
if st.button("Apply Custom Schedule", use_container_width=True):
|
||||
st.success(f"Delivery rescheduled to {custom_date} at {custom_time}")
|
||||
|
||||
|
||||
def render_feedback():
|
||||
"""Render feedback section."""
|
||||
st.markdown("### ⭐ Rate Your Experience")
|
||||
|
||||
col1, col2, col3, col4, col5 = st.columns(5)
|
||||
|
||||
ratings = ["😞", "😐", "🙂", "😊", "🤩"]
|
||||
selected = st.feedback(options="faces")
|
||||
|
||||
if selected is not None:
|
||||
st.success(f"Thank you for your {ratings[selected]} feedback!")
|
||||
|
||||
|
||||
def render_notifications():
|
||||
"""Render notification preferences."""
|
||||
st.markdown("### 🔔 Notification Preferences")
|
||||
|
||||
col1, col2 = st.columns(2)
|
||||
|
||||
with col1:
|
||||
st.checkbox("📱 SMS Notifications", value=True)
|
||||
st.checkbox("📧 Email Updates", value=True)
|
||||
|
||||
with col2:
|
||||
st.checkbox("💬 WhatsApp Updates", value=True)
|
||||
st.checkbox("🔔 Push Notifications", value=True)
|
||||
|
||||
|
||||
def main():
|
||||
"""Main customer portal function."""
|
||||
|
||||
# Tabs
|
||||
tab1, tab2, tab3, tab4 = st.tabs(["📍 Track", "📋 Details", "💬 Help", "⚙️ Settings"])
|
||||
|
||||
with tab1:
|
||||
render_tracking_header()
|
||||
order_id, search = render_order_search()
|
||||
|
||||
if order_id or search:
|
||||
render_map_placeholder()
|
||||
render_tracking_timeline()
|
||||
render_quick_actions()
|
||||
render_delivery_schedule()
|
||||
render_ai_assistant()
|
||||
|
||||
with tab2:
|
||||
st.header("📋 Order Details")
|
||||
render_order_details()
|
||||
render_delivery_partner()
|
||||
|
||||
with tab3:
|
||||
st.header("💬 Help & Support")
|
||||
|
||||
st.markdown("### Frequently Asked Questions")
|
||||
|
||||
with st.expander("📦 Where is my order?"):
|
||||
st.write("Your order is currently out for delivery. Use the tracking tab above to see real-time location updates.")
|
||||
|
||||
with st.expander("⏱️ When will my order arrive?"):
|
||||
st.write("Expected delivery is today between 4:00 PM - 6:00 PM. You can track the exact location in real-time.")
|
||||
|
||||
with st.expander("🔄 Can I reschedule delivery?"):
|
||||
st.write("Yes! You can reschedule your delivery to any available time slot. Go to the Track tab and use the reschedule option.")
|
||||
|
||||
with st.expander("❌ Can I cancel my order?"):
|
||||
st.write("Cancellation is possible only before the order is dispatched. Once out for delivery, you can reschedule instead.")
|
||||
|
||||
with st.expander("📞 How do I contact support?"):
|
||||
st.write("You can call our 24/7 support at 1800-123-4567 or use the in-app chat for instant assistance.")
|
||||
|
||||
st.markdown("### Contact Us")
|
||||
st.write("📞 1800-123-4567 (Toll Free)")
|
||||
st.write("📧 support@logiflow.ai")
|
||||
st.write("💬 Chat with us (Available 24/7)")
|
||||
|
||||
with tab4:
|
||||
st.header("⚙️ Settings")
|
||||
|
||||
st.markdown("### 📱 Communication Preferences")
|
||||
render_notifications()
|
||||
|
||||
st.markdown("### 🔐 Account")
|
||||
st.write("**Email:** rajesh@example.com")
|
||||
st.write("**Phone:** +919876543210")
|
||||
st.write("**Member since:** January 2024")
|
||||
|
||||
if st.button("✏️ Edit Profile"):
|
||||
st.info("Profile editing coming soon!")
|
||||
|
||||
if st.button("🚪 Sign Out"):
|
||||
st.warning("Sign out functionality coming soon!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user