Skip to content

Instantly share code, notes, and snippets.

@emersonlaurentino
Created June 17, 2021 14:31
Show Gist options
  • Save emersonlaurentino/80d4bd21edad3c452e2c7218385d8ca1 to your computer and use it in GitHub Desktop.
Save emersonlaurentino/80d4bd21edad3c452e2c7218385d8ca1 to your computer and use it in GitHub Desktop.
SFJ Newsletter
import type { SxStyleProp } from '@vtex/store-ui'
import { Spinner, UIButton } from '@vtex/store-ui'
import type { ComponentPropsWithoutRef, FC } from 'react'
import React from 'react'
interface Props extends ComponentPropsWithoutRef<typeof UIButton> {
loading: boolean
}
const defaultStyles: SxStyleProp = {
width: ['100%', '130px'],
height: '42px',
px: '24px',
fontWeight: 500,
fontFamily: 'Effra Regular',
textTransform: 'uppercase',
background: '#4E6F5E 0% 0% no-repeat padding-box',
boxshadow: '0px 3px 6px #232E2889',
borderRadius: ['5px', '0px 5px 5px 0px'],
cursor: 'pointer',
'&:disabled': {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#DEDBDB',
},
}
const ButtonWithLoading: FC<Props> = ({ sx, loading, children, ...props }) => {
return (
<UIButton
sx={{
...defaultStyles,
...sx,
}}
{...props}
>
{loading ? <Spinner size="20px" color="white" /> : children}
</UIButton>
)
}
export default ButtonWithLoading
import { Box, Flex, UIInput } from "@vtex/store-ui";
import type { ChangeEvent, FC } from "react";
import React, { useCallback, useState } from "react";
import Button from "./ButtonWithLoading";
import useNewsletter from "./UseNewsletter";
interface NewsletterProps {
variant: string;
}
const Newsletter: FC<NewsletterProps> = ({ variant }) => {
const { error, addUser, loading, data } = useNewsletter();
const [email, setEmail] = useState("");
const onSubmit = useCallback(
(e: React.FormEvent<HTMLDivElement>) => {
e.preventDefault();
addUser({ email });
},
[addUser, email]
);
return (
<Box variant={variant}>
<Flex as="form" onSubmit={onSubmit} variant={`${variant}.form`}>
<label htmlFor="email">
<UIInput
id="email"
name="email"
type="email"
value={email}
placeholder="Enter your e-mail"
onChange={(e: ChangeEvent<HTMLInputElement>) =>
setEmail(e.target.value)
}
disabled={loading}
required
/>
</label>
<Button loading={loading} disabled={!checked ? "disabled" : ""}>
Register
</Button>
</Flex>
<Box variant={`${variant}.feedback`}>
{error && (
<Box as="span" variant={`${variant}.feedback.error`}>
Error
</Box>
)}
{data && (
<Box as="span" variant={`${variant}.feedback.success`}>
Success
</Box>
)}
</Box>
</Box>
);
};
export default Newsletter;
import { useCallback, useState } from 'react'
type MDResponse = {
Id: string
Href: string
DocumentId: string
}
const addToNewsletter = async (data: { nome: string; email: string }) =>
fetch('/api/dataentities/NW/documents/', {
headers: {
'Content-Type': 'application/json',
accept: 'application/vnd.vtex.ds.v10+json',
},
method: 'PATCH',
body: JSON.stringify({ ...data, isNewsletterOptIn: true }),
}).then((response) => {
if (response.ok) {
return response.json()
}
throw new Error()
})
const useNewsletter = () => {
const [loading, setLoading] = useState(false)
const [data, setData] = useState<MDResponse | null>(null)
const [error, setError] = useState(false)
const addUser = useCallback(
(user: { nome: string; email: string }) => {
setError(false)
setData(null)
setLoading(true)
return addToNewsletter(user)
.then((response) => {
setData(response as MDResponse)
})
.catch(() => {
setError(true)
})
.finally(() => {
setLoading(false)
})
},
[setError, setData, setLoading]
)
const reset = useCallback(() => {
setData(null)
setError(false)
setLoading(false)
}, [])
return {
error,
addUser,
loading,
data,
reset,
}
}
export default useNewsletter
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment