From ebfe8404c18cf28e439512cdc884ce3d6b712f52 Mon Sep 17 00:00:00 2001 From: TheCatLady <52870424+TheCatLady@users.noreply.github.com> Date: Tue, 3 Oct 2023 13:05:19 -0700 Subject: [PATCH] feat: create Attio list entry upon early access request --- package.json | 23 +- src/app/api/request-early-access/route.ts | 64 ++- src/app/cookie-policy/page.tsx | 4 +- src/app/not-found.tsx | 2 +- src/components/RequestEarlyAccessForm.tsx | 20 +- src/interfaces/attio.ts | 340 ++++++++++++++++ yarn.lock | 456 +++++++++------------- 7 files changed, 606 insertions(+), 303 deletions(-) create mode 100644 src/interfaces/attio.ts diff --git a/package.json b/package.json index dbe3b0e..426f02c 100644 --- a/package.json +++ b/package.json @@ -19,44 +19,43 @@ "dependencies": { "@headlessui/react": "1.7.17", "@hookform/resolvers": "3.3.1", - "axios": "1.5.1", "clsx": "2.0.0", "graphql": "16.8.1", "graphql-request": "6.1.0", - "next": "13.5.3", - "next-client-cookies": "1.0.3", + "next": "13.5.4", + "next-client-cookies": "1.0.4", "react": "18.2.0", "react-dom": "18.2.0", "react-google-recaptcha": "3.1.0", - "react-hook-form": "7.46.2", + "react-hook-form": "7.47.0", "react-icons": "4.11.0", "tailwind-merge": "1.14.0", - "zod": "3.22.2", + "zod": "3.22.3", "zod-form-data": "2.0.1" }, "devDependencies": { - "@commitlint/cli": "17.7.1", + "@commitlint/cli": "17.7.2", "@commitlint/config-conventional": "17.7.0", "@svgr/webpack": "8.1.0", "@tailwindcss/forms": "0.5.6", "@types/gtag.js": "0.0.14", - "@types/react": "18.2.23", + "@types/react": "18.2.24", "@types/react-google-recaptcha": "2.1.6", - "@typescript-eslint/eslint-plugin": "6.7.3", - "@typescript-eslint/parser": "6.7.3", + "@typescript-eslint/eslint-plugin": "6.7.4", + "@typescript-eslint/parser": "6.7.4", "autoprefixer": "10.4.16", "encoding": "0.1.13", "eslint": "8.50.0", - "eslint-config-next": "13.5.3", + "eslint-config-next": "13.5.4", "eslint-config-prettier": "9.0.0", "eslint-plugin-simple-import-sort": "10.0.0", "eslint-plugin-unused-imports": "3.0.0", "husky": "8.0.3", "lint-staged": "14.0.1", "next-sitemap": "4.2.3", - "postcss": "8.4.30", + "postcss": "8.4.31", "prettier": "3.0.3", - "prettier-plugin-tailwindcss": "0.5.4", + "prettier-plugin-tailwindcss": "0.5.5", "svgo": "3.0.2", "tailwindcss": "3.3.3", "typescript": "5.2.2" diff --git a/src/app/api/request-early-access/route.ts b/src/app/api/request-early-access/route.ts index 0fb99dc..6ed5d76 100644 --- a/src/app/api/request-early-access/route.ts +++ b/src/app/api/request-early-access/route.ts @@ -1,4 +1,3 @@ -import axios from 'axios'; import type { NextRequest } from 'next/server'; import { z } from 'zod'; import { zfd } from 'zod-form-data'; @@ -9,34 +8,71 @@ import { RECAPTCHA_SECRET } from '@/constants/google'; export async function POST(req: NextRequest) { const schema = zfd.formData({ email: zfd.text(z.string().email()), - captcha: zfd.text(z.string().optional()), + captcha: zfd.text(), }); - const { email, captcha } = schema.parse(await req.formData()); + const { email, captcha } = schema.parse(await req.json()); - const { data: captchaResponse } = await axios.post( + const captchaResponse = await fetch( 'https://www.google.com/recaptcha/api/siteverify', - null, { - params: { secret: RECAPTCHA_SECRET!, response: captcha }, + method: 'POST', + body: new URLSearchParams({ + secret: RECAPTCHA_SECRET!, + response: captcha, + }), + }, + ); + + if (!captchaResponse.ok) { + return new Response('Invalid captcha', { status: 500 }); + } + + const personResponse = await fetch( + 'https://api.attio.com/v2/objects/people/records?matching_attribute=email_addresses', + { + method: 'PUT', headers: { - 'Content-Type': 'application/x-www-form-urlencoded', + Authorization: `Bearer ${ATTIO_API_KEY}`, + 'Content-Type': 'application/json', }, + body: JSON.stringify({ + data: { values: { email_addresses: [{ email_address: email }] } }, + }), }, ); - if (!captchaResponse.success) { - return new Response('Invalid captcha', { status: 500 }); + if (!personResponse.ok) { + return new Response('Failed to assert Attio person record', { + status: 500, + }); } - await axios.put( - 'https://api.attio.com/v1/people', - { email_addresses: [email] }, + const listResponse = await fetch( + 'https://api.attio.com/v2/lists/fix_early_access/entries', { - auth: { username: ATTIO_API_KEY!, password: '' }, - headers: { 'Content-Type': 'application/json' }, + method: 'POST', + headers: { + Authorization: `Bearer ${ATTIO_API_KEY}`, + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + data: { + entry_values: { + status: [{ status: '60179743-3e4f-417e-8aa9-73623cd93715' }], + }, + parent_object: 'people', + parent_record_id: (await personResponse.json()).data.id.record_id, + }, + }), }, ); + if (!listResponse.ok) { + return new Response('Failed to create Attio list entry', { + status: 500, + }); + } + return new Response(); } diff --git a/src/app/cookie-policy/page.tsx b/src/app/cookie-policy/page.tsx index 7163ffd..b27ce18 100644 --- a/src/app/cookie-policy/page.tsx +++ b/src/app/cookie-policy/page.tsx @@ -6,9 +6,9 @@ export const metadata: Metadata = { title: 'Cookie policy', }; -export default function CookiePolicy() { +export default function CookiePolicyPage() { return ( -
404
diff --git a/src/components/RequestEarlyAccessForm.tsx b/src/components/RequestEarlyAccessForm.tsx index 1145eae..2e00c79 100644 --- a/src/components/RequestEarlyAccessForm.tsx +++ b/src/components/RequestEarlyAccessForm.tsx @@ -2,7 +2,6 @@ import { Disclosure } from '@headlessui/react'; import { zodResolver } from '@hookform/resolvers/zod'; -import axios from 'axios'; import { useRef, useState } from 'react'; import ReCAPTCHA from 'react-google-recaptcha'; import { useForm } from 'react-hook-form'; @@ -76,15 +75,18 @@ export function RequestEarlyAccessForm() {