diff options
Diffstat (limited to 'packages/merchant-backoffice-ui/src/paths/instance/reserves/list')
-rw-r--r-- | packages/merchant-backoffice-ui/src/paths/instance/reserves/list/AutorizeRewardModal.tsx (renamed from packages/merchant-backoffice-ui/src/paths/instance/reserves/list/AutorizeTipModal.tsx) | 40 | ||||
-rw-r--r-- | packages/merchant-backoffice-ui/src/paths/instance/reserves/list/CreatedSuccessfully.tsx | 18 | ||||
-rw-r--r-- | packages/merchant-backoffice-ui/src/paths/instance/reserves/list/List.stories.tsx | 6 | ||||
-rw-r--r-- | packages/merchant-backoffice-ui/src/paths/instance/reserves/list/Table.tsx | 39 | ||||
-rw-r--r-- | packages/merchant-backoffice-ui/src/paths/instance/reserves/list/index.tsx | 82 |
5 files changed, 112 insertions, 73 deletions
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/reserves/list/AutorizeTipModal.tsx b/packages/merchant-backoffice-ui/src/paths/instance/reserves/list/AutorizeRewardModal.tsx index 1882f50d3..e205ee621 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/reserves/list/AutorizeTipModal.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/reserves/list/AutorizeRewardModal.tsx @@ -34,32 +34,32 @@ import { ContinueModal, } from "../../../../components/modal/index.js"; import { MerchantBackend } from "../../../../declaration.js"; -import { AuthorizeTipSchema } from "../../../../schemas/index.js"; +import { AuthorizeRewardSchema } from "../../../../schemas/index.js"; import { CreatedSuccessfully } from "./CreatedSuccessfully.js"; -interface AuthorizeTipModalProps { +interface AuthorizeRewardModalProps { onCancel: () => void; - onConfirm: (value: MerchantBackend.Tips.TipCreateRequest) => void; - tipAuthorized?: { - response: MerchantBackend.Tips.TipCreateConfirmation; - request: MerchantBackend.Tips.TipCreateRequest; + onConfirm: (value: MerchantBackend.Rewards.RewardCreateRequest) => void; + rewardAuthorized?: { + response: MerchantBackend.Rewards.RewardCreateConfirmation; + request: MerchantBackend.Rewards.RewardCreateRequest; }; } -export function AuthorizeTipModal({ +export function AuthorizeRewardModal({ onCancel, onConfirm, - tipAuthorized, -}: AuthorizeTipModalProps): VNode { + rewardAuthorized, +}: AuthorizeRewardModalProps): VNode { // const result = useOrderDetails(id) - type State = MerchantBackend.Tips.TipCreateRequest; + type State = MerchantBackend.Rewards.RewardCreateRequest; const [form, setValue] = useState<Partial<State>>({}); const { i18n } = useTranslationContext(); // const [errors, setErrors] = useState<FormErrors<State>>({}) let errors: FormErrors<State> = {}; try { - AuthorizeTipSchema.validateSync(form, { abortEarly: false }); + AuthorizeRewardSchema.validateSync(form, { abortEarly: false }); } catch (err) { if (err instanceof yup.ValidationError) { const yupErrors = err.inner as any[]; @@ -77,12 +77,12 @@ export function AuthorizeTipModal({ const validateAndConfirm = () => { onConfirm(form as State); }; - if (tipAuthorized) { + if (rewardAuthorized) { return ( - <ContinueModal description="tip" active onConfirm={onCancel}> + <ContinueModal description="reward" active onConfirm={onCancel}> <CreatedSuccessfully - entity={tipAuthorized.response} - request={tipAuthorized.request} + entity={rewardAuthorized.response} + request={rewardAuthorized.request} onConfirm={onCancel} /> </ContinueModal> @@ -91,7 +91,7 @@ export function AuthorizeTipModal({ return ( <ConfirmModal - description="tip" + description="New reward" active onCancel={onCancel} disabled={hasErrors} @@ -105,18 +105,18 @@ export function AuthorizeTipModal({ <InputCurrency<State> name="amount" label={i18n.str`Amount`} - tooltip={i18n.str`amount of tip`} + tooltip={i18n.str`amount of reward`} /> <Input<State> name="justification" label={i18n.str`Justification`} inputType="multiline" - tooltip={i18n.str`reason for the tip`} + tooltip={i18n.str`reason for the reward`} /> <Input<State> name="next_url" - label={i18n.str`URL after tip`} - tooltip={i18n.str`URL to visit after tip payment`} + label={i18n.str`URL after reward`} + tooltip={i18n.str`URL to visit after reward payment`} /> </FormProvider> </ConfirmModal> diff --git a/packages/merchant-backoffice-ui/src/paths/instance/reserves/list/CreatedSuccessfully.tsx b/packages/merchant-backoffice-ui/src/paths/instance/reserves/list/CreatedSuccessfully.tsx index 643651b52..b78236bc7 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/reserves/list/CreatedSuccessfully.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/reserves/list/CreatedSuccessfully.tsx @@ -17,12 +17,13 @@ import { format } from "date-fns"; import { Fragment, h, VNode } from "preact"; import { CreatedSuccessfully as Template } from "../../../../components/notifications/CreatedSuccessfully.js"; import { MerchantBackend } from "../../../../declaration.js"; +import { datetimeFormatForSettings, useSettings } from "../../../../hooks/useSettings.js"; -type Entity = MerchantBackend.Tips.TipCreateConfirmation; +type Entity = MerchantBackend.Rewards.RewardCreateConfirmation; interface Props { entity: Entity; - request: MerchantBackend.Tips.TipCreateRequest; + request: MerchantBackend.Rewards.RewardCreateRequest; onConfirm: () => void; onCreateAnother?: () => void; } @@ -33,6 +34,7 @@ export function CreatedSuccessfully({ onConfirm, onCreateAnother, }: Props): VNode { + const [settings] = useSettings(); return ( <Fragment> <div class="field is-horizontal"> @@ -66,7 +68,7 @@ export function CreatedSuccessfully({ <div class="field-body is-flex-grow-3"> <div class="field"> <p class="control"> - <input readonly class="input" value={entity.tip_status_url} /> + <input readonly class="input" value={entity.reward_status_url} /> </p> </div> </div> @@ -82,13 +84,13 @@ export function CreatedSuccessfully({ class="input" readonly value={ - !entity.tip_expiration || - entity.tip_expiration.t_s === "never" + !entity.reward_expiration || + entity.reward_expiration.t_s === "never" ? "never" : format( - entity.tip_expiration.t_s * 1000, - "yyyy/MM/dd HH:mm:ss", - ) + entity.reward_expiration.t_s * 1000, + datetimeFormatForSettings(settings), + ) } /> </p> diff --git a/packages/merchant-backoffice-ui/src/paths/instance/reserves/list/List.stories.tsx b/packages/merchant-backoffice-ui/src/paths/instance/reserves/list/List.stories.tsx index fe305f4fd..b070bbde3 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/reserves/list/List.stories.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/reserves/list/List.stories.tsx @@ -25,12 +25,6 @@ import { CardTable as TestedComponent } from "./Table.js"; export default { title: "Pages/Reserve/List", component: TestedComponent, - argTypes: { - onCreate: { action: "onCreate" }, - onDelete: { action: "onDelete" }, - onNewTip: { action: "onNewTip" }, - onSelect: { action: "onSelect" }, - }, }; function createExample<Props>( diff --git a/packages/merchant-backoffice-ui/src/paths/instance/reserves/list/Table.tsx b/packages/merchant-backoffice-ui/src/paths/instance/reserves/list/Table.tsx index 1f229d7cb..795e7ec82 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/reserves/list/Table.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/reserves/list/Table.tsx @@ -23,12 +23,13 @@ import { useTranslationContext } from "@gnu-taler/web-util/browser"; import { format } from "date-fns"; import { Fragment, h, VNode } from "preact"; import { MerchantBackend, WithId } from "../../../../declaration.js"; +import { datetimeFormatForSettings, useSettings } from "../../../../hooks/useSettings.js"; -type Entity = MerchantBackend.Tips.ReserveStatusEntry & WithId; +type Entity = MerchantBackend.Rewards.ReserveStatusEntry & WithId; interface Props { instances: Entity[]; - onNewTip: (id: Entity) => void; + onNewReward: (id: Entity) => void; onSelect: (id: Entity) => void; onDelete: (id: Entity) => void; onCreate: () => void; @@ -38,7 +39,7 @@ export function CardTable({ instances, onCreate, onSelect, - onNewTip, + onNewReward, onDelete, }: Props): VNode { const [withoutFunds, withFunds] = instances.reduce((prev, current) => { @@ -70,7 +71,7 @@ export function CardTable({ <div class="table-wrapper has-mobile-cards"> <TableWithoutFund instances={withoutFunds} - onNewTip={onNewTip} + onNewReward={onNewReward} onSelect={onSelect} onDelete={onDelete} /> @@ -108,7 +109,7 @@ export function CardTable({ {withFunds.length > 0 ? ( <Table instances={withFunds} - onNewTip={onNewTip} + onNewReward={onNewReward} onSelect={onSelect} onDelete={onDelete} /> @@ -124,13 +125,14 @@ export function CardTable({ } interface TableProps { instances: Entity[]; - onNewTip: (id: Entity) => void; + onNewReward: (id: Entity) => void; onDelete: (id: Entity) => void; onSelect: (id: Entity) => void; } -function Table({ instances, onNewTip, onSelect, onDelete }: TableProps): VNode { +function Table({ instances, onNewReward, onSelect, onDelete }: TableProps): VNode { const { i18n } = useTranslationContext(); + const [settings] = useSettings(); return ( <div class="table-container"> <table class="table is-fullwidth is-striped is-hoverable is-fullwidth"> @@ -164,7 +166,7 @@ function Table({ instances, onNewTip, onSelect, onDelete }: TableProps): VNode { > {i.creation_time.t_s === "never" ? "never" - : format(i.creation_time.t_s * 1000, "yyyy/MM/dd HH:mm:ss")} + : format(i.creation_time.t_s * 1000, datetimeFormatForSettings(settings))} </td> <td onClick={(): void => onSelect(i)} @@ -173,9 +175,9 @@ function Table({ instances, onNewTip, onSelect, onDelete }: TableProps): VNode { {i.expiration_time.t_s === "never" ? "never" : format( - i.expiration_time.t_s * 1000, - "yyyy/MM/dd HH:mm:ss", - )} + i.expiration_time.t_s * 1000, + datetimeFormatForSettings(settings), + )} </td> <td onClick={(): void => onSelect(i)} @@ -207,11 +209,11 @@ function Table({ instances, onNewTip, onSelect, onDelete }: TableProps): VNode { </button> <button class="button is-small is-info has-tooltip-left" - data-tooltip={i18n.str`authorize new tip from selected reserve`} + data-tooltip={i18n.str`authorize new reward from selected reserve`} type="button" - onClick={(): void => onNewTip(i)} + onClick={(): void => onNewReward(i)} > - New Tip + New Reward </button> </div> </td> @@ -249,6 +251,7 @@ function TableWithoutFund({ onDelete, }: TableProps): VNode { const { i18n } = useTranslationContext(); + const [settings] = useSettings(); return ( <div class="table-container"> <table class="table is-fullwidth is-striped is-hoverable is-fullwidth"> @@ -276,7 +279,7 @@ function TableWithoutFund({ > {i.creation_time.t_s === "never" ? "never" - : format(i.creation_time.t_s * 1000, "yyyy/MM/dd HH:mm:ss")} + : format(i.creation_time.t_s * 1000, datetimeFormatForSettings(settings))} </td> <td onClick={(): void => onSelect(i)} @@ -285,9 +288,9 @@ function TableWithoutFund({ {i.expiration_time.t_s === "never" ? "never" : format( - i.expiration_time.t_s * 1000, - "yyyy/MM/dd HH:mm:ss", - )} + i.expiration_time.t_s * 1000, + datetimeFormatForSettings(settings), + )} </td> <td onClick={(): void => onSelect(i)} diff --git a/packages/merchant-backoffice-ui/src/paths/instance/reserves/list/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/reserves/list/index.tsx index 14387c2a9..b26ff0000 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/reserves/list/index.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/reserves/list/index.tsx @@ -34,9 +34,10 @@ import { useReservesAPI, } from "../../../../hooks/reserves.js"; import { Notification } from "../../../../utils/types.js"; -import { AuthorizeTipModal } from "./AutorizeTipModal.js"; +import { AuthorizeRewardModal } from "./AutorizeRewardModal.js"; import { CardTable } from "./Table.js"; import { HttpStatusCode } from "@gnu-taler/taler-util"; +import { ConfirmModal } from "../../../../components/modal/index.js"; interface Props { onUnauthorized: () => VNode; @@ -46,12 +47,12 @@ interface Props { onCreate: () => void; } -interface TipConfirmation { - response: MerchantBackend.Tips.TipCreateConfirmation; - request: MerchantBackend.Tips.TipCreateRequest; +interface RewardConfirmation { + response: MerchantBackend.Rewards.RewardCreateConfirmation; + request: MerchantBackend.Rewards.RewardCreateRequest; } -export default function ListTips({ +export default function ListRewards({ onUnauthorized, onLoadError, onNotFound, @@ -59,14 +60,16 @@ export default function ListTips({ onCreate, }: Props): VNode { const result = useInstanceReserves(); - const { deleteReserve, authorizeTipReserve } = useReservesAPI(); + const { deleteReserve, authorizeRewardReserve } = useReservesAPI(); const [notif, setNotif] = useState<Notification | undefined>(undefined); const { i18n } = useTranslationContext(); - const [reserveForTip, setReserveForTip] = useState<string | undefined>( + const [reserveForReward, setReserveForReward] = useState<string | undefined>( undefined, ); - const [tipAuthorized, setTipAuthorized] = useState< - TipConfirmation | undefined + const [deleting, setDeleting] = + useState<MerchantBackend.Rewards.ReserveStatusEntry | null>(null); + const [rewardAuthorized, setRewardAuthorized] = useState< + RewardConfirmation | undefined >(undefined); if (result.loading) return <Loading />; @@ -88,30 +91,30 @@ export default function ListTips({ <section class="section is-main-section"> <NotificationCard notification={notif} /> - {reserveForTip && ( - <AuthorizeTipModal + {reserveForReward && ( + <AuthorizeRewardModal onCancel={() => { - setReserveForTip(undefined); - setTipAuthorized(undefined); + setReserveForReward(undefined); + setRewardAuthorized(undefined); }} - tipAuthorized={tipAuthorized} + rewardAuthorized={rewardAuthorized} onConfirm={async (request) => { try { - const response = await authorizeTipReserve( - reserveForTip, + const response = await authorizeRewardReserve( + reserveForReward, request, ); - setTipAuthorized({ + setRewardAuthorized({ request, response: response.data, }); } catch (error) { setNotif({ - message: i18n.str`could not create the tip`, + message: i18n.str`could not create the reward`, type: "ERROR", description: error instanceof Error ? error.message : undefined, }); - setReserveForTip(undefined); + setReserveForReward(undefined); } }} /> @@ -122,10 +125,47 @@ export default function ListTips({ .filter((r) => r.active) .map((o) => ({ ...o, id: o.reserve_pub }))} onCreate={onCreate} - onDelete={(reserve) => deleteReserve(reserve.reserve_pub)} + onDelete={(reserve) => { + setDeleting(reserve) + }} onSelect={(reserve) => onSelect(reserve.id)} - onNewTip={(reserve) => setReserveForTip(reserve.id)} + onNewReward={(reserve) => setReserveForReward(reserve.id)} /> + + {deleting && ( + <ConfirmModal + label={`Delete reserve`} + description={`Delete the reserve`} + danger + active + onCancel={() => setDeleting(null)} + onConfirm={async (): Promise<void> => { + try { + await deleteReserve(deleting.reserve_pub); + setNotif({ + message: i18n.str`Reserve for "${deleting.merchant_initial_amount}" (ID: ${deleting.reserve_pub}) has been deleted`, + type: "SUCCESS", + }); + } catch (error) { + setNotif({ + message: i18n.str`Failed to delete reserve`, + type: "ERROR", + description: error instanceof Error ? error.message : undefined, + }); + } + setDeleting(null); + }} + > + <p> + If you delete the reserve for <b>"{deleting.merchant_initial_amount}"</b> you won't be able to create more rewards. <br /> + Reserve ID: <b>{deleting.reserve_pub}</b> + </p> + <p class="warning"> + Deleting an template <b>cannot be undone</b>. + </p> + </ConfirmModal> + )} + </section> ); } |