aboutsummaryrefslogtreecommitdiff
path: root/packages/demobank-ui/src/components/Cashouts/views.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'packages/demobank-ui/src/components/Cashouts/views.tsx')
-rw-r--r--packages/demobank-ui/src/components/Cashouts/views.tsx159
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" }}>&lt;{i18n.str`invalid value`}&gt;</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>
);
+ // }
+
}