Skip to content

Commit

Permalink
✨ Add dynamic loading with suspense for auth, header, and gate compon…
Browse files Browse the repository at this point in the history
…ents

♻️ Refactor loading components to use suspense for better code splitting and loading
🔥 Remove standalone loading components in favor of inline suspense fallbacks
✨ Introduce new dynamic components for connected and not connected states
🚚 Rename variables and functions for clarity and better readability

✨ (shopify feature): add OffKeyHeaderConnectedSkeleton for loading state
♻️ (shopify & external-api-handlers): refactor imports and error handling for clarity
🐛 (external-api-handlers): fix customer creation logic to prevent duplicates
🔧 (external-api-handlers): adjust logging for better debugging and error tracking
  • Loading branch information
sebpalluel committed Apr 30, 2024
1 parent d547637 commit 9aa543c
Show file tree
Hide file tree
Showing 14 changed files with 111 additions and 78 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { OffKeyAuthSkelton } from '@features/unlock/shopify';
import { getShopifyCampaignParametersForNotConnected } from '@features/unlock/shopify-api';
import { Locale } from '@gql/shared/types';
import dynamic from 'next/dynamic';
import { notFound } from 'next/navigation';
import { Suspense } from 'react';

interface AuthProps {
params: {
Expand All @@ -15,7 +17,15 @@ const OffKeyAuth = dynamic(
{ ssr: false },
);

export default async function Auth({ params: { locale, gateId } }: AuthProps) {
export default function AuthSection(props: AuthProps) {
return (
<Suspense fallback={<OffKeyAuthSkelton />}>
<Auth {...props} />
</Suspense>
);
}

async function Auth({ params: { locale, gateId } }: AuthProps) {
const campaign = await getShopifyCampaignParametersForNotConnected({
gateId,
locale,
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { OffKeyHeaderNotConnectedSkeleton } from '@features/unlock/shopify';
import { getShopifyCampaignParametersForNotConnected } from '@features/unlock/shopify-api';
import { Locale } from '@gql/shared/types';
import dynamic from 'next/dynamic';
import { notFound } from 'next/navigation';
import { Suspense } from 'react';

interface HeaderProps {
params: {
Expand All @@ -18,9 +20,15 @@ const OffKeyHeaderNotConnected = dynamic(
{ ssr: false },
);

export default async function Header({
params: { locale, gateId },
}: HeaderProps) {
export default function HeaderSection(props: HeaderProps) {
return (
<Suspense fallback={<OffKeyHeaderNotConnectedSkeleton />}>
<Header {...props} />
</Suspense>
);
}

async function Header({ params: { locale, gateId } }: HeaderProps) {
const campaign = await getShopifyCampaignParametersForNotConnected({
gateId,
locale,
Expand Down

This file was deleted.

This file was deleted.

16 changes: 14 additions & 2 deletions apps/unlock/app/[locale]/shopify/[gateId]/(notConnected)/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import { ShopifyCustomerStatus } from '@features/unlock/shopify';
import {
OffKeyGateNotConnectedSkeleton,
ShopifyCustomerStatus,
} from '@features/unlock/shopify';
import { getShopifyCampaignParametersForNotConnected } from '@features/unlock/shopify-api';
import { Locale } from '@gql/shared/types';
import dynamic from 'next/dynamic';
import { notFound } from 'next/navigation';
import { Suspense } from 'react';

const OffKeyGateNotConnected = dynamic(
() =>
Expand All @@ -19,7 +23,15 @@ interface GateNotConnectedProps {
};
}

export default async function GateSignIn({
export default function GateNotConnectedSection(props: GateNotConnectedProps) {
return (
<Suspense fallback={<OffKeyGateNotConnectedSkeleton />}>
<GateNotConnected {...props} />
</Suspense>
);
}

async function GateNotConnected({
params: { locale, gateId },
}: GateNotConnectedProps) {
const campaign = await getShopifyCampaignParametersForNotConnected({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import { OffKeyViewHeaderConnected } from '@features/unlock/shopify';
import {
OffKeyHeaderConnectedSkeleton,
OffKeyViewHeaderConnected,
} from '@features/unlock/shopify';
import { getShopifyCampaignParametersForConnected } from '@features/unlock/shopify-api';
import { Locale } from '@gql/shared/types';
import dynamic from 'next/dynamic';
import { notFound } from 'next/navigation';
import { Suspense } from 'react';

interface HeaderProps {
params: {
Expand All @@ -22,9 +26,15 @@ const OffKeyHeaderConnected = dynamic(
{ ssr: false },
);

export default async function Header({
params: { locale, gateId, address },
}: HeaderProps) {
export default function HeaderSection(props: HeaderProps) {
return (
<Suspense fallback={<OffKeyHeaderConnectedSkeleton />}>
<Header {...props} />
</Suspense>
);
}

async function Header({ params: { locale, gateId, address } }: HeaderProps) {
const campaign = await getShopifyCampaignParametersForConnected({
gateId,
locale,
Expand Down

This file was deleted.

14 changes: 11 additions & 3 deletions apps/unlock/app/[locale]/shopify/[gateId]/[address]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { OffKeyGateSkeleton } from '@features/unlock/shopify';
import { getShopifyCampaignParametersForConnected } from '@features/unlock/shopify-api';
import { Locale } from '@gql/shared/types';
import { OffKeyState } from '@next/iframe';
import dynamic from 'next/dynamic';
import { notFound } from 'next/navigation';
import { Suspense } from 'react';

interface GateProps {
params: {
Expand All @@ -17,9 +19,15 @@ const OffKeyGate = dynamic(
{ ssr: false },
);

export default async function Gate({
params: { locale, gateId, address },
}: GateProps) {
export default function GateSection(props: GateProps) {
return (
<Suspense fallback={<OffKeyGateSkeleton />}>
<Gate {...props} />
</Suspense>
);
}

async function Gate({ params: { locale, gateId, address } }: GateProps) {
const campaign = await getShopifyCampaignParametersForConnected({
gateId,
locale,
Expand Down
3 changes: 3 additions & 0 deletions libs/features/unlock/shopify/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { OffKeyViewHeaderConnected } from './lib/types';

export { default as OffKeyAuth } from './lib/OffKeyAuth/OffKeyAuth';
export { OffKeyAuthSkelton } from './lib/OffKeyAuth/OffKeyAuthSkelton';
export { default as OffKeyGate } from './lib/OffKeyGate/OffKeyGate';
Expand All @@ -6,6 +8,7 @@ export { default as OffKeyGateNotConnected } from './lib/OffKeyGateNotConnected/
export { OffKeyGateNotConnectedSkeleton } from './lib/OffKeyGateNotConnected/OffKeyGateNotConnectedSkeleton';
export { OffKeyHeader } from './lib/OffKeyHeader/OffKeyHeader';
export { default as OffKeyHeaderConnected } from './lib/OffKeyHeaderConnected/OffKeyHeaderConnected';
export { OffKeyHeaderConnectedSkeleton } from './lib/OffKeyHeaderConnected/OffKeyHeaderConnectedSkeleton';
export { default as OffKeyHeaderNotConnected } from './lib/OffKeyHeaderNotConnected/OffKeyHeaderNotConnected';
export { OffKeyHeaderNotConnectedSkeleton } from './lib/OffKeyHeaderNotConnected/OffKeyHeaderNotConnectedSkeleton';
export { OffKeyLayout } from './lib/OffKeyLayout/OffKeyLayout';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
'use client';

import { interpolateString, Locale } from '@next/i18n';
import { Text, TextSkeleton } from '@ui/components';
import { OffKeyHeader, OffKeyHeaderProps } from '../OffKeyHeader/OffKeyHeader';
import { Text } from '@ui/components';
import { useShopifyCustomer } from '../hooks/useShopifyCustomer';
import { OffKeyHeader, OffKeyHeaderProps } from '../OffKeyHeader/OffKeyHeader';
import { OffKeyViewHeaderConnected } from '../types';
import { OffKeyHeaderConnectedSkeleton } from './OffKeyHeaderConnectedSkeleton';

export interface OffKeyHeaderConnectedProps
extends Required<Pick<OffKeyHeaderProps, 'profile'>> {
Expand All @@ -27,10 +28,7 @@ export default function OffKeyHeaderConnected({
const { customer } = useShopifyCustomer({
organizerId,
});
if (!customer)
return (
<OffKeyHeader profile={profile} title={<TextSkeleton variant="h6" />} />
);
if (!customer) return <OffKeyHeaderConnectedSkeleton />;
const texts = {
[OffKeyViewHeaderConnected.Default]: interpolateString(
textHeaderConnected.default,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { TextSkeleton } from '@ui/components';
import { OffKeyHeader } from '../OffKeyHeader/OffKeyHeader';
import { OffKeyProfileSkeleton } from '../OffKeyProfile/OffKeyProfile';

export function OffKeyHeaderConnectedSkeleton() {
return (
<OffKeyHeader
profile={<OffKeyProfileSkeleton />}
title={<TextSkeleton variant="h6" />}
/>
);
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { handleAccount } from '@features/account/api';
import { adminSdk } from '@gql/admin/api';
import {
BadRequestError,
Expand All @@ -8,7 +9,6 @@ import { getCurrentChain } from '@next/chains';
import { LoyaltyCardNftWrapper } from '@nft/loyalty-card';
import { NextRequest } from 'next/server';
import { MintLoyaltyCardOptions, ShopifyWebhookAndApiHandler } from './index';
import { handleAccount } from '@features/account/api';

jest.mock('@features/account/api');
jest.mock('@integrations/api-keys');
Expand Down Expand Up @@ -466,7 +466,6 @@ describe('ShopifyWebhookAndApiHandler', () => {
chainId: getCurrentChain().chainIdHex,
organizerId: 'test-organizer-id',
});
expect(adminSdk.InsertShopifyCustomer).not.toHaveBeenCalled();
});

it('should create a new Shopify customer if one does not exist', async () => {
Expand All @@ -482,14 +481,6 @@ describe('ShopifyWebhookAndApiHandler', () => {
contractAddress: 'test-contract',
loyaltyCardSdk: mockLoyaltyCardSdk,
});

expect(adminSdk.InsertShopifyCustomer).toHaveBeenCalledWith({
object: {
organizerId: 'test-organizer-id',
customerId: 'test-customer-id',
address: 'test-address',
},
});
});

it('should throw ForbiddenError if the owner address does not match the customer address', async () => {
Expand Down Expand Up @@ -579,6 +570,7 @@ describe('ShopifyWebhookAndApiHandler', () => {
});

it('should create a new Shopify customer', async () => {
(adminSdk.InsertShopifyCustomer as jest.Mock).mockResolvedValue({});
const response = await handler.createShopifyCustomer({
req: mockRequest,
id: 'test-customer-id',
Expand All @@ -590,7 +582,7 @@ describe('ShopifyWebhookAndApiHandler', () => {
expect(adminSdk.InsertShopifyCustomer).toHaveBeenCalledWith({
object: {
organizerId: 'test-organizer-id',
id: 'test-customer-id',
customerId: 'test-customer-id',
address: 'test-address',
},
});
Expand All @@ -600,13 +592,15 @@ describe('ShopifyWebhookAndApiHandler', () => {
(adminSdk.GetShopifyCustomer as jest.Mock).mockResolvedValue({
shopifyCustomer: [{ address: 'test-address' }],
});
(adminSdk.InsertShopifyCustomer as jest.Mock).mockReset();

const response = await handler.createShopifyCustomer({
req: mockRequest,
id: 'test-customer-id',
});

expect(response.status).toBe(400);
expect(adminSdk.InsertShopifyCustomer).not.toHaveBeenCalled();
expect(JSON.parse(response.body)).toEqual(
expect.objectContaining({
error: expect.stringContaining('Customer already exists'),
Expand Down
Loading

0 comments on commit 9aa543c

Please sign in to comment.