merchant-backoffice

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

commit a8f51ec0f991bb6ea2b4171c4b3ec50a3dc7ac9b
parent 92be26c1a5981004923b46ce6dac8977103c65a4
Author: Sebastian <sebasjm@gmail.com>
Date:   Thu,  2 Dec 2021 15:07:25 -0300

-format with prettier

Diffstat:
Mpackages/merchant-backoffice/src/InstanceRoutes.tsx | 623+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
Mpackages/merchant-backoffice/src/components/menu/index.tsx | 219+++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------
Mpackages/merchant-backoffice/src/utils/types.ts | 7+++----
3 files changed, 521 insertions(+), 328 deletions(-)

diff --git a/packages/merchant-backoffice/src/InstanceRoutes.tsx b/packages/merchant-backoffice/src/InstanceRoutes.tsx @@ -15,327 +15,448 @@ */ /** -* -* @author Sebastian Javier Marchano (sebasjm) -*/ + * + * @author Sebastian Javier Marchano (sebasjm) + */ -import { Fragment, FunctionComponent, h, VNode } from 'preact'; -import { Route, route, Router } from 'preact-router'; +import { Fragment, FunctionComponent, h, VNode } from "preact"; +import { Route, route, Router } from "preact-router"; import { useCallback, useEffect, useMemo, useState } from "preact/hooks"; -import { Loading } from './components/exception/loading'; -import { NotificationCard } from './components/menu'; -import { useBackendContext } from './context/backend'; -import { InstanceContextProvider } from './context/instance'; -import { useBackendDefaultToken, useBackendInstanceToken } from './hooks'; +import { Loading } from "./components/exception/loading"; +import { NotificationCard } from "./components/menu"; +import { useBackendContext } from "./context/backend"; +import { InstanceContextProvider } from "./context/instance"; +import { useBackendDefaultToken, useBackendInstanceToken } from "./hooks"; import { HttpError } from "./hooks/backend"; -import { useTranslator } from './i18n'; +import { useTranslator } from "./i18n"; import InstanceCreatePage from "./paths/admin/create"; -import InstanceListPage from './paths/admin/list'; -import OrderCreatePage from './paths/instance/orders/create'; -import OrderDetailsPage from './paths/instance/orders/details'; -import OrderListPage from './paths/instance/orders/list'; -import ProductCreatePage from './paths/instance/products/create'; -import ProductListPage from './paths/instance/products/list'; -import ProductUpdatePage from './paths/instance/products/update'; -import TransferListPage from './paths/instance/transfers/list'; -import TransferCreatePage from './paths/instance/transfers/create'; -import ReservesCreatePage from './paths/instance/reserves/create'; -import ReservesDetailsPage from './paths/instance/reserves/details'; -import ReservesListPage from './paths/instance/reserves/list'; -import InstanceUpdatePage, { Props as InstanceUpdatePageProps, AdminUpdate as InstanceAdminUpdatePage } from "./paths/instance/update"; -import LoginPage from './paths/login'; -import NotFoundPage from './paths/notfound'; -import { Notification } from './utils/types'; +import InstanceListPage from "./paths/admin/list"; +import OrderCreatePage from "./paths/instance/orders/create"; +import OrderDetailsPage from "./paths/instance/orders/details"; +import OrderListPage from "./paths/instance/orders/list"; +import ProductCreatePage from "./paths/instance/products/create"; +import ProductListPage from "./paths/instance/products/list"; +import ProductUpdatePage from "./paths/instance/products/update"; +import TransferListPage from "./paths/instance/transfers/list"; +import TransferCreatePage from "./paths/instance/transfers/create"; +import ReservesCreatePage from "./paths/instance/reserves/create"; +import ReservesDetailsPage from "./paths/instance/reserves/details"; +import ReservesListPage from "./paths/instance/reserves/list"; +import InstanceUpdatePage, { + Props as InstanceUpdatePageProps, + AdminUpdate as InstanceAdminUpdatePage, +} from "./paths/instance/update"; +import LoginPage from "./paths/login"; +import NotFoundPage from "./paths/notfound"; +import { Notification } from "./utils/types"; export enum InstancePaths { // details = '/', - error = '/error', - update = '/update', + error = "/error", + update = "/update", - product_list = '/products', - product_update = '/product/:pid/update', - product_new = '/product/new', + product_list = "/products", + product_update = "/product/:pid/update", + product_new = "/product/new", - order_list = '/orders', - order_new = '/order/new', - order_details = '/order/:oid/details', + order_list = "/orders", + order_new = "/order/new", + order_details = "/order/:oid/details", - reserves_list = '/reserves', - reserves_details = '/reserves/:rid/details', - reserves_new = '/reserves/new', + reserves_list = "/reserves", + reserves_details = "/reserves/:rid/details", + reserves_new = "/reserves/new", - transfers_list = '/transfers', - transfers_new = '/transfer/new', + transfers_list = "/transfers", + transfers_new = "/transfer/new", } // eslint-disable-next-line @typescript-eslint/no-empty-function -const noop = () => { } +const noop = () => {}; export enum AdminPaths { - list_instances = '/instances', - new_instance = '/instance/new', - update_instance = '/instance/:id/update', + list_instances = "/instances", + new_instance = "/instance/new", + update_instance = "/instance/:id/update", } export interface Props { id: string; admin?: boolean; - setInstanceName: (s:string) => void + setInstanceName: (s: string) => void; } export function InstanceRoutes({ id, admin, setInstanceName }: Props): VNode { - const [_, updateDefaultToken] = useBackendDefaultToken() + const [_, updateDefaultToken] = useBackendDefaultToken(); const [token, updateToken] = useBackendInstanceToken(id); - const { updateLoginStatus: changeBackend, addTokenCleaner } = useBackendContext(); - const cleaner = useCallback(() => { updateToken(undefined); }, [id]); + const { updateLoginStatus: changeBackend, addTokenCleaner } = + useBackendContext(); + const cleaner = useCallback(() => { + updateToken(undefined); + }, [id]); const i18n = useTranslator(); - const [globalNotification, setGlobalNotification] = useState<Notification & { to: string } | undefined>(undefined) + const [globalNotification, setGlobalNotification] = useState< + (Notification & { to: string }) | undefined + >(undefined); useEffect(() => { addTokenCleaner(cleaner); }, [addTokenCleaner, cleaner]); - const changeToken = (token?:string) => { + const changeToken = (token?: string) => { if (admin) { updateToken(token); } else { - updateDefaultToken(token) + updateDefaultToken(token); } - } + }; const updateLoginStatus = (url: string, token?: string) => { changeBackend(url); - if (!token) return - changeToken(token) + if (!token) return; + changeToken(token); }; - const value = useMemo(() => ({ id, token, admin, changeToken }), [id, token, admin]) - - const ServerErrorRedirectTo = (to: InstancePaths | AdminPaths) => (error: HttpError) => { - setGlobalNotification({ - message: i18n`The backend reported a problem: HTTP status #${error.status}`, - description: i18n`Diagnostic from ${error.info?.url} is "${error.message}"`, - type: 'ERROR', - to - }) - return <Redirect to={to} /> - } - - const LoginPageAccessDenied = () => <Fragment> - <NotificationCard notification={{ message: i18n`Access denied`, description: i18n`The access token provided is invalid.`, type: 'ERROR', }} /> - <LoginPage onConfirm={updateLoginStatus} /> - </Fragment> + const value = useMemo( + () => ({ id, token, admin, changeToken }), + [id, token, admin] + ); + + const ServerErrorRedirectTo = + (to: InstancePaths | AdminPaths) => (error: HttpError) => { + setGlobalNotification({ + message: i18n`The backend reported a problem: HTTP status #${error.status}`, + description: i18n`Diagnostic from ${error.info?.url} is "${error.message}"`, + type: "ERROR", + to, + }); + return <Redirect to={to} />; + }; + + const LoginPageAccessDenied = () => ( + <Fragment> + <NotificationCard + notification={{ + message: i18n`Access denied`, + description: i18n`The access token provided is invalid.`, + type: "ERROR", + }} + /> + <LoginPage onConfirm={updateLoginStatus} /> + </Fragment> + ); function IfAdminCreateDefaultOr<T>(Next: FunctionComponent<any>) { return function IfAdminCreateDefaultOrImpl(props?: T) { - if (admin && id === 'default') { - return <Fragment> - <NotificationCard notification={{ - message: i18n`No 'default' instance configured yet.`, - description: i18n`Create a 'default' instance to begin using the merchant backoffice.`, - type: 'INFO' - }} /> - <InstanceCreatePage forceId="default" onConfirm={() => { - route(AdminPaths.list_instances) - }} /> - </Fragment> + if (admin && id === "default") { + return ( + <Fragment> + <NotificationCard + notification={{ + message: i18n`No 'default' instance configured yet.`, + description: i18n`Create a 'default' instance to begin using the merchant backoffice.`, + type: "INFO", + }} + /> + <InstanceCreatePage + forceId="default" + onConfirm={() => { + route(AdminPaths.list_instances); + }} + /> + </Fragment> + ); } if (props) { - return <Next {...props} /> + return <Next {...props} />; } - return <Next /> - - } + return <Next />; + }; } - return <InstanceContextProvider value={value}> - - <NotificationCard notification={globalNotification} /> - - <Router onChange={(e) => { - const movingOutFromNotification = globalNotification && e.url !== globalNotification.to - if (movingOutFromNotification) { - setGlobalNotification(undefined) - } - }} > - - <Route path="/" component={Redirect} to={InstancePaths.order_list} /> - - {/** - * Admin pages - */} - {admin && - <Route path={AdminPaths.list_instances} component={InstanceListPage} - onCreate={() => { route(AdminPaths.new_instance) }} - onUpdate={(id: string): void => { route(`/instance/${id}/update`); }} - setInstanceName={setInstanceName} + return ( + <InstanceContextProvider value={value}> + <NotificationCard notification={globalNotification} /> + + <Router + onChange={(e) => { + const movingOutFromNotification = + globalNotification && e.url !== globalNotification.to; + if (movingOutFromNotification) { + setGlobalNotification(undefined); + } + }} + > + <Route path="/" component={Redirect} to={InstancePaths.order_list} /> + + {/** + * Admin pages + */} + {admin && ( + <Route + path={AdminPaths.list_instances} + component={InstanceListPage} + onCreate={() => { + route(AdminPaths.new_instance); + }} + onUpdate={(id: string): void => { + route(`/instance/${id}/update`); + }} + setInstanceName={setInstanceName} + onUnauthorized={LoginPageAccessDenied} + onLoadError={ServerErrorRedirectTo(InstancePaths.error)} + /> + )} + + {admin && ( + <Route + path={AdminPaths.new_instance} + component={InstanceCreatePage} + onBack={() => route(AdminPaths.list_instances)} + onConfirm={() => { + route(AdminPaths.list_instances); + }} + /> + )} + + {admin && ( + <Route + path={AdminPaths.update_instance} + component={AdminInstanceUpdatePage} + onBack={() => route(AdminPaths.list_instances)} + onConfirm={() => { + route(AdminPaths.list_instances); + }} + onUpdateError={ServerErrorRedirectTo(AdminPaths.list_instances)} + onLoadError={ServerErrorRedirectTo(AdminPaths.list_instances)} + onNotFound={NotFoundPage} + /> + )} + + {/** + * Update instance page + */} + <Route + path={InstancePaths.update} + component={InstanceUpdatePage} + onBack={() => { + route(`/`); + }} + onConfirm={() => { + route(`/`); + }} + onUpdateError={noop} + onNotFound={IfAdminCreateDefaultOr(NotFoundPage)} onUnauthorized={LoginPageAccessDenied} onLoadError={ServerErrorRedirectTo(InstancePaths.error)} /> - } - {admin && - <Route path={AdminPaths.new_instance} component={InstanceCreatePage} - onBack={() => route(AdminPaths.list_instances)} - onConfirm={() => { route(AdminPaths.list_instances); }} + {/** + * Product pages + */} + <Route + path={InstancePaths.product_list} + component={ProductListPage} + onUnauthorized={LoginPageAccessDenied} + onLoadError={ServerErrorRedirectTo(InstancePaths.update)} + onCreate={() => { + route(InstancePaths.product_new); + }} + onSelect={(id: string) => { + route(InstancePaths.product_update.replace(":pid", id)); + }} + onNotFound={IfAdminCreateDefaultOr(NotFoundPage)} /> - } - - {admin && - <Route path={AdminPaths.update_instance} component={AdminInstanceUpdatePage} - onBack={() => route(AdminPaths.list_instances)} - onConfirm={() => { route(AdminPaths.list_instances); }} - onUpdateError={ServerErrorRedirectTo(AdminPaths.list_instances)} - onLoadError={ServerErrorRedirectTo(AdminPaths.list_instances)} - onNotFound={NotFoundPage} + <Route + path={InstancePaths.product_update} + component={ProductUpdatePage} + onUnauthorized={LoginPageAccessDenied} + onLoadError={ServerErrorRedirectTo(InstancePaths.product_list)} + onConfirm={() => { + route(InstancePaths.product_list); + }} + onBack={() => { + route(InstancePaths.product_list); + }} + onNotFound={IfAdminCreateDefaultOr(NotFoundPage)} + /> + <Route + path={InstancePaths.product_new} + component={ProductCreatePage} + onConfirm={() => { + route(InstancePaths.product_list); + }} + onBack={() => { + route(InstancePaths.product_list); + }} /> - } - - {/** - * Update instance page - */} - <Route path={InstancePaths.update} component={InstanceUpdatePage} - onBack={() => { route(`/`); }} - onConfirm={() => { route(`/`); }} - onUpdateError={noop} - onNotFound={IfAdminCreateDefaultOr(NotFoundPage)} - onUnauthorized={LoginPageAccessDenied} - onLoadError={ServerErrorRedirectTo(InstancePaths.error)} - /> - - {/** - * Product pages - */} - <Route path={InstancePaths.product_list} component={ProductListPage} - onUnauthorized={LoginPageAccessDenied} - onLoadError={ServerErrorRedirectTo(InstancePaths.update)} - onCreate={() => { route(InstancePaths.product_new) }} - onSelect={(id: string) => { route(InstancePaths.product_update.replace(':pid', id)) }} - onNotFound={IfAdminCreateDefaultOr(NotFoundPage)} - /> - <Route path={InstancePaths.product_update} component={ProductUpdatePage} - onUnauthorized={LoginPageAccessDenied} - onLoadError={ServerErrorRedirectTo(InstancePaths.product_list)} - onConfirm={() => { route(InstancePaths.product_list); }} - onBack={() => { route(InstancePaths.product_list); }} - onNotFound={IfAdminCreateDefaultOr(NotFoundPage)} - /> - <Route path={InstancePaths.product_new} - component={ProductCreatePage} - onConfirm={() => { route(InstancePaths.product_list); }} - onBack={() => { route(InstancePaths.product_list); }} - /> - - {/** - * Order pages - */} - <Route path={InstancePaths.order_list} component={OrderListPage} - onCreate={() => { route(InstancePaths.order_new) }} - onSelect={(id: string) => { route(InstancePaths.order_details.replace(':oid', id)) }} - onUnauthorized={LoginPageAccessDenied} - onLoadError={ServerErrorRedirectTo(InstancePaths.update)} - onNotFound={IfAdminCreateDefaultOr(NotFoundPage)} - /> - <Route path={InstancePaths.order_details} component={OrderDetailsPage} - onUnauthorized={LoginPageAccessDenied} - onLoadError={ServerErrorRedirectTo(InstancePaths.order_list)} - onNotFound={IfAdminCreateDefaultOr(NotFoundPage)} - onBack={() => { route(InstancePaths.order_list) }} - /> - <Route path={InstancePaths.order_new} component={OrderCreatePage} - onConfirm={() => { route(InstancePaths.order_list) }} - onBack={() => { route(InstancePaths.order_list) }} - /> - {/** - * Transfer pages - */} - <Route path={InstancePaths.transfers_list} component={TransferListPage} - onUnauthorized={LoginPageAccessDenied} - onNotFound={IfAdminCreateDefaultOr(NotFoundPage)} - onLoadError={ServerErrorRedirectTo(InstancePaths.update)} - onCreate={() => { route(InstancePaths.transfers_new) }} - /> + {/** + * Order pages + */} + <Route + path={InstancePaths.order_list} + component={OrderListPage} + onCreate={() => { + route(InstancePaths.order_new); + }} + onSelect={(id: string) => { + route(InstancePaths.order_details.replace(":oid", id)); + }} + onUnauthorized={LoginPageAccessDenied} + onLoadError={ServerErrorRedirectTo(InstancePaths.update)} + onNotFound={IfAdminCreateDefaultOr(NotFoundPage)} + /> + <Route + path={InstancePaths.order_details} + component={OrderDetailsPage} + onUnauthorized={LoginPageAccessDenied} + onLoadError={ServerErrorRedirectTo(InstancePaths.order_list)} + onNotFound={IfAdminCreateDefaultOr(NotFoundPage)} + onBack={() => { + route(InstancePaths.order_list); + }} + /> + <Route + path={InstancePaths.order_new} + component={OrderCreatePage} + onConfirm={() => { + route(InstancePaths.order_list); + }} + onBack={() => { + route(InstancePaths.order_list); + }} + /> - <Route path={InstancePaths.transfers_new} component={TransferCreatePage} - onConfirm={() => { route(InstancePaths.transfers_list) }} - onBack={() => { route(InstancePaths.transfers_list) }} - /> + {/** + * Transfer pages + */} + <Route + path={InstancePaths.transfers_list} + component={TransferListPage} + onUnauthorized={LoginPageAccessDenied} + onNotFound={IfAdminCreateDefaultOr(NotFoundPage)} + onLoadError={ServerErrorRedirectTo(InstancePaths.update)} + onCreate={() => { + route(InstancePaths.transfers_new); + }} + /> - {/** - * reserves pages - */} - <Route path={InstancePaths.reserves_list} component={ReservesListPage} - onUnauthorized={LoginPageAccessDenied} - onNotFound={IfAdminCreateDefaultOr(NotFoundPage)} - onLoadError={ServerErrorRedirectTo(InstancePaths.update)} - onSelect={(id: string) => { route(InstancePaths.reserves_details.replace(':rid', id)) }} - onCreate={() => { route(InstancePaths.reserves_new) }} - /> + <Route + path={InstancePaths.transfers_new} + component={TransferCreatePage} + onConfirm={() => { + route(InstancePaths.transfers_list); + }} + onBack={() => { + route(InstancePaths.transfers_list); + }} + /> - <Route path={InstancePaths.reserves_details} component={ReservesDetailsPage} - onUnauthorized={LoginPageAccessDenied} - onLoadError={ServerErrorRedirectTo(InstancePaths.reserves_list)} - onNotFound={IfAdminCreateDefaultOr(NotFoundPage)} - onBack={() => { route(InstancePaths.reserves_list) }} - /> + {/** + * reserves pages + */} + <Route + path={InstancePaths.reserves_list} + component={ReservesListPage} + onUnauthorized={LoginPageAccessDenied} + onNotFound={IfAdminCreateDefaultOr(NotFoundPage)} + onLoadError={ServerErrorRedirectTo(InstancePaths.update)} + onSelect={(id: string) => { + route(InstancePaths.reserves_details.replace(":rid", id)); + }} + onCreate={() => { + route(InstancePaths.reserves_new); + }} + /> - <Route path={InstancePaths.reserves_new} component={ReservesCreatePage} - onConfirm={() => { route(InstancePaths.reserves_list) }} - onBack={() => { route(InstancePaths.reserves_list) }} - /> - {/** - * Example pages - */} - <Route path="/loading" component={Loading} /> - <Route default component={NotFoundPage} /> - </Router> - </InstanceContextProvider>; + <Route + path={InstancePaths.reserves_details} + component={ReservesDetailsPage} + onUnauthorized={LoginPageAccessDenied} + onLoadError={ServerErrorRedirectTo(InstancePaths.reserves_list)} + onNotFound={IfAdminCreateDefaultOr(NotFoundPage)} + onBack={() => { + route(InstancePaths.reserves_list); + }} + /> + <Route + path={InstancePaths.reserves_new} + component={ReservesCreatePage} + onConfirm={() => { + route(InstancePaths.reserves_list); + }} + onBack={() => { + route(InstancePaths.reserves_list); + }} + /> + {/** + * Example pages + */} + <Route path="/loading" component={Loading} /> + <Route default component={NotFoundPage} /> + </Router> + </InstanceContextProvider> + ); } export function Redirect({ to }: { to: string }): null { useEffect(() => { - route(to, true) - }) - return null + route(to, true); + }); + return null; } -function AdminInstanceUpdatePage({ id, ...rest }: { id: string } & InstanceUpdatePageProps) { +function AdminInstanceUpdatePage({ + id, + ...rest +}: { id: string } & InstanceUpdatePageProps) { const [token, changeToken] = useBackendInstanceToken(id); const { updateLoginStatus: changeBackend } = useBackendContext(); const updateLoginStatus = (url: string, token?: string) => { changeBackend(url); - if (token) - changeToken(token); + if (token) changeToken(token); }; - const value = useMemo(() => ({ id, token, admin: true, changeToken }), [id, token]) + const value = useMemo( + () => ({ id, token, admin: true, changeToken }), + [id, token] + ); const i18n = useTranslator(); - return <InstanceContextProvider value={value}> - <InstanceAdminUpdatePage {...rest} - instanceId={id} - onLoadError={(error: HttpError) => { - return <Fragment> - <NotificationCard notification={{ - message: i18n`The backend reported a problem: HTTP status #${error.status}`, - description: i18n`Diagnostic from ${error.info?.url} is "${error.message}"`, - type: 'ERROR' - }} /> - <LoginPage onConfirm={updateLoginStatus} /> - </Fragment> - }} - - onUnauthorized={() => { - return <Fragment> - <NotificationCard notification={{ - message: i18n`Access denied`, - description: i18n`The access token provided is invalid`, - type: 'ERROR', - }} /> - <LoginPage onConfirm={updateLoginStatus} /> - </Fragment> - }} - - /> - </InstanceContextProvider> + return ( + <InstanceContextProvider value={value}> + <InstanceAdminUpdatePage + {...rest} + instanceId={id} + onLoadError={(error: HttpError) => { + return ( + <Fragment> + <NotificationCard + notification={{ + message: i18n`The backend reported a problem: HTTP status #${error.status}`, + description: i18n`Diagnostic from ${error.info?.url} is "${error.message}"`, + type: "ERROR", + }} + /> + <LoginPage onConfirm={updateLoginStatus} /> + </Fragment> + ); + }} + onUnauthorized={() => { + return ( + <Fragment> + <NotificationCard + notification={{ + message: i18n`Access denied`, + description: i18n`The access token provided is invalid`, + type: "ERROR", + }} + /> + <LoginPage onConfirm={updateLoginStatus} /> + </Fragment> + ); + }} + /> + </InstanceContextProvider> + ); } diff --git a/packages/merchant-backoffice/src/components/menu/index.tsx b/packages/merchant-backoffice/src/components/menu/index.tsx @@ -15,7 +15,7 @@ */ import { ComponentChildren, Fragment, h, VNode } from "preact"; -import Match from 'preact-router/match'; +import Match from "preact-router/match"; import { useEffect, useState } from "preact/hooks"; import { AdminPaths } from "../../AdminRoutes"; import { InstancePaths } from "../../InstanceRoutes"; @@ -23,28 +23,37 @@ import { Notification } from "../../utils/types"; import { NavigationBar } from "./NavigationBar"; import { Sidebar } from "./SideBar"; - function getInstanceTitle(path: string, id: string): string { - switch (path) { - case InstancePaths.update: return `${id}: Settings` - case InstancePaths.order_list: return `${id}: Orders` - case InstancePaths.order_new: return `${id}: New order` - case InstancePaths.product_list: return `${id}: Products` - case InstancePaths.product_new: return `${id}: New product` - case InstancePaths.product_update: return `${id}: Update product` - case InstancePaths.reserves_new: return `${id}: New reserve` - case InstancePaths.reserves_list: return `${id}: Reserves` - case InstancePaths.transfers_list: return `${id}: Transfers` - case InstancePaths.transfers_new: return `${id}: New transfer` - default: return ''; + case InstancePaths.update: + return `${id}: Settings`; + case InstancePaths.order_list: + return `${id}: Orders`; + case InstancePaths.order_new: + return `${id}: New order`; + case InstancePaths.product_list: + return `${id}: Products`; + case InstancePaths.product_new: + return `${id}: New product`; + case InstancePaths.product_update: + return `${id}: Update product`; + case InstancePaths.reserves_new: + return `${id}: New reserve`; + case InstancePaths.reserves_list: + return `${id}: Reserves`; + case InstancePaths.transfers_list: + return `${id}: Transfers`; + case InstancePaths.transfers_new: + return `${id}: New transfer`; + default: + return ""; } } function getAdminTitle(path: string, instance: string) { - if (path === AdminPaths.new_instance) return `New instance` - if (path === AdminPaths.list_instances) return `Instances` - return getInstanceTitle(path, instance) + if (path === AdminPaths.new_instance) return `New instance`; + if (path === AdminPaths.list_instances) return `Instances`; + return getInstanceTitle(path, instance); } interface MenuProps { @@ -52,41 +61,85 @@ interface MenuProps { instance: string; admin?: boolean; onLogout?: () => void; - setInstanceName: (s:string) => void; + setInstanceName: (s: string) => void; } -function WithTitle({ title, children }: { title: string, children: ComponentChildren }): VNode { +function WithTitle({ + title, + children, +}: { + title: string; + children: ComponentChildren; +}): VNode { useEffect(() => { - document.title = `Taler Backoffice: ${title}` - }, [title]) - return <Fragment>{children}</Fragment> + document.title = `Taler Backoffice: ${title}`; + }, [title]); + return <Fragment>{children}</Fragment>; } -export function Menu({ onLogout, title, instance, admin, setInstanceName }: MenuProps): VNode { - const [mobileOpen, setMobileOpen] = useState(false) - - return <Match>{({ path }: any) => { - const titleWithSubtitle = title ? title : (!admin ? getInstanceTitle(path, instance) : getAdminTitle(path, instance)) - const adminInstance = instance === "default" - const mimic = admin && !adminInstance - return (<WithTitle title={titleWithSubtitle}> - <div class={mobileOpen ? "has-aside-mobile-expanded" : ""} onClick={() => setMobileOpen(false)}> - <NavigationBar onMobileMenu={() => setMobileOpen(!mobileOpen)} title={titleWithSubtitle} /> - - {onLogout && <Sidebar onLogout={onLogout} admin={admin} mimic={mimic} instance={instance} mobile={mobileOpen} />} - - {mimic && <nav class="level"> - <div class="level-item has-text-centered has-background-warning"> - <p class="is-size-5">You are viewing the instance <b>"{instance}"</b>. <a href="#/instances" onClick={(e) => { - setInstanceName('default') - }}>go back</a></p> - </div> - </nav>} - </div> - </WithTitle> - ) - }}</Match> - +export function Menu({ + onLogout, + title, + instance, + admin, + setInstanceName, +}: MenuProps): VNode { + const [mobileOpen, setMobileOpen] = useState(false); + + return ( + <Match> + {({ path }: any) => { + const titleWithSubtitle = title + ? title + : !admin + ? getInstanceTitle(path, instance) + : getAdminTitle(path, instance); + const adminInstance = instance === "default"; + const mimic = admin && !adminInstance; + return ( + <WithTitle title={titleWithSubtitle}> + <div + class={mobileOpen ? "has-aside-mobile-expanded" : ""} + onClick={() => setMobileOpen(false)} + > + <NavigationBar + onMobileMenu={() => setMobileOpen(!mobileOpen)} + title={titleWithSubtitle} + /> + + {onLogout && ( + <Sidebar + onLogout={onLogout} + admin={admin} + mimic={mimic} + instance={instance} + mobile={mobileOpen} + /> + )} + + {mimic && ( + <nav class="level"> + <div class="level-item has-text-centered has-background-warning"> + <p class="is-size-5"> + You are viewing the instance <b>"{instance}"</b>.{" "} + <a + href="#/instances" + onClick={(e) => { + setInstanceName("default"); + }} + > + go back + </a> + </p> + </div> + </nav> + )} + </div> + </WithTitle> + ); + }} + </Match> + ); } interface NotYetReadyAppMenuProps { @@ -97,36 +150,56 @@ interface NotYetReadyAppMenuProps { interface NotifProps { notification?: Notification; } -export function NotificationCard({ notification: n }: NotifProps): VNode | null { - if (!n) return null - return <div class="notification"> - <div class="columns is-vcentered"> - <div class="column is-12"> - <article class={n.type === 'ERROR' ? "message is-danger" : (n.type === 'WARN' ? "message is-warning" : "message is-info")}> - <div class="message-header"> - <p>{n.message}</p> - </div> - {n.description && - <div class="message-body"> - {n.description} - </div>} - </article> +export function NotificationCard({ + notification: n, +}: NotifProps): VNode | null { + if (!n) return null; + return ( + <div class="notification"> + <div class="columns is-vcentered"> + <div class="column is-12"> + <article + class={ + n.type === "ERROR" + ? "message is-danger" + : n.type === "WARN" + ? "message is-warning" + : "message is-info" + } + > + <div class="message-header"> + <p>{n.message}</p> + </div> + {n.description && <div class="message-body">{n.description}</div>} + </article> + </div> </div> </div> - </div> + ); } -export function NotYetReadyAppMenu({ onLogout, title }: NotYetReadyAppMenuProps): VNode { - const [mobileOpen, setMobileOpen] = useState(false) +export function NotYetReadyAppMenu({ + onLogout, + title, +}: NotYetReadyAppMenuProps): VNode { + const [mobileOpen, setMobileOpen] = useState(false); useEffect(() => { - document.title = `Taler Backoffice: ${title}` - }, [title]) - - return <div class={mobileOpen ? "has-aside-mobile-expanded" : ""} onClick={() => setMobileOpen(false)}> - <NavigationBar onMobileMenu={() => setMobileOpen(!mobileOpen)} title={title} /> - {onLogout && <Sidebar onLogout={onLogout} instance="" mobile={mobileOpen} />} - </div> - + document.title = `Taler Backoffice: ${title}`; + }, [title]); + + return ( + <div + class={mobileOpen ? "has-aside-mobile-expanded" : ""} + onClick={() => setMobileOpen(false)} + > + <NavigationBar + onMobileMenu={() => setMobileOpen(!mobileOpen)} + title={title} + /> + {onLogout && ( + <Sidebar onLogout={onLogout} instance="" mobile={mobileOpen} /> + )} + </div> + ); } - diff --git a/packages/merchant-backoffice/src/utils/types.ts b/packages/merchant-backoffice/src/utils/types.ts @@ -14,7 +14,7 @@ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ -import { VNode } from "preact" +import { VNode } from "preact"; export interface KeyValue { [key: string]: string; @@ -26,6 +26,5 @@ export interface Notification { type: MessageType; } -export type ValueOrFunction<T> = T | ((p: T) => T) -export type MessageType = 'INFO' | 'WARN' | 'ERROR' | 'SUCCESS' - +export type ValueOrFunction<T> = T | ((p: T) => T); +export type MessageType = "INFO" | "WARN" | "ERROR" | "SUCCESS";