Skip to content

Commit

Permalink
Lead Form & Homepage integration
Browse files Browse the repository at this point in the history
  • Loading branch information
pantheredeye committed Dec 13, 2024
1 parent 05d5949 commit 13bb2e3
Show file tree
Hide file tree
Showing 10 changed files with 254 additions and 10 deletions.
8 changes: 8 additions & 0 deletions api/db/migrations/20241213114416_l_ead_form/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
-- CreateTable
CREATE TABLE "Lead" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"name" TEXT,
"email" TEXT NOT NULL,
"feedback" TEXT,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
8 changes: 8 additions & 0 deletions api/db/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -122,3 +122,11 @@ model Media {
url String
description String
}

model Lead {
id Int @id @default(autoincrement())
name String?
email String
feedback String?
createdAt DateTime @default(now())
}
32 changes: 32 additions & 0 deletions api/src/graphql/leads.sdl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
export const schema = gql`
type Lead {
id: Int!
name: String
email: String!
feedback: String
createdAt: DateTime!
}
type Query {
leads: [Lead!]! @requireAuth
lead(id: Int!): Lead @requireAuth
}
input CreateLeadInput {
name: String
email: String!
feedback: String
}
input UpdateLeadInput {
name: String
email: String
feedback: String
}
type Mutation {
createLead(input: CreateLeadInput!): Lead! @requireAuth
updateLead(id: Int!, input: UpdateLeadInput!): Lead! @requireAuth
deleteLead(id: Int!): Lead! @requireAuth
}
`
12 changes: 12 additions & 0 deletions api/src/services/leads/leads.scenarios.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { Prisma, Lead } from '@prisma/client'

import type { ScenarioData } from '@redwoodjs/testing/api'

export const standard = defineScenario<Prisma.LeadCreateArgs>({
lead: {
one: { data: { email: 'String' } },
two: { data: { email: 'String' } },
},
})

export type StandardScenario = ScenarioData<Lead, 'lead'>
49 changes: 49 additions & 0 deletions api/src/services/leads/leads.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import type { Lead } from '@prisma/client'

import { leads, lead, createLead, updateLead, deleteLead } from './leads'
import type { StandardScenario } from './leads.scenarios'

// Generated boilerplate tests do not account for all circumstances
// and can fail without adjustments, e.g. Float.
// Please refer to the RedwoodJS Testing Docs:
// https://redwoodjs.com/docs/testing#testing-services
// https://redwoodjs.com/docs/testing#jest-expect-type-considerations

describe('leads', () => {
scenario('returns all leads', async (scenario: StandardScenario) => {
const result = await leads()

expect(result.length).toEqual(Object.keys(scenario.lead).length)
})

scenario('returns a single lead', async (scenario: StandardScenario) => {
const result = await lead({ id: scenario.lead.one.id })

expect(result).toEqual(scenario.lead.one)
})

scenario('creates a lead', async () => {
const result = await createLead({
input: { email: 'String' },
})

expect(result.email).toEqual('String')
})

scenario('updates a lead', async (scenario: StandardScenario) => {
const original = (await lead({ id: scenario.lead.one.id })) as Lead
const result = await updateLead({
id: original.id,
input: { email: 'String2' },
})

expect(result.email).toEqual('String2')
})

scenario('deletes a lead', async (scenario: StandardScenario) => {
const original = (await deleteLead({ id: scenario.lead.one.id })) as Lead
const result = await lead({ id: original.id })

expect(result).toEqual(null)
})
})
32 changes: 32 additions & 0 deletions api/src/services/leads/leads.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import type { QueryResolvers, MutationResolvers } from 'types/graphql'

import { db } from 'src/lib/db'

export const leads: QueryResolvers['leads'] = () => {
return db.lead.findMany()
}

export const lead: QueryResolvers['lead'] = ({ id }) => {
return db.lead.findUnique({
where: { id },
})
}

export const createLead: MutationResolvers['createLead'] = ({ input }) => {
return db.lead.create({
data: input,
})
}

export const updateLead: MutationResolvers['updateLead'] = ({ id, input }) => {
return db.lead.update({
data: input,
where: { id },
})
}

export const deleteLead: MutationResolvers['deleteLead'] = ({ id }) => {
return db.lead.delete({
where: { id },
})
}
26 changes: 26 additions & 0 deletions web/src/components/LeadForm/LeadForm.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Pass props to your component by passing an `args` object to your story
//
// ```tsx
// export const Primary: Story = {
// args: {
// propName: propValue
// }
// }
// ```
//
// See https://storybook.js.org/docs/react/writing-stories/args.

import type { Meta, StoryObj } from '@storybook/react'

import LeadForm from './LeadForm'

const meta: Meta<typeof LeadForm> = {
component: LeadForm,
tags: ['autodocs'],
}

export default meta

type Story = StoryObj<typeof LeadForm>

export const Primary: Story = {}
14 changes: 14 additions & 0 deletions web/src/components/LeadForm/LeadForm.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { render } from '@redwoodjs/testing/web'

import LeadForm from './LeadForm'

// Improve this test with help from the Redwood Testing Doc:
// https://redwoodjs.com/docs/testing#testing-components

describe('LeadForm', () => {
it('renders successfully', () => {
expect(() => {
render(<LeadForm />)
}).not.toThrow()
})
})
48 changes: 48 additions & 0 deletions web/src/components/LeadForm/LeadForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { Form, TextField, TextAreaField, Submit } from '@redwoodjs/forms'
import { useMutation } from '@redwoodjs/web'

const CREATE_LEAD = gql`
mutation CreateLead($input: CreateLeadInput!) {
createLead(input: $input) {
id
}
}
`

const LeadForm = () => {
const [createLead] = useMutation(CREATE_LEAD, {
onCompleted: () => {
alert('Thanks for signing up!')
},
})

const onSubmit = (data) => {
createLead({ variables: { input: data } })
}

return (
<Form onSubmit={onSubmit} className="space-y-4">
<TextField
name="name"
placeholder="Your Name"
className="w-full rounded-lg bg-gray-700 p-3 text-white"
/>
<TextField
name="email"
placeholder="Your Email"
className="w-full rounded-lg bg-gray-700 p-3 text-white"
required
/>
<TextAreaField
name="feedback"
placeholder="Feature Requests or Feedback"
className="w-full rounded-lg bg-gray-700 p-3 text-white"
/>
<Submit className="rounded-xl bg-indigo-600 px-6 py-3 text-lg font-medium text-white shadow-lg hover:bg-indigo-500 focus:outline-none">
Submit
</Submit>
</Form>
)
}

export default LeadForm
35 changes: 25 additions & 10 deletions web/src/pages/HomePage/HomePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import * as HeroIcons from '@heroicons/react/24/outline'

import { Link, routes } from '@redwoodjs/router'

import LeadForm from 'src/components/LeadForm/LeadForm'

import background from './Daytime Background.png'

const features = [
Expand Down Expand Up @@ -91,20 +93,33 @@ const HomePage = () => {
of communication
</p>

<Link
{/* <Link
to={routes.signup()}
className="rounded-xl bg-indigo-600 px-6 py-3 text-lg font-medium text-white shadow-lg hover:bg-indigo-500 focus:outline-none"
>
Get Started Today
</Link>
<button
onClick={() =>
(window.location.href = 'mailto:[email protected]')
}
className="rounded-xl bg-gray-700 px-6 py-3 font-medium text-white hover:bg-gray-600"
>
Contact Us
</button>
</Link> */}

<div className="py-8 px-4 text-center">
<h2 className="text-4xl font-semibold text-gray-200">
Stay Updated
</h2>
<p className="text-lg text-black-900 mt-4">
Fill out the form below to share get updates, share feature ideas
or join the waitlist.
</p>
<div className="mt-8 mx-auto max-w-md">
<LeadForm />
</div>
<button
onClick={() =>
(window.location.href = 'mailto:[email protected]')
}
className="mt-8 rounded-xl bg-indigo-600 px-6 py-3 text-lg font-medium text-white shadow-lg hover:bg-indigo-500 focus:outline-none"
>
Contact Us
</button>
</div>
</div>
</div>

Expand Down

0 comments on commit 13bb2e3

Please sign in to comment.