parent
da0130db58
commit
08c938de76
@ -22,6 +22,7 @@
|
||||
"@graphql-codegen/typescript-graphql-request": "^4.4.5",
|
||||
"@graphql-codegen/typescript-operations": "^2.3.5",
|
||||
"@juggle/resize-observer": "^3.3.1",
|
||||
"@notionhq/client": "^1.0.4",
|
||||
"@radix-ui/react-polymorphic": "^0.0.14",
|
||||
"@reach/dialog": "^0.17.0",
|
||||
"@types/lodash": "^4.14.182",
|
||||
@ -52,7 +53,8 @@
|
||||
"react-use-measure": "^2.1.1",
|
||||
"react-youtube": "^9.0.2",
|
||||
"sharp": "^0.30.4",
|
||||
"tiny-json-http": "^7.4.2"
|
||||
"tiny-json-http": "^7.4.2",
|
||||
"zod": "^3.17.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@graphql-codegen/cli": "^2.6.2",
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
margin-top: 0;
|
||||
display: flex;
|
||||
place-content: center;
|
||||
padding-bottom: tovw(80px, 'default', 80px);
|
||||
}
|
||||
|
||||
position: relative;
|
||||
@ -49,87 +50,113 @@
|
||||
}
|
||||
}
|
||||
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.form {
|
||||
position: relative;
|
||||
height: fit-content;
|
||||
|
||||
> div:first-child {
|
||||
> div {
|
||||
@include respond-to('mobile') {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
left: 0;
|
||||
bottom: tovw(-75px, 'mobile', -165px);
|
||||
font-size: tovw(8px, 'mobile', 12px);
|
||||
width: 90%;
|
||||
text-align: center;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
display: grid;
|
||||
margin-top: tovw(60px, 'default', 40px);
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: tovw(40px, 'default', 25px);
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
text-align: end;
|
||||
position: absolute;
|
||||
width: tovw(245px, 'default', 80px);
|
||||
color: var(--color-white);
|
||||
font-size: tovw(14px, 'default', 9px);
|
||||
text-transform: uppercase;
|
||||
font-family: var(--font-dm-mono);
|
||||
}
|
||||
|
||||
label {
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-family: var(--font-tt-hoves);
|
||||
font-size: tovw(30px, 'default', 18px);
|
||||
|
||||
input,
|
||||
textarea,
|
||||
select {
|
||||
appearance: none;
|
||||
width: 100%;
|
||||
font-size: tovw(24px, 'default', 18px);
|
||||
padding: tovw(16px, 'default', 12px) tovw(12px, 'default', 10px);
|
||||
margin-top: tovw(20px, 'default', 16px);
|
||||
background: rgb(142 142 142 / 0.1);
|
||||
border: tovw(1px, 'default', 1px) solid var(--color-grey);
|
||||
border-radius: tovw(8px, 'default', 8px);
|
||||
|
||||
&:focus {
|
||||
border: tovw(1px, 'default', 1px) solid var(--color-accent);
|
||||
background: rgb(0 0 244 / 0.1);
|
||||
transition: all 250ms;
|
||||
> div:first-child {
|
||||
@include respond-to('mobile') {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
&::placeholder {
|
||||
color: var(--color-grey-light);
|
||||
display: grid;
|
||||
margin-top: tovw(60px, 'default', 40px);
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: tovw(40px, 'default', 25px);
|
||||
}
|
||||
|
||||
label {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-family: var(--font-tt-hoves);
|
||||
font-size: tovw(30px, 'default', 18px);
|
||||
|
||||
input,
|
||||
textarea,
|
||||
select {
|
||||
appearance: none;
|
||||
width: 100%;
|
||||
font-size: tovw(24px, 'default', 18px);
|
||||
padding: tovw(16px, 'default', 12px) tovw(12px, 'default', 10px);
|
||||
margin-top: tovw(20px, 'default', 16px);
|
||||
background: rgb(142 142 142 / 0.1);
|
||||
border: tovw(1px, 'default', 1px) solid var(--color-grey);
|
||||
border-radius: tovw(8px, 'default', 8px);
|
||||
|
||||
&:focus {
|
||||
border: tovw(1px, 'default', 1px) solid var(--color-accent);
|
||||
background: rgb(0 0 244 / 0.1);
|
||||
transition: all 250ms;
|
||||
}
|
||||
|
||||
&::placeholder {
|
||||
color: var(--color-grey-light);
|
||||
}
|
||||
|
||||
option {
|
||||
background-color: black;
|
||||
opacity: 50%;
|
||||
border: none;
|
||||
color: var(--color-white);
|
||||
}
|
||||
}
|
||||
|
||||
option {
|
||||
background-color: black;
|
||||
opacity: 50%;
|
||||
border: none;
|
||||
color: var(--color-white);
|
||||
select {
|
||||
background: url('/images/dropdown.svg') no-repeat 95% 50%;
|
||||
background-color: rgb(142 142 142 / 0.1);
|
||||
background-size: tovw(20px, 'default', 16px);
|
||||
|
||||
&:invalid {
|
||||
color: var(--color-grey-light);
|
||||
}
|
||||
}
|
||||
|
||||
textarea {
|
||||
resize: none;
|
||||
}
|
||||
}
|
||||
|
||||
select {
|
||||
background: url('/images/dropdown.svg') no-repeat 95% 50%;
|
||||
background-color: rgb(142 142 142 / 0.1);
|
||||
background-size: tovw(20px, 'default', 16px);
|
||||
> label:nth-child(2) {
|
||||
margin-top: tovw(60px, 'default', 35px);
|
||||
}
|
||||
|
||||
&:invalid {
|
||||
color: var(--color-grey-light);
|
||||
button {
|
||||
@include respond-to('mobile') {
|
||||
width: 100%;
|
||||
font-size: tovw(18px, 'default', 18px);
|
||||
}
|
||||
|
||||
width: fit-content;
|
||||
align-self: center;
|
||||
font-size: tovw(18px, 'default', 14px);
|
||||
margin-top: tovw(50px, 'default', 35px);
|
||||
}
|
||||
|
||||
textarea {
|
||||
resize: none;
|
||||
}
|
||||
}
|
||||
|
||||
> label:nth-child(2) {
|
||||
margin-top: tovw(60px, 'default', 35px);
|
||||
}
|
||||
|
||||
button {
|
||||
@include respond-to('mobile') {
|
||||
width: 100%;
|
||||
font-size: tovw(18px, 'default', 18px);
|
||||
}
|
||||
|
||||
width: fit-content;
|
||||
align-self: center;
|
||||
font-size: tovw(18px, 'default', 14px);
|
||||
margin-top: tovw(50px, 'default', 35px);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -6,9 +6,10 @@ import Section from '~/components/layout/section'
|
||||
import { Button } from '~/components/primitives/button'
|
||||
import Heading from '~/components/primitives/heading'
|
||||
|
||||
// import { notion } from '~/lib/notion'
|
||||
import s from './form.module.scss'
|
||||
|
||||
interface Props {
|
||||
interface DataProps {
|
||||
data: {
|
||||
formHeading: string
|
||||
formWarning: string
|
||||
@ -26,9 +27,111 @@ interface Props {
|
||||
}
|
||||
}
|
||||
|
||||
const Form = ({ data }: Props) => {
|
||||
const [selectedOption, setSelectedOption] = useState<any>(null)
|
||||
type FormProps = {
|
||||
data: DataProps['data']
|
||||
style?: React.CSSProperties
|
||||
}
|
||||
|
||||
const CustomForm = ({ data }: FormProps) => {
|
||||
const [selectedOption, setSelectedOption] = useState<any>(null)
|
||||
const [email, setEmail] = useState('')
|
||||
const [text, setText] = useState('')
|
||||
const [errorMsg, setErrorMsg] = useState('')
|
||||
const [isFormSent, setIsFormSent] = useState(false)
|
||||
const [isSending, setIsSending] = useState(false)
|
||||
|
||||
const handleSubmit = async (e: any) => {
|
||||
e.preventDefault()
|
||||
|
||||
try {
|
||||
setErrorMsg('')
|
||||
|
||||
if (!selectedOption?.value) {
|
||||
setErrorMsg('Inquiry is required')
|
||||
return
|
||||
}
|
||||
|
||||
setIsSending(true)
|
||||
|
||||
const data = {
|
||||
email: email,
|
||||
message: text,
|
||||
inquiry: selectedOption.value
|
||||
}
|
||||
|
||||
await fetch('/api/contact', {
|
||||
method: 'POST',
|
||||
mode: 'no-cors',
|
||||
body: JSON.stringify(data),
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
|
||||
setIsSending(false)
|
||||
setIsFormSent(true)
|
||||
} catch (error) {
|
||||
// console.log(error)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={s.form}>
|
||||
{isSending && <div>sending...</div>}
|
||||
{errorMsg !== '' && (
|
||||
<div dangerouslySetInnerHTML={{ __html: errorMsg }} />
|
||||
)}
|
||||
{isFormSent && errorMsg === '' && (
|
||||
<div>Thanks for reaching out! We'll contact you shortly.</div>
|
||||
)}
|
||||
<form action="/" onSubmit={(e) => handleSubmit(e)}>
|
||||
<div>
|
||||
<label htmlFor="partnership">
|
||||
{data?.formLabelPartner}
|
||||
<Select
|
||||
instanceId={'Contact'}
|
||||
className="select"
|
||||
classNamePrefix="select"
|
||||
placeholder={data?.formPlaceholderPartner}
|
||||
value={selectedOption}
|
||||
onChange={setSelectedOption}
|
||||
options={data?.formSelectOptions}
|
||||
/>
|
||||
</label>
|
||||
<label htmlFor="email">
|
||||
{data?.formLabelEmail}
|
||||
<input
|
||||
placeholder={data?.formPlaceholderEmail}
|
||||
type="email"
|
||||
name="email"
|
||||
id="email"
|
||||
required
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<label htmlFor="message">
|
||||
{data?.formLabelMsg}
|
||||
<textarea
|
||||
placeholder={data?.formPlaceholderMsg}
|
||||
name="message"
|
||||
id="message"
|
||||
rows={5}
|
||||
required
|
||||
value={text}
|
||||
onChange={(e) => setText(e.target.value)}
|
||||
></textarea>
|
||||
</label>
|
||||
<Button size="medium" variant="primary">
|
||||
{data?.formLabelButton}
|
||||
</Button>
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const Form = ({ data }: DataProps) => {
|
||||
return (
|
||||
<Section className={s['section']} id="contactform">
|
||||
<Container className={s['container']}>
|
||||
@ -38,45 +141,7 @@ const Form = ({ data }: Props) => {
|
||||
</Heading>
|
||||
<span>{data?.formWarning}</span>
|
||||
</div>
|
||||
<form action="/">
|
||||
<div>
|
||||
<label htmlFor="partnership">
|
||||
{data?.formLabelPartner}
|
||||
<Select
|
||||
instanceId={'Contact'}
|
||||
className="select"
|
||||
classNamePrefix="select"
|
||||
placeholder={data?.formPlaceholderPartner}
|
||||
value={selectedOption}
|
||||
onChange={setSelectedOption}
|
||||
options={data?.formSelectOptions}
|
||||
/>
|
||||
</label>
|
||||
<label htmlFor="email">
|
||||
{data?.formLabelEmail}
|
||||
<input
|
||||
placeholder={data?.formPlaceholderEmail}
|
||||
type="email"
|
||||
name="email"
|
||||
id="email"
|
||||
required
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<label htmlFor="message">
|
||||
{data?.formLabelMsg}
|
||||
<textarea
|
||||
placeholder={data?.formPlaceholderMsg}
|
||||
name="message"
|
||||
id="message"
|
||||
rows={5}
|
||||
required
|
||||
></textarea>
|
||||
</label>
|
||||
<Button size="medium" variant="primary">
|
||||
{data?.formLabelButton}
|
||||
</Button>
|
||||
</form>
|
||||
<CustomForm data={data} />
|
||||
<div className={s['gradient']} />
|
||||
</Container>
|
||||
</Section>
|
||||
|
||||
@ -111,88 +111,114 @@
|
||||
}
|
||||
}
|
||||
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.form {
|
||||
position: relative;
|
||||
height: fit-content;
|
||||
|
||||
> div:first-child {
|
||||
> div {
|
||||
@include respond-to('mobile') {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
left: 0;
|
||||
bottom: tovw(-75px, 'mobile', -165px);
|
||||
font-size: tovw(8px, 'mobile', 12px);
|
||||
width: 90%;
|
||||
text-align: center;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
display: grid;
|
||||
margin-top: tovw(60px, 'default', 40px);
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: tovw(40px, 'default', 25px);
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
text-align: end;
|
||||
position: absolute;
|
||||
width: tovw(250px, 'default', 80px);
|
||||
color: var(--color-white);
|
||||
font-size: tovw(14px, 'default', 9px);
|
||||
text-transform: uppercase;
|
||||
font-family: var(--font-dm-mono);
|
||||
}
|
||||
|
||||
label {
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
font-family: var(--font-tt-hoves);
|
||||
font-size: tovw(30px, 'default', 18px);
|
||||
|
||||
input,
|
||||
textarea,
|
||||
select {
|
||||
appearance: none;
|
||||
width: 100%;
|
||||
font-size: tovw(24px, 'default', 18px);
|
||||
padding: tovw(16px, 'default', 12px) tovw(12px, 'default', 10px);
|
||||
margin-top: tovw(20px, 'default', 16px);
|
||||
background: rgb(142 142 142 / 0.1);
|
||||
border: tovw(1px, 'default', 1px) solid var(--color-grey);
|
||||
border-radius: tovw(8px, 'default', 8px);
|
||||
|
||||
&:focus {
|
||||
border: tovw(1px, 'default', 1px) solid var(--color-accent);
|
||||
background: rgb(0 0 244 / 0.1);
|
||||
transition: all 250ms;
|
||||
> div:first-child {
|
||||
@include respond-to('mobile') {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
&::placeholder {
|
||||
color: var(--color-grey-light);
|
||||
display: grid;
|
||||
margin-top: tovw(60px, 'default', 40px);
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: tovw(40px, 'default', 25px);
|
||||
}
|
||||
|
||||
label {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
font-family: var(--font-tt-hoves);
|
||||
font-size: tovw(30px, 'default', 18px);
|
||||
|
||||
input,
|
||||
textarea,
|
||||
select {
|
||||
appearance: none;
|
||||
width: 100%;
|
||||
font-size: tovw(24px, 'default', 18px);
|
||||
padding: tovw(16px, 'default', 12px) tovw(12px, 'default', 10px);
|
||||
margin-top: tovw(20px, 'default', 16px);
|
||||
background: rgb(142 142 142 / 0.1);
|
||||
border: tovw(1px, 'default', 1px) solid var(--color-grey);
|
||||
border-radius: tovw(8px, 'default', 8px);
|
||||
|
||||
&:focus {
|
||||
border: tovw(1px, 'default', 1px) solid var(--color-accent);
|
||||
background: rgb(0 0 244 / 0.1);
|
||||
transition: all 250ms;
|
||||
}
|
||||
|
||||
&::placeholder {
|
||||
color: var(--color-grey-light);
|
||||
}
|
||||
|
||||
option {
|
||||
background-color: black;
|
||||
opacity: 50%;
|
||||
border: none;
|
||||
color: var(--color-white);
|
||||
}
|
||||
}
|
||||
|
||||
option {
|
||||
background-color: black;
|
||||
opacity: 50%;
|
||||
border: none;
|
||||
color: var(--color-white);
|
||||
select {
|
||||
background: url('/images/dropdown.svg') no-repeat 95% 52%;
|
||||
background-color: rgb(142 142 142 / 0.1);
|
||||
background-size: tovw(20px, 'default', 16px);
|
||||
|
||||
&:invalid {
|
||||
color: var(--color-grey-light);
|
||||
}
|
||||
}
|
||||
|
||||
textarea {
|
||||
resize: none;
|
||||
}
|
||||
}
|
||||
|
||||
select {
|
||||
background: url('/images/dropdown.svg') no-repeat 95% 52%;
|
||||
background-color: rgb(142 142 142 / 0.1);
|
||||
background-size: tovw(20px, 'default', 16px);
|
||||
> label:nth-child(2) {
|
||||
margin-top: tovw(60px, 'default', 35px);
|
||||
}
|
||||
|
||||
&:invalid {
|
||||
color: var(--color-grey-light);
|
||||
button {
|
||||
@include respond-to('mobile') {
|
||||
width: 100%;
|
||||
font-size: tovw(18px, 'default', 18px);
|
||||
}
|
||||
|
||||
width: fit-content;
|
||||
align-self: center;
|
||||
font-size: tovw(18px, 'default', 14px);
|
||||
margin-top: tovw(50px, 'default', 35px);
|
||||
}
|
||||
|
||||
textarea {
|
||||
resize: none;
|
||||
}
|
||||
}
|
||||
|
||||
> label:nth-child(2) {
|
||||
margin-top: tovw(60px, 'default', 35px);
|
||||
}
|
||||
|
||||
button {
|
||||
@include respond-to('mobile') {
|
||||
width: 100%;
|
||||
font-size: tovw(18px, 'default', 18px);
|
||||
}
|
||||
|
||||
width: fit-content;
|
||||
align-self: center;
|
||||
font-size: tovw(18px, 'default', 14px);
|
||||
margin-top: tovw(50px, 'default', 35px);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@ import Heading from '~/components/primitives/heading'
|
||||
|
||||
import s from './contact.module.scss'
|
||||
|
||||
interface Props {
|
||||
interface DataProps {
|
||||
data: {
|
||||
contactHeading: string
|
||||
contactDescription: string
|
||||
@ -37,9 +37,168 @@ interface Props {
|
||||
}
|
||||
}
|
||||
|
||||
const Contact = ({ data }: Props) => {
|
||||
type FormProps = {
|
||||
data: DataProps['data']
|
||||
}
|
||||
|
||||
const CustomForm = ({ data }: FormProps) => {
|
||||
const [selectedOption, setSelectedOption] = useState<any>(null)
|
||||
|
||||
const [name, setName] = useState('')
|
||||
const [email, setEmail] = useState('')
|
||||
const [role, setRole] = useState('')
|
||||
const [company, setCompany] = useState('')
|
||||
const [jurisdiction, setJurisdiction] = useState('')
|
||||
const [text, setText] = useState('')
|
||||
|
||||
const [errorMsg, setErrorMsg] = useState('')
|
||||
const [isFormSent, setIsFormSent] = useState(false)
|
||||
const [isSending, setIsSending] = useState(false)
|
||||
|
||||
const handleSubmit = async (e: any) => {
|
||||
e.preventDefault()
|
||||
|
||||
try {
|
||||
setErrorMsg('')
|
||||
|
||||
if (!selectedOption?.value) {
|
||||
setErrorMsg('Inquiry is required')
|
||||
return
|
||||
}
|
||||
|
||||
setIsSending(true)
|
||||
|
||||
const data = {
|
||||
name: name,
|
||||
email: email,
|
||||
message: text,
|
||||
inquiry: selectedOption.value,
|
||||
jurisdiction: jurisdiction,
|
||||
company: company,
|
||||
role: role
|
||||
}
|
||||
|
||||
await fetch('/api/inquiry', {
|
||||
method: 'POST',
|
||||
mode: 'no-cors',
|
||||
body: JSON.stringify(data),
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
|
||||
setIsSending(false)
|
||||
setIsFormSent(true)
|
||||
} catch (error) {
|
||||
// console.log(error)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={s.form}>
|
||||
{isSending && <div>sending...</div>}
|
||||
{errorMsg !== '' && (
|
||||
<div dangerouslySetInnerHTML={{ __html: errorMsg }} />
|
||||
)}
|
||||
{isFormSent && errorMsg === '' && (
|
||||
<div>Thanks for reaching out! We'll contact you shortly.</div>
|
||||
)}
|
||||
<form action="/" onSubmit={(e) => handleSubmit(e)}>
|
||||
<div>
|
||||
<label htmlFor="name">
|
||||
{data?.contactNameLabel}
|
||||
<input
|
||||
placeholder={data?.contactNamePlaceholder}
|
||||
type="text"
|
||||
name="name"
|
||||
id="name"
|
||||
required
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
/>
|
||||
</label>
|
||||
<label htmlFor="email">
|
||||
{data?.contactEmailLabel}
|
||||
<input
|
||||
placeholder={data?.contactEmailPlaceholder}
|
||||
type="email"
|
||||
name="email"
|
||||
id="email"
|
||||
required
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
/>
|
||||
</label>
|
||||
<label htmlFor="role">
|
||||
{data?.contactRoleLabel}
|
||||
<input
|
||||
placeholder={data?.contactRolePlaceholder}
|
||||
type="text"
|
||||
name="role"
|
||||
id="role"
|
||||
required
|
||||
value={role}
|
||||
onChange={(e) => setRole(e.target.value)}
|
||||
/>
|
||||
</label>
|
||||
<label htmlFor="company">
|
||||
{data?.contactCompanyLabel}
|
||||
<input
|
||||
placeholder={data?.contactCompanyPlaceholder}
|
||||
type="text"
|
||||
name="company"
|
||||
id="company"
|
||||
required
|
||||
value={company}
|
||||
onChange={(e) => setCompany(e.target.value)}
|
||||
/>
|
||||
</label>
|
||||
<label htmlFor="jurisdiction">
|
||||
{data?.contactLegalLabel}
|
||||
<input
|
||||
placeholder={data?.contactLegalPlaceholder}
|
||||
type="text"
|
||||
name="jurisdiction"
|
||||
id="jurisdiction"
|
||||
required
|
||||
value={jurisdiction}
|
||||
onChange={(e) => setJurisdiction(e.target.value)}
|
||||
/>
|
||||
</label>
|
||||
<label htmlFor="partnership">
|
||||
{data?.contactInquiryLabel}
|
||||
<Select
|
||||
instanceId={'Partners'}
|
||||
className="select"
|
||||
classNamePrefix="select"
|
||||
placeholder={data?.contactInquiryPlaceholder}
|
||||
value={selectedOption}
|
||||
onChange={setSelectedOption}
|
||||
options={data?.contactInquiryOptions}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<label htmlFor="message">
|
||||
{data?.contactMsgLabel}
|
||||
<textarea
|
||||
placeholder={data?.contactMsgPlaceholder}
|
||||
name="message"
|
||||
id="message"
|
||||
rows={5}
|
||||
required
|
||||
value={text}
|
||||
onChange={(e) => setText(e.target.value)}
|
||||
></textarea>
|
||||
</label>
|
||||
<Button size="medium" variant="primary">
|
||||
{data?.contactButtonLabel}
|
||||
</Button>
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const Contact = ({ data }: DataProps) => {
|
||||
return (
|
||||
<Section className={s['section']}>
|
||||
<Container className={s['container']}>
|
||||
@ -57,85 +216,7 @@ const Contact = ({ data }: Props) => {
|
||||
</Heading>
|
||||
<span>{data?.contactFormWarning}</span>
|
||||
</div>
|
||||
<form action="/">
|
||||
<div>
|
||||
<label htmlFor="name">
|
||||
{data?.contactNameLabel}
|
||||
<input
|
||||
placeholder={data?.contactNamePlaceholder}
|
||||
type="text"
|
||||
name="name"
|
||||
id="name"
|
||||
required
|
||||
/>
|
||||
</label>
|
||||
<label htmlFor="email">
|
||||
{data?.contactEmailLabel}
|
||||
<input
|
||||
placeholder={data?.contactEmailPlaceholder}
|
||||
type="email"
|
||||
name="email"
|
||||
id="email"
|
||||
required
|
||||
/>
|
||||
</label>
|
||||
<label htmlFor="role">
|
||||
{data?.contactRoleLabel}
|
||||
<input
|
||||
placeholder={data?.contactRolePlaceholder}
|
||||
type="text"
|
||||
name="role"
|
||||
id="role"
|
||||
required
|
||||
/>
|
||||
</label>
|
||||
<label htmlFor="company">
|
||||
{data?.contactCompanyLabel}
|
||||
<input
|
||||
placeholder={data?.contactCompanyPlaceholder}
|
||||
type="text"
|
||||
name="company"
|
||||
id="company"
|
||||
required
|
||||
/>
|
||||
</label>
|
||||
<label htmlFor="jurisdiction">
|
||||
{data?.contactLegalLabel}
|
||||
<input
|
||||
placeholder={data?.contactLegalPlaceholder}
|
||||
type="text"
|
||||
name="jurisdiction"
|
||||
id="jurisdiction"
|
||||
required
|
||||
/>
|
||||
</label>
|
||||
<label htmlFor="partnership">
|
||||
{data?.contactInquiryLabel}
|
||||
<Select
|
||||
instanceId={'Partners'}
|
||||
className="select"
|
||||
classNamePrefix="select"
|
||||
placeholder={data?.contactInquiryPlaceholder}
|
||||
value={selectedOption}
|
||||
onChange={setSelectedOption}
|
||||
options={data?.contactInquiryOptions}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<label htmlFor="message">
|
||||
{data?.contactMsgLabel}
|
||||
<textarea
|
||||
placeholder={data?.contactMsgPlaceholder}
|
||||
name="message"
|
||||
id="message"
|
||||
rows={5}
|
||||
required
|
||||
></textarea>
|
||||
</label>
|
||||
<Button size="medium" variant="primary">
|
||||
{data?.contactButtonLabel}
|
||||
</Button>
|
||||
</form>
|
||||
<CustomForm data={data} />
|
||||
</div>
|
||||
<div className={s['gradient']} />
|
||||
</Container>
|
||||
|
||||
9
src/lib/notion/index.ts
Normal file
9
src/lib/notion/index.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { Client } from '@notionhq/client'
|
||||
|
||||
export const notion = new Client({
|
||||
auth: process.env.NOTION_TOKEN
|
||||
})
|
||||
|
||||
export const notionAlt = new Client({
|
||||
auth: process.env.NOTION_TOKEN_ALT
|
||||
})
|
||||
33
src/pages/api/contact.ts
Normal file
33
src/pages/api/contact.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import { NextApiRequest, NextApiResponse } from 'next'
|
||||
|
||||
import { internalServerError, success } from '../../lib/api-responses'
|
||||
import { notion } from '../../lib/notion'
|
||||
|
||||
export default async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
try {
|
||||
const { email, message, inquiry } = JSON.parse(req.body)
|
||||
await notion.pages.create({
|
||||
parent: {
|
||||
database_id: '03c225f0469d436db60bd1b225deffef' as string
|
||||
},
|
||||
properties: {
|
||||
Email: {
|
||||
email,
|
||||
type: 'email'
|
||||
},
|
||||
Message: {
|
||||
type: 'rich_text',
|
||||
rich_text: [{ text: { content: message }, type: 'text' }]
|
||||
},
|
||||
'Type of inquiry': {
|
||||
type: 'select',
|
||||
select: { name: inquiry }
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
success(res)
|
||||
} catch (error) {
|
||||
internalServerError(res, error)
|
||||
}
|
||||
}
|
||||
55
src/pages/api/inquiry.ts
Normal file
55
src/pages/api/inquiry.ts
Normal file
@ -0,0 +1,55 @@
|
||||
import { NextApiRequest, NextApiResponse } from 'next'
|
||||
|
||||
import { internalServerError, success } from '../../lib/api-responses'
|
||||
import { notionAlt } from '../../lib/notion'
|
||||
|
||||
export default async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
try {
|
||||
const { name, email, message, inquiry, role, company, jurisdiction } =
|
||||
JSON.parse(req.body)
|
||||
await notionAlt.pages.create({
|
||||
parent: {
|
||||
database_id: '90a7d71e342f4b91b7ca263a14d839ea' as string
|
||||
},
|
||||
properties: {
|
||||
Name: {
|
||||
title: [
|
||||
{
|
||||
text: {
|
||||
content: name
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
Email: {
|
||||
email,
|
||||
type: 'email'
|
||||
},
|
||||
Message: {
|
||||
type: 'rich_text',
|
||||
rich_text: [{ text: { content: message }, type: 'text' }]
|
||||
},
|
||||
Role: {
|
||||
type: 'rich_text',
|
||||
rich_text: [{ text: { content: role }, type: 'text' }]
|
||||
},
|
||||
Company: {
|
||||
type: 'rich_text',
|
||||
rich_text: [{ text: { content: company }, type: 'text' }]
|
||||
},
|
||||
'Legal jurisdiction': {
|
||||
type: 'rich_text',
|
||||
rich_text: [{ text: { content: jurisdiction }, type: 'text' }]
|
||||
},
|
||||
Inquiry: {
|
||||
type: 'select',
|
||||
select: { name: inquiry }
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
success(res)
|
||||
} catch (error) {
|
||||
internalServerError(res, error)
|
||||
}
|
||||
}
|
||||
21
yarn.lock
21
yarn.lock
@ -1101,6 +1101,14 @@
|
||||
"@nodelib/fs.scandir" "2.1.5"
|
||||
fastq "^1.6.0"
|
||||
|
||||
"@notionhq/client@^1.0.4":
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@notionhq/client/-/client-1.0.4.tgz#405e9468576baf81019db4d791f4b52d091f4a57"
|
||||
integrity sha512-m7zZ5l3RUktayf1lRBV1XMb8HSKsmWTv/LZPqP7UGC1NMzOlc+bbTOPNQ4CP/c1P4cP61VWLb/zBq7a3c0nMaw==
|
||||
dependencies:
|
||||
"@types/node-fetch" "^2.5.10"
|
||||
node-fetch "^2.6.1"
|
||||
|
||||
"@polka/url@^1.0.0-next.20":
|
||||
version "1.0.0-next.21"
|
||||
resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.21.tgz#5de5a2385a35309427f6011992b544514d559aa1"
|
||||
@ -1216,6 +1224,14 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.2.tgz#ee771e2ba4b3dc5b372935d549fd9617bf345b8c"
|
||||
integrity sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==
|
||||
|
||||
"@types/node-fetch@^2.5.10":
|
||||
version "2.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.1.tgz#8f127c50481db65886800ef496f20bbf15518975"
|
||||
integrity sha512-oMqjURCaxoSIsHSr1E47QHzbmzNR5rK8McHuNb11BOM9cHcIK3Avy0s/b2JlXHoQGTYS3NsvWzV1M0iK7l0wbA==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
form-data "^3.0.0"
|
||||
|
||||
"@types/node@*":
|
||||
version "17.0.23"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.23.tgz#3b41a6e643589ac6442bdbd7a4a3ded62f33f7da"
|
||||
@ -6674,3 +6690,8 @@ youtube-player@5.5.2:
|
||||
debug "^2.6.6"
|
||||
load-script "^1.0.0"
|
||||
sister "^3.0.0"
|
||||
|
||||
zod@^3.17.3:
|
||||
version "3.17.3"
|
||||
resolved "https://registry.yarnpkg.com/zod/-/zod-3.17.3.tgz#86abbc670ff0063a4588d85a4dcc917d6e4af2ba"
|
||||
integrity sha512-4oKP5zvG6GGbMlqBkI5FESOAweldEhSOZ6LI6cG+JzUT7ofj1ZOC0PJudpQOpT1iqOFpYYtX5Pw0+o403y4bcg==
|
||||
|
||||
Loading…
Reference in New Issue
Block a user