diff options
author | Sebastian <sebasjm@gmail.com> | 2022-05-09 13:29:55 -0300 |
---|---|---|
committer | Sebastian <sebasjm@gmail.com> | 2022-05-09 13:30:22 -0300 |
commit | d5671c2ff13a9ff7c3836ba6ee9200b89d22dccc (patch) | |
tree | 7f769101220af7816783aa722c722357072ecd9e /packages | |
parent | 3beb4dc7aa430c8cd6c26f339f77b01bd4776413 (diff) | |
download | merchant-backoffice-d5671c2ff13a9ff7c3836ba6ee9200b89d22dccc.tar.gz merchant-backoffice-d5671c2ff13a9ff7c3836ba6ee9200b89d22dccc.tar.bz2 merchant-backoffice-d5671c2ff13a9ff7c3836ba6ee9200b89d22dccc.zip |
add min age in the contract terms form
Diffstat (limited to 'packages')
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 index 95045aa..9cfef07 100644 --- 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 index e481f1b..e177caf 100644 --- 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 index 377b030..6699601 100644 --- 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 index e648daa..38ac657 100644 --- 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 index 4223596..a1cd597 100644 --- 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(), }) |