Skip to content
This repository has been archived by the owner on Mar 30, 2022. It is now read-only.

feature/mantine form with validation for host signup #9

Merged
merged 2 commits into from
Feb 27, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
# next.js
/.next/
/out/

.trunk
# production
/build

Expand All @@ -36,3 +36,4 @@ yarn-error.log*

# typescript
*.tsbuildinfo
.markdownlint.yaml
41 changes: 20 additions & 21 deletions components/hostLookup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@ export const HostLookup = ({ hosts }: HostLookupProps) => {
const rows = hosts?.map((element) => (
<tr key={element.fields.firstName}>
<td>{element.fields.cityRegion}</td>
<td>{element.fields.firstName} {element.fields.lastName}</td>
<td>
{element.fields.firstName} {element.fields.lastName}
</td>
<td>{element.fields.hostCapacity}</td>
<td>
<Button variant="light" size="xs">
<MdOutlineHouse style={{ height: '1rem', width: '1rem' }} />
Contact
</Button>
<Button variant="light" size="xs">
<MdOutlineHouse style={{ height: '1rem', width: '1rem' }} />
Contact
</Button>
</td>
</tr>
));
Expand All @@ -37,22 +39,19 @@ export const HostLookup = ({ hosts }: HostLookupProps) => {
<Title order={3} style={{ padding: '1rem' }}>
Available hosts
</Title>

<Table
striped
horizontalSpacing={5}
style={{ display: 'block', height: 350, overflow: 'auto' }}
>
<thead>
<tr>
<th>Location</th>
<th>Name</th>
<th>Cap.</th>
<th>Contact host</th>
</tr>
</thead>
<tbody>{rows}</tbody>
</Table>
<div style={{ width: '100%', maxHeight: 500, overflow: 'auto' }}>
<Table striped horizontalSpacing={5}>
<thead>
<tr>
<th>Location</th>
<th>Name</th>
<th>Cap.</th>
<th>Contact host</th>
</tr>
</thead>
<tbody>{rows}</tbody>
</Table>
</div>
</Paper>
<Space h="xl" />

Expand Down
133 changes: 117 additions & 16 deletions components/hostSignup.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,125 @@
import { useState } from 'react';
import { useForm } from 'react-hook-form';
import { Space } from '@mantine/core';
import { useForm } from '@mantine/hooks';

import {
Space,
Paper,
Title,
TextInput,
Textarea,
Button,
NumberInput,
MultiSelect,
Checkbox,
} from '@mantine/core';
import { MdOutlineMailOutline, MdMap, MdPhone } from 'react-icons/md';
import axios from 'axios';

const languagesOptions = [
{ value: 'English', label: 'English' },
{ value: 'Ukrainian', label: 'Ukrainian' },
{ value: 'Russian', label: 'Russian' },
{ value: 'Polish', label: 'Polish' },
{ value: 'Romanian', label: 'Romanian' },
{ value: 'German', label: 'German' },
{ value: 'Hungarian', label: 'Hungarian' },
];

export const HostSignup = () => {
const { register, handleSubmit } = useForm();
const [data, setData] = useState('');
const form = useForm({
initialValues: {
firstName: '',
lastName: '',
phoneNumber: '',
email: '',
cityRegion: '',
accomodationDetails: '',
hostCapacity: 0,
languages: '',
termsOfService: false,
},

validationRules: {
email: (value) => /^\S+@\S+$/.test(value),
},
});

const onSubmitHandler = (values: typeof form['values']) => {
console.log(values);
axios({ method: 'POST', url: '/api/host', data: values });
};

return (
<>
<Space h="sm" />
<iframe
className="airtable-embed"
src="https://airtable.com/embed/shrGJ9QFefvxi47xL?backgroundColor=yellow"
frameBorder="0"
style={{
width: '100%',
height: '100%',
background: 'transparent',
display: 'block',
}}
></iframe>
<Paper padding="lg" shadow="sm" radius="md" withBorder>
<Title order={3}>Find a host</Title>
<Space h="lg" />

<form onSubmit={form.onSubmit(onSubmitHandler)}>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we just use the session.user.name from NextAuth for this instead of having them fill it out?

<TextInput
{...form.getInputProps('firstName')}
placeholder="First Name"
label="First Name"
required
/>
<TextInput
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we just use the session.user.name from NextAuth for this instead of having them fill it out?

{...form.getInputProps('lastName')}
placeholder="Last Name"
label="Last Name"
required
/>
<TextInput
{...form.getInputProps('phoneNumber')}
icon={<MdPhone />}
placeholder="+03 123 456 789"
label="Phone Number"
required
/>
<TextInput
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we just use the session.user.email from NextAuth for this instead of having them fill it out?

{...form.getInputProps('email')}
icon={<MdOutlineMailOutline />}
placeholder="Email"
label="Email address"
required
/>
<TextInput
{...form.getInputProps('cityRegion')}
icon={<MdMap />}
placeholder="City"
label="City / Region Name"
required
/>
<Textarea
{...form.getInputProps('accomodationDetails')}
placeholder="About the accomodation and Rules"
label="Accomodation details"
/>
<NumberInput
defaultValue={1}
{...form.getInputProps('hostCapacity')}
placeholder="Number of people"
label="Host capacity"
required
/>
<MultiSelect
{...form.getInputProps('languages')}
data={languagesOptions}
label="Spoken languages"
placeholder="Pick all that you like"
/>
<Space h="lg" />
<Checkbox
{...form.getInputProps('termsOfService')}
label="I agree to sell my privacy"
required
/>
<Space h="xl" />

<Button type="submit" color="teal">
Submit
</Button>
</form>
</Paper>
</>
);
};
4 changes: 2 additions & 2 deletions config/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export const AIRTABLE_URL = `https://api.airtable.com/v0/${process.env.AIRTABLE_APP_ID}/Hosts?maxRecords=50&view=Grid%20view`;
export const AIRTABLE_API_KEY = process.env.AIRTABLE_API_KEY;
export const AIRTABLE_URL = `https://api.airtable.com/v0/${process.env.AIRTABLE_APP_ID}/Hosts`;
export const AIRTABLE_API_KEY = process.env.AIRTABLE_API_KEY;
50 changes: 50 additions & 0 deletions pages/api/host.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import axios from 'axios';
import { AIRTABLE_API_KEY, AIRTABLE_URL } from '../../config';
import type { NextApiRequest, NextApiResponse } from 'next';

const handler = async (req: NextApiRequest, res: NextApiResponse) => {
if (req.method === 'POST') {
console.log('Called with', req.body);
const {
firstName,
lastName,
phoneNumber,
email,
cityRegion,
accomodationDetails,
hostCapacity,
languages,
} = req.body;
try {
const response = await axios({
method: 'POST',
url: AIRTABLE_URL,
data: {
records: [
{
fields: {
firstName,
lastName,
phoneNumber,
email,
cityRegion,
accomodationDetails,
hostCapacity,
languages,
},
},
],
typecast: true,
},
headers: { Authorization: `Bearer ${AIRTABLE_API_KEY}` },
});
res.status(200).json({ created: response.data });
} catch (err) {
res.status(500).json({ error: err });
}
} else {
res.status(404).json({ info: 'method not implemented' });
}
};

export default handler;
2 changes: 1 addition & 1 deletion pages/host-lookup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export default Home;
export async function getServerSideProps() {
const response = await axios({
method: 'GET',
url: AIRTABLE_URL,
url: `${AIRTABLE_URL}?maxRecords=50&view=Grid%20view`,
headers: { Authorization: `Bearer ${AIRTABLE_API_KEY}` },
});

Expand Down