merchant-backoffice

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

commit f4e5ed9e9e6973f5c21b347321fe6d6531414960
parent 0399b8a12591a0529d7b399508b9b63d811bcb93
Author: Sebastian <sebasjm@gmail.com>
Date:   Thu, 24 Jun 2021 12:22:31 -0300

refactor transfer list

Diffstat:
Mpackages/frontend/src/components/form/FormProvider.tsx | 18+++++++++---------
Mpackages/frontend/src/components/product/NonInventoryProductForm.tsx | 4++--
Mpackages/frontend/src/components/product/ProductForm.tsx | 2+-
Mpackages/frontend/src/paths/instance/transfers/list/List.stories.tsx | 23+++++++++++++----------
Apackages/frontend/src/paths/instance/transfers/list/ListPage.tsx | 89+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mpackages/frontend/src/paths/instance/transfers/list/Table.tsx | 9+++------
Mpackages/frontend/src/paths/instance/transfers/list/index.tsx | 95++++++++++++++++++-------------------------------------------------------------
7 files changed, 138 insertions(+), 102 deletions(-)

diff --git a/packages/frontend/src/components/form/FormProvider.tsx b/packages/frontend/src/components/form/FormProvider.tsx @@ -20,28 +20,28 @@ */ import { ComponentChildren, createContext, h, VNode } from "preact"; -import { StateUpdater, useContext, useMemo } from "preact/hooks"; +import { useContext, useMemo } from "preact/hooks"; + +type Updater<S> = (value: ((prevState: S) => S) ) => void; export interface Props<T> { object?: Partial<T>; errors?: FormErrors<T>; name?: string; - valueHandler: StateUpdater<Partial<T>> | null; + valueHandler: Updater<Partial<T>> | null; children: ComponentChildren } -function noop() { - //do nothing -} +const noUpdater: Updater<Partial<unknown>> = () => (s: unknown) => s export function FormProvider<T>({ object = {}, errors = {}, name = '', valueHandler, children }: Props<T>): VNode { const initialObject = useMemo(() => object, []); - const value = useMemo<FormType<T>>(() => ({ errors, object, initialObject, valueHandler: valueHandler ? valueHandler : noop, name, toStr: {}, fromStr: {} }), [errors, object, valueHandler]); + const value = useMemo<FormType<T>>(() => ({ errors, object, initialObject, valueHandler: valueHandler ? valueHandler : noUpdater, name, toStr: {}, fromStr: {} }), [errors, object, valueHandler]); return <FormContext.Provider value={value}> <form class="field" onSubmit={(e) => { e.preventDefault(); - if (valueHandler) valueHandler(object); + // if (valueHandler) valueHandler(object); }}> {children} </form> @@ -55,10 +55,10 @@ export interface FormType<T> { toStr: FormtoStr<T>; name: string; fromStr: FormfromStr<T>; - valueHandler: StateUpdater<Partial<T>>; + valueHandler: Updater<Partial<T>>; } -const FormContext = createContext<FormType<any>>(null!) +const FormContext = createContext<FormType<unknown>>(null!) export function useFormContext<T>() { return useContext<FormType<T>>(FormContext) diff --git a/packages/frontend/src/components/product/NonInventoryProductForm.tsx b/packages/frontend/src/components/product/NonInventoryProductForm.tsx @@ -102,7 +102,7 @@ interface NonInventoryProduct { taxes: MerchantBackend.Tax[]; } -export function ProductForm({ onSubscribe, initial }: ProductProps) { +export function ProductForm({ onSubscribe, initial }: ProductProps): VNode { const [value, valueHandler] = useState<Partial<NonInventoryProduct>>({ taxes: [], ...initial, @@ -123,7 +123,7 @@ export function ProductForm({ onSubscribe, initial }: ProductProps) { useEffect(() => { onSubscribe(hasErrors ? undefined : submit) - }, [submit, hasErrors]) + }, [submit, hasErrors, onSubscribe]) const i18n = useTranslator() diff --git a/packages/frontend/src/components/product/ProductForm.tsx b/packages/frontend/src/components/product/ProductForm.tsx @@ -88,7 +88,7 @@ export function ProductForm({ onSubscribe, initial, alreadyExist, }: Props) { useEffect(() => { onSubscribe(hasErrors ? undefined : submit) - }, [submit, hasErrors]) + }, [submit, hasErrors, onSubscribe]) const backend = useBackendContext(); const i18n = useTranslator() diff --git a/packages/frontend/src/paths/instance/transfers/list/List.stories.tsx b/packages/frontend/src/paths/instance/transfers/list/List.stories.tsx @@ -20,7 +20,7 @@ */ import { h, VNode, FunctionalComponent } from 'preact'; -import { CardTable as TestedComponent } from './Table'; +import { ListPage as TestedComponent } from './ListPage'; export default { @@ -29,8 +29,12 @@ export default { argTypes: { onCreate: { action: 'onCreate' }, onDelete: { action: 'onDelete' }, - onNewTip: { action: 'onNewTip' }, - onSelect: { action: 'onSelect' }, + onLoadMoreBefore: { action: 'onLoadMoreBefore' }, + onLoadMoreAfter: { action: 'onLoadMoreAfter' }, + onShowAll: { action: 'onShowAll' }, + onShowVerified: { action: 'onShowVerified' }, + onShowUnverified: { action: 'onShowUnverified' }, + onChangePayTo: { action: 'onChangePayTo' } }, }; @@ -43,7 +47,6 @@ function createExample<Props>(Component: FunctionalComponent<Props>, props: Part export const Example = createExample(TestedComponent, { transfers: [{ exchange_url: 'http://exchange.url/', - id: 'transferid', credit_amount: 'TESTKUDOS:10', payto_uri: 'payto//x-taler-bank/bank:8080/account', transfer_serial_id: 123123123, @@ -53,9 +56,8 @@ export const Example = createExample(TestedComponent, { t_ms: new Date().getTime() }, verified: false, - },{ + }, { exchange_url: 'http://exchange.url/', - id: 'transferid', credit_amount: 'TESTKUDOS:10', payto_uri: 'payto//x-taler-bank/bank:8080/account', transfer_serial_id: 123123123, @@ -65,9 +67,8 @@ export const Example = createExample(TestedComponent, { t_ms: new Date().getTime() }, verified: false, - },{ + }, { exchange_url: 'http://exchange.url/', - id: 'transferid', credit_amount: 'TESTKUDOS:10', payto_uri: 'payto//x-taler-bank/bank:8080/account', transfer_serial_id: 123123123, @@ -77,8 +78,10 @@ export const Example = createExample(TestedComponent, { t_ms: new Date().getTime() }, verified: false, - }] + }], + accounts: ['payto://x-taler-bank/bank/some_account'] }); export const Empty = createExample(TestedComponent, { - transfers: [] + transfers: [], + accounts: [] }); diff --git a/packages/frontend/src/paths/instance/transfers/list/ListPage.tsx b/packages/frontend/src/paths/instance/transfers/list/ListPage.tsx @@ -0,0 +1,89 @@ +/* + This file is part of GNU Taler + (C) 2021 Taler Systems S.A. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ + +/** +* +* @author Sebastian Javier Marchano (sebasjm) +*/ + +import { h, VNode } from 'preact'; +import { FormProvider } from '../../../../components/form/FormProvider'; +import { InputSelector } from '../../../../components/form/InputSelector'; +import { MerchantBackend } from '../../../../declaration'; +import { Translate, useTranslator } from '../../../../i18n'; +import { CardTable } from './Table'; + +export interface Props { + transfers: MerchantBackend.Transfers.TransferDetails[]; + onLoadMoreBefore?: () => void; + onLoadMoreAfter?: () => void; + onShowAll: () => void; + onShowVerified: () => void; + onShowUnverified: () => void; + isVerifiedTransfers?: boolean; + isNonVerifiedTransfers?: boolean; + isAllTransfers?: boolean; + accounts: string[]; + onChangePayTo: (p?: string) => void; + payTo?: string; + onCreate: () => void; + onDelete: () => void; +} + +export function ListPage({ payTo, onChangePayTo, transfers, onCreate, onDelete, accounts, onLoadMoreBefore, onLoadMoreAfter, isAllTransfers, isNonVerifiedTransfers, isVerifiedTransfers, onShowAll, onShowUnverified, onShowVerified }: Props): VNode { + const form = { payto_uri: payTo } + + const i18n = useTranslator(); + return <section class="section is-main-section"> + <div class="columns"> + <div class="column" /> + <div class="column is-10"> + <FormProvider object={form} valueHandler={(updater) => onChangePayTo(updater(form).payto_uri)}> + <InputSelector name="payto_uri" label={i18n`Address`} + values={accounts} + placeholder={i18n`Select one account`} + tooltip={i18n`filter by account address`} /> + </FormProvider> + </div> + <div class="column" /> + </div> + <div class="tabs"> + <ul> + <li class={isAllTransfers ? 'is-active' : ''}> + <div class="has-tooltip-right" data-tooltip={i18n`remove all filters`}> + <a onClick={onShowAll}><Translate>All</Translate></a> + </div> + </li> + <li class={isVerifiedTransfers ? 'is-active' : ''}> + <div class="has-tooltip-right" data-tooltip={i18n`only show wire transfers confirmed by the merchant`}> + <a onClick={onShowVerified}><Translate>Verified</Translate></a> + </div> + </li> + <li class={isNonVerifiedTransfers ? 'is-active' : ''}> + <div class="has-tooltip-right" data-tooltip={i18n`only show wire transfers claimed by the exchange`}> + <a onClick={onShowUnverified}><Translate>Unverified</Translate></a> + </div> + </li> + </ul> + </div> + <CardTable transfers={transfers.map(o => ({ ...o, id: String(o.transfer_serial_id) }))} + accounts={accounts} + onCreate={onCreate} + onDelete={onDelete} + onLoadMoreBefore={onLoadMoreBefore} hasMoreBefore={!onLoadMoreBefore} + onLoadMoreAfter={onLoadMoreAfter} hasMoreAfter={!onLoadMoreAfter} /> + </section>; +} diff --git a/packages/frontend/src/paths/instance/transfers/list/Table.tsx b/packages/frontend/src/paths/instance/transfers/list/Table.tsx @@ -21,16 +21,14 @@ import { format } from "date-fns" import { h, VNode } from "preact" -import { StateUpdater, useEffect, useState } from "preact/hooks" +import { StateUpdater, useState } from "preact/hooks" import { MerchantBackend, WithId } from "../../../../declaration" import { Translate, useTranslator } from "../../../../i18n" -import { Actions, buildActions } from "../../../../utils/table" type Entity = MerchantBackend.Transfers.TransferDetails & WithId interface Props { transfers: Entity[]; - onUpdate: (id: string) => void; onDelete: (id: Entity) => void; onCreate: () => void; accounts: string[]; @@ -40,7 +38,7 @@ interface Props { onLoadMoreAfter?: () => void; } -export function CardTable({ transfers, onCreate, onUpdate, onDelete, onLoadMoreAfter, onLoadMoreBefore, hasMoreAfter, hasMoreBefore }: Props): VNode { +export function CardTable({ transfers, onCreate, onDelete, onLoadMoreAfter, onLoadMoreBefore, hasMoreAfter, hasMoreBefore }: Props): VNode { const [rowSelection, rowSelectionHandler] = useState<string[]>([]) const i18n = useTranslator() @@ -61,7 +59,7 @@ export function CardTable({ transfers, onCreate, onUpdate, onDelete, onLoadMoreA <div class="b-table has-pagination"> <div class="table-wrapper has-mobile-cards"> {transfers.length > 0 ? - <Table instances={transfers} onUpdate={onUpdate} + <Table instances={transfers} onDelete={onDelete} rowSelection={rowSelection} rowSelectionHandler={rowSelectionHandler} onLoadMoreAfter={onLoadMoreAfter} onLoadMoreBefore={onLoadMoreBefore} @@ -77,7 +75,6 @@ export function CardTable({ transfers, onCreate, onUpdate, onDelete, onLoadMoreA interface TableProps { rowSelection: string[]; instances: Entity[]; - onUpdate: (id: string) => void; onDelete: (id: Entity) => void; rowSelectionHandler: StateUpdater<string[]>; onLoadMoreBefore?: () => void; diff --git a/packages/frontend/src/paths/instance/transfers/list/index.tsx b/packages/frontend/src/paths/instance/transfers/list/index.tsx @@ -21,19 +21,12 @@ import { h, VNode } from 'preact'; import { useState } from 'preact/hooks'; -import { boolean } from 'yup/lib/locale'; import { Loading } from '../../../../components/exception/loading'; -import { FormProvider } from '../../../../components/form/FormProvider'; -import { Input } from '../../../../components/form/Input'; -import { InputBoolean } from '../../../../components/form/InputBoolean'; -import { InputSearchProduct } from '../../../../components/form/InputSearchProduct'; -import { InputSelector } from '../../../../components/form/InputSelector'; import { MerchantBackend } from '../../../../declaration'; import { HttpError } from '../../../../hooks/backend'; import { useInstanceDetails } from '../../../../hooks/instance'; -import { useInstanceTransfers, useTransferAPI } from "../../../../hooks/transfer"; -import { Translate, useTranslator } from '../../../../i18n'; -import { CardTable } from './Table'; +import { useInstanceTransfers } from "../../../../hooks/transfer"; +import { ListPage } from './ListPage'; interface Props { onUnauthorized: () => VNode; @@ -50,15 +43,14 @@ export default function ListTransfer({ onUnauthorized, onLoadError, onCreate, on const [form, setForm] = useState<Form>({ payto_uri: '' }) const setFilter = (s?: 'yes' | 'no') => setForm({ ...form, verified: s }) - const i18n = useTranslator() const [position, setPosition] = useState<string | undefined>(undefined) const instance = useInstanceDetails() const accounts = !instance.ok ? [] : instance.data.accounts.map(a => a.payto_uri) - const isVerifiedTransfers = form.verified === 'yes' ? "is-active" : '' - const isNonVerifiedTransfers = form.verified === 'no' ? "is-active" : '' - const isAllTransfers = form.verified === undefined ? 'is-active' : '' + const isVerifiedTransfers = form.verified === 'yes' + const isNonVerifiedTransfers = form.verified === 'no' + const isAllTransfers = form.verified === undefined const result = useInstanceTransfers({ position, @@ -71,68 +63,23 @@ export default function ListTransfer({ onUnauthorized, onLoadError, onCreate, on if (result.loading) return <Loading /> if (!result.ok) return onLoadError(result) - return <section class="section is-main-section"> - <div class="columns"> - <div class="column" /> - <div class="column is-10"> - <FormProvider object={form} valueHandler={setForm as any}> - <InputSelector name="payto_uri" label={i18n`Address`} - values={accounts} - placeholder={i18n`Select one account`} - tooltip={i18n`filter by account address`} - /> - </FormProvider> - </div> - <div class="column" /> - </div> - <div class="tabs"> - <ul> - <li class={isAllTransfers}> - <div class="has-tooltip-right" data-tooltip={i18n`remove all filters`}> - <a onClick={() => setFilter(undefined)}><Translate>All</Translate></a> - </div> - </li> - <li class={isVerifiedTransfers}> - <div class="has-tooltip-right" data-tooltip={i18n`only show wire transfers confirmed by the merchant`}> - <a onClick={() => setFilter('yes')}><Translate>Verified</Translate></a> - </div> - </li> - <li class={isNonVerifiedTransfers}> - <div class="has-tooltip-right" data-tooltip={i18n`only show wire transfers claimed by the exchange`}> - <a onClick={() => setFilter('no')}><Translate>Unverified</Translate></a> - </div> - </li> - </ul> - </div> - <View - accounts={accounts} - transfers={result.data.transfers} - onLoadMoreBefore={result.isReachingStart ? result.loadMorePrev : undefined} - onLoadMoreAfter={result.isReachingEnd ? result.loadMore : undefined} - form={form} onCreate={onCreate} onLoadError={onLoadError} onNotFound={onNotFound} onUnauthorized={onUnauthorized} - position={position} setPosition={setPosition} - /> - </section> -} - -interface ViewProps extends Props { - transfers: MerchantBackend.Transfers.TransferDetails[]; - onLoadMoreBefore?: () => void; - onLoadMoreAfter?: () => void; - position?: string; - setPosition: (s: string) => void; - form: Form; - accounts: string[]; -} - -function View({ transfers, onCreate, accounts, onLoadMoreBefore, onLoadMoreAfter }: ViewProps) { - return <CardTable transfers={transfers.map(o => ({ ...o, id: String(o.transfer_serial_id) }))} + return <ListPage accounts={accounts} - onCreate={onCreate} - onDelete={() => null} - onUpdate={() => null} - onLoadMoreBefore={onLoadMoreBefore} hasMoreBefore={!onLoadMoreBefore} - onLoadMoreAfter={onLoadMoreAfter} hasMoreAfter={!onLoadMoreAfter} + transfers={result.data.transfers} + onLoadMoreBefore={result.isReachingStart ? result.loadMorePrev : undefined} + onLoadMoreAfter={result.isReachingEnd ? result.loadMore : undefined} + onCreate={onCreate} + onDelete={() => {null}} + // position={position} setPosition={setPosition} + onShowAll={() => setFilter(undefined)} + onShowUnverified={() => setFilter('no')} + onShowVerified={() => setFilter('yes')} + isAllTransfers={isAllTransfers} + isVerifiedTransfers={isVerifiedTransfers} + isNonVerifiedTransfers={isNonVerifiedTransfers} + payTo={form.payto_uri} + onChangePayTo={(p) => setForm(v => ({ ...v, payto_uri: p }))} /> } +