Skip to content

Commit

Permalink
Merge pull request #2519 from Shopify/my/posExtensibilityDocMigration
Browse files Browse the repository at this point in the history
POS Extensibility Tutorial Conversion to MDX
  • Loading branch information
merkoyep authored Dec 9, 2024
2 parents 66ccd32 + dd5885b commit ba12160
Show file tree
Hide file tree
Showing 21 changed files with 111 additions and 608 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
} from '@shopify/ui-extensions/point-of-sale';

export default extension('pos.home.modal.render', (root, api) => {
// [START modal.define-onpress]
const onButtonPress = (
type: CartDiscountType,
title: string,
Expand All @@ -18,13 +19,13 @@ export default extension('pos.home.modal.render', (root, api) => {
// You can show a toast to notify the user of something
api.toast.show('Discount applied');
};

// [END modal.define-onpress]
let mainScreen = root.createComponent(Screen, {
name: 'Discounts',
title: 'Available Discounts',
});
let scrollView = root.createComponent(ScrollView);

// [START modal.create-buttons]
const percentageDiscountButton = root.createComponent(Button, {
title: '25%',
onPress: () => {
Expand All @@ -41,6 +42,8 @@ export default extension('pos.home.modal.render', (root, api) => {

scrollView.append(percentageDiscountButton);
scrollView.append(fixedAmountDiscountButton);
// [END modal.create-buttons]

mainScreen.append(scrollView);
root.append(mainScreen);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React from 'react';

import {CartDiscountType} from '@shopify/ui-extensions/point-of-sale';
import {
ScrollView,
Button,
Navigator,
Screen,
useApi,
reactExtension,
} from '@shopify/ui-extensions-react/point-of-sale';

const SmartGridModal = () => {
const api = useApi<'pos.home.modal.render'>();
// [START modal.define-onpress]
const onButtonPress = (
type: CartDiscountType,
title: string,
amount: string,
) => {
api.cart.applyCartDiscount(type, title, amount);
api.toast.show('Discount applied');
};
// [END modal.define-onpress]
return (
<Navigator>
<Screen name="Discounts" title="Available Discounts">
<ScrollView>
<Button
title="25%"
onPress={() => onButtonPress('Percentage', '25% off', '25')}
/>
<Button
title="$10"
onPress={() => onButtonPress('FixedAmount', '$10 off', '10')}
/>
</ScrollView>
</Screen>
</Navigator>
);
};

export default reactExtension('pos.home.modal.render', () => {
return <SmartGridModal />;
});
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,22 @@ export default extension('pos.home.tile.render', (root, api) => {
const shouldEnable = (subtotal: string): boolean => {
return Number(subtotal) > 100;
};

// [START tile.enable]
// You can use the initial cart value to set up state
const tile = root.createComponent(Tile, {
title: 'Discount Example App',
subtitle: 'Javascript',
enabled: shouldEnable(api.cart.subscribable.initial.subtotal),
onPress: api.action.presentModal,
});
// [END tile.enable]

// [START tile.subscribe]
// You can subscribe to changes in the cart to mutate state
api.cart.subscribable.subscribe((cart) => {
tile.updateProps({enabled: shouldEnable(cart.subtotal)});
});

// [END tile.subscribe]
root.append(tile);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React, {useState} from 'react';

import {
Tile,
useApi,
reactExtension,
} from '@shopify/ui-extensions-react/point-of-sale';

const SmartGridTile = () => {
const api = useApi<'pos.home.tile.render'>();

const shouldEnable = (subtotal: string): boolean => {
return Number(subtotal) > 100;
};

// [START tile.enable]
const [enabled, setEnabled] = useState(
shouldEnable(api.cart.subscribable.initial.subtotal),
);
// [END tile.enable]

// [START tile.subscribe]
api.cart.subscribable.subscribe((cart) => {
setEnabled(shouldEnable(cart.subtotal));
});
// [END tile.subscribe]

return (
<Tile
title="Discount Example App"
subtitle="React"
onPress={api.action.presentModal}
enabled={enabled}
/>
);
};

export default reactExtension('pos.home.tile.render', () => {
return <SmartGridTile />;
});
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ interface DocumentOption {
}

const Modal = () => {
// Step 1: Create state for managing document selection and loading
// [START modal.api]
const api = useApi();
const [isLoading, setIsLoading] = useState(false);
const [src, setSrc] = useState<string | null>(null);
Expand Down Expand Up @@ -57,8 +57,9 @@ const Modal = () => {
selected: false,
},
]);
// [END modal.api]

// Step 2: Set up document selection with List component
// [START modal.document-list]
const listData: ListRow[] = documents.map((doc) => ({
id: doc.id,
onPress: () => handleSelection(doc.id),
Expand All @@ -73,8 +74,9 @@ const Modal = () => {
},
},
}));
// [END modal.document-list]

// Step 3: Handle document selection and URL updates
// [START modal.handle-selection]
const handleSelection = (selectedId: string) => {
setDocuments((prevDocs) =>
prevDocs.map((doc) => ({
Expand All @@ -96,8 +98,9 @@ const Modal = () => {
setSrc(null);
}
}, [documents]);
// [END modal.handle-selection]

// Step 4: Implement print functionality with error handling
// [START modal.print]
const handlePrint = async () => {
if (!src) return;
setIsLoading(true);
Expand All @@ -109,6 +112,7 @@ const Modal = () => {
setIsLoading(false);
}
};
// [END modal.print]

// Return Navigator component with document selection and preview screens
return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import {authenticate} from '../shopify.server';

export async function loader({request}) {
// Step 1: Set up the route and handle authentication
// [START route.authenticate]
const {cors} = await authenticate.admin(request);
// [END route.authenticate]

// Step 2: Process URL parameters for document configuration
// [START route.process-url]
const url = new URL(request.url);
const printTypes = url.searchParams.get('printTypes')?.split(',') || [];
// [END route.process-url]

// Step 3: Generate the HTML content
// [START route.generate-html]
const pages = printTypes.map((type) => createPage(type));
const print = printHTML(pages);
// [END route.generate-html]

// Step 4: Return properly formatted response with CORS headers
// [START route.return-response]
return cors(
new Response(print, {
status: 200,
Expand All @@ -21,6 +24,7 @@ export async function loader({request}) {
},
}),
);
// [END route.return-response]
}

// Helper function to create document pages based on type
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Loading

0 comments on commit ba12160

Please sign in to comment.