Skip to content

Commit

Permalink
test dirty integration
Browse files Browse the repository at this point in the history
  • Loading branch information
arzafran committed Sep 6, 2024
1 parent 4178137 commit dfb9896
Show file tree
Hide file tree
Showing 8 changed files with 360 additions and 2 deletions.
77 changes: 77 additions & 0 deletions app/(pages)/shopify/(components)/customer/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
'use client'

import { Form, SubmitButton } from 'libs/form'
import { InputField } from 'libs/form/fields'

// import {
// LoginCustomerAction,
// LogoutCustomerAction,
// CreateCustomerAction,
// } from 'libs/shopify/customer/actions'

// function InputField({ type, id, placeholder, required, value, onChange }) {
// return (
// <div className="field">
// <input
// type={type}
// id={id}
// name={id}
// required={required}
// placeholder={placeholder}
// className="input"
// value={value}
// onChange={onChange}
// />
// </div>
// )
// }

export function LoginForm() {
return (
<Form action={'LoginCustomerAction'}>
<InputField type="email" id="email" placeholder="Email" required={true} />
<InputField
type="password"
id="password"
placeholder="Password"
required={true}
/>
<SubmitButton defaultText="Login" />
</Form>
)
}

export function RegisterForm() {
return (
<Form action={'CreateCustomerAction'}>
<InputField
type="text"
id="firstName"
placeholder="First Name"
required={true}
/>
<InputField
type="text"
id="lastName"
placeholder="Last Name"
required={true}
/>
<InputField type="email" id="email" placeholder="Email" required={true} />
<InputField
type="password"
id="password"
placeholder="Password"
required={true}
/>
<SubmitButton defaultText="Register" />
</Form>
)
}

export function LogoutButton() {
return (
<Form action={'LogoutCustomerAction'}>
<SubmitButton defaultText="Logout" />
</Form>
)
}
17 changes: 17 additions & 0 deletions app/(pages)/shopify/account/account.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.page {
text-transform: uppercase;
font-family: var(--font-mono);
overflow: clip;
}

.inner {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
flex-grow: 1;

@include mobile {
padding: 0 mobile-vw(16px);
}
}
48 changes: 48 additions & 0 deletions app/(pages)/shopify/account/page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { getCustomer } from 'libs/shopify/customer/actions'
import { Suspense } from 'react'
import { LoginForm, LogoutButton, RegisterForm } from '../(components)/customer'
import { Wrapper } from '../../(components)/wrapper'
import s from './account.module.scss'

export default async function AccountPage() {
const customer = await getCustomer()

return (
<Wrapper theme="red" className={s.page}>
<section className={s.inner}>
<h1 className="p">My Account</h1>
{customer ? (
<Suspense fallback={<div>Loading...</div>}>
<CustomerInfo customer={customer} />
<LogoutButton />
</Suspense>
) : (
<div>
<h2>Login</h2>
<LoginForm />
<h2>Register</h2>
<RegisterForm />
</div>
)}
</section>
</Wrapper>
)
}

function CustomerInfo({ customer }) {
return (
<>
<h2>Welcome, {customer.firstName}!</h2>
<p>Email: {customer.email}</p>
<h3>Recent Orders</h3>
<ul>
{customer.orders.edges.map(({ node }) => (
<li key={node.id}>
Order #{node.orderNumber} - {node.totalPrice.amount}{' '}
{node.totalPrice.currencyCode}
</li>
))}
</ul>
</>
)
}
2 changes: 1 addition & 1 deletion libs/form/hook.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const useForm = ({
function onSubmit(event) {
event.preventDefault()
const formData = new FormData(event.currentTarget)
formData.append('formId', formId)
formId && formData.append('formId', formId)

startTransition(async () => {
await formAction(formData)
Expand Down
10 changes: 9 additions & 1 deletion libs/form/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

import cn from 'clsx'
import { HubspotNewsletterAction } from 'libs/hubspot-forms/action'
import {
CreateCustomerAction,
LoginCustomerAction,
LogoutCustomerAction,
} from 'libs/shopify/customer/actions'
import { createContext, useContext, useEffect, useState } from 'react'
import s from './form.module.scss'
import { useForm } from './hook'
Expand Down Expand Up @@ -32,7 +37,7 @@ export const FormProvider = ({
const { formAction, onSubmit, ...helpers } = useForm({
action: formsActions[action],
formId,
initalState: null,
initialState: null,
dependencies: [],
})

Expand Down Expand Up @@ -115,4 +120,7 @@ export const Messages = ({ className }) => {

const formsActions = {
HubspotNewsletterAction: HubspotNewsletterAction,
LoginCustomerAction: LoginCustomerAction,
LogoutCustomerAction: LogoutCustomerAction,
CreateCustomerAction: CreateCustomerAction,
}
124 changes: 124 additions & 0 deletions libs/shopify/customer/actions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
'use server'

import { shopifyFetch } from 'libs/shopify'
import { cookies } from 'next/headers'
import {
customerAccessTokenCreateMutation,
customerAccessTokenDeleteMutation,
customerCreateMutation,
} from '../mutations/customer'
import { getCustomerQuery } from '../queries/customer'

export async function LoginCustomerAction(prevState, formData) {
const email = formData.get('email')
const password = formData.get('password')

try {
const res = await shopifyFetch({
query: customerAccessTokenCreateMutation,
variables: {
input: {
email,
password,
},
},
cache: 'no-store',
})

const { customerAccessToken, customerUserErrors } =
res.body.data.customerAccessTokenCreate

if (customerUserErrors.length) {
return { error: customerUserErrors[0].message }
}

if (customerAccessToken) {
cookies().set('customerAccessToken', customerAccessToken.accessToken, {
expires: new Date(customerAccessToken.expiresAt),
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
})
}

return { success: true }
} catch (error) {
return { error: 'An unexpected error occurred. Please try again.' }
}
}

export async function LogoutCustomerAction() {
const customerAccessToken = cookies().get('customerAccessToken')?.value

if (customerAccessToken) {
try {
await shopifyFetch({
query: customerAccessTokenDeleteMutation,
variables: {
customerAccessToken,
},
cache: 'no-store',
})
} catch (error) {
console.error('Error during logout:', error)
}

cookies().delete('customerAccessToken')
}

return { success: true }
}

export async function CreateCustomerAction(prevState, formData) {
const firstName = formData.get('firstName')
const lastName = formData.get('lastName')
const email = formData.get('email')
const password = formData.get('password')

try {
const res = await shopifyFetch({
query: customerCreateMutation,
variables: {
input: {
firstName,
lastName,
email,
password,
},
},
cache: 'no-store',
})

const { customer, customerUserErrors } = res.body.data.customerCreate

if (customerUserErrors.length) {
return { error: customerUserErrors[0].message }
}

return { success: true, customer }
} catch (error) {
return { error: 'An unexpected error occurred. Please try again.' }
}
}

export async function getCustomer() {
const customerAccessToken = cookies().get('customerAccessToken')?.value

if (!customerAccessToken) {
return null
}

try {
const res = await shopifyFetch({
query: getCustomerQuery,
variables: {
customerAccessToken,
},
cache: 'no-store',
})

return res.body.data.customer
} catch (error) {
console.error('Error fetching customer data:', error)
return null
}
}
46 changes: 46 additions & 0 deletions libs/shopify/mutations/customer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
export const customerAccessTokenCreateMutation = /* GraphQL */ `
mutation customerAccessTokenCreate($input: CustomerAccessTokenCreateInput!) {
customerAccessTokenCreate(input: $input) {
customerAccessToken {
accessToken
expiresAt
}
customerUserErrors {
code
field
message
}
}
}
`

export const customerAccessTokenDeleteMutation = /* GraphQL */ `
mutation customerAccessTokenDelete($customerAccessToken: String!) {
customerAccessTokenDelete(customerAccessToken: $customerAccessToken) {
deletedAccessToken
deletedCustomerAccessTokenId
userErrors {
field
message
}
}
}
`

export const customerCreateMutation = /* GraphQL */ `
mutation customerCreate($input: CustomerCreateInput!) {
customerCreate(input: $input) {
customer {
id
email
firstName
lastName
}
customerUserErrors {
code
field
message
}
}
}
`
38 changes: 38 additions & 0 deletions libs/shopify/queries/customer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
export const getCustomerQuery = /* GraphQL */ `
query getCustomer($customerAccessToken: String!) {
customer(customerAccessToken: $customerAccessToken) {
id
firstName
lastName
email
phone
addresses(first: 5) {
edges {
node {
id
address1
address2
city
province
country
zip
}
}
}
orders(first: 5) {
edges {
node {
id
orderNumber
totalPrice {
amount
currencyCode
}
processedAt
fulfillmentStatus
}
}
}
}
}
`

1 comment on commit dfb9896

@github-actions
Copy link

Choose a reason for hiding this comment

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

"⚡️ Lighthouse report for the changes in this commit:

🟠 Performance: 70
🟢 Accessibility: 90
🟢 Best practices: 96
🟠 SEO: 63

Lighthouse ran on https://satus-efk0t4ajf-darkroom-engineering.vercel.app/"

Please sign in to comment.