143 lines
4.0 KiB
TypeScript
143 lines
4.0 KiB
TypeScript
import React, { useEffect, useState } from 'react';
|
|
import {
|
|
IonButton,
|
|
IonButtons,
|
|
IonContent,
|
|
IonHeader,
|
|
IonIcon,
|
|
IonList,
|
|
IonLoading,
|
|
IonPage,
|
|
IonText,
|
|
IonTitle,
|
|
IonToolbar,
|
|
useIonViewWillEnter,
|
|
} from '@ionic/react';
|
|
import { chevronForwardOutline, receiptOutline } from 'ionicons/icons';
|
|
import { useHistory } from 'react-router-dom';
|
|
import { supabase } from '../supabase';
|
|
import type { Tables } from '../database.types';
|
|
import {
|
|
setStatusBarBackground,
|
|
setStatusBarStyle,
|
|
Style,
|
|
} from '../utils/statusBar';
|
|
|
|
type Order = Tables<'orders'>;
|
|
|
|
const statusCopy: Record<string, string> = {
|
|
pending: 'Pending',
|
|
confirmed: 'Confirmed',
|
|
packed: 'Packed',
|
|
out_for_delivery: 'Out for delivery',
|
|
delivered: 'Delivered',
|
|
};
|
|
|
|
const MyOrders: React.FC = () => {
|
|
const history = useHistory();
|
|
const [orders, setOrders] = useState<Order[]>([]);
|
|
const [isLoading, setIsLoading] = useState(true);
|
|
const [errorMessage, setErrorMessage] = useState('');
|
|
|
|
useIonViewWillEnter(() => {
|
|
setStatusBarStyle(Style.Dark);
|
|
setStatusBarBackground('#ffffff');
|
|
});
|
|
|
|
useEffect(() => {
|
|
const loadOrders = async () => {
|
|
setIsLoading(true);
|
|
const { data, error } = await supabase
|
|
.from('orders')
|
|
.select('*')
|
|
.order('created_at', { ascending: false });
|
|
|
|
if (error) {
|
|
setErrorMessage('We could not load your orders right now.');
|
|
window.setTimeout(() => setErrorMessage(''), 4000);
|
|
setOrders([]);
|
|
setIsLoading(false);
|
|
return;
|
|
}
|
|
|
|
setOrders(data ?? []);
|
|
setIsLoading(false);
|
|
};
|
|
|
|
loadOrders();
|
|
}, []);
|
|
|
|
return (
|
|
<IonPage>
|
|
<IonHeader className="ion-no-border">
|
|
<IonToolbar>
|
|
<IonButtons slot="start">
|
|
<IonButton fill="clear" onClick={() => history.replace('/home')}>
|
|
Back
|
|
</IonButton>
|
|
</IonButtons>
|
|
<IonTitle>My Orders</IonTitle>
|
|
</IonToolbar>
|
|
</IonHeader>
|
|
<IonContent className="ion-padding">
|
|
<IonLoading isOpen={isLoading} message="Loading your orders..." />
|
|
|
|
{errorMessage && (
|
|
<IonText color="danger">
|
|
<p>{errorMessage}</p>
|
|
</IonText>
|
|
)}
|
|
|
|
{!isLoading && orders.length === 0 ? (
|
|
<div className="empty-state cart-empty">
|
|
<IonIcon icon={receiptOutline} />
|
|
<h3>No orders yet</h3>
|
|
<p className="muted-text">
|
|
Your placed orders will appear here so you can track their status.
|
|
</p>
|
|
<IonButton onClick={() => history.push('/home')}>
|
|
Start shopping
|
|
</IonButton>
|
|
</div>
|
|
) : (
|
|
<IonList lines="none" className="orders-list">
|
|
{orders.map((order) => (
|
|
<button
|
|
key={order.id}
|
|
type="button"
|
|
className="order-card"
|
|
onClick={() => history.push(`/orders/${order.id}`)}
|
|
>
|
|
<div className="order-card-top">
|
|
<div>
|
|
<span className="order-label">Order</span>
|
|
<h3>{order.order_number}</h3>
|
|
</div>
|
|
<IonIcon icon={chevronForwardOutline} />
|
|
</div>
|
|
<div className="order-card-row">
|
|
<span>Status</span>
|
|
<strong>{statusCopy[order.status] ?? order.status}</strong>
|
|
</div>
|
|
<div className="order-card-row">
|
|
<span>Items</span>
|
|
<strong>{order.item_count}</strong>
|
|
</div>
|
|
<div className="order-card-row">
|
|
<span>Total</span>
|
|
<strong>${Number(order.total).toFixed(2)}</strong>
|
|
</div>
|
|
<div className="order-card-date">
|
|
{new Date(order.created_at).toLocaleString()}
|
|
</div>
|
|
</button>
|
|
))}
|
|
</IonList>
|
|
)}
|
|
</IonContent>
|
|
</IonPage>
|
|
);
|
|
};
|
|
|
|
export default MyOrders;
|