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:
@@ -23,21 +23,56 @@ export default function Shop() {
|
||||
const [sortBy, setSortBy] = useState('');
|
||||
const { addItem } = useCartStore();
|
||||
|
||||
// Map grid columns setting to Tailwind classes
|
||||
const gridColsClass = {
|
||||
'2': 'grid-cols-1 sm:grid-cols-2',
|
||||
'3': 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-3',
|
||||
'4': 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4',
|
||||
'5': 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-5',
|
||||
'6': 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 xl:grid-cols-6',
|
||||
}[shopLayout.grid_columns] || 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4';
|
||||
// Map grid columns setting to Tailwind classes (responsive)
|
||||
const gridCols = typeof shopLayout.grid_columns === 'object'
|
||||
? shopLayout.grid_columns
|
||||
: { mobile: '2', tablet: '3', desktop: '4' };
|
||||
|
||||
// Masonry column classes (CSS columns)
|
||||
const masonryColsClass = {
|
||||
'2': 'columns-1 sm:columns-2',
|
||||
'3': 'columns-1 sm:columns-2 lg:columns-3',
|
||||
'4': 'columns-1 sm:columns-2 lg:columns-3 xl:columns-4',
|
||||
}[shopLayout.grid_columns] || 'columns-1 sm:columns-2 lg:columns-3';
|
||||
// Map to actual Tailwind classes (can't use template literals due to purging)
|
||||
const mobileClass = {
|
||||
'1': 'grid-cols-1',
|
||||
'2': 'grid-cols-2',
|
||||
'3': 'grid-cols-3',
|
||||
}[gridCols.mobile] || 'grid-cols-2';
|
||||
|
||||
const tabletClass = {
|
||||
'2': 'md:grid-cols-2',
|
||||
'3': 'md:grid-cols-3',
|
||||
'4': 'md:grid-cols-4',
|
||||
}[gridCols.tablet] || 'md:grid-cols-3';
|
||||
|
||||
const desktopClass = {
|
||||
'2': 'lg:grid-cols-2',
|
||||
'3': 'lg:grid-cols-3',
|
||||
'4': 'lg:grid-cols-4',
|
||||
'5': 'lg:grid-cols-5',
|
||||
'6': 'lg:grid-cols-6',
|
||||
}[gridCols.desktop] || 'lg:grid-cols-4';
|
||||
|
||||
const gridColsClass = `${mobileClass} ${tabletClass} ${desktopClass}`;
|
||||
|
||||
// Masonry column classes
|
||||
const masonryMobileClass = {
|
||||
'1': 'columns-1',
|
||||
'2': 'columns-2',
|
||||
'3': 'columns-3',
|
||||
}[gridCols.mobile] || 'columns-2';
|
||||
|
||||
const masonryTabletClass = {
|
||||
'2': 'md:columns-2',
|
||||
'3': 'md:columns-3',
|
||||
'4': 'md:columns-4',
|
||||
}[gridCols.tablet] || 'md:columns-3';
|
||||
|
||||
const masonryDesktopClass = {
|
||||
'2': 'lg:columns-2',
|
||||
'3': 'lg:columns-3',
|
||||
'4': 'lg:columns-4',
|
||||
'5': 'lg:columns-5',
|
||||
'6': 'lg:columns-6',
|
||||
}[gridCols.desktop] || 'lg:columns-4';
|
||||
|
||||
const masonryColsClass = `${masonryMobileClass} ${masonryTabletClass} ${masonryDesktopClass}`;
|
||||
|
||||
const isMasonry = shopLayout.grid_style === 'masonry';
|
||||
|
||||
@@ -114,7 +149,7 @@ export default function Shop() {
|
||||
{search && (
|
||||
<button
|
||||
onClick={() => setSearch('')}
|
||||
className="absolute right-3 top-1/2 -translate-y-1/2 p-1 hover:bg-gray-100 rounded-full transition-colors"
|
||||
className="font-[inherit] absolute right-3 top-1/2 -translate-y-1/2 p-1 hover:bg-gray-100 rounded-full transition-colors"
|
||||
>
|
||||
<X className="h-4 w-4 text-muted-foreground" />
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user