merchant-backoffice

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

commit d5671c2ff13a9ff7c3836ba6ee9200b89d22dccc
parent 3beb4dc7aa430c8cd6c26f339f77b01bd4776413
Author: Sebastian <sebasjm@gmail.com>
Date:   Mon,  9 May 2022 13:29:55 -0300

add min age in the contract terms form

Diffstat:
Mpackages/merchant-backoffice/src/components/form/InputPaytoForm.tsx | 22++++++++++++++++------
Mpackages/merchant-backoffice/src/components/product/ProductForm.tsx | 9+++++++++
Mpackages/merchant-backoffice/src/declaration.d.ts | 12++++++++++++
Mpackages/merchant-backoffice/src/paths/instance/orders/create/CreatePage.tsx | 20+++++++++++++++++++-
Mpackages/merchant-backoffice/src/schemas/index.ts | 2++
5 files changed, 58 insertions(+), 7 deletions(-)

diff --git a/packages/merchant-backoffice/src/components/form/InputPaytoForm.tsx b/packages/merchant-backoffice/src/components/form/InputPaytoForm.tsx @@ -182,13 +182,15 @@ export function InputPaytoForm<T>({ } const i18n = useTranslator(); - const url = new URL(`payto://${value.target}${payToPath}`); const ops = value.options!; - Object.keys(ops).forEach((opt_key) => { - const opt_value = ops[opt_key]; - if (opt_value) url.searchParams.set(opt_key, opt_value); - }); - const paytoURL = url.toString(); + const url = tryUrl(`payto://${value.target}${payToPath}`); + if (url) { + Object.keys(ops).forEach((opt_key) => { + const opt_value = ops[opt_key]; + if (opt_value) url.searchParams.set(opt_key, opt_value); + }); + } + const paytoURL = !url ? "" : url.toString(); const errors: FormErrors<Entity> = { target: value.target === noTargetValue ? i18n`required` : undefined, @@ -380,3 +382,11 @@ export function InputPaytoForm<T>({ </InputGroup> ); } + +function tryUrl(s: string): URL | undefined { + try { + return new URL(s); + } catch (e) { + return undefined; + } +} diff --git a/packages/merchant-backoffice/src/components/product/ProductForm.tsx b/packages/merchant-backoffice/src/components/product/ProductForm.tsx @@ -100,6 +100,10 @@ export function ProductForm({ onSubscribe, initial, alreadyExist }: Props) { } delete (value as any).stock; + if (typeof value.minimum_age !== "undefined" && value.minimum_age < 1) { + delete value.minimum_age; + } + return value as MerchantBackend.Products.ProductDetail & { product_id: string; }; @@ -140,6 +144,11 @@ export function ProductForm({ onSubscribe, initial, alreadyExist }: Props) { tooltip={i18n`product description for customers`} /> <Input<Entity> + name="minimum_age" + label={i18n`Ages restricted`} + tooltip={i18n`is this product restricted for customer below certain age?`} + /> + <Input<Entity> name="unit" label={i18n`Unit`} tooltip={i18n`unit describing quantity of product sold (e.g. 2 kilograms, 5 liters, 3 items, 5 meters) for customers`} diff --git a/packages/merchant-backoffice/src/declaration.d.ts b/packages/merchant-backoffice/src/declaration.d.ts @@ -189,6 +189,9 @@ export namespace MerchantBackend { // time indicating when this product should be delivered delivery_date?: TalerProtocolTimestamp; + + // Minimum age buyer must have (in years). Default is 0. + minimum_age?: Integer; } interface Merchant { // label for a location with the business address of the merchant @@ -536,6 +539,8 @@ export namespace MerchantBackend { // Identifies when we expect the next restocking to happen. next_restock?: Timestamp; + // Minimum age buyer must have (in years). Default is 0. + minimum_age?: Integer; } // PATCH /private/products/$PRODUCT_ID interface ProductPatchDetail { @@ -577,6 +582,8 @@ export namespace MerchantBackend { // Identifies when we expect the next restocking to happen. next_restock?: Timestamp; + // Minimum age buyer must have (in years). Default is 0. + minimum_age?: Integer; } // GET /private/products @@ -633,6 +640,8 @@ export namespace MerchantBackend { // Identifies when we expect the next restocking to happen. next_restock?: Timestamp; + // Minimum age buyer must have (in years). Default is 0. + minimum_age?: Integer; } // POST /private/products/$PRODUCT_ID/lock @@ -1417,6 +1426,9 @@ export namespace MerchantBackend { // Useful when the merchant needs to store extra information on a // contract without storing it separately in their database. extra?: any; + + // Minimum age buyer must have (in years). Default is 0. + minimum_age?: Integer; } } diff --git a/packages/merchant-backoffice/src/paths/instance/orders/create/CreatePage.tsx b/packages/merchant-backoffice/src/paths/instance/orders/create/CreatePage.tsx @@ -106,6 +106,7 @@ interface Payments { max_wire_fee?: string; wire_fee_amortization?: number; createToken: boolean; + minimum_age?: number; } interface Entity { inventoryProducts: ProductMap; @@ -247,6 +248,7 @@ export function CreatePage({ : undefined, delivery_location: value.shipping.delivery_location, fulfillment_url: value.shipping.fullfilment_url, + minimum_age: value.payments.minimum_age, }, inventory_products: inventoryList.map((p) => ({ product_id: p.product.id, @@ -331,6 +333,11 @@ export function CreatePage({ totalAsString ); + const minAgeByProducts = allProducts.reduce( + (cur, prev) => + !prev.minimum_age || cur > prev.minimum_age ? cur : prev.minimum_age, + 0 + ); return ( <div> <section class="section is-main-section"> @@ -500,6 +507,16 @@ export function CreatePage({ label={i18n`Create token`} tooltip={i18n`Uncheck this option if the merchant backend generated an order ID with enough entropy to prevent adversarial claims.`} /> + <InputNumber + name="payments.minimum_age" + label={i18n`Minimum age required`} + tooltip={i18n`Any value greater than 0 will limit the coins able be used to pay this contract. If empty the age restriction will be defined by the products`} + help={ + minAgeByProducts > 0 + ? i18n`Min age defined by the producs is ${minAgeByProducts}` + : undefined + } + /> </InputGroup> <InputGroup @@ -538,7 +555,7 @@ export function CreatePage({ ); } -function asProduct(p: ProductAndQuantity) { +function asProduct(p: ProductAndQuantity): MerchantBackend.Product { return { product_id: p.product.id, image: p.product.image, @@ -547,5 +564,6 @@ function asProduct(p: ProductAndQuantity) { quantity: p.quantity, description: p.product.description, taxes: p.product.taxes, + minimum_age: p.product.minimum_age, }; } diff --git a/packages/merchant-backoffice/src/schemas/index.ts b/packages/merchant-backoffice/src/schemas/index.ts @@ -179,6 +179,7 @@ export const ProductCreateSchema = yup.object().shape({ stock: yup.object({ }).optional(), + minimum_age: yup.number().optional().positive(), }) export const ProductUpdateSchema = yup.object().shape({ @@ -189,6 +190,7 @@ export const ProductUpdateSchema = yup.object().shape({ stock: yup.object({ }).optional(), + minimum_age: yup.number().optional().positive(), })