feat: implement multiple saved addresses with modal selector in checkout
- Add AddressController with full CRUD API for saved addresses - Implement address management UI in My Account > Addresses - Add modal-based address selector in checkout (Tokopedia-style) - Hide checkout forms when saved address is selected - Add search functionality in address modal - Auto-select default addresses on page load - Fix variable products to show 'Select Options' instead of 'Add to Cart' - Add admin toggle for multiple addresses feature - Clean up debug logs and fix TypeScript errors
This commit is contained in:
@@ -63,10 +63,10 @@ export default function AppearanceHeader() {
|
||||
style,
|
||||
sticky,
|
||||
height,
|
||||
mobile_menu: mobileMenu,
|
||||
mobile_logo: mobileLogo,
|
||||
logo_width: logoWidth,
|
||||
logo_height: logoHeight,
|
||||
mobileMenu,
|
||||
mobileLogo,
|
||||
logoWidth,
|
||||
logoHeight,
|
||||
elements,
|
||||
});
|
||||
toast.success('Header settings saved successfully');
|
||||
|
||||
@@ -11,7 +11,11 @@ import { api } from '@/lib/api';
|
||||
|
||||
export default function AppearanceShop() {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [gridColumns, setGridColumns] = useState('3');
|
||||
const [gridColumns, setGridColumns] = useState({
|
||||
mobile: '2',
|
||||
tablet: '3',
|
||||
desktop: '4'
|
||||
});
|
||||
const [gridStyle, setGridStyle] = useState('standard');
|
||||
const [cardStyle, setCardStyle] = useState('card');
|
||||
const [aspectRatio, setAspectRatio] = useState('square');
|
||||
@@ -37,7 +41,11 @@ export default function AppearanceShop() {
|
||||
const shop = response.data?.pages?.shop;
|
||||
|
||||
if (shop) {
|
||||
setGridColumns(shop.layout?.grid_columns || '3');
|
||||
setGridColumns(shop.layout?.grid_columns || {
|
||||
mobile: '2',
|
||||
tablet: '3',
|
||||
desktop: '4'
|
||||
});
|
||||
setGridStyle(shop.layout?.grid_style || 'standard');
|
||||
setCardStyle(shop.layout?.card_style || 'card');
|
||||
setAspectRatio(shop.layout?.aspect_ratio || 'square');
|
||||
@@ -110,17 +118,55 @@ export default function AppearanceShop() {
|
||||
title="Layout"
|
||||
description="Configure shop page layout and product display"
|
||||
>
|
||||
<SettingsSection label="Grid Columns" htmlFor="grid-columns">
|
||||
<Select value={gridColumns} onValueChange={setGridColumns}>
|
||||
<SelectTrigger id="grid-columns">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="2">2 Columns</SelectItem>
|
||||
<SelectItem value="3">3 Columns</SelectItem>
|
||||
<SelectItem value="4">4 Columns</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<SettingsSection label="Grid Columns" description="Set columns for each breakpoint">
|
||||
<div className="grid grid-cols-3 gap-4">
|
||||
<div>
|
||||
<Label htmlFor="grid-columns-mobile" className="text-sm font-medium mb-2 block">Mobile</Label>
|
||||
<Select value={gridColumns.mobile} onValueChange={(value) => setGridColumns({ ...gridColumns, mobile: value })}>
|
||||
<SelectTrigger id="grid-columns-mobile">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="1">1</SelectItem>
|
||||
<SelectItem value="2">2</SelectItem>
|
||||
<SelectItem value="3">3</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<p className="text-xs text-gray-500 mt-1"><768px</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label htmlFor="grid-columns-tablet" className="text-sm font-medium mb-2 block">Tablet</Label>
|
||||
<Select value={gridColumns.tablet} onValueChange={(value) => setGridColumns({ ...gridColumns, tablet: value })}>
|
||||
<SelectTrigger id="grid-columns-tablet">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="2">2</SelectItem>
|
||||
<SelectItem value="3">3</SelectItem>
|
||||
<SelectItem value="4">4</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<p className="text-xs text-gray-500 mt-1">768-1024px</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label htmlFor="grid-columns-desktop" className="text-sm font-medium mb-2 block">Desktop</Label>
|
||||
<Select value={gridColumns.desktop} onValueChange={(value) => setGridColumns({ ...gridColumns, desktop: value })}>
|
||||
<SelectTrigger id="grid-columns-desktop">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="2">2</SelectItem>
|
||||
<SelectItem value="3">3</SelectItem>
|
||||
<SelectItem value="4">4</SelectItem>
|
||||
<SelectItem value="5">5</SelectItem>
|
||||
<SelectItem value="6">6</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<p className="text-xs text-gray-500 mt-1">>1024px</p>
|
||||
</div>
|
||||
</div>
|
||||
</SettingsSection>
|
||||
|
||||
<SettingsSection label="Grid Style" htmlFor="grid-style" description="Masonry creates a Pinterest-like layout with varying heights">
|
||||
|
||||
@@ -12,6 +12,7 @@ import { formatMoney, getStoreCurrency } from '@/lib/currency';
|
||||
|
||||
interface CustomerSettings {
|
||||
auto_register_members: boolean;
|
||||
multiple_addresses_enabled: boolean;
|
||||
vip_min_spent: number;
|
||||
vip_min_orders: number;
|
||||
vip_timeframe: 'all' | '30' | '90' | '365';
|
||||
@@ -22,6 +23,7 @@ interface CustomerSettings {
|
||||
export default function CustomersSettings() {
|
||||
const [settings, setSettings] = useState<CustomerSettings>({
|
||||
auto_register_members: false,
|
||||
multiple_addresses_enabled: true,
|
||||
vip_min_spent: 1000,
|
||||
vip_min_orders: 10,
|
||||
vip_timeframe: 'all',
|
||||
@@ -119,13 +121,23 @@ export default function CustomersSettings() {
|
||||
title={__('General')}
|
||||
description={__('General customer settings')}
|
||||
>
|
||||
<ToggleField
|
||||
id="auto_register_members"
|
||||
label={__('Auto-register customers as site members')}
|
||||
description={__('Automatically create WordPress user accounts for new customers when orders are created. Customers will receive login credentials via email and can track their orders.')}
|
||||
checked={settings.auto_register_members}
|
||||
onCheckedChange={(checked) => setSettings({ ...settings, auto_register_members: checked })}
|
||||
/>
|
||||
<div className="space-y-6">
|
||||
<ToggleField
|
||||
id="auto_register_members"
|
||||
label={__('Auto-register customers as site members')}
|
||||
description={__('Automatically create WordPress user accounts for new customers when orders are created. Customers will receive login credentials via email and can track their orders.')}
|
||||
checked={settings.auto_register_members}
|
||||
onCheckedChange={(checked) => setSettings({ ...settings, auto_register_members: checked })}
|
||||
/>
|
||||
|
||||
<ToggleField
|
||||
id="multiple_addresses_enabled"
|
||||
label={__('Enable multiple saved addresses')}
|
||||
description={__('Allow customers to save multiple billing and shipping addresses in their account. Customers can select from saved addresses during checkout for faster ordering.')}
|
||||
checked={settings.multiple_addresses_enabled}
|
||||
onCheckedChange={(checked) => setSettings({ ...settings, multiple_addresses_enabled: checked })}
|
||||
/>
|
||||
</div>
|
||||
</SettingsCard>
|
||||
|
||||
<SettingsCard
|
||||
|
||||
Reference in New Issue
Block a user