diff options
author | Sebastian <sebasjm@gmail.com> | 2024-04-04 16:24:55 -0300 |
---|---|---|
committer | Sebastian <sebasjm@gmail.com> | 2024-04-04 16:25:08 -0300 |
commit | 072ac43b9f69807b8514eb11f8214637561a2573 (patch) | |
tree | b5b464682589f2b80dc4d8f547e9d549a4df353a /packages/aml-backoffice-ui/src/pages | |
parent | 01838bfcc74a2e4e828885d5ab0d6f64cc96f328 (diff) | |
download | wallet-core-072ac43b9f69807b8514eb11f8214637561a2573.tar.xz |
fix some API differences including whatwg-url params
Diffstat (limited to 'packages/aml-backoffice-ui/src/pages')
-rw-r--r-- | packages/aml-backoffice-ui/src/pages/Cases.tsx | 398 |
1 files changed, 237 insertions, 161 deletions
diff --git a/packages/aml-backoffice-ui/src/pages/Cases.tsx b/packages/aml-backoffice-ui/src/pages/Cases.tsx index 88580a4ce..faef0ca54 100644 --- a/packages/aml-backoffice-ui/src/pages/Cases.tsx +++ b/packages/aml-backoffice-ui/src/pages/Cases.tsx @@ -1,168 +1,198 @@ -import { HttpStatusCode, TalerError, TalerExchangeApi, TranslatedString, assertUnreachable } from "@gnu-taler/taler-util"; -import { ErrorLoading, Loading, createNewForm, useTranslationContext } from "@gnu-taler/web-util/browser"; +/* + This file is part of GNU Taler + (C) 2022 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/> + */ +import { + HttpStatusCode, + TalerError, + TalerExchangeApi, + assertUnreachable +} from "@gnu-taler/taler-util"; +import { + ErrorLoading, + Loading, + createNewForm, + useTranslationContext, +} from "@gnu-taler/web-util/browser"; import { VNode, h } from "preact"; import { useState } from "preact/hooks"; import { useCases } from "../hooks/useCases.js"; import { Pages } from "../pages.js"; -import { Officer } from "./Officer.js"; import { amlStateConverter } from "../utils/converter.js"; import { AmlExchangeBackend } from "../utils/types.js"; +import { Officer } from "./Officer.js"; -export function CasesUI({ records, filter, onChangeFilter, onFirstPage, onNext }: { onFirstPage?: () => void, onNext?: () => void, filter: AmlExchangeBackend.AmlState, onChangeFilter: (f: AmlExchangeBackend.AmlState) => void, records: TalerExchangeApi.AmlRecord[] }): VNode { +export function CasesUI({ + records, + filter, + onChangeFilter, + onFirstPage, + onNext, +}: { + onFirstPage?: () => void; + onNext?: () => void; + filter: AmlExchangeBackend.AmlState; + onChangeFilter: (f: AmlExchangeBackend.AmlState) => void; + records: TalerExchangeApi.AmlRecord[]; +}): VNode { const { i18n } = useTranslationContext(); const form = createNewForm<{ state: AmlExchangeBackend.AmlState }>(); - return <div> - <div class="sm:flex sm:items-center"> - <div class="px-2 sm:flex-auto"> - <h1 class="text-base font-semibold leading-6 text-gray-900"> - <i18n.Translate> - Cases - </i18n.Translate> - </h1> - <p class="mt-2 text-sm text-gray-700 w-80"> - <i18n.Translate> - A list of all the account with the status - </i18n.Translate> - </p> - </div> - <div class="px-2"> - <form.Provider - initial={{ state: filter }} - onUpdate={(v) => { - onChangeFilter(v.state ?? filter); - }} - onSubmit={(v) => { }} - > - <form.InputChoiceHorizontal - name="state" - label={i18n.str`Filter`} - converter={amlStateConverter} - choices={[ - { - label: i18n.str`Pending`, - value: AmlExchangeBackend.AmlState.pending, - }, - { - label: i18n.str`Frozen`, - value: AmlExchangeBackend.AmlState.frozen, - }, - { - label: i18n.str`Normal`, - value: AmlExchangeBackend.AmlState.normal, - }, - ]} - /> - - </form.Provider> + return ( + <div> + <div class="sm:flex sm:items-center"> + <div class="px-2 sm:flex-auto"> + <h1 class="text-base font-semibold leading-6 text-gray-900"> + <i18n.Translate>Cases</i18n.Translate> + </h1> + <p class="mt-2 text-sm text-gray-700 w-80"> + <i18n.Translate> + A list of all the account with the status + </i18n.Translate> + </p> + </div> + <div class="px-2"> + <form.Provider + initial={{ state: filter }} + onUpdate={(v) => { + onChangeFilter(v.state ?? filter); + }} + onSubmit={(_v) => {}} + > + <form.InputChoiceHorizontal + name="state" + label={i18n.str`Filter`} + converter={amlStateConverter} + choices={[ + { + label: i18n.str`Pending`, + value: AmlExchangeBackend.AmlState.pending, + }, + { + label: i18n.str`Frozen`, + value: AmlExchangeBackend.AmlState.frozen, + }, + { + label: i18n.str`Normal`, + value: AmlExchangeBackend.AmlState.normal, + }, + ]} + /> + </form.Provider> + </div> </div> - </div> - <div class="mt-8 flow-root"> - <div class="overflow-x-auto"> - {!records.length ? ( - <div>empty result </div> - ) : ( - <div class="inline-block min-w-full py-2 align-middle sm:px-6 lg:px-8"> - <table class="min-w-full divide-y divide-gray-300"> - <thead> - <tr> - <th - scope="col" - class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 w-80" - > - <i18n.Translate> - Account Id - </i18n.Translate> - </th> - <th - scope="col" - class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 w-40" - > - <i18n.Translate> - Status - </i18n.Translate> - </th> - <th - scope="col" - class="sm:hidden px-3 py-3.5 text-left text-sm font-semibold text-gray-900 w-40" - > - <i18n.Translate> - Threshold - </i18n.Translate> - </th> - </tr> - </thead> - <tbody class="divide-y divide-gray-200 bg-white"> - {records.map((r) => { - return ( - <tr class="hover:bg-gray-100 "> - <td class="whitespace-nowrap px-3 py-5 text-sm text-gray-500 "> - <div class="text-gray-900"> - <a - href={Pages.account.url({ account: r.h_payto })} - class="text-indigo-600 hover:text-indigo-900" - > - {r.h_payto.substring(0, 16)}... - </a> - </div> - </td> - <td class="whitespace-nowrap px-3 py-5 text-sm text-gray-500"> - {((state: AmlExchangeBackend.AmlState): VNode => { - switch (state) { - case AmlExchangeBackend.AmlState.normal: { - return ( - <span class="inline-flex items-center rounded-md bg-green-50 px-2 py-1 text-xs font-medium text-green-700 ring-1 ring-inset ring-green-600/20"> - Normal - </span> - ); - } - case AmlExchangeBackend.AmlState.pending: { - return ( - <span class="inline-flex items-center rounded-md bg-yellow-50 px-2 py-1 text-xs font-medium text-yellow-700 ring-1 ring-inset ring-green-600/20"> - Pending - </span> - ); + <div class="mt-8 flow-root"> + <div class="overflow-x-auto"> + {!records.length ? ( + <div>empty result </div> + ) : ( + <div class="inline-block min-w-full py-2 align-middle sm:px-6 lg:px-8"> + <table class="min-w-full divide-y divide-gray-300"> + <thead> + <tr> + <th + scope="col" + class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 w-80" + > + <i18n.Translate>Account Id</i18n.Translate> + </th> + <th + scope="col" + class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 w-40" + > + <i18n.Translate>Status</i18n.Translate> + </th> + <th + scope="col" + class="sm:hidden px-3 py-3.5 text-left text-sm font-semibold text-gray-900 w-40" + > + <i18n.Translate>Threshold</i18n.Translate> + </th> + </tr> + </thead> + <tbody class="divide-y divide-gray-200 bg-white"> + {records.map((r) => { + return ( + <tr key={r.h_payto} class="hover:bg-gray-100 "> + <td class="whitespace-nowrap px-3 py-5 text-sm text-gray-500 "> + <div class="text-gray-900"> + <a + href={Pages.account.url({ account: r.h_payto })} + class="text-indigo-600 hover:text-indigo-900" + > + {r.h_payto.substring(0, 16)}... + </a> + </div> + </td> + <td class="whitespace-nowrap px-3 py-5 text-sm text-gray-500"> + {((state: AmlExchangeBackend.AmlState): VNode => { + switch (state) { + case AmlExchangeBackend.AmlState.normal: { + return ( + <span class="inline-flex items-center rounded-md bg-green-50 px-2 py-1 text-xs font-medium text-green-700 ring-1 ring-inset ring-green-600/20"> + Normal + </span> + ); + } + case AmlExchangeBackend.AmlState.pending: { + return ( + <span class="inline-flex items-center rounded-md bg-yellow-50 px-2 py-1 text-xs font-medium text-yellow-700 ring-1 ring-inset ring-green-600/20"> + Pending + </span> + ); + } + case AmlExchangeBackend.AmlState.frozen: { + return ( + <span class="inline-flex items-center rounded-md bg-red-50 px-2 py-1 text-xs font-medium text-red-700 ring-1 ring-inset ring-green-600/20"> + Frozen + </span> + ); + } } - case AmlExchangeBackend.AmlState.frozen: { - return ( - <span class="inline-flex items-center rounded-md bg-red-50 px-2 py-1 text-xs font-medium text-red-700 ring-1 ring-inset ring-green-600/20"> - Frozen - </span> - ); - } - } - })(r.current_state)} - </td> - <td class="whitespace-nowrap px-3 py-5 text-sm text-gray-900"> - {r.threshold} - </td> - </tr> - ); - })} - </tbody> - </table> - <Pagination onFirstPage={onFirstPage} onNext={onNext} /> - </div> - )} + })(r.current_state)} + </td> + <td class="whitespace-nowrap px-3 py-5 text-sm text-gray-900"> + {r.threshold} + </td> + </tr> + ); + })} + </tbody> + </table> + <Pagination onFirstPage={onFirstPage} onNext={onNext} /> + </div> + )} + </div> </div> </div> - </div> - + ); } - export function Cases() { - const [stateFilter, setStateFilter] = useState(AmlExchangeBackend.AmlState.pending); + const [stateFilter, setStateFilter] = useState( + AmlExchangeBackend.AmlState.pending, + ); const list = useCases(stateFilter); if (!list) { - return <Loading /> + return <Loading />; } if (list instanceof TalerError) { - return <ErrorLoading error={list} /> + return <ErrorLoading error={list} />; } if (list.data.type === "fail") { @@ -170,34 +200,81 @@ export function Cases() { case HttpStatusCode.Unauthorized: case HttpStatusCode.Forbidden: case HttpStatusCode.NotFound: - case HttpStatusCode.Conflict: return <Officer /> - default: assertUnreachable(list.data) + case HttpStatusCode.Conflict: + return <Officer />; + default: + assertUnreachable(list.data); } } - const { records } = list.data.body + const { records } = list.data.body; - return <CasesUI - records={records} - onFirstPage={list.pagination && !list.pagination.isFirstPage ? list.pagination.reset : undefined} - onNext={list.pagination && !list.pagination.isLastPage ? list.pagination.loadMore : undefined} - filter={stateFilter} - onChangeFilter={setStateFilter} - /> + return ( + <CasesUI + records={records} + onFirstPage={ + list.pagination && !list.pagination.isFirstPage + ? list.pagination.reset + : undefined + } + onNext={ + list.pagination && !list.pagination.isLastPage + ? list.pagination.loadMore + : undefined + } + filter={stateFilter} + onChangeFilter={setStateFilter} + /> + ); } -export const PeopleIcon = () => <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6"> - <path stroke-linecap="round" stroke-linejoin="round" d="M15.75 6a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0zM4.501 20.118a7.5 7.5 0 0114.998 0A17.933 17.933 0 0112 21.75c-2.676 0-5.216-.584-7.499-1.632z" /> -</svg> +export const PeopleIcon = () => ( + <svg + xmlns="http://www.w3.org/2000/svg" + fill="none" + viewBox="0 0 24 24" + stroke-width="1.5" + stroke="currentColor" + class="w-6 h-6" + > + <path + stroke-linecap="round" + stroke-linejoin="round" + d="M15.75 6a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0zM4.501 20.118a7.5 7.5 0 0114.998 0A17.933 17.933 0 0112 21.75c-2.676 0-5.216-.584-7.499-1.632z" + /> + </svg> +); -export const HomeIcon = () => <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6"> - <path stroke-linecap="round" stroke-linejoin="round" d="M2.25 12l8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25" /> -</svg> +export const HomeIcon = () => ( + <svg + xmlns="http://www.w3.org/2000/svg" + fill="none" + viewBox="0 0 24 24" + stroke-width="1.5" + stroke="currentColor" + class="w-6 h-6" + > + <path + stroke-linecap="round" + stroke-linejoin="round" + d="M2.25 12l8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25" + /> + </svg> +); -function Pagination({ onFirstPage, onNext }: { onFirstPage?: () => void, onNext?: () => void, }) { - const { i18n } = useTranslationContext() +function Pagination({ + onFirstPage, + onNext, +}: { + onFirstPage?: () => void; + onNext?: () => void; +}) { + const { i18n } = useTranslationContext(); return ( - <nav class="flex items-center justify-between border-t border-gray-200 bg-white px-4 py-3 sm:px-6 rounded-lg" aria-label="Pagination"> + <nav + class="flex items-center justify-between border-t border-gray-200 bg-white px-4 py-3 sm:px-6 rounded-lg" + aria-label="Pagination" + > <div class="flex flex-1 justify-between sm:justify-end"> <button class="relative disabled:bg-gray-100 disabled:text-gray-500 inline-flex items-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus-visible:outline-offset-0" @@ -215,6 +292,5 @@ function Pagination({ onFirstPage, onNext }: { onFirstPage?: () => void, onNext? </button> </div> </nav> - - ) + ); } |