From b783e7219cc6ee4ae60301f560e2edf6cc44a489 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Thu, 30 Sep 2021 18:39:32 -0300 Subject: new show template and mustache example --- packages/backend/package.json | 5 +- packages/backend/render-examples.ts | 83 ++++++ packages/backend/render-mustache.js | 18 -- packages/backend/src/hooks/transfer.ts | 4 +- .../backend/src/pages/ShowOrderDetails.examples.ts | 219 +++++++++++++++ .../backend/src/pages/ShowOrderDetails.stories.tsx | 111 +------- packages/backend/src/pages/ShowOrderDetails.tsx | 302 +++++++++++++++++---- .../backend/tests/__mocks__/fileTransformer.js | 2 +- 8 files changed, 559 insertions(+), 185 deletions(-) create mode 100644 packages/backend/render-examples.ts delete mode 100644 packages/backend/render-mustache.js create mode 100644 packages/backend/src/pages/ShowOrderDetails.examples.ts (limited to 'packages') diff --git a/packages/backend/package.json b/packages/backend/package.json index f84c238..2593b1c 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -5,14 +5,14 @@ "license": "MIT", "scripts": { "build": "rollup -c", - "compile": "tsc", "dev": "rollup -c -w", + "render-examples": "ts-node -O '{\"module\": \"commonjs\"}' -T render-examples.ts dist/pages dist/examples", "lint-check": "eslint '{src,tests}/**/*.{js,jsx,ts,tsx}'", "lint-fix": "eslint --fix '{src,tests}/**/*.{js,jsx,ts,tsx}'", "test": "jest ./tests", "dev-test": "jest ./tests --watch", "typedoc": "typedoc src", - "clean": "rimraf build storybook-static docs single", + "clean": "rimraf build storybook-static docs single dist", "serve-dist": "sirv --port ${PORT:=8080} --cors --single dist", "build-storybook": "build-storybook", "storybook": "start-storybook -p 6006" @@ -83,6 +83,7 @@ "@types/history": "^4.7.8", "@types/jest": "^26.0.23", "@types/mocha": "^8.2.2", + "@types/mustache": "^4.1.2", "@typescript-eslint/eslint-plugin": "^4.22.0", "@typescript-eslint/parser": "^4.22.0", "babel-loader": "^8.2.2", diff --git a/packages/backend/render-examples.ts b/packages/backend/render-examples.ts new file mode 100644 index 0000000..c1da3ce --- /dev/null +++ b/packages/backend/render-examples.ts @@ -0,0 +1,83 @@ +/* + This file is part of GNU Taler + (C) 2021 Taler Systems S.A. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see + */ + +/** +* +* @author Sebastian Javier Marchano (sebasjm) +*/ + +import mustache from "mustache"; +import fs from "fs"; +import { format, formatDuration, intervalToDuration } from "date-fns"; + +/** + * This script will emulate what the merchant backend will do when being requested + * +*/ + +const sourceDirectory = process.argv[2] +const destDirectory = process.argv[3] + +if (!sourceDirectory || !destDirectory) { + console.log('usage: render-mustache ') + process.exit(1); +} + +if (!fs.existsSync(destDirectory)) { + fs.mkdirSync(destDirectory); +} + +/** + * Load all the html files + */ +const files = fs.readdirSync(sourceDirectory).filter(f => /.html/.test(f)) + +files.forEach(file => { + const html = fs.readFileSync(`${sourceDirectory}/${file}`, 'utf8') + + const testName = file.replace('.html', '') + if (testName !== 'ShowOrderDetails') return; + // eslint-disable-next-line @typescript-eslint/no-var-requires + const { exampleData } = require(`./src/pages/${testName}.examples`) + + Object.keys(exampleData).forEach(exampleName => { + const example = exampleData[exampleName] + + //enhance the example with more information + example.contract_terms_json = () => JSON.stringify(example.contract_terms); + example.contract_terms.timestamp_str = () => example.contract_terms.timestamp && format(example.contract_terms.timestamp.t_ms, 'dd MMM yyyy HH:mm:ss'); + + example.contract_terms.hasProducts = () => example.contract_terms.products?.length > 0; + example.contract_terms.hasAuditors = () => example.contract_terms.auditors?.length > 0; + example.contract_terms.hasExchanges = () => example.contract_terms.exchanges?.length > 0; + + example.contract_terms.products.forEach(p => { + p.delivery_date_str = () => p.delivery_date && format(p.delivery_date.t_ms, 'dd MM yyyy HH:mm:ss') + p.hasTaxes = () => p.taxes?.length > 0 + }) + example.contract_terms.has_delivery_info = () => example.contract_terms.delivery_date || example.contract_terms.delivery_location + + example.contract_terms.delivery_date_str = () => example.contract_terms.delivery_date && format(example.contract_terms.delivery_date.t_ms, 'dd MM yyyy HH:mm:ss') + example.contract_terms.pay_deadline_str = () => example.contract_terms.pay_deadline && format(example.contract_terms.pay_deadline.t_ms, 'dd MM yyyy HH:mm:ss') + example.contract_terms.wire_transfer_deadline_str = () => example.contract_terms.wire_transfer_deadline && format(example.contract_terms.wire_transfer_deadline.t_ms, 'dd MM yyyy HH:mm:ss') + example.contract_terms.refund_deadline_str = () => example.contract_terms.refund_deadline && format(example.contract_terms.refund_deadline.t_ms, 'dd MM yyyy HH:mm:ss') + example.contract_terms.auto_refund_str = () => example.contract_terms.auto_refund && formatDuration(intervalToDuration({ start: 0, end: example.contract_terms.auto_refund.d_ms })) + + const output = mustache.render(html, example); + + fs.writeFileSync(`${destDirectory}/${testName}.${exampleName}.html`, output) + }) +}) diff --git a/packages/backend/render-mustache.js b/packages/backend/render-mustache.js deleted file mode 100644 index 74b68dd..0000000 --- a/packages/backend/render-mustache.js +++ /dev/null @@ -1,18 +0,0 @@ -const mustache = require('mustache') -const fs = require('fs') - -const htmlFile = process.argv[2] -const exampleJson = process.argv[3] - -if (!htmlFile || !exampleJson) { - console.log('usage: render-mustache ') - return 1 -} - -const html = fs.readFileSync(htmlFile, 'utf8') -const json = fs.readFileSync(exampleJson, 'utf8') -const example = JSON.parse(json) - -const output = mustache.render(html, example); - -console.log(output) diff --git a/packages/backend/src/hooks/transfer.ts b/packages/backend/src/hooks/transfer.ts index 02e041a..482f00d 100644 --- a/packages/backend/src/hooks/transfer.ts +++ b/packages/backend/src/hooks/transfer.ts @@ -124,7 +124,7 @@ export function useInstanceTransfers(args?: InstanceTransferFilter, updatePositi if (afterData.data.transfers.length < MAX_RESULT_SIZE) { setPageAfter(pageAfter + 1) } else { - const from = ""+afterData.data.transfers[afterData.data.transfers.length - 1].transfer_serial_id + const from = `${afterData.data.transfers[afterData.data.transfers.length - 1].transfer_serial_id}` if (from && updatePosition) updatePosition(from) } }, @@ -133,7 +133,7 @@ export function useInstanceTransfers(args?: InstanceTransferFilter, updatePositi if (beforeData.data.transfers.length < MAX_RESULT_SIZE) { setPageBefore(pageBefore + 1) } else if (beforeData) { - const from = ""+beforeData.data.transfers[beforeData.data.transfers.length - 1].transfer_serial_id + const from = `${beforeData.data.transfers[beforeData.data.transfers.length - 1].transfer_serial_id}` if (from && updatePosition) updatePosition(from) } }, diff --git a/packages/backend/src/pages/ShowOrderDetails.examples.ts b/packages/backend/src/pages/ShowOrderDetails.examples.ts new file mode 100644 index 0000000..8d76900 --- /dev/null +++ b/packages/backend/src/pages/ShowOrderDetails.examples.ts @@ -0,0 +1,219 @@ +/* + This file is part of GNU Taler + (C) 2021 Taler Systems S.A. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see + */ + +/** +* +* @author Sebastian Javier Marchano (sebasjm) +*/ + +import { MerchantBackend } from '../declaration'; +import { Props } from './ShowOrderDetails'; + + +const defaultContractTerms: MerchantBackend.ContractTerms = { + order_id: 'XRS8876388373', + amount: 'USD:10', + summary: 'this is a short summary', + pay_deadline: { + t_ms: new Date().getTime() + 6 * 24 * 60 * 60 * 1000 + }, + merchant: { + name: 'the merchant (inc)', + address: { + country_subdivision: 'Buenos Aires', + town: 'CABA', + country: 'Argentina' + }, + jurisdiction: { + country_subdivision: 'Cordoba', + town: 'Capital', + country: 'Argentina' + }, + }, + max_fee: 'USD:0.1', + max_wire_fee: 'USD:0.2', + wire_fee_amortization: 1, + products: [], + timestamp: { + t_ms: new Date().getTime() + }, + auditors: [], + exchanges: [], + h_wire: '', + merchant_base_url: 'http://merchant.base.url/', + merchant_pub: 'QWEASDQWEASD', + nonce: 'NONCE', + refund_deadline: { + t_ms: new Date().getTime() + 6 * 24 * 60 * 60 * 1000 + }, + wire_method: 'x-taler-bank', + wire_transfer_deadline: { + t_ms: new Date().getTime() + 3 * 24 * 60 * 60 * 1000 + }, +}; + +const inSixDays = new Date().getTime() + 6 * 24 * 60 * 60 * 1000 +const in10Minutes = new Date().getTime() + 10 * 60 * 1000 +const in15Minutes = new Date().getTime() + 15 * 60 * 1000 +const in20Minutes = new Date().getTime() + 20 * 60 * 1000 + +export const exampleData: { [name: string]: Props } = { + Simplest: { + order_summary: 'here goes the order summary', + contract_terms: defaultContractTerms, + }, + WithRefundAmount: { + order_summary: 'here goes the order summary', + refund_amount: 'USD:10', + contract_terms: defaultContractTerms, + }, + WithDeliveryDate: { + order_summary: 'here goes the order summary', + contract_terms: { + ...defaultContractTerms, + delivery_date: { + t_ms: inSixDays + }, + }, + }, + WithDeliveryLocation: { + order_summary: 'here goes the order summary', + contract_terms: { + ...defaultContractTerms, + delivery_location: { + address_lines: ['addr line 1', 'addr line 2', 'addr line 3', 'addr line 4', 'addr line 5', 'addr line 6', 'addr line 7'], + building_name: 'building-name', + building_number: 'building-number', + country: 'country', + country_subdivision: 'country sub', + district: 'district', + post_code: 'post-code', + street: 'street', + town: 'town', + town_location: 'town loc', + }, + }, + }, + WithDeliveryLocationAndDate: { + order_summary: 'here goes the order summary', + contract_terms: { + ...defaultContractTerms, + delivery_location: { + address_lines: ['addr1', 'addr2', 'addr3', 'addr4', 'addr5', 'addr6', 'addr7'], + building_name: 'building-name', + building_number: 'building-number', + country: 'country', + country_subdivision: 'country sub', + district: 'district', + post_code: 'post-code', + street: 'street', + town: 'town', + town_location: 'town loc', + }, + delivery_date: { + t_ms: inSixDays + }, + }, + }, + WithThreeProducts: { + order_summary: 'here goes the order summary', + contract_terms: { + ...defaultContractTerms, + products: [{ + description: 'description of the first product', + price: '5:USD', + quantity: 1, + delivery_date: { t_ms: in10Minutes }, + product_id: '12333', + }, { + description: 'another description', + price: '10:USD', + quantity: 5, + unit: 't-shirt', + }, { + description: 'one last description', + price: '10:USD', + quantity: 5 + }] + } as MerchantBackend.ContractTerms + }, + WithProductWithTaxes: { + order_summary: 'here goes the order summary', + contract_terms: { + ...defaultContractTerms, + products: [{ + description: 'description of the first product', + price: '5:USD', + quantity: 1, + unit: 'beer', + delivery_date: { t_ms: in10Minutes }, + product_id: '456', + taxes: [{ + name: 'VAT', tax: 'USD:1' + }], + }, { + description: 'one last description', + price: '10:USD', + quantity: 5, + product_id: '123', + unit: 'beer', + taxes: [{ + name: 'VAT', tax: 'USD:1' + }], + }] + } as MerchantBackend.ContractTerms + }, + WithExchangeList: { + order_summary: 'here goes the order summary', + contract_terms: { + ...defaultContractTerms, + exchanges: [{ + master_pub: 'ABCDEFGHIJKLMNO', + url: 'http://exchange0.taler.net' + }, { + master_pub: 'AAAAAAAAAAAAAAA', + url: 'http://exchange1.taler.net' + }, { + master_pub: 'BBBBBBBBBBBBBBB', + url: 'http://exchange2.taler.net' + }] + }, + }, + WithAuditorList: { + order_summary: 'here goes the order summary', + contract_terms: { + ...defaultContractTerms, + auditors: [{ + auditor_pub: 'ABCDEFGHIJKLMNO', + name: 'the USD auditor', + url: 'http://auditor-usd.taler.net' + }, { + auditor_pub: 'OPQRSTUVWXYZABCD', + name: 'the EUR auditor', + url: 'http://auditor-eur.taler.net' + }] + }, + }, + WithAutoRefund: { + order_summary: 'here goes the order summary', + contract_terms: { + ...defaultContractTerms, + auto_refund: { + d_ms: 1000 * 60 * 60 * 26 + 1000 * 60 * 30 + } + }, + }, +} diff --git a/packages/backend/src/pages/ShowOrderDetails.stories.tsx b/packages/backend/src/pages/ShowOrderDetails.stories.tsx index 616af7f..6a902cc 100644 --- a/packages/backend/src/pages/ShowOrderDetails.stories.tsx +++ b/packages/backend/src/pages/ShowOrderDetails.stories.tsx @@ -20,8 +20,8 @@ */ import { FunctionalComponent, h } from 'preact'; -import { MerchantBackend } from '../declaration'; -import { Props, ShowOrderDetails as TestedComponent } from './ShowOrderDetails'; +import { ShowOrderDetails as TestedComponent } from './ShowOrderDetails'; +import { exampleData } from './ShowOrderDetails.examples'; export default { title: 'ShowOrderDetails', @@ -37,110 +37,13 @@ function createExample(Component: FunctionalComponent, props: Part return r } -const defaultContractTerms: MerchantBackend.ContractTerms = { - order_id: 'XRS8876388373', - amount: 'USD:10', - summary: 'this is a short summary', - pay_deadline: { - t_ms: new Date().getTime() + 6 * 24 * 60 * 60 * 1000 - }, - merchant: { - name: 'the merchant (inc)', - address: {}, - jurisdiction: {}, - }, - max_fee: '', - max_wire_fee: '', - wire_fee_amortization: 1, - products: [], - timestamp: { - t_ms: new Date().getTime() - }, - auditors: [], - exchanges: [], - h_wire: '', - merchant_base_url : '://merchant.base.url/', - merchant_pub: 'QWEASDQWEASD', - nonce: 'NONCE', - refund_deadline: { - t_ms: new Date().getTime() + 6 * 24 * 60 * 60 * 1000 - }, - wire_method: 'x-taler-bank', - wire_transfer_deadline: { - t_ms: new Date().getTime() + 3 * 24 * 60 * 60 * 1000 - } -}; - - -export const exampleData: { [name: string]: Props } = { - Simplest: { - order_summary: 'here goes the order summary', - contract_terms: defaultContractTerms, - }, - WithRefundAmount: { - order_summary: 'here goes the order summary', - refund_amount: 'USD:10', - contract_terms: defaultContractTerms, - }, - WithDeliveryDate: { - order_summary: 'here goes the order summary', - contract_terms: { - ...defaultContractTerms, - delivery_date: { - t_ms: new Date().getTime() + 6 * 24 * 60 * 60 * 1000 - } - }, - }, - WithDeliveryLocation: { - order_summary: 'here goes the order summary', - contract_terms: { - ...defaultContractTerms, - delivery_location: { - address_lines: ['addr1', 'addr2', 'addr3', 'addr4', 'addr5', 'addr6', 'addr7'], - building_name: 'building-name', - building_number: 'building-number', - country: 'country', - country_subdivision: 'country sub', - district: 'district', - post_code: 'post-code', - street: 'street', - town: 'town', - town_location: 'town loc', - }, - }, - }, - WithThreeProducts: { - order_summary: 'here goes the order summary', - contract_terms: { - order_id: 'XRS8876388373', - amount: 'USD:10', - summary: 'this is a short summary', - pay_deadline: { - t_ms: new Date().getTime() + 6 * 24 * 60 * 60 * 1000 - }, - merchant: { - name: 'the merchant (inc)' - }, - products: [{ - description: 'description of the first product', - price: '5:USD', - quantity: 1, - delivery_date: { t_ms: new Date().getTime() } - }, { - description: 'another description', - price: '10:USD', - quantity: 5, - }, { - description: 'one last description', - price: '10:USD', - quantity: 5 - }] - } as MerchantBackend.ContractTerms - }, -} - export const Simplest = createExample(TestedComponent, exampleData.Simplest); export const WithRefundAmount = createExample(TestedComponent, exampleData.WithRefundAmount); export const WithDeliveryDate = createExample(TestedComponent, exampleData.WithDeliveryDate); export const WithDeliveryLocation = createExample(TestedComponent, exampleData.WithDeliveryLocation); +export const WithDeliveryLocationAndDate = createExample(TestedComponent, exampleData.WithDeliveryLocationAndDate); export const WithThreeProducts = createExample(TestedComponent, exampleData.WithThreeProducts); +export const WithAuditorList = createExample(TestedComponent, exampleData.WithAuditorList); +export const WithExchangeList = createExample(TestedComponent, exampleData.WithExchangeList); +export const WithAutoRefund = createExample(TestedComponent, exampleData.WithAutoRefund); +export const WithProductWithTaxes = createExample(TestedComponent, exampleData.WithProductWithTaxes); diff --git a/packages/backend/src/pages/ShowOrderDetails.tsx b/packages/backend/src/pages/ShowOrderDetails.tsx index b791c91..43b730c 100644 --- a/packages/backend/src/pages/ShowOrderDetails.tsx +++ b/packages/backend/src/pages/ShowOrderDetails.tsx @@ -18,8 +18,8 @@ * * @author Sebastian Javier Marchano (sebasjm) */ -import { Product } from '@gnu-taler/taler-util'; -import { format } from 'date-fns'; +import { format, formatDuration } from 'date-fns'; +import { intervalToDuration } from 'date-fns/esm'; import { Fragment, h, render, VNode } from 'preact'; import { render as renderToString } from 'preact-render-to-string'; import { Footer } from '../components/Footer'; @@ -59,11 +59,54 @@ function Head({ order_summary }: { order_summary?: string }): VNode { Status of your order for {order_summary ? order_summary : `{{ order_summary }}`} + + +} + +function Location({ templateName, location, btr }: { templateName: string, location: MerchantBackend.Location | undefined, btr?: boolean }) { + //FIXME: mustache strings show be constructed in a way that ends in the final output of the html but is not present in the + // javascript code, otherwise when mustache render engine run over the html it will also replace string in the javascript code + // that is made to run when the browser has javascript enable leading into undefined behavior. + // that's why in the next fields we are using concatenations to build the mustache placeholder. + return + {btr && `{{`+`#${templateName}.building_name}}`} +
{location?.building_name || (btr && `{{ ${templateName}.building_name }}`)} {location?.building_number || (btr && `{{ ${templateName}.building_number }}`)}
+ {btr && `{{`+`/${templateName}.building_name}}`} + + {btr && `{{`+`#${templateName}.country}}`} +
{location?.country || (btr && `{{ ${templateName}.country }}`)} {location?.country_subdivision || (btr && `{{ ${templateName}.country_subdivision }}`)}
+ {btr && `{{`+`/${templateName}.country}}`} + + {btr && `{{`+`#${templateName}.district}}`} +
{location?.district || (btr && `{{ ${templateName}.district }}`)}
+ {btr && `{{`+`/${templateName}.district}}`} + + {btr && `{{`+`#${templateName}.post_code}}`} +
{location?.post_code || (btr && `{{ ${templateName}.post_code }}`)}
+ {btr && `{{`+`/${templateName}.post_code}}`} + + {btr && `{{`+`#${templateName}.street}}`} +
{location?.street || (btr && `{{ ${templateName}.street }}`)}
+ {btr && `{{`+`/${templateName}.street}}`} + + {btr && `{{`+`#${templateName}.town}}`} +
{location?.town || (btr && `{{ ${templateName}.town }}`)}
+ {btr && `{{`+`/${templateName}.town}}`} + + {btr && `{{`+`#${templateName}.town_location}}`} +
{location?.town_location || (btr && `{{ ${templateName}.town_location }}`)}
+ {btr && `{{`+`/${templateName}.town_location}}`}
} export function ShowOrderDetails({ order_summary, refund_amount, contract_terms, btr }: Props): VNode { - const productList = (btr ? [{} as Product] : (contract_terms?.products || [])) + const productList = (btr ? [{} as MerchantBackend.Product] : (contract_terms?.products || [])) + const auditorsList = (btr ? [{} as MerchantBackend.Auditor] : (contract_terms?.auditors || [])) + const exchangesList = (btr ? [{} as MerchantBackend.Exchange] : (contract_terms?.exchanges || [])) + const hasDeliveryInfo = btr || !!contract_terms?.delivery_date || !!contract_terms?.delivery_location + return

Details of order {contract_terms?.order_id || `{{ contract_terms.order_id }}`}

@@ -84,72 +127,46 @@ export function ShowOrderDetails({ order_summary, refund_amount, contract_terms,
{contract_terms?.summary || `{{ contract_terms.summary }}`}
Amount paid:
{contract_terms?.amount || `{{ contract_terms.amount }}`}
+
Order date:
+
{contract_terms?.timestamp ? + (contract_terms?.timestamp.t_ms != 'never' ? + format(contract_terms?.timestamp.t_ms, 'dd MMM yyyy HH:mm:ss') : + 'never') + : `{{ contract_terms.timestamp_str }}`}
Merchant name:
{contract_terms?.merchant.name || `{{ contract_terms.merchant.name }}`}
- - {btr && `{{#contract_terms.delivery_location}}`} - {(btr || contract_terms?.delivery_location) && -
Delivery address:
- - {btr && `{{#contract_terms.delivery_location.building_name}}`} -
{contract_terms?.delivery_location?.building_name || `{{ contract_terms.delivery_location.building_name }}`} {contract_terms?.delivery_location?.building_number || `{{ contract_terms.delivery_location.building_number }}`}
- {btr && `{{/contract_terms.delivery_location.building_name}}`} - - {btr && `{{#contract_terms.delivery_location.country}}`} -
{contract_terms?.delivery_location?.country || `{{ contract_terms.delivery_location.country }}`} {contract_terms?.delivery_location?.country_subdivision || `{{ contract_terms.delivery_location.country_subdivision }}`}
- {btr && `{{/contract_terms.delivery_location.country}}`} - - {btr && `{{#contract_terms.delivery_location.district}}`} -
{contract_terms?.delivery_location?.district || `{{ contract_terms.delivery_location.district }}`}
- {btr && `{{/contract_terms.delivery_location.district}}`} - - {btr && `{{#contract_terms.delivery_location.post_code}}`} -
{contract_terms?.delivery_location?.post_code || `{{ contract_terms.delivery_location.post_code }}`}
- {btr && `{{/contract_terms.delivery_location.post_code}}`} - - {btr && `{{#contract_terms.delivery_location.street}}`} -
{contract_terms?.delivery_location?.street || `{{ contract_terms.delivery_location.street }}`}
- {btr && `{{/contract_terms.delivery_location.street}}`} - - {btr && `{{#contract_terms.delivery_location.town}}`} -
{contract_terms?.delivery_location?.town || `{{ contract_terms.delivery_location.town }}`}
- {btr && `{{/contract_terms.delivery_location.town}}`} - - {btr && `{{#contract_terms.delivery_location.town_location}}`} -
{contract_terms?.delivery_location?.town_location || `{{ contract_terms.delivery_location.town_location }}`}
- {btr && `{{/contract_terms.delivery_location.town_location}}`} -
} - {btr && `{{/contract_terms.delivery_location}}`} - - {btr && `{{#contract_terms.delivery_date}}`} - {(btr || contract_terms?.delivery_date) && -
Delivery date:
-
{contract_terms?.delivery_date ? - (contract_terms?.delivery_date.t_ms != 'never' ? - format(contract_terms?.delivery_date.t_ms, 'dd MMM yyyy HH:mm:ss') : - 'never') - : `{{ contract_terms.delivery_date }}`}
- -
} - {btr && `{{/contract_terms.delivery_date}}`} - {btr && `{{#contract_terms.products.0}}`} + {btr && `{{#contract_terms.hasProducts}}`} {!productList.length ? null :

Products purchased

- {btr && `{{#contract_terms.products}}`} + {btr && '{{' + '#contract_terms.products' + '}}'} {productList.map((p, i) => { + const taxList = (btr ? [{} as MerchantBackend.Tax] : (p.taxes || [])) + return

{p.description || `{{description}}`}

- -
Amount:
-
{p.quantity || `{{description}}`}
+
Quantity:
+
{p.quantity || `{{quantity}}`}
Price:
-
{p.price || `{{quantity}}`}
+
{p.price || `{{price}}`}
+ + {btr && `{{#hasTaxes}}`} + {!taxList.length ? null : + {btr && '{{' + '#taxes' + '}}'} + {taxList.map((t, i) => { + return +
{t.name || `{{name}}`}
+
{t.tax || `{{tax}}`}
+
+ })} + {btr && '{{' + '/taxes' + '}}'} +
} + {btr && `{{/hasTaxes}}`} {btr && `{{#delivery_date}}`} {(btr || p.delivery_date) && @@ -158,18 +175,181 @@ export function ShowOrderDetails({ order_summary, refund_amount, contract_terms, (p.delivery_date.t_ms != 'never' ? format(p.delivery_date.t_ms, 'dd MMM yyyy HH:mm:ss') : 'never') - : `{{ delivery_date }}`} + : `{{ delivery_date_str }}`} } {btr && `{{/delivery_date}}`} + {btr && `{{#unit}}`} + {(btr || p.unit) && +
Product unit:
+
{p.unit || `{{.}}`}
+
} + {btr && `{{/unit}}`} + + {btr && `{{#product_id}}`} + {(btr || p.product_id) && +
Product ID:
+
{p.product_id || `{{.}}`}
+
} + {btr && `{{/product_id}}`} +
})} - {btr && `{{/contract_terms.products}}`} + {btr && '{{' + '/contract_terms.products' + '}}'}
} - {btr && `{{/contract_terms.products.0}}`} + {btr && `{{/contract_terms.hasProducts}}`} + + + {btr && `{{#contract_terms.has_delivery_info}}`} + {!hasDeliveryInfo ? null :
+

Delivery information

+ + {btr && `{{#contract_terms.delivery_date}}`} + {(btr || contract_terms?.delivery_date) && +
Delivery date:
+
{contract_terms?.delivery_date ? + (contract_terms?.delivery_date.t_ms != 'never' ? + format(contract_terms?.delivery_date.t_ms, 'dd MMM yyyy HH:mm:ss') : + 'never') + : `{{ contract_terms.delivery_date_str }}`}
+ +
} + {btr && `{{/contract_terms.delivery_date}}`} + + {btr && `{{#contract_terms.delivery_location}}`} + {(btr || contract_terms?.delivery_location) && +
Delivery address:
+ +
} + {btr && `{{/contract_terms.delivery_location}}`} +
+
} + {btr && `{{/contract_terms.has_delivery_info}}`} + +
+

Full payment information

+ +
Amount paid:
+
{contract_terms?.amount || `{{ contract_terms.amount }}`}
+
Wire transfer method:
+
{contract_terms?.wire_method || `{{ contract_terms.wire_method }}`}
+
Payment deadline:
+
{contract_terms?.pay_deadline ? + (contract_terms?.pay_deadline.t_ms != 'never' ? + format(contract_terms?.pay_deadline.t_ms, 'dd MMM yyyy HH:mm:ss') : + 'never') + : `{{ contract_terms.pay_deadline_str }}`}
+
Exchange transfer deadline:
+
{contract_terms?.wire_transfer_deadline ? + (contract_terms?.wire_transfer_deadline.t_ms != 'never' ? + format(contract_terms?.wire_transfer_deadline.t_ms, 'dd MMM yyyy HH:mm:ss') : + 'never') + : `{{ contract_terms.wire_transfer_deadline_str }}`}
+
Maximum deposit fee:
+
{contract_terms?.max_fee || `{{ contract_terms.max_fee }}`}
+
Maximum wire fee:
+
{contract_terms?.max_wire_fee || `{{ contract_terms.max_wire_fee }}`}
+
Wire fee amortization:
+
{contract_terms?.wire_fee_amortization || `{{ contract_terms.wire_fee_amortization }}`} transactions
+
+
+ +
+

Refund information

+ +
Refund deadline:
+
{contract_terms?.refund_deadline ? + (contract_terms?.refund_deadline.t_ms != 'never' ? + format(contract_terms?.refund_deadline.t_ms, 'dd MMM yyyy HH:mm:ss') : + 'never') + : `{{ contract_terms.refund_deadline_str }}`}
+ + {btr && `{{#contract_terms.auto_refund}}`} + {(btr || contract_terms?.auto_refund) && +
Attempt autorefund for:
+
{contract_terms?.auto_refund ? + (contract_terms?.auto_refund.d_ms != 'forever' ? + formatDuration(intervalToDuration({ start: 0, end: contract_terms?.auto_refund.d_ms })) : + 'forever') + : `{{ contract_terms.auto_refund_str }}`}
+
} + {btr && `{{/contract_terms.auto_refund}}`} +
+
+ +
+

Additional order details

+ +
Public reorder URL:
+
-- not defined yet --
+ {btr && `{{#contract_terms.fulfillment_url}}`} + {(btr || contract_terms?.fulfillment_url) && +
Fulfillment URL:
+
{contract_terms?.fulfillment_url || (btr && `{{ contract_terms.fulfillment_url }}`)}
+
} + {btr && `{{/contract_terms.fulfillment_url}}`} + {/*
Fulfillment message:
+
-- not defined yet --
*/} +
+
+ +
+

Full merchant information

+ +
Merchant name:
+
{contract_terms?.merchant.name || `{{ contract_terms.merchant.name }}`}
+
Merchant address:
+ +
Merchant's jurisdiction:
+ +
Merchant URI:
+
{contract_terms?.merchant_base_url || `{{ contract_terms.merchant_base_url }}`}
+
Merchant's public key:
+
{contract_terms?.merchant_pub || `{{ contract_terms.merchant_pub }}`}
+ {/*
Merchant's hash:
+
-- not defined yet --
*/} +
+
+ + {btr && `{{#contract_terms.hasAuditors}}`} + {!auditorsList.length ? null :
+

Auditors accepted by the merchant

+ + {btr && '{{' + '#contract_terms.auditors' + '}}'} + {auditorsList.map((p, i) => { + return +

{p.name || `{{name}}`}

+
Auditor's public key:
+
{p.auditor_pub || `{{auditor_pub}}`}
+
Auditor's URL:
+
{p.url || `{{url}}`}
+
+ })} + {btr && '{{' + '/contract_terms.auditors' + '}}'} +
+
} + {btr && `{{/contract_terms.hasAuditors}}`} + + {btr && `{{#contract_terms.hasExchanges}}`} + {!exchangesList.length ? null :
+

Exchanges accepted by the merchant

+ + {btr && '{{' + '#contract_terms.exchanges' + '}}'} + {exchangesList.map((p, i) => { + return +
Exchange's URL:
+
{p.url || `{{url}}`}
+
Public key:
+
{p.master_pub || `{{master_pub}}`}
+
+ })} + {btr && '{{' + '/contract_terms.exchanges' + '}}'} +
+
} + {btr && `{{/contract_terms.hasExchanges}}`}