From 5fc342434d618870ed2d1d3730beb5e4207d65d2 Mon Sep 17 00:00:00 2001 From: Sam Mejl Date: Sun, 19 Jul 2026 13:03:45 +0100 Subject: [PATCH] chore(example): remove legacy Offerings flow from sample app Offerings are being sunset in favor of Remote Configs. Drop the Offerings catalog from the example app so it no longer demonstrates the legacy flow. Products are now surfaced only via Qonversion.getSharedInstance().products(). - Delete OfferingsScreen (screen + styles) and its route/navigation - Remove offerings state, action and reducer branch from AppStore - Remove the Offerings menu item from MainScreen - Drop the Offering ID field from ProductDetailScreen - Remove the OfferingsScreen export from the example index See: https://documentation.qonversion.io/docs/migrate-offerings-to-remote-configs Co-Authored-By: Claude Fable 5 --- example/src/App.tsx | 3 - example/src/index.ts | 1 - example/src/screens/MainScreen/index.tsx | 1 - example/src/screens/OfferingsScreen/index.tsx | 82 ------------- example/src/screens/OfferingsScreen/styles.ts | 113 ------------------ .../src/screens/ProductDetailScreen/index.tsx | 1 - example/src/store/AppStore.ts | 6 - 7 files changed, 207 deletions(-) delete mode 100644 example/src/screens/OfferingsScreen/index.tsx delete mode 100644 example/src/screens/OfferingsScreen/styles.ts diff --git a/example/src/App.tsx b/example/src/App.tsx index ee2ade15..58ae41d6 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -24,7 +24,6 @@ import ProductsScreen from './screens/ProductsScreen'; import ProductDetailScreen from './screens/ProductDetailScreen'; import EntitlementsScreen from './screens/EntitlementsScreen'; import EntitlementDetailScreen from './screens/EntitlementDetailScreen'; -import OfferingsScreen from './screens/OfferingsScreen'; import RemoteConfigsScreen from './screens/RemoteConfigsScreen'; import UserScreen from './screens/UserScreen'; import NoCodesScreen from './screens/NoCodesScreen'; @@ -113,8 +112,6 @@ const App: React.FC = () => { ) : ( ); - case 'offerings': - return ; case 'remoteConfigs': return ; case 'user': diff --git a/example/src/index.ts b/example/src/index.ts index c8aa9dec..e6464d8c 100644 --- a/example/src/index.ts +++ b/example/src/index.ts @@ -14,7 +14,6 @@ export { default as SkeletonLoader } from './components/SkeletonLoader'; export { default as MainScreen } from './screens/MainScreen'; export { default as ProductsScreen } from './screens/ProductsScreen'; export { default as EntitlementsScreen } from './screens/EntitlementsScreen'; -export { default as OfferingsScreen } from './screens/OfferingsScreen'; export { default as RemoteConfigsScreen } from './screens/RemoteConfigsScreen'; export { default as UserScreen } from './screens/UserScreen'; export { default as NoCodesScreen } from './screens/NoCodesScreen'; diff --git a/example/src/screens/MainScreen/index.tsx b/example/src/screens/MainScreen/index.tsx index 83f2dd13..6ab0f21d 100644 --- a/example/src/screens/MainScreen/index.tsx +++ b/example/src/screens/MainScreen/index.tsx @@ -21,7 +21,6 @@ const MainScreen: React.FC = () => { const menuItems = [ { id: 'products', title: 'Products' }, { id: 'entitlements', title: 'Entitlements' }, - { id: 'offerings', title: 'Offerings' }, { id: 'remoteConfigs', title: 'Remote Configs' }, { id: 'user', title: 'User' }, { id: 'noCodes', title: 'No-Codes' }, diff --git a/example/src/screens/OfferingsScreen/index.tsx b/example/src/screens/OfferingsScreen/index.tsx deleted file mode 100644 index d4eea491..00000000 --- a/example/src/screens/OfferingsScreen/index.tsx +++ /dev/null @@ -1,82 +0,0 @@ -import React from 'react'; -import { Text, View, TouchableOpacity, Alert, ScrollView } from 'react-native'; -import Qonversion from '@qonversion/react-native-sdk'; -import { AppContext } from '../../store/AppStore'; -import SkeletonLoader from '../../components/SkeletonLoader'; -import ProductCard from '../../components/ProductCard'; -import styles from './styles'; - -const OfferingsScreen: React.FC = () => { - const context = React.useContext(AppContext); - if (!context) return null; - const { state, dispatch } = context; - - const loadOfferings = async () => { - try { - console.log('🔄 [Qonversion] Starting offerings() call...'); - dispatch({ type: 'SET_LOADING', payload: true }); - const offerings = await Qonversion.getSharedInstance().offerings(); - console.log('✅ [Qonversion] offerings() call successful:', offerings); - if (offerings) { - dispatch({ type: 'SET_OFFERINGS', payload: offerings }); - } - } catch (error: any) { - console.error('❌ [Qonversion] offerings() call failed:', error); - Alert.alert('Error', error.message); - } finally { - dispatch({ type: 'SET_LOADING', payload: false }); - } - }; - - if (state.loading) { - return ; - } - - return ( - - - Load Offerings - - - {state.offerings ? ( - - - Main Offering ID: {state.offerings.main?.id} - - - {state.offerings.availableOffering.map((offering) => ( - - {offering.id} - Tag: {offering.tag} - - {offering.products.length > 0 ? ( - - Products: - {offering.products.map((product) => ( - - ))} - - ) : ( - - No products in this offering - - )} - - ))} - - ) : ( - - No Offerings Loaded - - Tap the button above to load available offerings - - - )} - - ); -}; - -export default OfferingsScreen; diff --git a/example/src/screens/OfferingsScreen/styles.ts b/example/src/screens/OfferingsScreen/styles.ts deleted file mode 100644 index f5140077..00000000 --- a/example/src/screens/OfferingsScreen/styles.ts +++ /dev/null @@ -1,113 +0,0 @@ -import { StyleSheet } from 'react-native'; - -export default StyleSheet.create({ - container: { - flex: 1, - padding: 16, - paddingBottom: 32, - }, - contentContainer: { - paddingBottom: 32, - }, - button: { - backgroundColor: '#007AFF', - padding: 16, - borderRadius: 8, - marginBottom: 12, - alignItems: 'center', - }, - buttonText: { - color: '#ffffff', - fontSize: 16, - fontWeight: '600', - }, - listContainer: { - marginTop: 20, - }, - sectionTitle: { - fontSize: 18, - fontWeight: 'bold', - marginBottom: 12, - color: '#000000', - }, - listItem: { - backgroundColor: '#ffffff', - padding: 16, - borderRadius: 8, - marginBottom: 12, - shadowColor: '#000000', - shadowOffset: { width: 0, height: 2 }, - shadowOpacity: 0.1, - shadowRadius: 4, - elevation: 3, - }, - listItemTitle: { - fontSize: 16, - fontWeight: 'bold', - marginBottom: 4, - color: '#000000', - }, - listItemSubtitle: { - fontSize: 14, - color: '#666666', - marginBottom: 4, - }, - emptyState: { - flex: 1, - justifyContent: 'center', - alignItems: 'center', - paddingVertical: 40, - }, - emptyStateTitle: { - fontSize: 18, - fontWeight: 'bold', - color: '#666666', - marginBottom: 8, - textAlign: 'center', - }, - emptyStateSubtitle: { - fontSize: 14, - color: '#999999', - textAlign: 'center', - lineHeight: 20, - }, - offeringContainer: { - backgroundColor: '#ffffff', - padding: 16, - borderRadius: 8, - marginBottom: 16, - shadowColor: '#000000', - shadowOffset: { width: 0, height: 2 }, - shadowOpacity: 0.1, - shadowRadius: 4, - elevation: 3, - borderWidth: 1, - borderColor: '#e0e0e0', - }, - offeringTitle: { - fontSize: 18, - fontWeight: 'bold', - marginBottom: 4, - color: '#000000', - }, - offeringSubtitle: { - fontSize: 14, - color: '#666666', - marginBottom: 12, - }, - productsContainer: { - marginTop: 8, - }, - productsTitle: { - fontSize: 16, - fontWeight: '600', - marginBottom: 8, - color: '#333333', - }, - noProductsText: { - fontSize: 14, - color: '#999999', - fontStyle: 'italic', - marginTop: 8, - }, -}); diff --git a/example/src/screens/ProductDetailScreen/index.tsx b/example/src/screens/ProductDetailScreen/index.tsx index 7a0e7e30..2804f1f6 100644 --- a/example/src/screens/ProductDetailScreen/index.tsx +++ b/example/src/screens/ProductDetailScreen/index.tsx @@ -101,7 +101,6 @@ const ProductDetailScreen: React.FC = ({ {renderField('Store ID', product.storeId)} {renderField('Base Plan ID', product.basePlanId)} {renderField('Type', product.type)} - {renderField('Offering ID', product.offeringId)} diff --git a/example/src/store/AppStore.ts b/example/src/store/AppStore.ts index 9f2d5c6f..62ddbd45 100644 --- a/example/src/store/AppStore.ts +++ b/example/src/store/AppStore.ts @@ -1,6 +1,5 @@ import React from 'react'; import { - Offerings, Product, RemoteConfigList, User, @@ -10,7 +9,6 @@ import Entitlement from '../../../src/dto/Entitlement'; // Global Store (Redux-like pattern) export interface AppState { products: Map | null; - offerings: Offerings | null; entitlements: Map | null; remoteConfigs: RemoteConfigList | null; userInfo: User | null; @@ -29,7 +27,6 @@ export interface AppState { export type AppAction = | { type: 'SET_PRODUCTS'; payload: Map } - | { type: 'SET_OFFERINGS'; payload: Offerings } | { type: 'SET_ENTITLEMENTS'; payload: Map } | { type: 'SET_REMOTE_CONFIGS'; payload: RemoteConfigList } | { type: 'SET_USER_INFO'; payload: User } @@ -48,7 +45,6 @@ export type AppAction = export const initialState: AppState = { products: null, - offerings: null, entitlements: null, remoteConfigs: null, userInfo: null, @@ -65,8 +61,6 @@ export function appReducer(state: AppState, action: AppAction): AppState { switch (action.type) { case 'SET_PRODUCTS': return { ...state, products: action.payload }; - case 'SET_OFFERINGS': - return { ...state, offerings: action.payload }; case 'SET_ENTITLEMENTS': return { ...state, entitlements: action.payload }; case 'SET_REMOTE_CONFIGS':