Skip to content

Commit b338d26

Browse files
bogdan-tsNikolayS
authored andcommitted
feat: PostgresAI copilot landing page
1 parent 7b2da28 commit b338d26

File tree

5 files changed

+513
-23
lines changed

5 files changed

+513
-23
lines changed
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import classNames from 'classnames'
2+
import React, { useState } from 'react'
3+
import BrowserOnly from '@docusaurus/BrowserOnly'
4+
import useDocusaurusContext from '@docusaurus/useDocusaurusContext'
5+
6+
import styles from './styles.module.css'
7+
8+
export default function SignupForm() {
9+
const { siteConfig } = useDocusaurusContext()
10+
const apiUrlPrefix = siteConfig.customFields.apiUrlPrefix
11+
12+
const [state, setState] = useState({
13+
email: '',
14+
error: '',
15+
isLoading: false,
16+
isSubmitted: false,
17+
})
18+
19+
const hasError = state.error.length > 0
20+
21+
const onSubmit = (event: React.FormEvent<HTMLFormElement>) => {
22+
event.preventDefault()
23+
24+
setState({ ...state, isLoading: true, error: '' })
25+
26+
fetch(`${apiUrlPrefix}/bot_leads`, {
27+
method: 'POST',
28+
headers: {
29+
'Content-Type': 'application/json',
30+
},
31+
body: JSON.stringify({
32+
email: state.email,
33+
}),
34+
})
35+
.then((response) => {
36+
if (response.ok) {
37+
setState({
38+
email: '',
39+
isSubmitted: true,
40+
isLoading: false,
41+
error: '',
42+
})
43+
} else {
44+
response.json().then((res) => {
45+
setState({
46+
...state,
47+
isLoading: false,
48+
isSubmitted: false,
49+
error: res?.message || 'Something went wrong',
50+
})
51+
})
52+
}
53+
})
54+
.catch((err) =>
55+
setState({
56+
...state,
57+
isLoading: false,
58+
isSubmitted: false,
59+
error: err?.message || err || 'Something went wrong',
60+
}),
61+
)
62+
}
63+
64+
return (
65+
<div id="signup" className={styles.form}>
66+
{state.isSubmitted ? (
67+
<div className={styles.container}>
68+
<h3>Thank you! We will get in touch.</h3>
69+
</div>
70+
) : (
71+
<form onSubmit={onSubmit} className={styles.container}>
72+
<h3 className={styles.formTitle}>Get early access</h3>
73+
<p className={styles.formDescription}>
74+
Currently in preview. Please use your work email address
75+
</p>
76+
<div className={styles.inputWrapper}>
77+
<input
78+
type="email"
79+
disabled={state.isLoading || state.isSubmitted}
80+
className={classNames(
81+
hasError && styles.inputError,
82+
styles.input,
83+
)}
84+
value={state.email}
85+
placeholder="[email protected]"
86+
required
87+
onChange={(evt) => {
88+
setState({
89+
...state,
90+
email: evt.target.value,
91+
error: '',
92+
})
93+
}}
94+
/>
95+
<button
96+
type="submit"
97+
className={styles.button}
98+
disabled={state.isLoading || state.isSubmitted || hasError}
99+
>
100+
{state.isLoading ? (
101+
<div className={styles.loading} />
102+
) : (
103+
'Join'
104+
)}
105+
</button>
106+
</div>
107+
{hasError && (
108+
<span className={styles.error}>{state.error}</span>
109+
)}
110+
</form>
111+
)}
112+
</div>
113+
)
114+
}
115+
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
.form {
2+
display: flex;
3+
flex-direction: column;
4+
justify-content: center;
5+
align-items: center;
6+
text-align: center;
7+
width: 100%;
8+
}
9+
10+
.container {
11+
width: 100%;
12+
max-width: 600px;
13+
margin: 0 auto;
14+
position: relative;
15+
padding: 40px;
16+
}
17+
18+
.formTitle {
19+
font-weight: bold;
20+
font-size: 28px;
21+
line-height: 1.3;
22+
margin-bottom: 15px;
23+
color: var(--ifm-heading-color);
24+
}
25+
26+
.formDescription {
27+
font-size: 12px;
28+
line-height: 18px;
29+
margin-bottom: 25px;
30+
color: var(--ifm-font-color-base);
31+
}
32+
33+
.inputWrapper {
34+
display: flex;
35+
flex-direction: row;
36+
justify-content: center;
37+
align-items: stretch;
38+
width: 100%;
39+
max-width: 500px;
40+
margin: 0 auto 15px auto;
41+
}
42+
43+
.helperText {
44+
font-size: 14px;
45+
color: #666;
46+
margin: 5px 0 10px 0;
47+
text-align: center;
48+
}
49+
50+
.error {
51+
display: block;
52+
color: #ff0000;
53+
font-size: 14px;
54+
margin-top: 10px;
55+
text-align: center;
56+
}
57+
58+
.inputError {
59+
border: 2px solid #ff0000 !important;
60+
}
61+
62+
.input {
63+
flex: 1;
64+
padding: 12px 16px;
65+
font-size: 16px;
66+
border: 2px solid #e0e0e0;
67+
border-right: none;
68+
border-radius: 4px 0 0 4px;
69+
background: #fff;
70+
transition: all 0.3s ease;
71+
font-family: inherit;
72+
}
73+
74+
.input:focus {
75+
outline: none;
76+
border-color: #ff6112;
77+
}
78+
79+
.input::placeholder {
80+
color: #999;
81+
}
82+
83+
.button {
84+
padding: 12px 30px;
85+
font-size: 16px;
86+
font-weight: 500;
87+
background-color: #ff6112;
88+
color: #fff;
89+
border: none;
90+
border-radius: 0 4px 4px 0;
91+
cursor: pointer;
92+
transition: background-color 0.3s ease;
93+
white-space: nowrap;
94+
min-width: 140px;
95+
}
96+
97+
.button:hover:not(:disabled) {
98+
background-color: #cd4400;
99+
}
100+
101+
.button:disabled {
102+
cursor: not-allowed;
103+
opacity: 0.6;
104+
}
105+
106+
.input:disabled {
107+
background-color: #f5f5f5;
108+
cursor: not-allowed;
109+
}
110+
111+
.loading {
112+
display: inline-block;
113+
width: 20px;
114+
height: 20px;
115+
border: 3px solid rgba(255, 255, 255, 0.3);
116+
border-radius: 50%;
117+
border-top-color: #fff;
118+
animation: spin 1s ease-in-out infinite;
119+
}
120+
121+
@keyframes spin {
122+
to {
123+
transform: rotate(360deg);
124+
}
125+
}
126+
127+
/* Mobile Responsive */
128+
@media (max-width: 767px) {
129+
.container {
130+
padding: 30px 20px;
131+
}
132+
133+
.formTitle {
134+
font-size: 22px;
135+
}
136+
137+
.formDescription {
138+
font-size: 14px;
139+
}
140+
141+
.inputWrapper {
142+
flex-direction: column;
143+
max-width: 100%;
144+
}
145+
146+
.input {
147+
border-right: 2px solid #e0e0e0;
148+
border-radius: 4px 4px 0 0;
149+
padding: 14px 16px;
150+
}
151+
152+
.button {
153+
border-radius: 0 0 4px 4px;
154+
padding: 14px 30px;
155+
min-width: auto;
156+
}
157+
158+
.helperText {
159+
font-size: 13px;
160+
}
161+
}
162+
163+
@media (min-width: 768px) and (max-width: 991px) {
164+
.formTitle {
165+
font-size: 24px;
166+
}
167+
}
168+
169+
html[data-theme="dark"] .input {
170+
background: #1b1b1d;
171+
border-color: #444;
172+
color: #fff;
173+
}
174+
175+
html[data-theme="dark"] .input:focus {
176+
border-color: #ff6112;
177+
}
178+
179+
html[data-theme="dark"] .helperText {
180+
color: #aaa;
181+
}

src/css/custom.css

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -196,21 +196,21 @@ html[data-theme="dark"] .DocSearch {
196196

197197
html[data-theme="light"] .banner {
198198
background: linear-gradient(180deg, #ffe1d2 0%, #ffffff 100%);
199-
min-height: 80vh;
199+
/* min-height: 80vh; */
200200
}
201201

202202
html[data-theme="dark"] .banner {
203-
min-height: 80vh;
203+
/* min-height: 80vh; */
204204
}
205205

206206
.banner .row {
207-
min-height: 80vh;
207+
/* min-height: 80vh; */
208208
}
209209

210210
.banner h1 {
211211
font-weight: bold;
212-
font-size: 28px;
213-
line-height: 32px;
212+
font-size: 48px !important;
213+
line-height: 1.2 !important;
214214
color: #ff6112;
215215
margin: 0;
216216
}
@@ -519,8 +519,8 @@ table.docs-home td {
519519
min-height: 540px;
520520
}
521521
.banner h1 {
522-
font-size: 32px;
523-
line-height: 37px;
522+
font-size: 48px !important;
523+
line-height: 1.2 !important;
524524
}
525525
.banner p {
526526
font-size: 26px;
@@ -600,8 +600,8 @@ table.docs-home td {
600600
min-height: 540px;
601601
}
602602
.banner h1 {
603-
font-size: 32px;
604-
line-height: 37px;
603+
font-size: 48px !important;
604+
line-height: 1.2 !important;
605605
}
606606
.banner p {
607607
font-size: 26px;

0 commit comments

Comments
 (0)