Major improvements to WooNooW Page Editor system: Schema & Architecture: - Canonical section schema with unified sectionSchema.ts - Normalized feature-grid to use items (not features) - Standardized default values across all section types - Schema versioning with automatic migration on read Backend (PHP): - Enhanced PlaceholderRenderer with typed output contracts - Added fallback behavior for empty/invalid dynamic sources - Added caching support for post data resolution - New SchemaMigration class for backward compatibility - New Features class for feature flags - Enhanced PageSSR with full style support - Removed controller-level special-casing for related_posts Frontend (Admin SPA): - Updated CanvasRenderer with schema-aware transformation - Enhanced InspectorPanel with canonical schema metadata - Added new section renderers Frontend (Customer SPA): - New section components: BentoCategoryGrid, MarqueeBanner, ProductCarousel, ShoppableImage - Updated FeatureGridSection for items prop contract Testing: - Add PHP tests: SchemaMigrationTest, PlaceholderRendererTest, PageSSRTest - Add TypeScript tests: schema-integration, feature-grid-regression - Add parity tests for React vs SSR content matching - Add CI script: check-schema-drift.mjs - Add VERIFICATION_CHECKLIST.md Documentation: - RELEASE_NOTES-v1.0.md with full release notes - docs/PAGE_EDITOR_SECTION_SCHEMA_V1.md - docs/PAGE_EDITOR_SSR_COVERAGE_AUDIT.md
110 lines
2.2 KiB
TypeScript
110 lines
2.2 KiB
TypeScript
import { api } from '../api';
|
|
|
|
export interface CustomerAddress {
|
|
first_name: string;
|
|
last_name: string;
|
|
company?: string;
|
|
address_1: string;
|
|
address_2?: string;
|
|
city: string;
|
|
state?: string;
|
|
postcode: string;
|
|
country: string;
|
|
phone?: string;
|
|
}
|
|
|
|
export interface CustomerStats {
|
|
total_orders: number;
|
|
total_spent: number;
|
|
}
|
|
|
|
export interface Customer {
|
|
id: number;
|
|
username: string;
|
|
email: string;
|
|
first_name: string;
|
|
last_name: string;
|
|
display_name: string;
|
|
registered: string;
|
|
role: string;
|
|
billing?: CustomerAddress;
|
|
shipping?: CustomerAddress;
|
|
stats?: CustomerStats;
|
|
}
|
|
|
|
export interface CustomerListResponse {
|
|
data: Customer[];
|
|
pagination: {
|
|
total: number;
|
|
total_pages: number;
|
|
current: number;
|
|
per_page: number;
|
|
};
|
|
}
|
|
|
|
export interface CustomerFormData {
|
|
email: string;
|
|
first_name: string;
|
|
last_name: string;
|
|
username?: string;
|
|
password?: string;
|
|
billing?: Partial<CustomerAddress>;
|
|
shipping?: Partial<CustomerAddress>;
|
|
send_email?: boolean;
|
|
}
|
|
|
|
export interface CustomerSearchResult {
|
|
id: number;
|
|
name: string;
|
|
email: string;
|
|
}
|
|
|
|
export const CustomersApi = {
|
|
/**
|
|
* List customers with pagination and filtering
|
|
*/
|
|
list: async (params?: {
|
|
page?: number;
|
|
per_page?: number;
|
|
search?: string;
|
|
role?: string;
|
|
}): Promise<CustomerListResponse> => {
|
|
return api.get('/customers', params);
|
|
},
|
|
|
|
/**
|
|
* Get single customer
|
|
*/
|
|
get: async (id: number): Promise<Customer> => {
|
|
return api.get(`/customers/${id}`);
|
|
},
|
|
|
|
/**
|
|
* Create new customer
|
|
*/
|
|
create: async (data: CustomerFormData): Promise<Customer> => {
|
|
return api.post('/customers', data);
|
|
},
|
|
|
|
/**
|
|
* Update customer
|
|
*/
|
|
update: async (id: number, data: Partial<CustomerFormData>): Promise<Customer> => {
|
|
return api.put(`/customers/${id}`, data);
|
|
},
|
|
|
|
/**
|
|
* Delete customer
|
|
*/
|
|
delete: async (id: number): Promise<void> => {
|
|
return api.del(`/customers/${id}`);
|
|
},
|
|
|
|
/**
|
|
* Search customers (for autocomplete)
|
|
*/
|
|
search: async (query: string, limit?: number): Promise<CustomerSearchResult[]> => {
|
|
return api.get('/customers/search', { q: query, limit });
|
|
},
|
|
};
|