@koia-ai/koia-eshop-sdk
v1.0.16
Published
A configurable React context provider for e-commerce functionality with cart management, discount codes, order processing, and API client for product management
Downloads
5
Readme
Koia Eshop SDK
A configurable React context provider for e-commerce functionality with cart management, discount codes, order processing, and API client for product management.
Features
- 🛒 Cart Management: Add, remove, and manage cart items
- 🏷️ Discount Codes: Configurable discount code system
- 💾 Persistence: Automatic localStorage persistence
- 🔧 Configurable: Customizable API endpoints and storage keys
- 📦 TypeScript: Full TypeScript support
- 🎯 Framework Agnostic: Works with any React setup
- 🌐 API Client: Built-in client for product management and API calls
Installation
npm install @koia-ai/koia-eshop-sdkor
yarn add @koia-ai/koia-eshop-sdkQuick Start
React Context Provider (Cart Management)
import { EshopProvider, useEshop } from '@koia-ai/koia-eshop-sdk';
// Configure your eshop
const config = {
discountCodes: {
'SAVE10': 10,
'SAVE20': 20,
'FREESHIP': 0 // Special code for free shipping
},
apiEndpoint: '/api/orders',
storageKeys: {
cart: 'my-cart',
discountCode: 'my-discount',
discountPercentage: 'my-discount-percentage'
}
};
function App() {
return (
<EshopProvider config={config}>
<YourApp />
</EshopProvider>
);
}
function ProductComponent() {
const { addToCart } = useEshop();
const handleAddToCart = () => {
addToCart({
id: 'product-1',
name: 'Awesome Product',
price: 29.99,
quantity: 1
});
};
return (
<button onClick={handleAddToCart}>
Add to Cart
</button>
);
}API Client (Product Management)
import { useEshopClient } from '@koia-ai/koia-eshop-sdk';
function ProductList() {
const eshop = useEshopClient(supabaseUrl, supabaseKey, baseUrl);
const [products, setProducts] = useState([]);
const [loading, setLoading] = useState(false);
const fetchProducts = async (organizationId: string) => {
setLoading(true);
const { data, error } = await eshop.getProducts(organizationId);
if (error) {
console.error('Failed to fetch products:', error);
} else {
setProducts(data || []);
}
setLoading(false);
};
useEffect(() => {
fetchProducts('your-organization-id');
}, []);
return (
<div>
{loading ? (
<p>Loading products...</p>
) : (
products.map(product => (
<div key={product.id}>
<h3>{product.name}</h3>
<p>{product.description}</p>
<p>${product.price}</p>
</div>
))
)}
</div>
);
}Configuration
EshopConfig Interface
interface EshopConfig {
discountCodes?: Record<string, number>; // Discount code -> percentage
apiEndpoint?: string; // API endpoint for order creation
storageKeys?: {
cart?: string; // localStorage key for cart
discountCode?: string; // localStorage key for discount code
discountPercentage?: string; // localStorage key for discount percentage
};
}Default Configuration
const defaultConfig: EshopConfig = {
discountCodes: {},
apiEndpoint: '/api/orders',
storageKeys: {
cart: 'cart',
discountCode: 'discountCode',
discountPercentage: 'discountPercentage'
}
};API Reference
EshopProvider
The main context provider component.
<EshopProvider config={config}>
{children}
</EshopProvider>Props:
children: React children componentsconfig: Optional configuration object
useEshop Hook
Returns the eshop context with all available methods and state.
const {
cart,
addToCart,
removeFromCart,
removeOneFromCart,
clearCart,
applyDiscountCode,
removeDiscountCode,
discountCode,
discountPercentage,
subtotal,
total,
shippingCost,
setShippingCost,
finalizeOrder
} = useEshop();EshopClient
Client class for making API calls with authentication.
const eshop = useEshopClient(supabaseUrl, supabaseKey, baseUrl);
// Set authentication token
eshop.setAccessToken('your-access-token');
// Fetch products
const { data: products, error } = await eshop.getProducts(organizationId);
// Make custom API requests
const { data, error } = await eshop.makeRequest('/api/custom-endpoint');useEshopClient Hook
Hook to create and manage an EshopClient instance.
const client = useEshopClient(supabaseUrl, supabaseKey, baseUrl);Cart Management
Adding Items
const { addToCart } = useEshop();
addToCart({
id: 'product-1',
name: 'Product Name',
price: 29.99,
quantity: 2
});Removing Items
const { removeFromCart, removeOneFromCart } = useEshop();
// Remove all quantities of an item
removeFromCart('product-1');
// Remove one quantity of an item
removeOneFromCart('product-1');Clearing Cart
const { clearCart } = useEshop();
clearCart(); // Clears cart and resets discount informationProduct Management
Fetching Products
const eshop = useEshopClient(supabaseUrl, supabaseKey, baseUrl);
const { data: products, error } = await eshop.getProducts(organizationId);
if (error) {
console.error('Failed to fetch products:', error);
} else {
console.log('Products:', products);
}Authentication
const eshop = useEshopClient(supabaseUrl, supabaseKey, baseUrl);
// Set access token for authenticated requests
eshop.setAccessToken('your-access-token');
// Clear access token
eshop.clearAccessToken();Discount Codes
Applying Discount Codes
const { applyDiscountCode } = useEshop();
const handleApplyCode = (code: string) => {
const isValid = applyDiscountCode(code);
if (isValid) {
console.log('Discount applied!');
} else {
console.log('Invalid discount code');
}
};Removing Discount Codes
const { removeDiscountCode } = useEshop();
removeDiscountCode(); // Removes current discount codeOrder Processing
Finalizing Orders
const { finalizeOrder } = useEshop();
const handleCheckout = async () => {
try {
const customerInfo = {
name: 'John Doe',
email: '[email protected]',
address: '123 Main St'
};
const result = await finalizeOrder(customerInfo);
console.log('Order created:', result.order);
} catch (error) {
console.error('Order failed:', error);
}
};State Values
Cart Information
const { cart, subtotal, total, shippingCost } = useEshop();
// cart: Array of CartItem objects
// subtotal: Sum of all items before discount and shipping
// total: Final total including discount and shipping
// shippingCost: Current shipping costDiscount Information
const { discountCode, discountPercentage } = useEshop();
// discountCode: Current applied discount code (string | null)
// discountPercentage: Current discount percentage (number)Complete Example
import React, { useState, useEffect } from 'react';
import { EshopProvider, useEshop, useEshopClient } from '@koia-ai/koia-eshop-sdk';
const config = {
discountCodes: {
'SAVE10': 10,
'SAVE20': 20
},
apiEndpoint: '/api/orders'
};
function ProductList() {
const eshop = useEshopClient(supabaseUrl, supabaseKey, baseUrl);
const { addToCart } = useEshop();
const [products, setProducts] = useState([]);
useEffect(() => {
const fetchProducts = async () => {
const { data, error } = await eshop.getProducts('your-org-id');
if (!error && data) {
setProducts(data);
}
};
fetchProducts();
}, []);
return (
<div>
{products.map(product => (
<div key={product.id}>
<h3>{product.name}</h3>
<p>{product.description}</p>
<p>${product.price}</p>
<button onClick={() => addToCart({
id: product.id,
name: product.name,
price: product.price,
quantity: 1
})}>
Add to Cart
</button>
</div>
))}
</div>
);
}
function CartComponent() {
const {
cart,
addToCart,
removeFromCart,
subtotal,
total,
applyDiscountCode,
discountCode
} = useEshop();
const [discountInput, setDiscountInput] = useState('');
const handleApplyDiscount = () => {
const success = applyDiscountCode(discountInput);
if (success) {
setDiscountInput('');
}
};
return (
<div>
<h2>Shopping Cart</h2>
{cart.map(item => (
<div key={item.id}>
<span>{item.name}</span>
<span>${item.price} x {item.quantity}</span>
<button onClick={() => removeFromCart(item.id)}>Remove</button>
</div>
))}
<div>
<p>Subtotal: ${subtotal}</p>
<p>Total: ${total}</p>
{discountCode && <p>Discount: {discountCode}</p>}
</div>
<div>
<input
value={discountInput}
onChange={(e) => setDiscountInput(e.target.value)}
placeholder="Enter discount code"
/>
<button onClick={handleApplyDiscount}>Apply</button>
</div>
</div>
);
}
function App() {
return (
<EshopProvider config={config}>
<ProductList />
<CartComponent />
</EshopProvider>
);
}Types
CartItem
interface CartItem {
id: string;
name: string;
price: number;
quantity: number;
}Product
interface Product {
id: string;
name: string;
description: string;
price: number;
organization_id: string;
created_at: string;
updated_at: string;
organizations: {
id: string;
name: string;
slug: string;
};
}EshopContextType
interface EshopContextType {
cart: CartItem[];
addToCart: (item: CartItem) => void;
removeFromCart: (id: string) => void;
removeOneFromCart: (id: string) => void;
clearCart: () => void;
applyDiscountCode: (code: string) => boolean;
removeDiscountCode: () => void;
discountCode: string | null;
discountPercentage: number;
subtotal: number;
total: number;
shippingCost: number;
setShippingCost: (cost: number) => void;
finalizeOrder: (customerInfo: any) => Promise<{ order: any }>;
}ApiResponse
interface ApiResponse<T> {
data?: T;
error?: string;
}Error Handling
The useEshop hook will throw an error if used outside of an EshopProvider:
try {
const { cart } = useEshop();
} catch (error) {
console.error('useEshop must be used within an EshopProvider');
}API calls return consistent error format:
const { data, error } = await eshop.getProducts(organizationId);
if (error) {
console.error('API Error:', error);
} else {
console.log('Products:', data);
}Browser Support
This package uses localStorage for persistence, which is supported in all modern browsers. For older browsers, consider using a polyfill.
License
MIT
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
