391 lines
14 KiB
Python
391 lines
14 KiB
Python
"""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() |