show simple order creation unless advance mode is selected
This commit is contained in:
parent
ef148b1501
commit
7d53aa2755
@ -0,0 +1,91 @@
|
||||
/*
|
||||
This file is part of GNU Taler
|
||||
(C) 2021-2023 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/>
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Javier Marchano (sebasjm)
|
||||
*/
|
||||
import { h, VNode } from "preact";
|
||||
import { InputProps, useField } from "./useField.js";
|
||||
|
||||
interface Props<T> extends InputProps<T> {
|
||||
name: T;
|
||||
readonly?: boolean;
|
||||
expand?: boolean;
|
||||
threeState?: boolean;
|
||||
toBoolean?: (v?: any) => boolean | undefined;
|
||||
fromBoolean?: (s: boolean | undefined) => any;
|
||||
}
|
||||
|
||||
const defaultToBoolean = (f?: any): boolean | undefined => f || "";
|
||||
const defaultFromBoolean = (v: boolean | undefined): any => v as any;
|
||||
|
||||
export function InputToggle<T>({
|
||||
name,
|
||||
readonly,
|
||||
placeholder,
|
||||
tooltip,
|
||||
label,
|
||||
help,
|
||||
threeState,
|
||||
expand,
|
||||
fromBoolean = defaultFromBoolean,
|
||||
toBoolean = defaultToBoolean,
|
||||
}: Props<keyof T>): VNode {
|
||||
const { error, value, onChange } = useField<T>(name);
|
||||
|
||||
const onCheckboxClick = (): void => {
|
||||
const c = toBoolean(value);
|
||||
if (c === false && threeState) return onChange(undefined as any);
|
||||
return onChange(fromBoolean(!c));
|
||||
};
|
||||
|
||||
return (
|
||||
<div class="field is-horizontal">
|
||||
<div class="field-label is-normal">
|
||||
<label class="label" style={{ width: 200 }}>
|
||||
{label}
|
||||
{tooltip && (
|
||||
<span class="icon has-tooltip-right" data-tooltip={tooltip}>
|
||||
<i class="mdi mdi-information" />
|
||||
</span>
|
||||
)}
|
||||
</label>
|
||||
</div>
|
||||
<div class="field-body is-flex-grow-1">
|
||||
<div class="field">
|
||||
<p class={expand ? "control is-expanded" : "control"}>
|
||||
<label class="toggle" style={{ marginLeft: 4, marginTop: 0 }}>
|
||||
<input
|
||||
type="checkbox"
|
||||
class={toBoolean(value) === undefined ? "is-indeterminate" : "toggle-checkbox"}
|
||||
checked={toBoolean(value)}
|
||||
placeholder={placeholder}
|
||||
readonly={readonly}
|
||||
name={String(name)}
|
||||
disabled={readonly}
|
||||
onChange={onCheckboxClick}
|
||||
/>
|
||||
<div class="toggle-switch"></div>
|
||||
</label>
|
||||
{help}
|
||||
</p>
|
||||
{error && <p class="help is-danger">{error}</p>}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -53,15 +53,17 @@ export function useBackendURL(
|
||||
|
||||
export function useBackendDefaultToken(
|
||||
initialValue?: string,
|
||||
): [string | undefined, ((d:string | undefined) => void)] {
|
||||
const {update, value} = useMemoryStorage(`backend-token`, initialValue)
|
||||
): [string | undefined, ((d: string | undefined) => void)] {
|
||||
// uncomment for testing
|
||||
initialValue = "secret-token:secret" as string | undefined
|
||||
const { update, value } = useMemoryStorage(`backend-token`, initialValue)
|
||||
return [value, update];
|
||||
}
|
||||
|
||||
export function useBackendInstanceToken(
|
||||
id: string,
|
||||
): [string | undefined, ((d:string | undefined) => void)] {
|
||||
const {update:setToken, value:token, reset} = useMemoryStorage(`backend-token-${id}`)
|
||||
): [string | undefined, ((d: string | undefined) => void)] {
|
||||
const { update: setToken, value: token, reset } = useMemoryStorage(`backend-token-${id}`)
|
||||
const [defaultToken, defaultSetToken] = useBackendDefaultToken();
|
||||
|
||||
// instance named 'default' use the default token
|
||||
|
59
packages/merchant-backoffice-ui/src/hooks/useSettings.ts
Normal file
59
packages/merchant-backoffice-ui/src/hooks/useSettings.ts
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
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 { buildStorageKey, useLocalStorage } from "@gnu-taler/web-util/browser";
|
||||
import {
|
||||
Codec,
|
||||
buildCodecForObject,
|
||||
codecForBoolean,
|
||||
} from "@gnu-taler/taler-util";
|
||||
|
||||
function parse_json_or_undefined<T>(str: string | undefined): T | undefined {
|
||||
if (str === undefined) return undefined;
|
||||
try {
|
||||
return JSON.parse(str);
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export interface Settings {
|
||||
advanceOrderMode: boolean
|
||||
}
|
||||
|
||||
const defaultSettings: Settings = {
|
||||
advanceOrderMode: false,
|
||||
}
|
||||
|
||||
export const codecForSettings = (): Codec<Settings> =>
|
||||
buildCodecForObject<Settings>()
|
||||
.property("advanceOrderMode", codecForBoolean())
|
||||
.build("Settings");
|
||||
|
||||
const SETTINGS_KEY = buildStorageKey("merchant-settings", codecForSettings());
|
||||
|
||||
export function useSettings(): [
|
||||
Readonly<Settings>,
|
||||
<T extends keyof Settings>(key: T, value: Settings[T]) => void,
|
||||
] {
|
||||
const { value, update } = useLocalStorage(SETTINGS_KEY);
|
||||
|
||||
const parsed: Settings = value ?? defaultSettings;
|
||||
function updateField<T extends keyof Settings>(k: T, v: Settings[T]) {
|
||||
update({ ...parsed, [k]: v });
|
||||
}
|
||||
return [parsed, updateField];
|
||||
}
|
@ -43,6 +43,7 @@ import { Duration, MerchantBackend, WithId } from "../../../../declaration.js";
|
||||
import { OrderCreateSchema as schema } from "../../../../schemas/index.js";
|
||||
import { rate } from "../../../../utils/amount.js";
|
||||
import { undefinedIfEmpty } from "../../../../utils/table.js";
|
||||
import { useSettings } from "../../../../hooks/useSettings.js";
|
||||
|
||||
interface Props {
|
||||
onCreate: (d: MerchantBackend.Orders.PostOrderRequest) => void;
|
||||
@ -138,7 +139,7 @@ export function CreatePage({
|
||||
const [value, valueHandler] = useState(with_defaults(instanceConfig));
|
||||
const config = useConfigContext();
|
||||
const zero = Amounts.zeroOfCurrency(config.currency);
|
||||
|
||||
const [settings] = useSettings()
|
||||
const inventoryList = Object.values(value.inventoryProducts || {});
|
||||
const productList = Object.values(value.products || {});
|
||||
|
||||
@ -374,6 +375,7 @@ export function CreatePage({
|
||||
inventory={instanceInventory}
|
||||
/>
|
||||
|
||||
{settings.advanceOrderMode &&
|
||||
<NonInventoryProductFrom
|
||||
productToEdit={editingProduct}
|
||||
onAddProduct={(p) => {
|
||||
@ -381,6 +383,7 @@ export function CreatePage({
|
||||
return addNewProduct(p);
|
||||
}}
|
||||
/>
|
||||
}
|
||||
|
||||
{allProducts.length > 0 && (
|
||||
<ProductList
|
||||
@ -445,6 +448,7 @@ export function CreatePage({
|
||||
tooltip={i18n.str`Title of the order to be shown to the customer`}
|
||||
/>
|
||||
|
||||
{settings.advanceOrderMode &&
|
||||
<InputGroup
|
||||
name="shipping"
|
||||
label={i18n.str`Shipping and Fulfillment`}
|
||||
@ -470,7 +474,9 @@ export function CreatePage({
|
||||
tooltip={i18n.str`URL to which the user will be redirected after successful payment.`}
|
||||
/>
|
||||
</InputGroup>
|
||||
}
|
||||
|
||||
{settings.advanceOrderMode &&
|
||||
<InputGroup
|
||||
name="payments"
|
||||
label={i18n.str`Taler payment options`}
|
||||
@ -528,7 +534,9 @@ export function CreatePage({
|
||||
}
|
||||
/>
|
||||
</InputGroup>
|
||||
}
|
||||
|
||||
{settings.advanceOrderMode &&
|
||||
<InputGroup
|
||||
name="extra"
|
||||
label={i18n.str`Additional information`}
|
||||
@ -541,6 +549,7 @@ export function CreatePage({
|
||||
tooltip={i18n.str`You must enter a value in JavaScript Object Notation (JSON).`}
|
||||
/>
|
||||
</InputGroup>
|
||||
}
|
||||
</FormProvider>
|
||||
|
||||
<div class="buttons is-right mt-5">
|
||||
|
Loading…
Reference in New Issue
Block a user