Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

300 unlock 6 shopify customer #301

Merged
merged 20 commits into from
Apr 26, 2024
Merged

Conversation

sebpalluel
Copy link
Contributor

@sebpalluel sebpalluel commented Apr 26, 2024

Type

enhancement


Description

  • Added and refactored the OffKeyAuth component to handle different customer statuses using the new useShopifyCustomer hook.
  • Introduced the useShopifyCustomer hook to manage and fetch customer data, improving the component's responsiveness to state changes.
  • Updated the OffKeyProfile component to integrate with the useShopifyCustomer hook for dynamic UI updates based on customer status.
  • Enhanced the OffKeyHeaderConnected component to support dynamic text and localization, improving user experience based on customer context.

Changes walkthrough

Relevant files
Tests
OffKeyAuth.stories.tsx
Add Storybook Stories for OffKeyAuth Component                     

libs/features/unlock/shopify/src/lib/OffKeyAuth/OffKeyAuth.stories.tsx

  • Added new stories for OffKeyAuth component to demonstrate various
    states and interactions.
  • Utilized authMocks to simulate different authentication states and
    customer data.
  • +96/-120
    Enhancement
    OffKeyAuth.tsx
    Refactor OffKeyAuth Component for Enhanced State Management

    libs/features/unlock/shopify/src/lib/OffKeyAuth/OffKeyAuth.tsx

  • Refactored to use ShopifyCustomerStatus for better state management.
  • Added handling for different customer statuses to render appropriate
    UI elements.
  • +181/-76
    OffKeyProfile.tsx
    Integrate useShopifyCustomer Hook in OffKeyProfile Component

    libs/features/unlock/shopify/src/lib/OffKeyProfile/OffKeyProfile.tsx

  • Integrated useShopifyCustomer hook to manage customer data and state.
  • Implemented dynamic rendering based on the customer's status.
  • +64/-51 
    useShopifyCustomer.tsx
    Implement useShopifyCustomer Hook for Customer Data Management

    libs/features/unlock/shopify/src/lib/hooks/useShopifyCustomer.tsx

  • Created a new hook useShopifyCustomer to fetch and manage customer
    data from Shopify.
  • Hook handles various states and provides customer data and status to
    components.
  • +73/-0   
    OffKeyHeaderConnected.tsx
    Enhance OffKeyHeaderConnected for Dynamic Text and Localization

    libs/features/unlock/shopify/src/lib/OffKeyHeaderConnected/OffKeyHeaderConnected.tsx

  • Enhanced to use interpolated strings for dynamic text based on
    customer data.
  • Added props for text customization and improved localization support.
  • +41/-9   

    PR-Agent usage:
    Comment /help on the PR to get a list of all available PR-Agent tools and their descriptions

    …ustomer data
    
    - Introduced `Text` component for dynamic title rendering in headers across the app for better flexibility and internationalization support.
    - Refactored `OffKeyHeaderConnected` to dynamically display customer information, improving user experience by personalizing the header based on the customer's data.
    - Implemented dynamic imports for `OffKeyHeaderConnected` to optimize loading times and resource usage, aligning with modern web performance best practices.
    - Updated storybook examples and tests to reflect changes and ensure components behave as expected with the new dynamic content.
    - Adjusted imports and exports to accommodate the new structure and usage of components, ensuring the codebase remains organized and maintainable.
    
    ✨ (examples.tsx, context.tsx, hooks.ts, types.ts, en.json): Enhance iframe integration with customer data support
    
    - Added customer data handling in iframe context to improve user experience by personalizing content.
    - Updated localization strings to include dynamic customer names, enhancing the personalization of welcome messages.
    - Introduced mock functionality for iframe API in storybook examples to facilitate testing and development with mocked customer data.
    ✨ (shopifyCustomer.yaml): Grant 'anonymous' role select permissions on shopifyCustomer table
    ✨ (OffKeyAuth.tsx): Introduce organizerId prop to OffKeyAuth component for enhanced Shopify customer handling
    ♻️ (examples.tsx): Replace OffKeyHeader with OffKeyHeaderNotConnected for better state representation when not connected
    ✨ (OffKeyHeaderNotConnected.*): Add OffKeyHeaderNotConnected component and stories for unconnected state display
    
    ✨ (useShopifyCustomer.spec.tsx, useShopifyCustomer.tsx, types.ts, shopifyCustomer.query.gql, en.json, hooks.ts): add Shopify customer hook with tests and types for Shopify integration
    
    📝 (en.json): update localization files to support new Shopify integration features
    
    💡 (hooks.ts): add comments to clarify the use of iframe readiness in Shopify customer hook
    🔧 (.swcrc, project.json): update SWC and project config to include jest tests
    ✅ (i18n): add unit tests for string interpolation functionality
    ♻️ (i18n): refactor string interpolation to use intl-messageformat
    …components for better flexibility and customization
    
    - Adjust default button and skeleton button heights for consistency
    - Allow dynamic padding for buttons
    - Include `className` prop in `EmojiAvatar` for additional styling
    - Introduce `auto` size option for avatars to support full container adaptation
    - Remove top margin from paragraphs by default for more consistent text layout
    
    ⬆️ (package.json): Add `intl-messageformat` dependency to support internationalization
    … auth flow
    
    - Introduce story states for loading, not connected, new account, existing account with new customer, and existing several accounts with new customer scenarios.
    - Implement ShopifyCustomerStatus to manage different states of customer authentication.
    - Refactor mock setup to include shopifyCustomerMocks and walletConnectedProps for a more streamlined and realistic testing environment.
    - Remove unused imports and refactor code for clarity and better readability.
    
    ✨ (OffKeyAuth.tsx, OffKeyAuthSignIn.tsx): Enhance Shopify auth with dynamic text and state management
    
    - Introduced dynamic localization support for authentication texts.
    - Added state management for account matching errors.
    - Refactored to use `useState` for local state management.
    - Removed unused imports and refactored for cleaner, more maintainable code.
    - Enhanced UI to handle multiple wallet addresses and account recovery scenarios.
    
    ✨ Introduce dynamic text rendering based on customer status
    ♻️ Refactor imports and usage of wallet and customer hooks for clarity
    📝 Add examples and storybook stories for component documentation and testing
    
    ✨ (examples.tsx, useShopifyCustomer.spec.tsx, useShopifyCustomer.tsx, types.ts, index.ts, useWalletAuth.tsx): Introduce new examples, update status enums, and enhance wallet connection logic
    
    - Added examples for OffKeyHeaderNotConnected component to demonstrate usage and provide mock setups for storybook integration.
    - Updated ShopifyCustomerStatus enums to more accurately reflect customer states, improving clarity and consistency across the codebase.
    - Enhanced useShopifyCustomer hook to include walletInStorage in return objects, supporting more nuanced wallet management.
    - Refined wallet connection logic in useWalletAuth hook to validate the wallet address against a specified address, enhancing security and accuracy in wallet connections.
    - Streamlined Shopify webhook and API handler by removing outdated comments and improving request verification logic, ensuring more reliable and secure Shopify integration.
    …, Button.tsx): Enhance UI components for better flexibility and consistency
    
    - Add styles for `.off-btn` with `.off-profile-avatar` and `.off-btn-icon-only` for improved layout handling.
    - Refactor `OffKeyAuthSignIn` and `OffKeyProfile` components to use `.off-profile-avatar` class for consistent avatar sizing.
    - Simplify `OffKeyProfile` component by removing `AutoAnimate` and `Spinner`, using `isLoading` prop for loading state.
    - Adjust `Button` component to correctly handle `isIconOnly` prop for consistent button styling across the app.
    - Update examples to demonstrate new layout and component adjustments.
    - Remove `Auth`, `WalletConnect` components, and related stories to streamline the auth feature.
    - Consolidate auth functionality, improving maintainability and reducing complexity.
    
    ♻️ refactor(shopify): streamline Shopify feature exports and remove unused components
    
    - Removed exports for `ShopifyAuth`, `ShopifyCard`, `ShopifyCardHeader`, and related components to simplify the module's public API.
    - Deleted `Card`, `CardConnected`, `CardHeader`, and their associated story and example files to focus on core functionality and reduce maintenance overhead.
    
    🔥 Remove CardNotConnected component and related stories, examples in shopify feature
    ♻️ Update import path for authMocks in OffKeyGate examples to reflect new structure
    …yHeaderConnected.tsx, OffKeyHeaderConnected.stories.tsx): introduce `AuthMocksParams` type for cleaner code and add localization support with dynamic text for `OffKeyHeaderConnected` component. Refactor stories to use new props and improve readability.
    
    ✨ (OffKeyProfile.stories.tsx, OffKeyProfile.tsx): Enhance Shopify integration with customer matching and dynamic text
    
    - **Why?** To better integrate Shopify customer data with the application, ensuring a more personalized and seamless user experience. This update allows for dynamic text based on customer information and improves the handling of user authentication and wallet connections specific to Shopify customers.
    
    ✨ (examples.tsx, useShopifyCustomer.tsx, hooks.ts): Enhance Shopify integration with offKeyState and dynamic message signing
    
    - Refactor imports and remove unused ones to streamline the codebase.
    - Introduce new props and mocks for `OffKeyProfile` to support enhanced Shopify customer matching and authentication flows.
    - Update `useShopifyCustomer` hook to include `offKeyState` in its return value, enabling better state management and integration with Shopify.
    - Modify `signWithEthereum` function to accept a dynamic message, allowing for more flexible and secure message signing within iframe environments.
    …r data and dynamic text interpolation for OffKeyGate components
    
    - **Why**: To enhance the OffKeyGate component's functionality by incorporating Shopify customer data, allowing for a more personalized user experience. The dynamic text interpolation based on the customer's state and locale provides tailored content, improving the overall user interaction with the gate feature. This update supports a broader range of scenarios, including unlocking, used, and locked states, by dynamically adjusting the displayed messages and information according to the user's current status and language preferences.
    
    ♻️ (OffKeyGate/examples.tsx, OffKeyInfo.tsx): refactor to simplify and enhance state management
    
    - Simplified import statements and removed unused mocks to streamline the codebase.
    - Introduced `offKeyGateProps` to centralize and clarify the configuration of OffKeyGate states and texts, improving readability and maintainability.
    - Enhanced `OffKeyInfo` component by directly passing `offKeyStatusText`, removing the dependency on `useTranslations` for a more straightforward and efficient implementation.
    …tent styling across components
    
    ♻️ (OffKeyInfo.tsx): Refactor OffKeyLogo size to `size-auto` for better flexibility
    ♻️ (OffKeyInfo.tsx): Adjust skeleton loader width from `w-24` to `w-32` for improved visual consistency
    …onents
    
    ♻️ (shopify feature): refactor export statements for consistency
    📝 (Auth.tsx, ProfileNav.tsx): mark components as deprecated
    💡 (OffKeyAuth.stories.tsx): update user interaction steps in stories for clarity
    …eters
    
    ✨ (Hasura metadata): update remote_schemas with ShopifyCampaignTemplate type
    ✨ (GraphQL queries): add new queries for Shopify campaign parameters and customer data
    …nd layout components to enhance code splitting and improve loading times
    
    ♻️ Refactor Shopify components to fetch campaign parameters dynamically and handle not found cases with `notFound()` for better user experience and error handling
    🌐 Update localization implementation by removing deprecated imports and using new methods for internationalization support
    
    ✨ (page.tsx): refactor Gate component to async for fetching campaign data
    ✨ (page.tsx): add dynamic text based on campaign state
    🚀 (shopify-api): add new library for Shopify API integration
    📝 (shopify-api): add README, eslint, swc, and jest configs for shopify-api lib
    🔧 (shopify-api): configure package.json and project.json for shopify-api lib
    ✨ (shopify-api): implement getShopifyCampaignParameters for connected and not connected states
    
    ✨ Add TypeScript config for Shopify API feature and refactor Shopify exports
    
    📝 Add examples and implementation for OffKeyGateNotConnected component
    
    ♻️ refactor(shopify): remove OffKeyGateSignIn component and related examples
    
    ♻️ refactor(stories): rename story in OffKeyHeaderConnected for clarity
    
    ✨ feat(nx): add new tasks for TypeScript and SWC with caching
    
    ✨ feat(tsconfig): add path alias for shopify-api feature
    …sections
    
    ♻️ Refactor Shopify API functions to streamline data handling
    🔧 Update TypeScript config to include "next" types for Shopify API feature
    🚚 Move `OffKeyAuthSkeleton` definition to its own file for better modularity
    
    ✨ (OffKeyAuthSkelton.tsx, OffKeyGateSkeleton.tsx, OffKeyGateNotConnectedSkeleton.tsx, OffKeyHeaderNotConnectedSkeleton.tsx, OffKeyInfoSkeleton.tsx): Add skeleton components for loading states
    
    ♻️ (OffKeyGate.tsx, OffKeyGateNotConnected.tsx, OffKeyHeaderNotConnected.tsx, OffKeyInfo.tsx): Refactor to use new skeleton components for consistent loading states
    
    🐛 (ProfileNav.tsx): Fix connectToDappMutation to include 'Offline' parameter for correct offline handling
    
    ✅ (useShopifyCustomer.spec.tsx): Update tests to reflect new logic and improve coverage on error handling and address mismatch scenarios
    
    ✨ (useShopifyCustomer.tsx): handle error state in addition to isLoading for customer data
    ⬆️ (tsconfig.json): enable resolveJsonModule to import JSON files in TypeScript
    ♻️ (index.ts): refactor StringMap and FormatXMLElementFn types for clarity and efficiency
    ♻️ (hooks.ts): type annotate messageToSign parameter and fix message value in signWithEthereum
    🔧 (.swcrc): update SWC configuration by removing exclusions for spec and test files
    …T requests
    
    ✨ (index.ts): introduce CreateShopifyCustomer and GetShopifyCustomer handling logic
    ✅ (index.spec.ts): update tests to reflect new authorization logic and error handling
    ♻️ (index.ts): refactor error handling to use ForbiddenError for address mismatches
    🔧 (index.ts): add CreateShopifyCustomerOptions and GetShopifyCustomerOptions types
    
    ✨ (validators.ts): Add CreateShopifyCustomerParams and GetShopifyCustomerParams for Shopify integration
    ♻️ (apiErrorHandlers.ts): Refactor NotAuthorizedError to use 401 status code and introduce ForbiddenError with 403 status
    ✅ (index.spec.ts): Update tests to reflect new error handling logic and test ForbiddenError handling
    @sebpalluel sebpalluel linked an issue Apr 26, 2024 that may be closed by this pull request
    Copy link

    vercel bot commented Apr 26, 2024

    The latest updates on your projects. Learn more about Vercel for Git ↗︎

    Name Status Preview Comments Updated (UTC)
    back-office ✅ Ready (Inspect) Visit Preview 💬 Add feedback Apr 26, 2024 5:07pm
    marketplace ✅ Ready (Inspect) Visit Preview 💬 Add feedback Apr 26, 2024 5:07pm
    unlock ✅ Ready (Inspect) Visit Preview 💬 Add feedback Apr 26, 2024 5:07pm

    @codiumai-pr-agent-free codiumai-pr-agent-free bot added the enhancement New feature or request label Apr 26, 2024
    Copy link

    PR Description updated to latest commit (f630df8)

    Copy link

    PR Review

    ⏱️ Estimated effort to review [1-5]

    5, because the PR introduces a significant amount of changes across multiple files and components, including new hooks, component modifications, and integration with external APIs. The complexity is high due to the need to understand the interactions between different parts of the system, such as authentication, customer status handling, and UI updates based on state changes.

    🧪 Relevant tests

    Yes

    🔍 Possible issues

    Possible Bug: The use of toLowerCase() directly on potentially undefined properties could lead to runtime errors. It's safer to ensure the property exists before calling toLowerCase().

    Performance Concern: There are multiple places where the code could be optimized to avoid unnecessary re-renders or computations, especially in context providers and hooks.

    🔒 Security concerns

    No apparent security vulnerabilities were introduced in the changes. However, thorough testing and code review should be conducted to ensure that all user input is properly sanitized and that there are no potential data leaks.


    ✨ Review tool usage guide:

    Overview:
    The review tool scans the PR code changes, and generates a PR review which includes several types of feedbacks, such as possible PR issues, security threats and relevant test in the PR. More feedbacks can be added by configuring the tool.

    The tool can be triggered automatically every time a new PR is opened, or can be invoked manually by commenting on any PR.

    • When commenting, to edit configurations related to the review tool (pr_reviewer section), use the following template:
    /review --pr_reviewer.some_config1=... --pr_reviewer.some_config2=...
    
    [pr_reviewer]
    some_config1=...
    some_config2=...
    

    See the review usage page for a comprehensive guide on using this tool.

    Copy link

    PR Code Suggestions

    CategorySuggestions                                                                                                                                                       
    Enhancement
    Replace Promise.resolve() with simulated asynchronous operations in test mocks.

    The Promise.resolve() used in the connect and disconnect methods of walletAuthMocks should
    ideally be replaced with more realistic asynchronous operations that simulate actual
    network requests or interactions. This will provide a more accurate test environment and
    help catch issues related to asynchronous operations.

    libs/features/unlock/shopify/src/lib/OffKeyAuth/OffKeyAuth.stories.tsx [22-23]

    -connect: () => Promise.resolve(),
    -disconnect: () => Promise.resolve(),
    +connect: () => new Promise(resolve => setTimeout(resolve, 1000)), // Simulates network delay
    +disconnect: () => new Promise(resolve => setTimeout(resolve, 1000)), // Simulates network delay
     
    Enhance error handling in the mutation's onError callback.

    The error handling in the onError callback of connectWalletMutation only checks for a
    specific error message. It's recommended to handle different types of errors more robustly
    or log them appropriately for better debugging and user feedback.

    libs/features/unlock/shopify/src/lib/OffKeyAuth/OffKeyAuth.tsx [82-84]

     if (error.message.includes('Wallet address does not match')) {
         setAccountNotMatching(true);
    +} else {
    +    console.error('Unhandled error:', error);
     }
     
    Add default text for missing customer or offKeyState to prevent UI issues.

    To ensure that the component handles the absence of customer or offKeyState gracefully,
    consider adding a fallback or default text when these values are not available. This can
    prevent potential runtime errors or display issues in the UI.

    libs/features/unlock/shopify/src/lib/OffKeyGate/OffKeyGate.tsx [99-104]

     {offKeyState && customer ? (
       <div className={`flex flex-col justify-between space-y-2 ${className}`}>
         <div className="flex flex-col space-y-2 px-2">
    -      <Text variant="h6">{textsSubtitle[offKeyState]}</Text>
    -      <Text variant="p">{textsMainText[offKeyState]}</Text>
    +      <Text variant="h6">{textsSubtitle[offKeyState] || 'Default subtitle'}</Text>
    +      <Text variant="p">{textsMainText[offKeyState] || 'Default main text'}</Text>
           ...
     
    Best practice
    Use a function to dynamically generate wallet addresses for testing.

    The walletInStorage array includes hardcoded addresses which might not reflect dynamic
    testing scenarios. Consider using a function or a factory to generate these addresses
    dynamically based on the test requirements.

    libs/features/unlock/shopify/src/lib/OffKeyAuth/OffKeyAuth.stories.tsx [45]

    -walletInStorage: [{ address }, { address: '0x214123135' }],
    +walletInStorage: generateWalletAddresses(),
     
    Replace direct console logging with a conditional check for environment or a dedicated error handling mechanism.

    Replace the console.log with a more robust error handling mechanism. Logging to the
    console is not suitable for production environments as it can expose sensitive information
    and does not provide a way to centrally manage errors. Consider using a dedicated error
    reporting service or at least wrapping the logging in a development mode check.

    libs/features/unlock/shopify/src/lib/OffKeyProfile/OffKeyProfile.tsx [85]

    -console.log('error connecting to dapp', error);
    +if (process.env.NODE_ENV === 'development') {
    +  console.error('Error connecting to dapp:', error);
    +} else {
    +  // Send error to monitoring service
    +  monitoringService.reportError(error);
    +}
     
    Use specific error handling in catch blocks to improve error management.

    Use a more specific error type in the catch block to handle different types of errors
    appropriately. Using a generic error catch can make debugging harder and might not provide
    the necessary information or actions based on the type of error.

    libs/features/unlock/shopify/src/lib/OffKeyProfile/OffKeyProfile.tsx [150-152]

     } catch (e) {
    -  console.error('Error signing out', e);
    +  if (e instanceof NetworkError) {
    +    console.error('Network error during sign out:', e);
    +  } else {
    +    console.error('Unexpected error during sign out:', e);
    +  }
       throw e;
     }
     
    Link TODO comments to an issue tracker for better tracking and clarity.

    Avoid using inline comments for TODOs without a clear action plan or ticket reference.
    This can lead to forgotten or unclear intentions in the codebase. Instead, link TODOs to
    an issue tracker or provide more detailed comments.

    libs/features/unlock/shopify/src/lib/OffKeyProfile/OffKeyProfile.tsx [87]

    -//TODO: Handle connection error display
    +// TODO: Implement user-friendly error display for connection issues. See issue #1234 in the issue tracker for more details.
     
    Use TypeScript enums for OffKeyState to enhance type safety and readability.

    To enhance the type safety and readability of the code, consider using TypeScript enums
    for the OffKeyState values instead of accessing them directly as string indexes. This
    approach can help prevent typos and logical errors.

    libs/features/unlock/shopify/src/lib/OffKeyGate/OffKeyGate.tsx [47]

    +enum OffKeyState {
    +  Unlocked = 'Unlocked',
    +  Unlocking = 'Unlocking',
    +  Used = 'Used',
    +  Locked = 'Locked'
    +}
    +
     [OffKeyState.Unlocked]: interpolateString(
       textGate.subtitle[OffKeyState.Unlocked],
       locale,
       customer,
     ),
     
    Add optional chaining to handle potential null or undefined responses safely.

    Consider handling the case where mintLoyaltyCardWithPassword might throw an exception or
    return a null/undefined response before accessing the status property.

    libs/integrations/external-api-handlers/src/lib/shopify/index.spec.ts [222-223]

     const response = await shopifyHandler.mintLoyaltyCardWithPassword(options);
    -expect(response.status).toBe(401);
    +expect(response?.status).toBe(401);
     
    Use descriptive naming for mock data to enhance the readability and maintainability of tests.

    To improve test clarity and maintainability, use descriptive names for mock values and
    constants, particularly for addresses and other identifiers.

    libs/integrations/external-api-handlers/src/lib/shopify/index.spec.ts [561-565]

    -address: 'test-address',
    -shop: 'example.myshopify.com',
    +address: 'mockTestAddress',
    +shop: 'mockExampleShop.myshopify.com',
     timestamp: Date.now().toString(),
    -signature: 'validSignature',
    +signature: 'mockValidSignature',
     
    Maintainability
    Ensure relevant parameters are passed to the connect function.

    The mutation function connect is being called with parameters that might not always be
    necessary. Refactor the code to ensure that only relevant parameters are passed based on
    the user's action.

    libs/features/unlock/shopify/src/lib/OffKeyAuth/OffKeyAuth.tsx [128]

    -connectWalletMutation.mutateAsync({ isCreatingAccount: true })
    +connectWalletMutation.mutateAsync({ walletAddress, isCreatingAccount: true })
     
    Refactor repeated string interpolation into a utility function.

    The interpolation of strings for UI text elements is done multiple times with similar
    parameters. Consider creating a utility function to handle this, reducing redundancy and
    improving maintainability.

    libs/features/unlock/shopify/src/lib/OffKeyAuth/OffKeyAuth.tsx [91-99]

    -createNewAccount: interpolateString(textAuth.createNewAccount, locale, customer),
    -useExistingAccount: interpolateString(textAuth.useExistingAccount, locale, customer),
    +function getLocalizedText(key) {
    +  return interpolateString(textAuth[key], locale, customer);
    +}
    +createNewAccount: getLocalizedText('createNewAccount'),
    +useExistingAccount: getLocalizedText('useExistingAccount'),
     
    Refactor the sign-out function to improve code maintainability and separation of concerns.

    Refactor the signOutUserAction function to separate concerns for better maintainability
    and testing. Currently, the function handles UI routing, state management, and business
    logic, which can be split into smaller, more manageable functions.

    libs/features/unlock/shopify/src/lib/OffKeyProfile/OffKeyProfile.tsx [136-157]

    -const signOutUserAction = useCallback(
    -  async (error?: boolean) => {
    -    try {
    -      setUserActionLoading(true);
    -      disconnectFromDapp(user.address);
    -      await disconnect();
    -      let newPathname = pathname.split('/0x')[0];
    -      if (searchParams?.toString()) {
    -        const params = new URLSearchParams(searchParams.toString());
    -        newPathname += `?${params.toString()}`;
    -      }
    -      await router.replace(newPathname);
    -    } catch (e) {
    -      console.error('Error signing out', e);
    -      throw e;
    -    } finally {
    -      setUserActionLoading(false);
    -    }
    -  },
    -  [disconnect],
    -);
    +const handleSignOut = useCallback(async () => {
    +  try {
    +    setUserActionLoading(true);
    +    await performSignOut();
    +  } catch (e) {
    +    console.error('Error during sign out:', e);
    +    throw e;
    +  } finally {
    +    setUserActionLoading(false);
    +  }
    +}, [performSignOut]);
     
    +const performSignOut = useCallback(async () => {
    +  disconnectFromDapp(user.address);
    +  await disconnect();
    +  await updateRouteAfterSignOut();
    +}, [disconnect, user.address, updateRouteAfterSignOut]);
    +
    +const updateRouteAfterSignOut = useCallback(() => {
    +  let newPathname = pathname.split('/0x')[0];
    +  if (searchParams?.toString()) {
    +    const params = new URLSearchParams(searchParams.toString());
    +    newPathname += `?${params.toString()}`;
    +  }
    +  router.replace(newPathname);
    +}, [pathname, searchParams, router]);
    +
    Refactor repetitive text assignments into a helper function for better maintainability.

    Consider using a more concise and maintainable approach to handle the state-dependent text
    assignments by creating a helper function. This function can take the textGate object,
    locale, and customer as parameters and return the appropriate text based on the
    offKeyState. This will reduce redundancy and improve code readability.

    libs/features/unlock/shopify/src/lib/OffKeyGate/OffKeyGate.tsx [46-88]

    -const textsSubtitle = {
    +const getTexts = (textType) => ({
       [OffKeyState.Unlocked]: interpolateString(
    -    textGate.subtitle[OffKeyState.Unlocked],
    +    textGate[textType][OffKeyState.Unlocked],
         locale,
         customer,
       ),
       [OffKeyState.Unlocking]: interpolateString(
    -    textGate.subtitle[OffKeyState.Unlocking],
    +    textGate[textType][OffKeyState.Unlocking],
         locale,
         customer,
       ),
       ...
    -};
    +});
     
    +const textsSubtitle = getTexts('subtitle');
    +const textsMainText = getTexts('mainText');
    +
    Extract repeated setup code into a separate function to reduce code duplication.

    Refactor the repeated setup code for ShopifyWebhookAndApiHandler and mockRequest into a
    separate function to avoid duplication and improve maintainability.

    libs/integrations/external-api-handlers/src/lib/shopify/index.spec.ts [557-566]

    -beforeEach(() => {
    -  handler = new ShopifyWebhookAndApiHandler();
    -  mockRequest = createMockRequest(
    +function setupHandlerAndRequest() {
    +  const handler = new ShopifyWebhookAndApiHandler();
    +  const mockRequest = createMockRequest(
         new URLSearchParams({
           address: 'test-address',
           shop: 'example.myshopify.com',
           timestamp: Date.now().toString(),
           signature: 'validSignature',
         }),
       );
    +  return { handler, mockRequest };
    +}
    +
    +beforeEach(() => {
    +  const { handler, mockRequest } = setupHandlerAndRequest();
     });
     
    Bug
    Normalize address comparisons to prevent case sensitivity issues.

    Ensure consistent use of string case comparison for addresses. The current implementation
    uses toLowerCase() inconsistently, which could lead to logical errors or security issues
    if addresses are compared in a case-sensitive manner elsewhere in the code.

    libs/integrations/external-api-handlers/src/lib/shopify/index.ts [201-205]

    -if (shopifyCustomer && shopifyCustomer.address.toLowerCase() !== ownerAddress.toLowerCase()) {
    +const normalizedCustomerAddress = shopifyCustomer.address.toLowerCase();
    +const normalizedOwnerAddress = ownerAddress.toLowerCase();
    +if (shopifyCustomer && normalizedCustomerAddress !== normalizedOwnerAddress) {
       throw new ForbiddenError('Invalid owner address. The owner address must match the address of the customer.');
     }
     
    Security
    Sanitize the className prop to prevent potential security risks.

    Instead of directly using the className prop in the JSX, it's a good practice to sanitize
    or validate this prop to avoid potential security risks such as Cross-Site Scripting (XSS)
    if the class names are dynamically generated or user-provided.

    libs/features/unlock/shopify/src/lib/OffKeyGate/OffKeyGate.tsx [100]

    -<div className={`flex flex-col justify-between space-y-2 ${className}`}>
    +<div className={classNames('flex flex-col justify-between space-y-2', className)}>
     
    Validate address and shop parameters to prevent processing invalid requests.

    Add validation to check if the address and shop parameters are well-formed before
    proceeding with the request handling in createShopifyCustomer.

    libs/integrations/external-api-handlers/src/lib/shopify/index.spec.ts [559-565]

     mockRequest = createMockRequest(
       new URLSearchParams({
         address: 'test-address',
         shop: 'example.myshopify.com',
         timestamp: Date.now().toString(),
         signature: 'validSignature',
       }),
     );
    +if (!isValidAddress(mockRequest.address) || !isValidShop(mockRequest.shop)) {
    +  throw new BadRequestError('Invalid address or shop');
    +}
     
    Performance
    Memoize text objects to improve component performance.

    To improve the performance of the component, consider memoizing the computed text objects
    (textsSubtitle, textsMainText, textsKeyStatus) using useMemo hook. This prevents
    unnecessary recalculations when the component re-renders without changes to its
    dependencies.

    libs/features/unlock/shopify/src/lib/OffKeyGate/OffKeyGate.tsx [46-66]

    -const textsSubtitle = {
    +const textsSubtitle = useMemo(() => ({
       [OffKeyState.Unlocked]: interpolateString(
         textGate.subtitle[OffKeyState.Unlocked],
         locale,
         customer,
       ),
       ...
    -};
    +}), [textGate, locale, customer]);
     
    Robustness
    Add error handling for the InsertShopifyCustomer method to ensure robustness.

    Ensure that the InsertShopifyCustomer method handles exceptions properly, especially when
    the database operation fails.

    libs/integrations/external-api-handlers/src/lib/shopify/index.spec.ts [587-592]

    -expect(adminSdk.InsertShopifyCustomer).toHaveBeenCalledWith({
    -  object: {
    -    organizerId: 'test-organizer-id',
    -    id: 'test-customer-id',
    -    address: 'test-address',
    -  },
    -});
    +try {
    +  await adminSdk.InsertShopifyCustomer({
    +    object: {
    +      organizerId: 'test-organizer-id',
    +      id: 'test-customer-id',
    +      address: 'test-address',
    +    },
    +  });
    +  expect(true).toBe(true); // Expect the operation to succeed without throwing
    +} catch (error) {
    +  expect(true).toBe(false); // Fail the test if an error is thrown
    +}
     

    ✨ Improve tool usage guide:

    Overview:
    The improve tool scans the PR code changes, and automatically generates suggestions for improving the PR code. The tool can be triggered automatically every time a new PR is opened, or can be invoked manually by commenting on a PR.

    • When commenting, to edit configurations related to the improve tool (pr_code_suggestions section), use the following template:
    /improve --pr_code_suggestions.some_config1=... --pr_code_suggestions.some_config2=...
    
    [pr_code_suggestions]
    some_config1=...
    some_config2=...
    

    See the improve usage page for a comprehensive guide on using this tool.

    …nt interactions
    
    ♻️ (OffKeyInfo.stories.tsx): separate OffKeyInfoSkeleton import for clarity
    🔥 (test-utils/functions): remove unused test-utils library to clean up project
    ✨ (.storybook/main.ts): enable SWC for Storybook to improve build performance
    ♻️ (Button.stories.tsx): replace delayData with sleep for consistency in utils usage
    
    ♻️ (button/examples.tsx): replace `delayData` with `sleep` for consistency
    🔧 (tsconfig.base.json): remove `@test-utils/functions` path to clean up unused dependencies
    …List component
    
    - Simplify Default story by removing commented code and adding new text checks for "6 x" and "General Admission"
    - Remove Opened story variant and integrate its setup into Default story for streamlined testing
    - Add Remove story with specific parameters to disable snapshots, ensuring focused testing on dynamic interactions
    …thRetry
    
    WHY: Simplify retry logic by handling specific error messages directly in the catch block, making the code easier to understand and maintain.
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    Projects
    None yet
    Development

    Successfully merging this pull request may close these issues.

    UNLOCK-6: Shopify customer
    1 participant