diff options
Diffstat (limited to 'packages/merchant-backoffice-ui/src/paths/instance/reserves')
11 files changed, 168 insertions, 126 deletions
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/reserves/create/CreatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/reserves/create/CreatePage.tsx index fccb20121..2201e75a5 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/reserves/create/CreatePage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/reserves/create/CreatePage.tsx @@ -36,7 +36,7 @@ import { URL_REGEX, } from "../../../../utils/constants.js"; -type Entity = MerchantBackend.Tips.ReserveCreateRequest; +type Entity = MerchantBackend.Rewards.ReserveCreateRequest; interface Props { onCreate: (d: Entity) => Promise<void>; @@ -80,15 +80,15 @@ function ViewStep({ initial_balance: !reserve.initial_balance ? "cannot be empty" : !(parseInt(reserve.initial_balance.split(":")[1], 10) > 0) - ? i18n.str`it should be greater than 0` - : undefined, + ? i18n.str`it should be greater than 0` + : undefined, exchange_url: !reserve.exchange_url ? i18n.str`cannot be empty` : !URL_REGEX.test(reserve.exchange_url) - ? i18n.str`must be a valid URL` - : !exchangeQueryError - ? undefined - : exchangeQueryError, + ? i18n.str`must be a valid URL` + : !exchangeQueryError + ? undefined + : exchangeQueryError, }; const hasErrors = Object.keys(errors).some( diff --git a/packages/merchant-backoffice-ui/src/paths/instance/reserves/create/CreatedSuccessfully.tsx b/packages/merchant-backoffice-ui/src/paths/instance/reserves/create/CreatedSuccessfully.tsx index 94fcdaff7..1d512c843 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/reserves/create/CreatedSuccessfully.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/reserves/create/CreatedSuccessfully.tsx @@ -22,8 +22,8 @@ import { CreatedSuccessfully as Template } from "../../../../components/notifica import { MerchantBackend, WireAccount } from "../../../../declaration.js"; type Entity = { - request: MerchantBackend.Tips.ReserveCreateRequest; - response: MerchantBackend.Tips.ReserveCreateConfirmation; + request: MerchantBackend.Rewards.ReserveCreateRequest; + response: MerchantBackend.Rewards.ReserveCreateConfirmation; }; interface Props { @@ -98,15 +98,15 @@ export function ShowAccountsOfReserveAsQRWithLink({ const accountsInfo = !accounts ? [] : accounts - .map((acc) => { - const p = parsePaytoUri(acc.payto_uri); - if (p) { - p.params["message"] = message; - p.params["amount"] = amount; - } - return p; - }) - .filter(isNotUndefined); + .map((acc) => { + const p = parsePaytoUri(acc.payto_uri); + if (p) { + p.params["message"] = message; + p.params["amount"] = amount; + } + return p; + }) + .filter(isNotUndefined); const links = accountsInfo.map((a) => stringifyPaytoUri(a)); diff --git a/packages/merchant-backoffice-ui/src/paths/instance/reserves/create/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/reserves/create/index.tsx index 8a4fe1565..4bbaf1459 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/reserves/create/index.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/reserves/create/index.tsx @@ -39,9 +39,9 @@ export default function CreateReserve({ onBack, onConfirm }: Props): VNode { const [createdOk, setCreatedOk] = useState< | { - request: MerchantBackend.Tips.ReserveCreateRequest; - response: MerchantBackend.Tips.ReserveCreateConfirmation; - } + request: MerchantBackend.Rewards.ReserveCreateRequest; + response: MerchantBackend.Rewards.ReserveCreateConfirmation; + } | undefined >(undefined); @@ -54,7 +54,7 @@ export default function CreateReserve({ onBack, onConfirm }: Props): VNode { <NotificationCard notification={notif} /> <CreatePage onBack={onBack} - onCreate={(request: MerchantBackend.Tips.ReserveCreateRequest) => { + onCreate={(request: MerchantBackend.Rewards.ReserveCreateRequest) => { return createReserve(request) .then((r) => setCreatedOk({ request, response: r.data })) .catch((error) => { diff --git a/packages/merchant-backoffice-ui/src/paths/instance/reserves/details/DetailPage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/reserves/details/DetailPage.tsx index b0173b5d3..d8840eeac 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/reserves/details/DetailPage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/reserves/details/DetailPage.tsx @@ -36,11 +36,12 @@ import { InputDate } from "../../../../components/form/InputDate.js"; import { TextField } from "../../../../components/form/TextField.js"; import { SimpleModal } from "../../../../components/modal/index.js"; import { MerchantBackend } from "../../../../declaration.js"; -import { useTipDetails } from "../../../../hooks/reserves.js"; -import { TipInfo } from "./TipInfo.js"; +import { useRewardDetails } from "../../../../hooks/reserves.js"; +import { RewardInfo } from "./RewardInfo.js"; import { ShowAccountsOfReserveAsQRWithLink } from "../create/CreatedSuccessfully.js"; +import { datetimeFormatForSettings, useSettings } from "../../../../hooks/useSettings.js"; -type Entity = MerchantBackend.Tips.ReserveDetail; +type Entity = MerchantBackend.Rewards.ReserveDetail; type CT = MerchantBackend.ContractTerms; interface Props { @@ -116,14 +117,14 @@ export function DetailPage({ id, selected, onBack }: Props): VNode { <span class="icon"> <i class="mdi mdi-cash-register" /> </span> - <i18n.Translate>Tips</i18n.Translate> + <i18n.Translate>Rewards</i18n.Translate> </p> </header> <div class="card-content"> <div class="b-table has-pagination"> <div class="table-wrapper has-mobile-cards"> - {selected.tips && selected.tips.length > 0 ? ( - <Table tips={selected.tips} /> + {selected.rewards && selected.rewards.length > 0 ? ( + <Table rewards={selected.rewards} /> ) : ( <EmptyTable /> )} @@ -163,7 +164,7 @@ function EmptyTable(): VNode { </p> <p> <i18n.Translate> - No tips has been authorized from this reserve + No reward has been authorized from this reserve </i18n.Translate> </p> </div> @@ -171,10 +172,10 @@ function EmptyTable(): VNode { } interface TableProps { - tips: MerchantBackend.Tips.TipStatusEntry[]; + rewards: MerchantBackend.Rewards.RewardStatusEntry[]; } -function Table({ tips }: TableProps): VNode { +function Table({ rewards }: TableProps): VNode { const { i18n } = useTranslationContext(); return ( <div class="table-container"> @@ -196,8 +197,8 @@ function Table({ tips }: TableProps): VNode { </tr> </thead> <tbody> - {tips.map((t, i) => { - return <TipRow id={t.tip_id} key={i} entry={t} />; + {rewards.map((t, i) => { + return <RewardRow id={t.reward_id} key={i} entry={t} />; })} </tbody> </table> @@ -205,15 +206,16 @@ function Table({ tips }: TableProps): VNode { ); } -function TipRow({ +function RewardRow({ id, entry, }: { id: string; - entry: MerchantBackend.Tips.TipStatusEntry; + entry: MerchantBackend.Rewards.RewardStatusEntry; }) { const [selected, setSelected] = useState(false); - const result = useTipDetails(id); + const result = useRewardDetails(id); + const [settings] = useSettings(); if (result.loading) { return ( <tr> @@ -242,11 +244,11 @@ function TipRow({ <Fragment> {selected && ( <SimpleModal - description="tip" + description="reward" active onCancel={() => setSelected(false)} > - <TipInfo id={id} amount={info.total_authorized} entity={info} /> + <RewardInfo id={id} amount={info.total_authorized} entity={info} /> </SimpleModal> )} <tr> @@ -256,7 +258,7 @@ function TipRow({ <td onClick={onSelect}> {info.expiration.t_s === "never" ? "never" - : format(info.expiration.t_s * 1000, "yyyy/MM/dd HH:mm:ss")} + : format(info.expiration.t_s * 1000, datetimeFormatForSettings(settings))} </td> </tr> </Fragment> diff --git a/packages/merchant-backoffice-ui/src/paths/instance/reserves/details/Details.stories.tsx b/packages/merchant-backoffice-ui/src/paths/instance/reserves/details/Details.stories.tsx index 2592e2c6e..41c715f20 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/reserves/details/Details.stories.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/reserves/details/Details.stories.tsx @@ -92,7 +92,7 @@ export const NotYetFunded = createExample(TestedComponent, { }, }); -export const FundedWithEmptyTips = createExample(TestedComponent, { +export const FundedWithEmptyRewards = createExample(TestedComponent, { id: "THISISTHERESERVEID", selected: { active: true, @@ -115,10 +115,10 @@ export const FundedWithEmptyTips = createExample(TestedComponent, { }, ], exchange_url: "http://exchange.taler/", - tips: [ + rewards: [ { reason: "asdasd", - tip_id: "123", + reward_id: "123", total_amount: "TESTKUDOS:1", }, ], diff --git a/packages/merchant-backoffice-ui/src/paths/instance/reserves/details/TipInfo.tsx b/packages/merchant-backoffice-ui/src/paths/instance/reserves/details/RewardInfo.tsx index 360d39aba..57a051ed7 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/reserves/details/TipInfo.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/reserves/details/RewardInfo.tsx @@ -17,8 +17,10 @@ import { format } from "date-fns"; import { Fragment, h, VNode } from "preact"; import { useBackendContext } from "../../../../context/backend.js"; import { MerchantBackend } from "../../../../declaration.js"; +import { datetimeFormatForSettings, useSettings } from "../../../../hooks/useSettings.js"; +import { stringifyRewardUri } from "@gnu-taler/taler-util"; -type Entity = MerchantBackend.Tips.TipDetails; +type Entity = MerchantBackend.Rewards.RewardDetails; interface Props { id: string; @@ -26,11 +28,10 @@ interface Props { amount: string; } -export function TipInfo({ id, amount, entity }: Props): VNode { - const { url } = useBackendContext(); - const tipHost = url.replace(/.*:\/\//, ""); // remove protocol part - const proto = url.startsWith("http://") ? "taler+http" : "taler"; - const tipURL = `${proto}://tip/${tipHost}/${id}`; +export function RewardInfo({ id: merchantRewardId, amount, entity }: Props): VNode { + const { url: merchantBaseUrl } = useBackendContext(); + const [settings] = useSettings(); + const rewardURL = stringifyRewardUri({ merchantBaseUrl, merchantRewardId }) return ( <Fragment> <div class="field is-horizontal"> @@ -52,8 +53,8 @@ export function TipInfo({ id, amount, entity }: Props): VNode { <div class="field-body is-flex-grow-3"> <div class="field" style={{ overflowWrap: "anywhere" }}> <p class="control"> - <a target="_blank" rel="noreferrer" href={tipURL}> - {tipURL} + <a target="_blank" rel="noreferrer" href={rewardURL}> + {rewardURL} </a> </p> </div> @@ -73,9 +74,9 @@ export function TipInfo({ id, amount, entity }: Props): VNode { !entity.expiration || entity.expiration.t_s === "never" ? "never" : format( - entity.expiration.t_s * 1000, - "yyyy/MM/dd HH:mm:ss", - ) + entity.expiration.t_s * 1000, + datetimeFormatForSettings(settings), + ) } /> </p> 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> ); } |