From 21fda5751d61594ee94d995232f0ce66647533b2 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Tue, 24 Oct 2023 09:41:53 -0300 Subject: better template UI --- .../paths/instance/templates/create/CreatePage.tsx | 92 +++++++++++++++---- .../paths/instance/templates/update/UpdatePage.tsx | 100 +++++++++++++++++---- 2 files changed, 158 insertions(+), 34 deletions(-) (limited to 'packages/merchant-backoffice-ui/src/paths') diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx index 78ea07477..947f3572c 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx @@ -41,8 +41,16 @@ import { useBackendContext } from "../../../../context/backend.js"; import { MerchantBackend } from "../../../../declaration.js"; import { useInstanceOtpDevices } from "../../../../hooks/otp.js"; import { undefinedIfEmpty } from "../../../../utils/table.js"; +import { InputTab } from "../../../../components/form/InputTab.js"; -type Entity = MerchantBackend.Template.TemplateAddDetails; +enum Steps { + BOTH_FIXED, + FIXED_PRICE, + FIXED_SUMMARY, + NON_FIXED, +} + +type Entity = MerchantBackend.Template.TemplateAddDetails & { type: Steps }; interface Props { onCreate: (d: Entity) => Promise; @@ -61,6 +69,7 @@ export function CreatePage({ onCreate, onBack }: Props): VNode { d_us: 1000 * 1000 * 60 * 30, //30 min }, }, + type: Steps.NON_FIXED, }); const parsedPrice = !state.template_contract?.amount @@ -79,13 +88,20 @@ export function CreatePage({ onCreate, onBack }: Props): VNode { template_contract: !state.template_contract ? undefined : undefinedIfEmpty({ - amount: !state.template_contract?.amount + amount: !(state.type === Steps.FIXED_PRICE || state.type === Steps.BOTH_FIXED) ? undefined - : !parsedPrice - ? i18n.str`not valid` - : Amounts.isZero(parsedPrice) - ? i18n.str`must be greater than 0` - : undefined, + : !state.template_contract?.amount + ? i18n.str`required` + : !parsedPrice + ? i18n.str`not valid` + : Amounts.isZero(parsedPrice) + ? i18n.str`must be greater than 0` + : undefined, + summary: !(state.type === Steps.FIXED_SUMMARY || state.type === Steps.BOTH_FIXED) + ? undefined + : !state.template_contract?.summary + ? i18n.str`required` + : undefined, minimum_age: state.template_contract.minimum_age < 0 ? i18n.str`should be greater that 0` @@ -106,6 +122,17 @@ export function CreatePage({ onCreate, onBack }: Props): VNode { const submitForm = () => { if (hasErrors) return Promise.reject(); + if (state.template_contract) { + if (state.type === Steps.NON_FIXED) { + delete state.template_contract.amount; + delete state.template_contract.summary; + } else if (state.type === Steps.FIXED_SUMMARY) { + delete state.template_contract.amount; + } else if (state.type === Steps.FIXED_PRICE) { + delete state.template_contract.summary; + } + } + delete state.type return onCreate(state as any); }; @@ -134,17 +161,48 @@ export function CreatePage({ onCreate, onBack }: Props): VNode { help="" tooltip={i18n.str`Describe what this template stands for`} /> - - { + switch (state.type) { + case Steps.NON_FIXED: return i18n.str`User will be able to input price and summary before payment.` + case Steps.FIXED_PRICE: return i18n.str`User will be able to add a summary before payment.` + case Steps.FIXED_SUMMARY: return i18n.str`User will be able to set the price before payment.` + case Steps.BOTH_FIXED: return i18n.str`User will not be able to change the price or the summary.` + } + })()} + tooltip={i18n.str`Define what the user be allowed to modify`} + values={[ + Steps.NON_FIXED, + Steps.FIXED_PRICE, + Steps.FIXED_SUMMARY, + Steps.BOTH_FIXED, + ]} + toStr={(v: Steps): string => { + switch (v) { + case Steps.NON_FIXED: return i18n.str`Simple` + case Steps.FIXED_PRICE: return i18n.str`With price` + case Steps.FIXED_SUMMARY: return i18n.str`With summary` + case Steps.BOTH_FIXED: return i18n.str`With price and summary` + } + }} /> + {state.type === Steps.BOTH_FIXED || state.type === Steps.FIXED_SUMMARY ? + + : undefined} + {state.type === Steps.BOTH_FIXED || state.type === Steps.FIXED_PRICE ? + + : undefined} >(template); + const intialStep = + template.template_contract?.amount === undefined && template.template_contract?.summary === undefined + ? Steps.NON_FIXED + : template.template_contract?.summary === undefined + ? Steps.FIXED_PRICE + : template.template_contract?.amount === undefined + ? Steps.FIXED_SUMMARY + : Steps.BOTH_FIXED; + + const [state, setState] = useState>({ ...template, type: intialStep }); const parsedPrice = !state.template_contract?.amount ? undefined @@ -65,13 +82,20 @@ export function UpdatePage({ template, onUpdate, onBack }: Props): VNode { template_contract: !state.template_contract ? undefined : undefinedIfEmpty({ - amount: !state.template_contract?.amount + amount: !(state.type === Steps.FIXED_PRICE || state.type === Steps.BOTH_FIXED) ? undefined - : !parsedPrice - ? i18n.str`not valid` - : Amounts.isZero(parsedPrice) - ? i18n.str`must be greater than 0` - : undefined, + : !state.template_contract?.amount + ? i18n.str`required` + : !parsedPrice + ? i18n.str`not valid` + : Amounts.isZero(parsedPrice) + ? i18n.str`must be greater than 0` + : undefined, + summary: !(state.type === Steps.FIXED_SUMMARY || state.type === Steps.BOTH_FIXED) + ? undefined + : !state.template_contract?.summary + ? i18n.str`required` + : undefined, minimum_age: state.template_contract.minimum_age < 0 ? i18n.str`should be greater that 0` @@ -92,6 +116,17 @@ export function UpdatePage({ template, onUpdate, onBack }: Props): VNode { const submitForm = () => { if (hasErrors) return Promise.reject(); + if (state.template_contract) { + if (state.type === Steps.NON_FIXED) { + delete state.template_contract.amount; + delete state.template_contract.summary; + } else if (state.type === Steps.FIXED_SUMMARY) { + delete state.template_contract.amount; + } else if (state.type === Steps.FIXED_PRICE) { + delete state.template_contract.summary; + } + } + delete state.type return onUpdate(state as any); }; @@ -136,17 +171,48 @@ export function UpdatePage({ template, onUpdate, onBack }: Props): VNode { help="" tooltip={i18n.str`Describe what this template stands for`} /> - - { + switch (state.type) { + case Steps.NON_FIXED: return i18n.str`User will be able to input price and summary before payment.` + case Steps.FIXED_PRICE: return i18n.str`User will be able to add a summary before payment.` + case Steps.FIXED_SUMMARY: return i18n.str`User will be able to set the price before payment.` + case Steps.BOTH_FIXED: return i18n.str`User will not be able to change the price or the summary.` + } + })()} + tooltip={i18n.str`Define what the user be allowed to modify`} + values={[ + Steps.NON_FIXED, + Steps.FIXED_PRICE, + Steps.FIXED_SUMMARY, + Steps.BOTH_FIXED, + ]} + toStr={(v: Steps): string => { + switch (v) { + case Steps.NON_FIXED: return i18n.str`Simple` + case Steps.FIXED_PRICE: return i18n.str`With price` + case Steps.FIXED_SUMMARY: return i18n.str`With summary` + case Steps.BOTH_FIXED: return i18n.str`With price and summary` + } + }} /> + {state.type === Steps.BOTH_FIXED || state.type === Steps.FIXED_SUMMARY ? + + : undefined} + {state.type === Steps.BOTH_FIXED || state.type === Steps.FIXED_PRICE ? + + : undefined}