cta stories and input filled mui

This commit is contained in:
Sebastian 2022-04-06 12:20:00 -03:00
parent bb56d61424
commit f300850b19
No known key found for this signature in database
GPG Key ID: BE4FF68352439FC1
13 changed files with 262 additions and 53 deletions

View File

@ -28,7 +28,7 @@ import firefoxAPI from "./platform/firefox.js";
import chromeAPI from "./platform/chrome.js";
import { wxMain } from "./wxBackend.js";
const isFirefox = typeof (window as any)['InstallTrigger'] !== 'undefined'
const isFirefox = typeof (window as any) !== 'undefined' && typeof (window as any)['InstallTrigger'] !== 'undefined'
// FIXME: create different entry point for any platform instead of
// switching in runtime

View File

@ -147,7 +147,7 @@ export const TicketWithAProductList = createExample(TestedComponent, {
},
});
export const AlreadyConfirmedWithFullfilment = createExample(TestedComponent, {
export const AlreadyConfirmedByOther = createExample(TestedComponent, {
payStatus: {
status: PreparePayResultType.AlreadyConfirmed,
amountEffective: "USD:10",
@ -156,8 +156,6 @@ export const AlreadyConfirmedWithFullfilment = createExample(TestedComponent, {
merchant: {
name: "someone",
},
fulfillment_message:
"congratulations! you are looking at the fulfillment message! ",
summary: "some beers",
amount: "USD:10",
} as Partial<ContractTerms> as any,
@ -167,28 +165,25 @@ export const AlreadyConfirmedWithFullfilment = createExample(TestedComponent, {
},
});
export const AlreadyConfirmedWithoutFullfilment = createExample(
TestedComponent,
{
payStatus: {
status: PreparePayResultType.AlreadyConfirmed,
amountEffective: "USD:10",
amountRaw: "USD:10",
contractTerms: {
merchant: {
name: "someone",
},
summary: "some beers",
amount: "USD:10",
} as Partial<ContractTerms> as any,
contractTermsHash: "123456",
proposalId: "proposal1234",
paid: false,
},
export const AlreadyPaidWithoutFulfillment = createExample(TestedComponent, {
payStatus: {
status: PreparePayResultType.AlreadyConfirmed,
amountEffective: "USD:10",
amountRaw: "USD:10",
contractTerms: {
merchant: {
name: "someone",
},
summary: "some beers",
amount: "USD:10",
} as Partial<ContractTerms> as any,
contractTermsHash: "123456",
proposalId: "proposal1234",
paid: true,
},
);
});
export const AlreadyPaid = createExample(TestedComponent, {
export const AlreadyPaidWithFulfillment = createExample(TestedComponent, {
payStatus: {
status: PreparePayResultType.AlreadyConfirmed,
amountEffective: "USD:10",

View File

@ -105,6 +105,23 @@ export function PayPage({
return { payStatus, balance };
}, [NotificationType.CoinWithdrawn]);
useEffect(() => {
const payStatus =
hook && !hook.hasError ? hook.response.payStatus : undefined;
if (
payStatus &&
payStatus.status === PreparePayResultType.AlreadyConfirmed &&
payStatus.paid
) {
const fu = payStatus.contractTerms.fulfillment_url;
if (fu) {
setTimeout(() => {
document.location.href = fu;
}, 3000);
}
}
}, []);
if (!hook) {
return <Loading />;
}
@ -172,20 +189,6 @@ export function PaymentRequestView({
let totalFees: AmountJson = Amounts.getZero(payStatus.amountRaw);
const contractTerms: ContractTerms = payStatus.contractTerms;
useEffect(() => {
if (
payStatus.status === PreparePayResultType.AlreadyConfirmed &&
payStatus.paid
) {
const fu = payStatus.contractTerms.fulfillment_url;
if (fu) {
setTimeout(() => {
document.location.href = fu;
}, 3000);
}
}
});
if (!contractTerms) {
return (
<ErrorMessage

View File

@ -136,9 +136,7 @@ export const TermsReviewingHTML = createExample(TestedComponent, {
terms: {
content: {
type: "html",
href: new URL(
`data:text/html;base64,${Buffer.from(termsHtml).toString("base64")}`,
),
href: new URL(`data:text/html;base64,${toBase64(termsHtml)}`),
},
version: "",
status: "new",
@ -146,6 +144,14 @@ export const TermsReviewingHTML = createExample(TestedComponent, {
reviewing: true,
});
function toBase64(str: string): string {
return btoa(
encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
return String.fromCharCode(parseInt(p1, 16));
}),
);
}
export const TermsReviewingPDF = createExample(TestedComponent, {
knownExchanges: exchangeList,
exchangeBaseUrl: "exchange.demo.taler.net",
@ -166,9 +172,7 @@ export const TermsReviewingPDF = createExample(TestedComponent, {
terms: {
content: {
type: "pdf",
location: new URL(
`data:text/html;base64,${Buffer.from(termsPdf).toString("base64")}`,
),
location: new URL(`data:text/html;base64,${toBase64(termsPdf)}`),
},
status: "new",
version: "",

View File

@ -0,0 +1,28 @@
/*
This file is part of GNU Taler
(C) 2021 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 * as a1 from "./Deposit.stories.jsx";
import * as a3 from "./Pay.stories.jsx";
import * as a4 from "./Refund.stories.jsx";
import * as a5 from "./Tip.stories.jsx";
import * as a6 from "./Withdraw.stories.jsx";
export default [a1, a3, a4, a5, a6];

View File

@ -33,7 +33,7 @@ const Container = styled.div`
display: flex;
flex-direction: column;
& > * {
margin: 20px;
margin-bottom: 20px !important;
}
`;

View File

@ -54,7 +54,7 @@ export function TextField({
select,
helperText,
children,
variant = "standard",
variant = "filled",
...props
}: Props): VNode {
// htmlFor={id} id={inputLabelId}

View File

@ -56,7 +56,7 @@ export function FormControl({
margin = "none",
required = false,
size = "medium",
variant = "standard",
variant = "filled",
children,
}: Partial<Props>): VNode {
const [filled, setFilled] = useState(false);
@ -138,7 +138,7 @@ const defaultContextValue: FCCProps = {
onFilled: () => null,
onFocus: () => null,
required: false,
variant: "outlined",
variant: "filled",
};
function withoutUndefinedProperties(obj: any): any {

View File

@ -61,7 +61,6 @@ const componentStyle = css`
font: inherit;
letter-spacing: inherit;
color: currentColor;
padding: 4px 0 5px;
border: 0px;
box-sizing: content-box;
background: none;
@ -128,6 +127,7 @@ export function InputBaseComponent({
size,
multiline,
type,
class: _class,
...props
}: any): VNode {
return (
@ -136,6 +136,7 @@ export function InputBaseComponent({
type={type}
class={[
componentStyle,
_class,
disabled && componentDisabledStyle,
size === "small" && componentSmallStyle,
multiline && componentMultilineStyle,

View File

@ -1,5 +1,170 @@
import { css } from "@linaria/core";
import { h, VNode } from "preact";
// eslint-disable-next-line import/extensions
import { Colors, theme } from "../style";
import { useFormControl } from "./FormControl.js";
import { InputBase, InputBaseComponent, InputBaseRoot } from "./InputBase.js";
export function InputFilled(): VNode {
return <div />;
export interface Props {
autoComplete?: string;
autoFocus?: boolean;
color?: Colors;
defaultValue?: string;
disabled?: boolean;
disableUnderline?: boolean;
endAdornment?: VNode;
error?: boolean;
fullWidth?: boolean;
id?: string;
margin?: "dense" | "normal" | "none";
maxRows?: number;
minRows?: number;
multiline?: boolean;
name?: string;
onChange?: (s: string) => void;
placeholder?: string;
readOnly?: boolean;
required?: boolean;
rows?: number;
startAdornment?: VNode;
type?: string;
value?: string;
}
export function InputFilled({
type = "text",
multiline,
...props
}: Props): VNode {
const fcs = useFormControl(props);
return (
<InputBase
Root={Root}
Input={Input}
fullWidth={fcs.fullWidth}
multiline={multiline}
type={type}
{...props}
/>
);
}
const light = theme.palette.mode === "light";
const bottomLineColor = light
? "rgba(0, 0, 0, 0.42)"
: "rgba(255, 255, 255, 0.7)";
const backgroundColor = light
? "rgba(0, 0, 0, 0.06)"
: "rgba(255, 255, 255, 0.09)";
const backgroundColorHover = light
? "rgba(0, 0, 0, 0.09)"
: "rgba(255, 255, 255, 0.13)";
const backgroundColorDisabled = light
? "rgba(0, 0, 0, 0.12)"
: "rgba(255, 255, 255, 0.12)";
const formControlStyle = css`
label + & {
margin-top: 16px;
}
`;
const filledRootStyle = css`
position: relative;
background-color: ${backgroundColor};
border-top-left-radius: ${theme.shape.borderRadius}px;
border-top-right-radius: ${theme.shape.borderRadius}px;
transition: ${theme.transitions.create("background-color", {
duration: theme.transitions.duration.shorter,
easing: theme.transitions.easing.easeOut,
})};
// when is not disabled underline
&:hover {
background-color: ${backgroundColorHover};
@media (hover: none) {
background-color: ${backgroundColor};
}
}
[data-focused] {
background-color: ${backgroundColor};
}
[data-disabled] {
background-color: ${backgroundColorDisabled};
}
`;
const underlineStyle = css`
// when is not disabled underline
&:after {
border-bottom: 2px solid var(--color-main);
left: 0px;
bottom: 0px;
content: "";
position: absolute;
right: 0px;
transform: scaleX(0);
transition: ${theme.transitions.create("transform", {
duration: theme.transitions.duration.shorter,
easing: theme.transitions.easing.easeOut,
})};
pointer-events: none;
}
&[data-focused]:after {
transform: scaleX(1);
}
&[data-error]:after {
border-bottom-color: ${theme.palette.error.main};
transform: scaleY(1);
}
&:before {
border-bottom: 1px solid
${theme.palette.mode === "light"
? "rgba(0, 0, 0, 0.42)"
: "rgba(255, 255, 255, 0.7)"};
left: 0px;
bottom: 0px;
right: 0px;
content: "\\00a0";
position: absolute;
transition: ${theme.transitions.create("border-bottom-color", {
duration: theme.transitions.duration.shorter,
})};
pointer-events: none;
}
&:hover:not([data-disabled]:before) {
border-bottom: 2px solid var(--color-main);
@media (hover: none) {
border-bottom: 1px solid
${theme.palette.mode === "light"
? "rgba(0, 0, 0, 0.42)"
: "rgba(255, 255, 255, 0.7)"};
}
}
&[data-disabled]:before {
border-bottom-style: solid;
}
`;
function Root({ fullWidth, disabled, focused, error, children }: any): VNode {
return (
<InputBaseRoot
disabled={disabled}
focused={focused}
fullWidth={fullWidth}
error={error}
class={[filledRootStyle, underlineStyle].join(" ")}
>
{children}
</InputBaseRoot>
);
}
const filledBaseStyle = css`
padding-top: 25px;
padding-right: 12px;
padding-bottom: 8px;
padding-left: 12px;
`;
function Input(props: any): VNode {
return <InputBaseComponent class={[filledBaseStyle].join(" ")} {...props} />;
}

View File

@ -50,6 +50,7 @@ export function InputStandard({
const rootStyle = css`
position: relative;
padding: 4px 0 5px;
`;
const formControlStyle = css`
label + & {
@ -57,6 +58,7 @@ const formControlStyle = css`
}
`;
const underlineStyle = css`
// when is not disabled underline
&:after {
border-bottom: 2px solid var(--color-main);
left: 0px;
@ -107,11 +109,12 @@ const underlineStyle = css`
}
`;
function Root({ disabled, focused, error, children }: any): VNode {
function Root({ fullWidth, disabled, focused, error, children }: any): VNode {
return (
<InputBaseRoot
disabled={disabled}
focused={focused}
fullWidth={fullWidth}
error={error}
class={[rootStyle, formControlStyle, underlineStyle].join(" ")}
>

View File

@ -147,6 +147,7 @@ function createTheme() {
circularBorder: css`
border-radius: 50%;
`,
borderRadius: 4,
};
/////////////////////

View File

@ -35,6 +35,7 @@ import * as mui from "./mui/index.stories.js";
import { PopupNavBar, WalletNavBar } from "./NavigationBar.js";
import * as popup from "./popup/index.stories.js";
import * as wallet from "./wallet/index.stories.js";
import * as cta from "./cta/index.stories.js";
import * as components from "./components/index.stories.js";
import { strings } from "./i18n/strings.js";
@ -112,7 +113,7 @@ function parseExampleImport(group: string, im: any): ComponentItem {
};
}
const allExamples = Object.entries({ popup, wallet, mui, components }).map(
const allExamples = Object.entries({ popup, wallet, cta, mui, components }).map(
([title, value]) => ({
title,
list: value.default.map((s) => parseExampleImport(title, s)),
@ -227,6 +228,14 @@ function getWrapperForGroup(group: string): FunctionComponent {
</Fragment>
);
};
case "cta":
return function WalletWrapper({ children }: any) {
return (
<Fragment>
<WalletBox>{children}</WalletBox>
</Fragment>
);
};
default:
return Fragment;
}