aboutsummaryrefslogtreecommitdiff
path: root/packages/exchange-backoffice-ui/src/Dashboard.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'packages/exchange-backoffice-ui/src/Dashboard.tsx')
-rw-r--r--packages/exchange-backoffice-ui/src/Dashboard.tsx599
1 files changed, 0 insertions, 599 deletions
diff --git a/packages/exchange-backoffice-ui/src/Dashboard.tsx b/packages/exchange-backoffice-ui/src/Dashboard.tsx
deleted file mode 100644
index 6794ca1f8..000000000
--- a/packages/exchange-backoffice-ui/src/Dashboard.tsx
+++ /dev/null
@@ -1,599 +0,0 @@
-import { useNotifications } from "@gnu-taler/web-util/browser";
-import { Dialog, Transition } from "@headlessui/react";
-import { UserIcon, XCircleIcon } from "@heroicons/react/20/solid";
-import { CheckCircleIcon, XMarkIcon } from "@heroicons/react/24/outline";
-import { InformationCircleIcon } from "@heroicons/react/24/solid";
-import { ComponentChildren, Fragment, VNode, h } from "preact";
-import { useState } from "preact/hooks";
-import logo from "./assets/logo-2021.svg";
-import { Pages } from "./pages.js";
-import { Router, useCurrentLocation } from "./route.js";
-
-function classNames(...classes: string[]) {
- return classes.filter(Boolean).join(" ");
-}
-
-/**
- * mapping route to view
- * not found (error page)
- * nested, index element, relative routes
- * link interception
- * form POST interception, call action
- * fromData => Object.fromEntries
- * segments in the URL
- * navigationState: idle, submitting, loading
- * form GET interception: does a navigateTo
- * form GET Sync:
- * 1.- back after submit: useEffect to sync URL to form
- * 2.- refresh after submit: input default value
- * useSubmit for form submission onChange, history replace
- *
- * post form without redirect
- *
- *
- * @param param0
- * @returns
- */
-
-const GIT_HASH = typeof __GIT_HASH__ !== "undefined" ? __GIT_HASH__ : undefined;
-const VERSION = typeof __VERSION__ !== "undefined" ? __VERSION__ : undefined;
-
-const versionText = VERSION
- ? GIT_HASH
- ? `v${VERSION} (${GIT_HASH.substring(0, 8)})`
- : VERSION
- : "";
-
-/**
- * TO BE FIXED:
- *
- * 1.- when the form change to other form and both form share the same structure
- * the same input component may be rendered in the same place,
- * since input are uncontrolled the are not re-rendered and since they are
- * uncontrolled it will keep the value of the previous form.
- * One solutions could be to remove the form when unloading and when the new
- * form load it will start without previous vdom, preventing the cache
- * to create this behavior.
- * Other solutions could be using IDs in the fields that are constructed
- * with the ID of the form, so two fields of different form will need to re-render
- * cleaning up the state of the previous form.
- *
- * 2.- currently the design prop and the behavior prop of the flexible form
- * are two side of the same coin. From the design point of view, it is important
- * to design the form in a list-of-field manner and there may be additional
- * content that is not directly mapped to the form structure (object)
- * So maybe we want to change the current shape so the computation of the state
- * of the form is in a field level, but this computation required the field value and
- * the whole form values and state (since one field may be disabled/hidden) because
- * of the value of other field.
- *
- * 3.- given the previous requirement, maybe the name of the field of the form could be
- * a function (P: F -> V) where F is the form (or parent object) and V is the type of the
- * property. That will help with the typing of the forms props
- *
- * 4.- tooltip are not placed correctly: the arrow should point the question mark
- * and the text area should be bigger
- *
- * 5.- date field should have the calendar icon clickable so the user can select date without
- * writing text with the correct format
- */
-
-function LeftMenu() {
- const currentLocation = useCurrentLocation(pageList);
-
- return (
- <nav class="flex flex-1 flex-col">
- <ul role="list" class="flex flex-1 flex-col gap-y-7">
- <li>
- <ul role="list" class="-mx-2 space-y-1">
- <li>
- <a
- href={Pages.info.url}
- class={classNames(
- Pages.info.url === currentLocation?.path
- ? "bg-indigo-700 text-white"
- : "text-indigo-200 hover:text-white hover:bg-indigo-700",
- "group flex gap-x-3 rounded-md p-2 text-sm leading-6 font-semibold",
- )}
- >
- <InformationCircleIcon
- class={classNames(
- Pages.info.url === currentLocation?.path
- ? "text-white"
- : "text-indigo-200 group-hover:text-white",
- "h-6 w-6 shrink-0",
- )}
- aria-hidden="true"
- />
- Cases
- </a>
- </li>
- <li>
- <a
- href={Pages.officer.url}
- class={classNames(
- Pages.officer.url === currentLocation?.path
- ? "bg-indigo-700 text-white"
- : "text-indigo-200 hover:text-white hover:bg-indigo-700",
- "group flex gap-x-3 rounded-md p-2 text-sm leading-6 font-semibold",
- )}
- >
- <UserIcon
- class={classNames(
- Pages.officer.url === currentLocation?.path
- ? "text-white"
- : "text-indigo-200 group-hover:text-white",
- "h-6 w-6 shrink-0",
- )}
- aria-hidden="true"
- />
- Account
- </a>
- </li>
- </ul>
- </li>
- {/* <li>
- <div class="text-xs font-semibold leading-6 text-indigo-200">
- Info
- </div>
- <ul role="list" class="-mx-2 mt-2 space-y-1">
- <li>
- <a
- href={Pages.info.url}
- class={classNames(
- Pages.info.url === currentLocation?.path
- ? "bg-indigo-700 text-white"
- : "text-indigo-200 hover:text-white hover:bg-indigo-700",
- "group flex gap-x-3 rounded-md p-2 text-sm leading-6 font-semibold",
- )}
- >
- <span class="flex h-6 w-6 shrink-0 items-center justify-center rounded-lg border border-indigo-400 bg-indigo-500 text-[0.625rem] font-medium text-white">
- asd
- </span>
- <span class="truncate">qwe</span>
- </a>
- </li>
- </ul>
- </li> */}
- {/* <li class="mt-auto">
- <a
- href={Pages.settings.url}
- class={classNames(
- Pages.settings.url === currentLocation?.path
- ? "bg-indigo-700 text-white"
- : "text-indigo-200 hover:text-white hover:bg-indigo-700",
- "group -mx-2 flex gap-x-3 rounded-md p-2 text-sm leading-6 font-semibold",
- )}
- >
- <Cog6ToothIcon
- class={classNames(
- Pages.officer.url === currentLocation?.path
- ? "text-white"
- : "text-indigo-200 group-hover:text-white",
- "h-6 w-6 shrink-0",
- )}
- aria-hidden="true"
- />
- Settings
- </a>
- </li> */}
- </ul>
- </nav>
- );
-}
-
-export function Dashboard({
- children,
-}: {
- children?: ComponentChildren;
-}): VNode {
- const [sidebarOpen, setSidebarOpen] = useState(false);
-
- return (
- <Fragment>
- <NavigationBar isOpen={sidebarOpen} setOpen={setSidebarOpen}>
- <div class="flex grow flex-col gap-y-5 overflow-y-auto bg-indigo-600 px-6 pb-4">
- <div class="flex h-16 shrink-0 items-center">
- <header class="flex items-center justify-between border-b border-white/5 ">
- <h1 class="text-base font-semibold leading-7 text-white">
- Exchange AML Backoffice
- </h1>
- </header>
- </div>
- <LeftMenu />
- <Footer />
- </div>
- </NavigationBar>
- <div class="lg:pl-72">
- <TopBar
- onOpenSidebar={() => {
- setSidebarOpen(true);
- }}
- />
- <Notifications />
- <main class="py-10 px-4 sm:px-6 lg:px-8">
- <div class="mx-auto max-w-3xl">
- <Router
- pageList={pageList}
- onNotFound={() => {
- return <div>not found</div>;
- }}
- />
- </div>
- </main>
- </div>
- </Fragment>
- );
-}
-
-const pageList = Object.values(Pages);
-
-function NavigationBar({
- isOpen,
- setOpen,
- children,
-}: {
- isOpen: boolean;
- setOpen: (v: boolean) => void;
- children: ComponentChildren;
-}) {
- return (
- <Fragment>
- <Transition.Root show={isOpen} as={Fragment}>
- <Dialog
- as="div"
- /* @ts-ignore */
- class="relative z-50 lg:hidden"
- onClose={setOpen}
- >
- <Transition.Child
- as={Fragment}
- enter="transition-opacity ease-linear duration-300"
- enterFrom="opacity-0"
- enterTo="opacity-100"
- leave="transition-opacity ease-linear duration-300"
- leaveFrom="opacity-100"
- leaveTo="opacity-0"
- >
- <div class="fixed inset-0 bg-gray-900/80" />
- </Transition.Child>
-
- <div class="fixed inset-0 flex">
- <Transition.Child
- as={Fragment}
- enter="transition ease-in-out duration-300 transform"
- enterFrom="-translate-x-full"
- enterTo="translate-x-0"
- leave="transition ease-in-out duration-300 transform"
- leaveFrom="translate-x-0"
- leaveTo="-translate-x-full"
- >
- <Dialog.Panel class="relative mr-16 flex w-full max-w-xs flex-1">
- <Transition.Child
- as={Fragment}
- enter="ease-in-out duration-300"
- enterFrom="opacity-0"
- enterTo="opacity-100"
- leave="ease-in-out duration-300"
- leaveFrom="opacity-100"
- leaveTo="opacity-0"
- >
- <div class="absolute left-full top-0 flex w-16 justify-center pt-5">
- <button
- type="button"
- class="-m-2.5 p-2.5"
- onClick={() => setOpen(false)}
- >
- <span class="sr-only">Close sidebar</span>
- <XMarkIcon
- class="h-6 w-6 text-white"
- aria-hidden="true"
- />
- </button>
- </div>
- </Transition.Child>
- {children}
- </Dialog.Panel>
- </Transition.Child>
- </div>
- </Dialog>
- </Transition.Root>
-
- <div class="hidden lg:fixed lg:inset-y-0 lg:z-50 lg:flex lg:w-72 lg:flex-col">
- {children}
- </div>
- </Fragment>
- );
-}
-
-function TopBar({ onOpenSidebar }: { onOpenSidebar: () => void }) {
- return (
- <div class="relative flex h-16 justify-between">
- <div class="relative z-10 flex p-2 lg:hidden">
- <button
- type="button"
- onClick={() => {
- onOpenSidebar();
- }}
- class="inline-flex items-center justify-center rounded-md p-2 text-gray-400 hover:bg-gray-700 hover:text-gray-900 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-gray-900"
- aria-controls="mobile-menu"
- aria-expanded="false"
- >
- <span class="sr-only">Open menu</span>
- <svg
- class="block h-6 w-6"
- fill="none"
- viewBox="0 0 24 24"
- stroke-width="1.5"
- stroke="currentColor"
- aria-hidden="true"
- >
- <path
- stroke-linecap="round"
- stroke-linejoin="round"
- d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5"
- />
- </svg>
- <svg
- class="hidden h-6 w-6"
- fill="none"
- viewBox="0 0 24 24"
- stroke-width="1.5"
- stroke="currentColor"
- aria-hidden="true"
- >
- <path
- stroke-linecap="round"
- stroke-linejoin="round"
- d="M6 18L18 6M6 6l12 12"
- />
- </svg>
- </button>
- </div>
- <div class="relative z-0 flex flex-1 items-center justify-center px-2 sm:absolute sm:inset-0">
- <div class="w-full sm:max-w-xs flex flex-1 items-center justify-center">
- <img
- class="h-8 w-auto"
- src={logo}
- alt="Taler"
- style={{ height: 35, margin: 10 }}
- />
- </div>
- </div>
- {/* <div class="relative z-10 flex items-center lg:hidden">dd</div> */}
- </div>
- );
-}
-
-// return (
-// <div class="sticky top-0 z-40 flex h-16 shrink-0 items-center gap-x-4 border-b border-gray-200 bg-white px-4 shadow-sm sm:gap-x-6 sm:px-6 lg:px-8">
-// <button
-// type="button"
-// class="-m-2.5 p-2.5 text-gray-700 lg:hidden"
-// onClick={onOpenSidebar}
-// >
-// <span class="sr-only">Open sidebar</span>
-// <Bars3Icon class="h-6 w-6" aria-hidden="true" />
-// </button>
-
-// {/* Separator */}
-// <div class="h-6 w-px bg-gray-900/10 lg:hidden" aria-hidden="true" />
-
-// <div class="flex flex-1 gap-x-4 self-stretch lg:gap-x-6">
-// <div class="relative flex flex-1" />
-// {/* <form class="relative flex flex-1" action="#" method="GET">
-// <label htmlFor="search-field" class="sr-only">
-// Search
-// </label>
-// <MagnifyingGlassIcon
-// class="pointer-events-none absolute inset-y-0 left-0 h-full w-5 text-gray-400"
-// aria-hidden="true"
-// />
-// <input
-// id="search-field"
-// class="block h-full w-full border-0 py-0 pl-8 pr-0 text-gray-900 placeholder:text-gray-400 focus:ring-0 sm:text-sm"
-// placeholder="Search..."
-// type="search"
-// name="search"
-// />
-// </form> */}
-// <div class="flex items-center gap-x-4 lg:gap-x-6">
-// {/* <button
-// type="button"
-// class="-m-2.5 p-2.5 text-gray-400 hover:text-gray-500"
-// >
-// <span class="sr-only">View notifications</span>
-// <BellIcon class="h-6 w-6" aria-hidden="true" />
-// </button> */}
-
-// {/* Separator */}
-// <div
-// class="hidden lg:block lg:h-6 lg:w-px lg:bg-gray-900/10"
-// aria-hidden="true"
-// />
-
-// {/* {officerName === undefined ? (
-// <div />
-// ) : (
-// <Menu
-// as="div"
-// class="relative"
-// >
-// <Menu.Button class="-m-1.5 flex items-center p-1.5">
-// <span class="sr-only">Open user menu</span>
-// <img
-// class="h-8 w-8 rounded-full bg-gray-50"
-// src="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80"
-// alt=""
-// />
-// <span class="hidden lg:flex lg:items-center">
-// <span
-// class="ml-4 text-sm font-semibold leading-6 text-gray-900"
-// aria-hidden="true"
-// >
-// {officerName}
-// </span>
-// <ChevronDownIcon
-// class="ml-2 h-5 w-5 text-gray-400"
-// aria-hidden="true"
-// />
-// </span>
-// </Menu.Button>
-// <Transition
-// as={Fragment}
-// enter="transition ease-out duration-100"
-// enterFrom="transform opacity-0 scale-95"
-// enterTo="transform opacity-100 scale-100"
-// leave="transition ease-in duration-75"
-// leaveFrom="transform opacity-100 scale-100"
-// leaveTo="transform opacity-0 scale-95"
-// >
-// <Menu.Items class="absolute right-0 z-10 mt-2.5 w-48 origin-top-right rounded-md bg-white py-2 shadow-lg ring-1 ring-gray-900/5 focus:outline-none">
-// <Menu.Item>
-// {({ active }: { active: boolean }) => (
-// <a
-// onClick={() => {
-// officer.reset();
-// password.reset();
-// }}
-// class={classNames(
-// active ? "bg-gray-50" : "",
-// "block px-3 py-1 text-sm leading-6 text-gray-900",
-// )}
-// >
-// Forget account
-// </a>
-// )}
-// </Menu.Item>
-// </Menu.Items>
-// </Transition>
-// </Menu>
-// )} */}
-// </div>
-// </div>
-// </div>
-// );
-// }
-
-function Footer() {
- return (
- <footer class="absolute bottom-4">
- <div class="mt-8 md:order-1 md:mt-0">
- <p class="text-xs leading-5 text-gray-300">
- Taler Systems SA. {versionText}
- </p>
- </div>
- </footer>
- );
-}
-
-function Notifications() {
- const ns = useNotifications();
-
- // useEffect(() => {
- // if (ns.length) {
- // // remove notifications after some timeout
- // }
- // }, []);
- {
- /* <!-- Global notification live region, render this permanently at the end of the document --> */
- }
- return (
- <div
- aria-live="assertive"
- class="pointer-events-none fixed inset-0 flex items-end px-4 py-6 sm:items-start sm:p-6 z-50"
- >
- <div class="flex w-full flex-col items-center space-y-4 sm:items-end ">
- {/* <!--
- Notification panel, dynamically insert this into the live region when it needs to be displayed
-
- Entering: "transform ease-out duration-300 transition"
- From: "translate-y-2 opacity-0 sm:translate-y-0 sm:translate-x-2"
- To: "translate-y-0 opacity-100 sm:translate-x-0"
- Leaving: "transition ease-in duration-100"
- From: "opacity-100"
- To: "opacity-0"
---> */}
- {ns.map(({ message, remove }) => {
- switch (message.type) {
- case "error": {
- return (
- <div class="pointer-events-auto w-full max-w-sm overflow-hidden rounded-lg bg-white shadow-lg ring-1 ring-black ring-opacity-5 ">
- <div class="p-4 ">
- <div class="flex items-start ">
- <div class="flex-shrink-0">
- <XCircleIcon class="h-6 w-6 text-red-400" />
- </div>
- <div class="ml-3 w-0 flex-1 pt-0.5">
- <p class="text-sm font-medium text-gray-900">
- {message.title}
- </p>
- {message.description && (
- <p class="mt-1 text-sm text-gray-500">
- {message.description}
- </p>
- )}
- </div>
- <div class="ml-4 flex flex-shrink-0">
- <button
- type="button"
- onClick={remove}
- class="inline-flex rounded-md bg-white text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
- >
- <span class="sr-only">Close</span>
- <svg
- class="h-5 w-5"
- viewBox="0 0 20 20"
- fill="currentColor"
- aria-hidden="true"
- >
- <path d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z" />
- </svg>
- </button>
- </div>
- </div>
- </div>
- </div>
- );
- }
- case "info": {
- return (
- <div class="pointer-events-auto w-full max-w-sm overflow-hidden rounded-lg bg-white shadow-lg ring-1 ring-black ring-opacity-5 ">
- <div class="p-4 ">
- <div class="flex items-start ">
- <div class="flex-shrink-0">
- <CheckCircleIcon class="h-6 w-6 text-green-400" />
- </div>
- <div class="ml-3 w-0 flex-1 pt-0.5">
- <p class="text-sm font-medium text-gray-900">
- {message.title}
- </p>
- </div>
- <div class="ml-4 flex flex-shrink-0">
- <button
- type="button"
- onClick={remove}
- class="inline-flex rounded-md bg-white text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
- >
- <span class="sr-only">Close</span>
- <svg
- class="h-5 w-5"
- viewBox="0 0 20 20"
- fill="currentColor"
- aria-hidden="true"
- >
- <path d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z" />
- </svg>
- </button>
- </div>
- </div>
- </div>
- </div>
- );
- }
- }
- })}
- </div>
- </div>
- );
-}