Skip to content

Latest commit

ย 

History

History
581 lines (497 loc) ยท 11.3 KB

File metadata and controls

581 lines (497 loc) ยท 11.3 KB

Theme Fetching Documentation

This document explains how themes are fetched and managed in the Fynd Commerce App, including GraphQL queries, data flow, and integration with the FPI system.

๐ŸŽฏ Overview

The theme fetching system:

  • Uses GraphQL queries to fetch theme data from the server
  • Integrates with FPI (Fynd Platform Integration) for data management
  • Provides real-time theme updates
  • Handles theme caching and state management
  • Supports different types of theme queries

๐Ÿ—๏ธ Architecture

Theme Data Flow

Theme Data Flow

๐Ÿ”ง GraphQL Queries

1. Theme Configuration Query

// src/graphql/queries/theme.query.ts
export const THEME_CONFIG_QUERY = `query theme($themeId: String!) {
  theme(themeId: $themeId) {
    preview_theme {
      id
      applied
      created_at
      styles
      tags
      updated_at
      version
      is_private
      application_id
      marketplace_theme_id
      name
      template_theme_id
      theme_type
      company_id
      src
      config {
        list {
          global_config
          name
        }
        global_schema {
          props {
            category
            id
            info
            label
            type
          }
        }
        current
      }
    }
    theme_pages {
      id
      path
      props
      text
      theme
      type
      value
      created_at
      updated_at
    }
  }
}`;

2. Applied Theme Query

export const APPLIED_THEME_QUERY = `query appliedTheme {
  appliedTheme {
    id
    applied
    available_sections {
      blocks
      label
      name
      props
    }
    config {
      current
    }
    created_at
    font {
      family
    }
    styles
    tags
    updated_at
    version
    is_private
    application_id
    marketplace_theme_id
    meta {
      description
      industry
      slug
      name
    }
    name
    template_theme_id
    theme_type
    company_id
    src
  }
}`;

3. Theme Data Query

export const THEME_DATA = `query Theme($themeId: String!, $pageValue: String!){
  theme(themeId: $themeId) {
    theme_page_detail(pageValue: $pageValue) {
      id
      path
      props
      sections {
        label
        name
        id
        custom_css
        source {
          type
          id
          bundle_name
        }
        assets {
          js
          css
        }
        blocks
        predicate {
          zones
          route {
            exact_url
            query
            selected
          }
          screen {
            desktop
            mobile
            tablet
          }
          platform{
            ios
            android
            web
          }
          user {
            anonymous
            authenticated
          }
        }
        props
        preset {
          blocks {
            type
            name
            props 
          }
        }
      }
      sections_meta {
        attributes
      }
      seo {
        description
        title
      }
      text
      theme
      type
      value
    }
  }
}`;

๐Ÿ”„ Theme Fetching Process

1. Initial Theme Fetch

// In ThemeProvider
const {fpi} = useFpi();
const themeConfig: ThemeDetail = useSelector(fpi?.getters?.THEME);

// Theme is automatically fetched when FPI client is initialized
useEffect(() => {
  if (fpi && !themeConfig) {
    // Fetch applied theme
    fpi.executeGQL(APPLIED_THEME_QUERY, {});
  }
}, [fpi, themeConfig]);

2. Theme Data Processing

// Theme data is processed when received
const updateTheme = useCallback(() => {
  if (themeConfig) {
    try {
      const themeObject = getThemeObject(themeConfig);
      setTheme(prev => ({
        ...prev,
        ...themeObject,
      }));
      setLoading(false);
    } catch (error) {
      Logger.error('Failed to update theme state', {
        error: error instanceof Error ? error.message : String(error),
        themeConfig: themeConfig,
      });
    }
  }
}, [getThemeObject, themeConfig]);

3. Page-Specific Theme Fetching

// In navigation tracker
const onRouteChange = useCallback(
  async (route: NavigationRoute) => {
    if (route.name === 'SectionPage' && route.params?.pageValue) {
      const pageValueResult = getPageValueFromPath(route.params.pageValue);

      try {
        await fpi.executeGQL(THEME_DATA, {
          themeId: theme?.id,
          pageValue: pageValueResult.pageValue,
        });
      } catch (error) {
        Logger.error('Failed to fetch theme data', {
          pageValue: pageValueResult.pageValue,
          themeId: theme?.id,
          error: error instanceof Error ? error.message : 'Unknown error',
        });
      }
    }
  },
  [fpi, getPageValueFromPath, theme?.id],
);

๐ŸŽจ Theme Data Structure

Server Response Structure

// Applied theme response
{
  appliedTheme: {
    id: string;
    applied: boolean;
    config: {
      current: string;
    };
    font: {
      family: string;
    };
    // ... other properties
  }
}

// Theme configuration response
{
  theme: {
    preview_theme: {
      config: {
        list: [
          {
            name: string;
            global_config: {
              custom: { props: object };
              static: { props: object };
            };
          }
        ];
        current: string;
      };
    };
    theme_pages: [
      {
        id: string;
        path: string;
        props: object;
        // ... other properties
      }
    ];
  }
}

Redux Store Structure

// Theme data in Redux store
{
  THEME: {
    id: string;
    applied: boolean;
    config: {
      list: Array<{
        name: string;
        global_config: {
          custom: {props: object};
          static: {props: object};
        };
      }>;
      current: string;
    }
    font: {
      family: string;
    }
    // ... other properties
  }
}

๐Ÿ”ง FPI Integration

1. FPI Client Setup

// FPI client provides theme data through Redux store
const {fpi} = useFpi();
const themeConfig: ThemeDetail = useSelector(fpi?.getters?.THEME);

2. Theme Queries Execution

// Execute theme queries using FPI client
const fetchTheme = async () => {
  try {
    const result = await fpi.executeGQL(APPLIED_THEME_QUERY, {});
    Logger.info('Theme fetched successfully', result);
  } catch (error) {
    Logger.error('Failed to fetch theme', error);
  }
};

const fetchThemeData = async (themeId: string, pageValue: string) => {
  try {
    const result = await fpi.executeGQL(THEME_DATA, {
      themeId,
      pageValue,
    });
    Logger.info('Theme data fetched successfully', result);
  } catch (error) {
    Logger.error('Failed to fetch theme data', error);
  }
};

3. Theme State Management

// Theme state is managed through Redux
const themeConfig = useSelector(fpi?.getters?.THEME);

// Theme updates are automatically handled by Redux
useEffect(() => {
  if (themeConfig) {
    updateTheme();
  }
}, [themeConfig, updateTheme]);

๐Ÿš€ Performance Optimization

1. Caching Strategy

// Theme data is cached in Redux store
const themeConfig = useSelector(fpi?.getters?.THEME);

// Only fetch if not already available
useEffect(() => {
  if (fpi && !themeConfig) {
    fpi.executeGQL(APPLIED_THEME_QUERY, {});
  }
}, [fpi, themeConfig]);

2. Selective Updates

// Only update theme when configuration changes
const updateTheme = useCallback(() => {
  if (themeConfig && themeConfig !== previousThemeConfig) {
    const themeObject = getThemeObject(themeConfig);
    setTheme(themeObject);
    setPreviousThemeConfig(themeConfig);
  }
}, [themeConfig, previousThemeConfig, getThemeObject]);

3. Memoized Queries

// Memoize query execution to prevent unnecessary requests
const memoizedThemeQuery = useMemo(() => {
  return fpi.executeGQL.bind(fpi, APPLIED_THEME_QUERY, {});
}, [fpi]);

๐Ÿ” Error Handling

1. Query Errors

const fetchTheme = async () => {
  try {
    const result = await fpi.executeGQL(APPLIED_THEME_QUERY, {});
    return result;
  } catch (error) {
    Logger.error('Theme query failed', {
      error: error instanceof Error ? error.message : String(error),
      query: APPLIED_THEME_QUERY,
    });

    // Fallback to default theme
    return null;
  }
};

2. Data Validation

const validateThemeData = (data: any): boolean => {
  if (!data?.appliedTheme) {
    Logger.warn('Invalid theme data structure', data);
    return false;
  }

  if (!data.appliedTheme.config?.current) {
    Logger.warn('Missing theme configuration', data);
    return false;
  }

  return true;
};

3. Network Errors

const fetchThemeWithRetry = async (retries = 3) => {
  for (let i = 0; i < retries; i++) {
    try {
      const result = await fpi.executeGQL(APPLIED_THEME_QUERY, {});
      return result;
    } catch (error) {
      Logger.warn(`Theme fetch attempt ${i + 1} failed`, error);

      if (i === retries - 1) {
        throw error;
      }

      // Wait before retry
      await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
    }
  }
};

๐Ÿ› Troubleshooting

Common Issues

1. Theme Not Loading

// Check FPI client
console.log('FPI client available:', !!fpi);

// Check theme data
console.log('Theme config:', themeConfig);

// Check Redux store
console.log('Redux state:', fpi?.getters?.THEME);

2. Query Errors

// Test theme query
const testThemeQuery = async () => {
  try {
    const result = await fpi.executeGQL(APPLIED_THEME_QUERY, {});
    console.log('Theme query result:', result);
  } catch (error) {
    console.error('Theme query error:', error);
  }
};

3. Data Structure Issues

// Validate theme data structure
const debugThemeData = () => {
  console.log('Theme config structure:', {
    hasConfig: !!themeConfig?.config,
    configList: themeConfig?.config?.list,
    currentConfig: themeConfig?.config?.current,
    hasFont: !!themeConfig?.font,
  });
};

Debug Tools

// Enable theme fetching debugging
const debugThemeFetching = () => {
  console.log('๐Ÿ” Theme Fetching Debug:', {
    fpiAvailable: !!fpi,
    themeConfig: themeConfig,
    loading,
    hasTheme: !!theme,
  });
};

// Use in development
if (__DEV__) {
  debugThemeFetching();
}

๐Ÿš€ Best Practices

1. Query Optimization

  • Use specific queries for different use cases
  • Implement proper error handling
  • Add retry logic for network failures

2. State Management

  • Use Redux for global theme state
  • Implement proper loading states
  • Handle theme updates efficiently

3. Performance

  • Cache theme data appropriately
  • Minimize unnecessary queries
  • Use memoization for expensive operations

4. Error Handling

  • Provide fallback themes
  • Log errors for debugging
  • Implement graceful degradation

๐Ÿ”ฎ Future Enhancements

  1. Advanced Caching: More sophisticated caching strategies
  2. Real-time Updates: WebSocket-based theme updates
  3. Offline Support: Offline theme caching and sync
  4. Theme Analytics: Theme usage and performance analytics

This documentation covers theme fetching and management. For more specific implementation details, refer to the other theme documentation sections.