diff options
Diffstat (limited to 'packages/demobank-ui/src/components/Cashouts/views.tsx')
-rw-r--r-- | packages/demobank-ui/src/components/Cashouts/views.tsx | 159 |
1 files changed, 111 insertions, 48 deletions
diff --git a/packages/demobank-ui/src/components/Cashouts/views.tsx b/packages/demobank-ui/src/components/Cashouts/views.tsx index 0602f507e..32fe0aa9e 100644 --- a/packages/demobank-ui/src/components/Cashouts/views.tsx +++ b/packages/demobank-ui/src/components/Cashouts/views.tsx @@ -14,7 +14,7 @@ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ -import { h, VNode } from "preact"; +import { Fragment, h, VNode } from "preact"; import { useTranslationContext } from "@gnu-taler/web-util/browser"; import { State } from "./index.js"; import { format } from "date-fns"; @@ -33,55 +33,118 @@ export function LoadingUriView({ error }: State.LoadingUriError): VNode { export function ReadyView({ cashouts, onSelected }: State.Ready): VNode { const { i18n } = useTranslationContext(); - if (!cashouts.length) { - return ( - <div> - <i18n.Translate>No cashout at the moment</i18n.Translate> - </div> - ); - } + if (!cashouts.length) return <div /> + const txByDate = cashouts.reduce((prev, cur) => { + const d = cur.creation_time.t_s === "never" + ? "" + : format(cur.creation_time.t_s * 1000, "dd/MM/yyyy") + if (!prev[d]) { + prev[d] = [] + } + prev[d].push(cur) + return prev + }, {} as Record<string, typeof cashouts>) return ( - <div class="results"> - <table class="pure-table pure-table-striped"> - <thead> - <tr> - <th>{i18n.str`Created`}</th> - <th>{i18n.str`Confirmed`}</th> - <th>{i18n.str`Total debit`}</th> - <th>{i18n.str`Total credit`}</th> - <th>{i18n.str`Status`}</th> - <th>{i18n.str`Subject`}</th> - </tr> - </thead> - <tbody> - {cashouts.map((item, idx) => { - return ( - <tr key={idx}> - <td>{item.creation_time.t_s === "never" ? i18n.str`never` : format(item.creation_time.t_s, "dd/MM/yyyy HH:mm:ss")}</td> - <td> - {item.confirmation_time + <div class="px-4 mt-4"> + <div class="sm:flex sm:items-center"> + <div class="sm:flex-auto"> + <h1 class="text-base font-semibold leading-6 text-gray-900"><i18n.Translate>Latest cashouts</i18n.Translate></h1> + </div> + </div> + <div class="-mx-4 mt-5 ring-1 ring-gray-300 sm:mx-0 rounded-lg min-w-fit bg-white"> + <table class="min-w-full divide-y divide-gray-300"> + <thead> + <tr> + <th scope="col" class=" pl-2 py-3.5 text-left text-sm font-semibold text-gray-900">{i18n.str`Created`}</th> + <th scope="col" class="hidden sm:table-cell pl-2 py-3.5 text-left text-sm font-semibold text-gray-900">{i18n.str`Confirmed`}</th> + <th scope="col" class="hidden sm:table-cell pl-2 py-3.5 text-left text-sm font-semibold text-gray-900">{i18n.str`Total debit`}</th> + <th scope="col" class="hidden sm:table-cell pl-2 py-3.5 text-left text-sm font-semibold text-gray-900">{i18n.str`Total credit`}</th> + <th scope="col" class="hidden sm:table-cell pl-2 py-3.5 text-left text-sm font-semibold text-gray-900">{i18n.str`Status`}</th> + <th scope="col" class="hidden sm:table-cell pl-2 py-3.5 text-left text-sm font-semibold text-gray-900">{i18n.str`Subject`}</th> + </tr> + </thead> + <tbody> + {Object.entries(txByDate).map(([date, txs], idx) => { + return <Fragment key={idx}> + <tr class="border-t border-gray-200"> + <th colSpan={4} scope="colgroup" class="bg-gray-50 py-2 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-3"> + {date} + </th> + </tr> + {txs.map(item => { + const creationTime = item.creation_time.t_s === "never" ? "" : format(item.creation_time.t_s * 1000, "HH:mm:ss") + const confirmationTime = item.confirmation_time ? item.confirmation_time.t_s === "never" ? i18n.str`never` : format(item.confirmation_time.t_s, "dd/MM/yyyy HH:mm:ss") - : "-"} - </td> - <td><RenderAmount value={Amounts.parseOrThrow(item.amount_debit)} /></td> - <td><RenderAmount value={Amounts.parseOrThrow(item.amount_credit)} /></td> - <td>{item.status}</td> - <td> - <a - href="#" - onClick={(e) => { - e.preventDefault(); - onSelected(item.id); - }} - > - {item.subject} - </a> - </td> - </tr> - ); - })} - </tbody> - </table> + : "-" + return (<tr key={idx} class="border-b border-gray-200 last:border-none"> + + <td class="relative py-2 pl-2 pr-2 text-sm "> + <div class="font-medium text-gray-900">{creationTime}</div> + {/* <dl class="font-normal sm:hidden"> + <dt class="sr-only sm:hidden"><i18n.Translate>Amount</i18n.Translate></dt> + <dd class="mt-1 truncate text-gray-700"> + {item.negative ? i18n.str`sent` : i18n.str`received`} {item.amount ? ( + <span data-negative={item.negative ? "true" : "false"} class="data-[negative=false]:text-green-600 data-[negative=true]:text-red-600"> + <RenderAmount value={item.amount} /> + </span> + ) : ( + <span style={{ color: "grey" }}><{i18n.str`invalid value`}></span> + )}</dd> + + <dt class="sr-only sm:hidden"><i18n.Translate>Counterpart</i18n.Translate></dt> + <dd class="mt-1 truncate text-gray-500 sm:hidden"> + {item.negative ? i18n.str`to` : i18n.str`from`} {item.counterpart} + </dd> + <dd class="mt-1 text-gray-500 sm:hidden" > + <pre class="break-words w-56 whitespace-break-spaces p-2 rounded-md mx-auto my-2 bg-gray-100"> + {item.subject} + </pre> + </dd> + </dl> */} + </td> + <td class="hidden sm:table-cell px-3 py-3.5 text-sm text-gray-500">{confirmationTime}</td> + <td class="hidden sm:table-cell px-3 py-3.5 text-sm text-red-600"><RenderAmount value={Amounts.parseOrThrow(item.amount_debit)} /></td> + <td class="hidden sm:table-cell px-3 py-3.5 text-sm text-green-600"><RenderAmount value={Amounts.parseOrThrow(item.amount_credit)} /></td> + + <td class="hidden sm:table-cell px-3 py-3.5 text-sm text-gray-500">{item.status}</td> + <td class="hidden sm:table-cell px-3 py-3.5 text-sm text-gray-500 break-all min-w-md"> + <a href="#" onClick={(e) => { + e.preventDefault(); + onSelected(item.id); + }}> + {item.subject} + </a> + </td> + </tr>) + })} + </Fragment> + + })} + </tbody> + + </table> + + {/* <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" + disabled={!onPrev} + onClick={onPrev} + > + <i18n.Translate>First page</i18n.Translate> + </button> + <button + class="relative disabled:bg-gray-100 disabled:text-gray-500 ml-3 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" + disabled={!onNext} + onClick={onNext} + > + <i18n.Translate>Next</i18n.Translate> + </button> + </div> + </nav> */} + </div> </div> ); + // } + } |