merchant-backoffice

ZZZ: Inactive/Deprecated
Log | Files | Refs | Submodules | README

commit dd03dc5877bbeca17efb4dc5007f62a7dd90eb16
parent 2444fb8a6d3160fe2ed639207a7856f026913fd4
Author: Sebastian <sebasjm@gmail.com>
Date:   Wed, 14 Apr 2021 14:27:22 -0300

product list into the order detail

Diffstat:
Apackages/frontend/src/components/product/ProductList.tsx | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Mpackages/frontend/src/paths/instance/orders/create/CreatePage.tsx | 141+++++++++++++++++++++++++++++--------------------------------------------------
Mpackages/frontend/src/paths/instance/orders/details/DetailPage.tsx | 22++++++++++++++--------
Mpackages/frontend/src/paths/instance/products/list/index.tsx | 15+++++++++++----
Mpackages/frontend/src/utils/amount.ts | 1+
5 files changed, 127 insertions(+), 101 deletions(-)

diff --git a/packages/frontend/src/components/product/ProductList.tsx b/packages/frontend/src/components/product/ProductList.tsx @@ -0,0 +1,49 @@ +import { h } from "preact" +import { MerchantBackend } from "../../declaration" +import { multiplyPrice } from "../../utils/amount" + +interface Props { + list: MerchantBackend.Product[], + actions?: { + name: string; + handler: (d: MerchantBackend.Product, index: number) => void; + }[] +} +export function ProductList({ list, actions = [] }: Props) { + return <div class="table-container"> + <table class="table is-fullwidth is-striped is-hoverable is-fullwidth"> + <thead> + <tr> + <th>image</th> + <th>description</th> + <th>quantity</th> + <th>unit price</th> + <th>total price</th> + <th /> + </tr> + </thead> + <tbody> + {list.map((entry, index) => { + return <tr> + <td>image</td> + <td >{entry.description}</td> + <td > + {entry.quantity} {entry.unit} + </td> + <td >{entry.price}</td> + <td >{multiplyPrice(entry.price, entry.quantity)}</td> + <td class="is-actions-cell right-sticky"> + {actions.map(a => { + <div class="buttons is-right"> + <button class="button is-small is-danger jb-modal" type="button" onClick={() => a.handler(entry, index)}> + {a.name} + </button> + </div> + })} + </td> + </tr> + })} + </tbody> + </table> + </div> +} diff --git a/packages/frontend/src/paths/instance/orders/create/CreatePage.tsx b/packages/frontend/src/paths/instance/orders/create/CreatePage.tsx @@ -36,6 +36,7 @@ import { InputDate } from "../../../../components/form/InputDate"; import { useInstanceDetails } from "../../../../hooks/instance"; import { add } from "date-fns"; import { multiplyPrice, rate, subtractPrices, sumPrices } from "../../../../utils/amount"; +import { ProductList } from "../../../../components/product/ProductList"; interface Props { onCreate: (d: MerchantBackend.Orders.PostOrderRequest) => void; @@ -52,11 +53,12 @@ function with_defaults(): Entity { }; } +interface ProductAndQuantity { + product: MerchantBackend.Products.ProductDetail & WithId, + quantity: number; +} export interface ProductMap { - [id: string]: { - product: MerchantBackend.Products.ProductDetail & WithId, - quantity: number; - } + [id: string]: ProductAndQuantity; } interface Pricing { @@ -82,7 +84,7 @@ interface Entity { products: MerchantBackend.Product[], pricing: Pricing; payments: Payments; - extra:string; + extra: string; } export function CreatePage({ onCreate, onBack }: Props): VNode { @@ -103,12 +105,12 @@ export function CreatePage({ onCreate, onBack }: Props): VNode { summary: order.pricing.summary, products: productList, extra: value.extra, - pay_deadline: value.payments.pay_deadline ? { t_ms: value.payments.pay_deadline.getTime()*1000 } : undefined, - wire_transfer_deadline: value.payments.pay_deadline ? { t_ms: value.payments.pay_deadline.getTime()*1000 } : undefined, - refund_deadline: value.payments.refund_deadline ? { t_ms: value.payments.refund_deadline.getTime()*1000 } : undefined, + pay_deadline: value.payments.pay_deadline ? { t_ms: value.payments.pay_deadline.getTime() * 1000 } : undefined, + wire_transfer_deadline: value.payments.pay_deadline ? { t_ms: value.payments.pay_deadline.getTime() * 1000 } : undefined, + refund_deadline: value.payments.refund_deadline ? { t_ms: value.payments.refund_deadline.getTime() * 1000 } : undefined, max_fee: value.payments.max_fee, max_wire_fee: value.payments.max_wire_fee, - delivery_date: value.payments.delivery_date ? { t_ms: value.payments.delivery_date.getTime()*1000 } : undefined, + delivery_date: value.payments.delivery_date ? { t_ms: value.payments.delivery_date.getTime() * 1000 } : undefined, delivery_location: value.payments.delivery_location, }, inventory_products: inventoryList.map(p => ({ @@ -116,6 +118,7 @@ export function CreatePage({ onCreate, onBack }: Props): VNode { quantity: p.quantity })), } + onCreate(request); } catch (err) { const errors = err.inner as yup.ValidationError[] @@ -185,6 +188,7 @@ export function CreatePage({ onCreate, onBack }: Props): VNode { const discountOrRise = rate(value.pricing.order_price, totalPrice) + useEffect(() => { valueHandler(v => { return ({ @@ -201,7 +205,7 @@ export function CreatePage({ onCreate, onBack }: Props): VNode { useEffect(() => { if (details_response.ok) { valueHandler(v => { - const defaultPayDeadline = !details_response.data.default_pay_delay || details_response.data.default_pay_delay.d_ms === "forever" ? undefined : add(new Date(), {seconds: details_response.data.default_pay_delay.d_ms/1000}) + const defaultPayDeadline = !details_response.data.default_pay_delay || details_response.data.default_pay_delay.d_ms === "forever" ? undefined : add(new Date(), { seconds: details_response.data.default_pay_delay.d_ms / 1000 }) return ({ ...v, payments: { ...v.payments, @@ -235,41 +239,13 @@ export function CreatePage({ onCreate, onBack }: Props): VNode { onAddProduct={addProductToTheInventoryList} /> - {inventoryList.length > 0 && <div class="table-container"> - <table class="table is-fullwidth is-striped is-hoverable is-fullwidth"> - <thead> - <tr> - <th>image</th> - <th>description</th> - <th>quantity</th> - <th>unit price</th> - <th>total price</th> - <th /> - </tr> - </thead> - <tbody> - {inventoryList.map((entry, index) => { - return <tr> - <td>image</td> - <td >{entry.product.description}</td> - <td > - {entry.quantity} {entry.product.unit} - </td> - <td >{entry.product.price}</td> - <td >{multiplyPrice(entry.product.price, entry.quantity)}</td> - <td class="is-actions-cell right-sticky"> - <div class="buttons is-right"> - <button class="button is-small is-danger jb-modal" type="button" onClick={(): void => removeProductFromTheInventoryList(entry.product.id)}> - Remove - </button> - </div> - </td> - </tr> - })} - - </tbody> - </table> - </div>} + {inventoryList.length > 0 && + <ProductList list={inventoryList.map(asProduct)} + actions={[{ + name: 'Remove', handler: (e) => removeProductFromTheInventoryList(e.product_id!) + }]} + /> + } </InputGroup> <InputGroup name="products" alternative={ @@ -283,46 +259,22 @@ export function CreatePage({ onCreate, onBack }: Props): VNode { setEditingProduct(undefined) addNewProduct(p) }} /> - {productList.length > 0 && <div class="table-container"> - <table class="table is-fullwidth is-striped is-hoverable is-fullwidth"> - <thead> - <tr> - <th>image</th> - <th>description</th> - <th>quantity</th> - <th>unit price</th> - <th>total price</th> - <th /> - </tr> - </thead> - <tbody> - {productList.map((entry, index) => { - return <tr> - <td>image</td> - <td >{entry.description}</td> - <td > - {entry.quantity} {entry.unit} - </td> - <td >{entry.price}</td> - <td >{multiplyPrice(entry.price, entry.quantity)}</td> - <td class="is-actions-cell right-sticky"> - <div class="buttons is-right"> - <button class="button is-small is-success jb-modal" type="button" onClick={(): void => { - removeFromNewProduct(index) - setEditingProduct(entry) - }}> - Edit - </button> - <button class="button is-small is-danger jb-modal" type="button" onClick={(): void => removeFromNewProduct(index)}> - Remove - </button> - </div> - </td> - </tr> - })} - </tbody> - </table> - </div>} + + {productList.length > 0 && + <ProductList list={productList} + actions={[{ + name: 'Update', handler: (e, index) => { + removeFromNewProduct(index); + setEditingProduct(e); + } + }, { + name: 'Remove', handler: (e, index) => { + removeFromNewProduct(index); + } + }]} + /> + + } </InputGroup> <FormProvider<Entity> errors={errors} object={value} valueHandler={valueHandler as any}> @@ -343,14 +295,13 @@ export function CreatePage({ onCreate, onBack }: Props): VNode { <Input name="pricing.summary" inputType="multiline" /> - <InputGroup name="payments"> <InputDate name="payments.auto_refund_deadline" /> <InputDate name="payments.refund_deadline" /> <InputDate name="payments.pay_deadline" /> <InputDate name="payments.delivery_date" /> - { value.payments.delivery_date && <InputGroup name="payments.delivery_location" > + {value.payments.delivery_date && <InputGroup name="payments.delivery_location" > <Input name="payments.delivery_location.country" /> <Input name="payments.delivery_location.address_lines" inputType="multiline" toStr={(v: string[] | undefined) => !v ? '' : v.join('\n')} @@ -364,13 +315,14 @@ export function CreatePage({ onCreate, onBack }: Props): VNode { <Input name="payments.delivery_location.town" /> <Input name="payments.delivery_location.district" /> <Input name="payments.delivery_location.country_subdivision" /> - </InputGroup> } + </InputGroup>} <InputCurrency name="payments.max_fee" currency={config.currency} /> <InputCurrency name="payments.max_wire_fee" currency={config.currency} /> <Input name="payments.wire_fee_amortization" /> <Input name="payments.fullfilment_url" /> </InputGroup> + <InputGroup name="extra"> <Input name="extra" inputType="multiline" /> </InputGroup> @@ -389,4 +341,14 @@ export function CreatePage({ onCreate, onBack }: Props): VNode { </div> } - +function asProduct(p: ProductAndQuantity) { + return ({ + product_id: p.product.id, + image: p.product.image, + price: p.product.price, + unit: p.product.unit, + quantity: p.quantity, + description: p.product.description, + taxes: p.product.taxes + }) +} +\ No newline at end of file diff --git a/packages/frontend/src/paths/instance/orders/details/DetailPage.tsx b/packages/frontend/src/paths/instance/orders/details/DetailPage.tsx @@ -32,6 +32,7 @@ import { format } from "date-fns"; import { Event, Timeline } from "./Timeline"; import { RefundModal } from "../list/Table"; import { mergeRefunds } from "../../../../utils/amount"; +import { ProductList } from "../../../../components/product/ProductList"; type Entity = MerchantBackend.Orders.MerchantOrderStatusResponse; interface Props { @@ -162,14 +163,9 @@ function ClaimedPage({ id, order }: { id: string; order: MerchantBackend.Orders. <section class="section"> <div class="columns"> - <div class="column is-2" /> - <div class="column is-8" > - <div class="title">Payment details</div> - <FormProvider<Claimed> errors={errors} object={value} valueHandler={valueHandler} > - <Input name="contract_terms.summary" readonly inputType="multiline" /> - <InputCurrency name="contract_terms.amount" readonly currency={config.currency} /> - <Input<Claimed> name="order_status" readonly /> - </FormProvider> + <div class="column is-12" > + <div class="title">Product list</div> + <ProductList list={order.contract_terms.products} /> </div> <div class="column" /> </div> @@ -324,6 +320,16 @@ function PaidPage({ id, order, onRefund }: { id: string; order: MerchantBackend. </div> </section> + {order.contract_terms.products.length ? <section class="section"> + <div class="columns"> + <div class="column is-12" > + <div class="title">Product list</div> + <ProductList list={order.contract_terms.products} /> + </div> + <div class="column" /> + </div> + </section> :undefined } + </div> <div class="column" /> </div> diff --git a/packages/frontend/src/paths/instance/products/list/index.tsx b/packages/frontend/src/paths/instance/products/list/index.tsx @@ -20,11 +20,9 @@ */ import { h, VNode } from 'preact'; -import { create } from 'yup/lib/Reference'; -import { HttpError, HttpResponseServerError, RequestInfo } from '../../../../hooks/backend'; +import { HttpError } from '../../../../hooks/backend'; import { useProductAPI } from "../../../../hooks/product"; import { CardTable } from './Table'; -import logo from '../../../../assets/logo.jpeg'; import { useConfigContext } from '../../../../context/backend'; import { MerchantBackend, WithId } from '../../../../declaration'; import { Loading } from '../../../../components/exception/loading'; @@ -92,7 +90,16 @@ export default function ({ onUnauthorized, onLoadError, onCreate, onSelect, onNo })) } onSelect={(product) => onSelect(product.id)} - onDelete={(prod: (MerchantBackend.Products.ProductDetail & WithId)) => deleteProduct(prod.id)} + onDelete={(prod: (MerchantBackend.Products.ProductDetail & WithId)) => deleteProduct(prod.id) + .then(() => setNotif({ + message: 'product delete successfully', + type: "SUCCESS" + })).catch((error) => setNotif({ + message: 'could not delete the product', + type: "ERROR", + description: error.message + })) + } /> </section> } \ No newline at end of file diff --git a/packages/frontend/src/utils/amount.ts b/packages/frontend/src/utils/amount.ts @@ -57,6 +57,7 @@ export const rate = (one?: string, two?: string) => { const intOne = parseInt(valueOne, 10) const intTwo = parseInt(valueTwo, 10) if (!intTwo) return intOne + if (!intOne) return 0 return intOne / intTwo }