New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[CHEC-1009] Customer account page #149
Changes from all commits
e4b459b
ad78d6d
2734323
cb94d13
cc0c43c
647051b
615442e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,264 @@ | ||
import React, { useState, useEffect } from 'react'; | ||
import { useRouter } from 'next/router'; | ||
import commerce from '../../lib/commerce'; | ||
import Head from 'next/head'; | ||
import Link from 'next/link'; | ||
import Root from '../../components/common/Root'; | ||
import Footer from '../../components/common/Footer'; | ||
import moment from 'moment'; | ||
import { useSelector } from 'react-redux' | ||
|
||
export default function SingleOrderPage() { | ||
const router = useRouter(); | ||
const { id } = router.query; | ||
const [data, setData] = useState(null); | ||
const [loading, setLoading] = useState(true); | ||
const [error, setError] = useState(null); | ||
const customer = useSelector(state => state.customer) | ||
|
||
useEffect(() => { | ||
const fetchOrderById = async (id) => { | ||
try { | ||
const order = await commerce.customer.getOrder(id, customer.id); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you want to store these in Redux instead, so they'll persist between pages and avoid refetching? |
||
|
||
setLoading(false); | ||
setData(order.data); | ||
} catch (err) { | ||
setLoading(false); | ||
setError(err?.message); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this operator supported enough to use yet? If our transpiler supports it then all good, otherwise it's not supported in IE which is a good reason not to use it in this repository |
||
} | ||
}; | ||
|
||
fetchOrderById(id); | ||
}, [id]); | ||
|
||
/** | ||
* Create order date if available | ||
*/ | ||
const OrderDate = ({ date: data }) => { | ||
if (!data) { | ||
return null; | ||
} | ||
|
||
const date = moment.unix(data); | ||
|
||
if (!date.isValid) { | ||
return null | ||
} | ||
return ( | ||
<small><strong>Ordered placed on:</strong> { moment(date).format('MMM Do Y') }</small> | ||
) | ||
}; | ||
|
||
/** | ||
* Create thumbnail if available | ||
*/ | ||
const ImageThumb = ({ image: data }) => { | ||
if (!data.media) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<img className="img-thumbnail h-72 mr-4" alt={data.product_name} src={data.media.source} /> | ||
) | ||
}; | ||
|
||
/** | ||
* Create the billing card | ||
*/ | ||
const BillingAddress = ({ address: data }) => { | ||
if (data.length === 0) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<div> | ||
<h5>Billing address</h5> | ||
<div className="card p-2 mb-4"> | ||
<div> | ||
<div><strong>{ data.name }</strong></div> | ||
<div>{ data.street }</div> | ||
<div>{ data.town_city}{(data.town_city && data.county_state) ? ',':'' } { data.county_state }</div> | ||
<div>{ data.country}{(data.town_city && data.county_state) ? ',':'' } { data.postal_zip_code }</div> | ||
</div> | ||
</div> | ||
</div> | ||
) | ||
}; | ||
|
||
/** | ||
* Create the shipping card | ||
*/ | ||
const ShippingAddress = ({ address: data }) => { | ||
if (data.length === 0) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<div> | ||
<h5>Shipping address</h5> | ||
<div className="card p-2"> | ||
<div> | ||
<div><strong>{ data.name }</strong></div> | ||
<div>{ data.street }</div> | ||
<div>{ data.town_city}{(data.town_city && data.county_state) ? ',':'' } { data.county_state }</div> | ||
<div>{ data.country}{(data.town_city && data.county_state) ? ',':'' } { data.postal_zip_code }</div> | ||
</div> | ||
</div> | ||
</div> | ||
) | ||
}; | ||
|
||
/** | ||
* Create error/loading page | ||
*/ | ||
const TemplatePage = ({ page: data }) => { | ||
return ( | ||
<Root> | ||
<Head> | ||
<title>commerce</title> | ||
</Head> | ||
<div className="py-5 my-5 text-center"> | ||
<h4 className="mt-4">{ data.message }</h4> | ||
</div> | ||
<Footer /> | ||
</Root> | ||
) | ||
}; | ||
|
||
/** | ||
* Render a page if an error occured | ||
*/ | ||
if (error) { | ||
return <TemplatePage page={ {message: 'Sorry something went wrong.'} } /> | ||
} | ||
|
||
/** | ||
* Render loading state | ||
*/ | ||
if (loading) { | ||
return <TemplatePage page={ {message: 'Loading'} } /> | ||
} | ||
|
||
/** | ||
* Render a page if no order found | ||
*/ | ||
if (!data) { | ||
return <TemplatePage page={ {message: 'Sorry we cannot find an order witht that number, if you think this is in error please contact us!'} } /> | ||
} | ||
|
||
/** | ||
* If no errors, return the order page. | ||
*/ | ||
return ( | ||
<Root> | ||
<Head> | ||
<title>{ data.customer_reference } | commerce</title> | ||
</Head> | ||
<div className="account-container"> | ||
<div className="custom-container py-5 my-4 my-sm-5"> | ||
<div className="row mt-4"> | ||
<div className="col-12"> | ||
{/* Breadcrumbs */} | ||
<div className="d-flex pb-4 breadcrumb-container"> | ||
<Link href="/account"> | ||
<div className="font-size-caption text-decoration-underline cursor-pointer"> | ||
Account | ||
</div> | ||
</Link> | ||
<img src="/icon/arrow-right.svg" className="w-16 mx-1" alt="Arrow icon"/> | ||
<div className="font-size-caption font-weight-bold cursor-pointer"> | ||
{ data.customer_reference } | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
<div className="row mt-5 pt-5"> | ||
<div className="col-12"> | ||
<h2 className="font-size-header mb-4 pt-5 text-center"> | ||
Order: #{ data.customer_reference } | ||
</h2> | ||
{alert} | ||
</div> | ||
</div> | ||
<div className="row mt-5 pt-5"> | ||
<div className="col-12 col-md-8 col-lg-8"> | ||
<div className="d-flex flex-row justify-content-between"> | ||
<h5>Items</h5> | ||
<OrderDate date={data.created}/> | ||
</div> | ||
<table className="table table-bordered"> | ||
<thead> | ||
<tr> | ||
<th>Product</th> | ||
<th>Price</th> | ||
<th>Quantity</th> | ||
<th>Total</th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
{ data.order.line_items.map((item) => { | ||
return ( | ||
<tr key={ item.id }> | ||
<td> | ||
<ImageThumb image={item}/> | ||
{ item.product_name } | ||
</td> | ||
<td>{ item.price.formatted_with_symbol }</td> | ||
<td>{ item.quantity }</td> | ||
<td>{ item.line_total.formatted_with_symbol }</td> | ||
</tr> | ||
) | ||
})} | ||
</tbody> | ||
<tfoot> | ||
<tr> | ||
<td colSpan="3" className="border-right-0"> | ||
Subtotal | ||
</td> | ||
<td className="border-left-0 text-right"> | ||
{ data.order.subtotal.formatted_with_symbol} | ||
</td> | ||
</tr> | ||
<tr> | ||
<td colSpan="3" className="border-right-0"> | ||
Shipping | ||
</td> | ||
<td className="border-left-0 text-right"> | ||
{ data.order.shipping.price.formatted_with_symbol} | ||
</td> | ||
</tr> | ||
<tr> | ||
<td colSpan="3" className="border-right-0"> | ||
Tax | ||
</td> | ||
<td className="border-left-0 text-right"> | ||
{ data.order.tax.amount.formatted_with_symbol} | ||
</td> | ||
</tr> | ||
<tr> | ||
<td colSpan="3" className="border-right-0"> | ||
<strong> | ||
Total | ||
</strong> | ||
</td> | ||
<td className="border-left-0 text-right"> | ||
<strong> | ||
{ data.order.total.formatted_with_symbol} | ||
</strong> | ||
</td> | ||
</tr> | ||
</tfoot> | ||
</table> | ||
</div> | ||
<div className="col-12 col-md-4 col-lg-4 row-content"> | ||
<BillingAddress address={data.billing} /> | ||
<ShippingAddress address={data.shipping} /> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
<Footer /> | ||
</Root> | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The rest of this repository uses components, it feels weird to me to move away from that in one place. Can you please refactor this so it uses components instead?