Spaces:
Running
Running
| # UI API Integration Prompt Instructions | |
| ## π― **System Overview** | |
| You are building a UI for a hierarchical B2B beauty supply chain management system. The backend provides REST APIs for managing merchants in a 4-level hierarchy: **Parent Company β cnf β distributors β retails**. | |
| ## ποΈ **API Base Configuration** | |
| ### Base URL & Authentication | |
| ```javascript | |
| const API_BASE_URL = 'http://localhost:8000' | |
| const API_ENDPOINTS = { | |
| merchants: '/merchants', | |
| merchantSettings: '/merchant-settings', | |
| users: '/system-users', | |
| roles: '/access-roles', | |
| auth: '/auth' | |
| } | |
| // JWT Token Authentication (implement as needed) | |
| const apiHeaders = { | |
| 'Content-Type': 'application/json', | |
| 'Authorization': `Bearer ${localStorage.getItem('authToken')}` | |
| } | |
| ``` | |
| ### Test Credentials for Development | |
| ```javascript | |
| const TEST_CREDENTIALS = { | |
| superAdmin: { username: 'superadmin', password: 'SuperAdmin@123' }, | |
| companyAdmin: { username: 'companyadmin', password: 'CompanyAdmin@123' }, | |
| cnfManager: { username: 'cnfmanager_north', password: 'cnfManager@123' }, | |
| distManager: { username: 'distmanager_delhi', password: 'DistManager@123' }, | |
| retailOwner: { username: 'owner_cp_luxury', password: 'retailOwner@123' } | |
| } | |
| ``` | |
| ## π± **Core UI Components to Build** | |
| ### 1. **Merchant Hierarchy Tree View** | |
| ```javascript | |
| // GET /merchants - Fetch all merchants | |
| const fetchMerchantsHierarchy = async () => { | |
| const response = await fetch(`${API_BASE_URL}/merchants`, { | |
| headers: apiHeaders | |
| }) | |
| const merchants = await response.json() | |
| // Build tree structure | |
| return buildHierarchyTree(merchants) | |
| } | |
| // Expected merchant object structure: | |
| const merchantStructure = { | |
| merchant_id: "string", | |
| merchant_name: "string", | |
| merchant_type: "parent_company|cnf|distributor|retail", | |
| merchant_code: "string", | |
| parent_merchant_id: "string|null", | |
| status: "active|inactive", | |
| contact: { | |
| phone: "string", | |
| email: "string", | |
| address_line1: "string", | |
| city: "string", | |
| state: "string", | |
| pincode: "string" | |
| }, | |
| kyc: { /* GST, PAN details */ } | |
| } | |
| ``` | |
| ### 2. **Merchant Management Dashboard** | |
| Create these UI sections: | |
| #### **A. Merchant List/Grid View** | |
| ```javascript | |
| // API Calls: | |
| // GET /merchants?merchant_type=retail - Filter by type | |
| // GET /merchants?status=active - Filter by status | |
| // GET /merchants/children/{parent_id} - Get child merchants | |
| const merchantListConfig = { | |
| columns: [ | |
| { key: 'merchant_code', label: 'Code', sortable: true }, | |
| { key: 'merchant_name', label: 'Name', sortable: true }, | |
| { key: 'merchant_type', label: 'Type', filterable: true }, | |
| { key: 'contact.city', label: 'City' }, | |
| { key: 'status', label: 'Status', filterable: true }, | |
| { key: 'actions', label: 'Actions' } | |
| ], | |
| filters: ['merchant_type', 'status', 'city'], | |
| actions: ['view', 'edit', 'settings', 'delete'] | |
| } | |
| ``` | |
| #### **B. Merchant Creation Form** | |
| ```javascript | |
| // POST /merchants - Create new merchant | |
| const createMerchantForm = { | |
| fields: { | |
| merchant_name: { type: 'text', required: true }, | |
| merchant_type: { | |
| type: 'select', | |
| options: ['cnf', 'distributor', 'retail'], | |
| required: true | |
| }, | |
| parent_merchant_id: { | |
| type: 'autocomplete', | |
| source: '/merchants', // Dynamic based on type | |
| required: true | |
| }, | |
| contact: { | |
| phone: { type: 'tel', required: true }, | |
| email: { type: 'email', required: true }, | |
| address_line1: { type: 'text', required: true }, | |
| city: { type: 'text', required: true }, | |
| state: { type: 'select', options: 'INDIAN_STATES' }, | |
| pincode: { type: 'text', pattern: '[0-9]{6}' } | |
| }, | |
| kyc: { | |
| gst_number: { type: 'text', pattern: 'GST_REGEX' }, | |
| pan_number: { type: 'text', pattern: 'PAN_REGEX' } | |
| } | |
| }, | |
| validation: 'client-side + server-side' | |
| } | |
| ``` | |
| ### 3. **Merchant Settings Management** | |
| ```javascript | |
| // GET /merchant-settings/{merchant_id} - Fetch settings | |
| // PUT /merchant-settings/{merchant_id} - Update settings | |
| const merchantSettingsForm = { | |
| businessSettings: { | |
| auto_allocate_stock: { type: 'toggle' }, | |
| credit_limit: { type: 'currency', min: 0 }, | |
| payment_terms_days: { type: 'number', min: 0, max: 365 } | |
| }, | |
| inventorySettings: { | |
| low_stock_threshold: { type: 'number', min: 1 }, | |
| enable_backorder: { type: 'toggle' }, | |
| auto_reorder: { type: 'toggle' } | |
| }, | |
| notifications: { | |
| email_notifications: { type: 'toggle' }, | |
| sms_notifications: { type: 'toggle' }, | |
| low_stock_alerts: { type: 'toggle' } | |
| }, | |
| operatingHours: { | |
| // Dynamic day-wise hour picker | |
| format: { open_time: 'HH:mm', close_time: 'HH:mm', is_open: boolean } | |
| }, | |
| pricing: { | |
| default_markup_percentage: { type: 'percentage', min: 0, max: 100 }, | |
| allow_discount: { type: 'toggle' }, | |
| max_discount_percentage: { type: 'percentage', min: 0, max: 50 } | |
| }, | |
| taxSettings: { | |
| gst_rate: { type: 'percentage', default: 18 }, | |
| inclusive_pricing: { type: 'toggle' }, | |
| tax_exemption: { type: 'toggle' } | |
| } | |
| } | |
| ``` | |
| ### 4. **User & Role Management** | |
| ```javascript | |
| // GET /access-roles - Fetch all roles | |
| // GET /system-users - Fetch all users | |
| // POST /system-users - Create user | |
| const userManagementConfig = { | |
| userForm: { | |
| username: { type: 'text', unique: true }, | |
| email: { type: 'email', unique: true }, | |
| full_name: { type: 'text' }, | |
| role_id: { | |
| type: 'select', | |
| source: '/access-roles', | |
| displayField: 'role_name' | |
| }, | |
| merchant_id: { | |
| type: 'autocomplete', | |
| source: '/merchants', | |
| filter: 'based on role permissions' | |
| }, | |
| password: { type: 'password', minLength: 8 } | |
| }, | |
| roleBasedAccess: { | |
| // Show/hide features based on user role | |
| 'role_super_admin': 'ALL_FEATURES', | |
| 'role_company_admin': 'EXCLUDE_DELETE_OPERATIONS', | |
| 'role_cnf_manager': 'REGIONAL_SCOPE_ONLY', | |
| 'role_distributor_manager': 'LOCAL_SCOPE_ONLY', | |
| 'role_retail_owner': 'OWN_MERCHANT_ONLY' | |
| } | |
| } | |
| ``` | |
| ## π **Key API Integration Patterns** | |
| ### 1. **Hierarchical Data Loading** | |
| ```javascript | |
| // Pattern: Load parent first, then children on-demand | |
| const loadHierarchicalData = async (parentId = null) => { | |
| if (!parentId) { | |
| // Load root level (Parent Company + cnfs) | |
| return await fetch(`${API_BASE_URL}/merchants?merchant_type=parent_company,cnf`) | |
| } else { | |
| // Load children of specific parent | |
| return await fetch(`${API_BASE_URL}/merchants/children/${parentId}`) | |
| } | |
| } | |
| // Tree expansion pattern | |
| const expandTreeNode = async (nodeId) => { | |
| const children = await fetch(`${API_BASE_URL}/merchants/children/${nodeId}`) | |
| // Update tree state with children | |
| } | |
| ``` | |
| ### 2. **Context-Aware Form Fields** | |
| ```javascript | |
| // Parent selection based on merchant type | |
| const getParentOptions = async (merchantType) => { | |
| const parentTypes = { | |
| 'cnf': ['parent_company'], | |
| 'distributor': ['cnf'], | |
| 'retail': ['distributor'] | |
| } | |
| const parentType = parentTypes[merchantType]?.[0] | |
| if (parentType) { | |
| return await fetch(`${API_BASE_URL}/merchants?merchant_type=${parentType}`) | |
| } | |
| } | |
| // Settings defaults based on merchant type | |
| const getSettingsDefaults = (merchantType) => { | |
| const defaults = { | |
| 'cnf': { credit_limit: 10000000, payment_terms_days: 90, markup: 5 }, | |
| 'distributor': { credit_limit: 3000000, payment_terms_days: 60, markup: 15 }, | |
| 'retail': { credit_limit: 500000, payment_terms_days: 30, markup: 30 } | |
| } | |
| return defaults[merchantType] || {} | |
| } | |
| ``` | |
| ### 3. **Error Handling & Validation** | |
| ```javascript | |
| const apiErrorHandler = (error) => { | |
| const errorMessages = { | |
| 400: 'Invalid request data. Please check your input.', | |
| 401: 'Authentication required. Please login.', | |
| 403: 'You do not have permission for this action.', | |
| 404: 'Resource not found.', | |
| 409: 'Duplicate entry. This record already exists.', | |
| 422: 'Validation failed. Please check highlighted fields.', | |
| 500: 'Server error. Please try again later.' | |
| } | |
| return errorMessages[error.status] || 'An unexpected error occurred.' | |
| } | |
| // Form validation | |
| const validateMerchantForm = (data) => { | |
| const errors = {} | |
| if (!data.merchant_name?.trim()) { | |
| errors.merchant_name = 'Merchant name is required' | |
| } | |
| if (data.merchant_type === 'retail' && !data.parent_merchant_id) { | |
| errors.parent_merchant_id = 'Parent distributor is required for retails' | |
| } | |
| // GST validation for Indian businesses | |
| if (data.kyc?.gst_number && !/^[0-9]{2}[A-Z]{5}[0-9]{4}[A-Z]{1}[1-9A-Z]{1}Z[0-9A-Z]{1}$/.test(data.kyc.gst_number)) { | |
| errors['kyc.gst_number'] = 'Invalid GST number format' | |
| } | |
| return errors | |
| } | |
| ``` | |
| ## π¨ **UI/UX Implementation Guidelines** | |
| ### 1. **Responsive Design Requirements** | |
| ```css | |
| /* Mobile-first approach for merchant management */ | |
| .merchant-card { | |
| /* Stack vertically on mobile */ | |
| @media (max-width: 768px) { | |
| flex-direction: column; | |
| } | |
| } | |
| .merchant-hierarchy-tree { | |
| /* Horizontal scroll on mobile */ | |
| @media (max-width: 768px) { | |
| overflow-x: auto; | |
| white-space: nowrap; | |
| } | |
| } | |
| ``` | |
| ### 2. **State Management Pattern** | |
| ```javascript | |
| // Redux/Zustand store structure | |
| const merchantStore = { | |
| state: { | |
| merchants: [], | |
| selectedMerchant: null, | |
| hierarchyTree: {}, | |
| filters: { type: 'all', status: 'active' }, | |
| loading: false, | |
| error: null | |
| }, | |
| actions: { | |
| fetchMerchants: async (filters) => { }, | |
| createMerchant: async (data) => { }, | |
| updateMerchant: async (id, data) => { }, | |
| deleteMerchant: async (id) => { }, | |
| setSelectedMerchant: (merchant) => { }, | |
| setFilters: (filters) => { } | |
| } | |
| } | |
| ``` | |
| ### 3. **Component Architecture** | |
| ```javascript | |
| // Component hierarchy | |
| const ComponentStructure = { | |
| 'MerchantDashboard': { | |
| 'MerchantHierarchyTree': ['TreeNode', 'TreeNodeActions'], | |
| 'MerchantListView': ['MerchantCard', 'FilterBar', 'Pagination'], | |
| 'MerchantFormModal': ['FormFields', 'ValidationErrors'], | |
| 'MerchantSettingsPanel': ['SettingsSections', 'OperatingHours'] | |
| }, | |
| 'UserManagement': { | |
| 'UserListView': ['UserCard', 'RoleFilter'], | |
| 'UserFormModal': ['UserForm', 'RoleSelector'], | |
| 'PermissionsMatrix': ['RolePermissions'] | |
| } | |
| } | |
| ``` | |
| ## π **Testing Checklist** | |
| ### 1. **API Integration Tests** | |
| - [ ] Fetch merchants hierarchy successfully | |
| - [ ] Create merchant with valid parent relationship | |
| - [ ] Update merchant settings with validation | |
| - [ ] Handle API errors gracefully | |
| - [ ] Implement proper loading states | |
| ### 2. **UI Functionality Tests** | |
| - [ ] Tree view expands/collapses correctly | |
| - [ ] Form validation works client-side | |
| - [ ] Filter/search functionality | |
| - [ ] Responsive design on mobile | |
| - [ ] Role-based feature visibility | |
| ### 3. **Business Logic Tests** | |
| - [ ] cnf can only have Parent Company as parent | |
| - [ ] distributor can only have cnf as parent | |
| - [ ] retail can only have distributor as parent | |
| - [ ] Credit limits are enforced based on merchant type | |
| - [ ] Operating hours format validation | |
| ## π **Development Workflow** | |
| ### 1. **Setup & Configuration** | |
| ```bash | |
| # Start the API server | |
| uvicorn app.main:app --reload --port 8000 | |
| # Access API documentation | |
| open http://localhost:8000/docs | |
| # Test API endpoints | |
| curl -X GET "http://localhost:8000/merchants" -H "Content-Type: application/json" | |
| ``` | |
| ### 2. **Implementation Order** | |
| 1. **Phase 1**: Basic merchant CRUD operations | |
| 2. **Phase 2**: Hierarchy tree view and navigation | |
| 3. **Phase 3**: Merchant settings management | |
| 4. **Phase 4**: User and role management | |
| 5. **Phase 5**: Advanced features (reports, analytics) | |
| ### 3. **Data Flow Examples** | |
| ```javascript | |
| // Example: Creating a new retail | |
| const createretail = async (retailData) => { | |
| // 1. Validate form data | |
| const errors = validateMerchantForm(retailData) | |
| if (Object.keys(errors).length > 0) { | |
| return { success: false, errors } | |
| } | |
| // 2. Call API | |
| const response = await fetch(`${API_BASE_URL}/merchants`, { | |
| method: 'POST', | |
| headers: apiHeaders, | |
| body: JSON.stringify({...retailData, merchant_type: 'retail'}) | |
| }) | |
| // 3. Handle response | |
| if (response.ok) { | |
| const newretail = await response.json() | |
| // Update local state | |
| addMerchantToStore(newretail) | |
| // Create default settings | |
| await createDefaultSettings(newretail.merchant_id) | |
| return { success: true, data: newretail } | |
| } else { | |
| const error = await response.json() | |
| return { success: false, error: error.detail } | |
| } | |
| } | |
| ``` | |
| ## π§ **Common Implementation Patterns** | |
| ### 1. **Autocomplete for Parent Selection** | |
| ```javascript | |
| const ParentMerchantSelector = ({ merchantType, value, onChange }) => { | |
| const [options, setOptions] = useState([]) | |
| useEffect(() => { | |
| const loadParentOptions = async () => { | |
| const parentType = getParentType(merchantType) | |
| const response = await fetch(`${API_BASE_URL}/merchants?merchant_type=${parentType}`) | |
| setOptions(await response.json()) | |
| } | |
| if (merchantType) { | |
| loadParentOptions() | |
| } | |
| }, [merchantType]) | |
| return ( | |
| <Autocomplete | |
| options={options} | |
| getOptionLabel={(option) => `${option.merchant_name} (${option.merchant_code})`} | |
| value={value} | |
| onChange={onChange} | |
| placeholder="Select parent merchant..." | |
| /> | |
| ) | |
| } | |
| ``` | |
| ### 2. **Operating Hours Component** | |
| ```javascript | |
| const OperatingHoursEditor = ({ value, onChange }) => { | |
| const days = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'] | |
| return ( | |
| <div className="operating-hours-grid"> | |
| {days.map(day => ( | |
| <div key={day} className="day-row"> | |
| <label>{day.charAt(0).toUpperCase() + day.slice(1)}</label> | |
| <input | |
| type="checkbox" | |
| checked={value[day]?.is_open || false} | |
| onChange={(e) => onChange(day, 'is_open', e.target.checked)} | |
| /> | |
| {value[day]?.is_open && ( | |
| <> | |
| <input | |
| type="time" | |
| value={value[day]?.open_time || '09:00'} | |
| onChange={(e) => onChange(day, 'open_time', e.target.value)} | |
| /> | |
| <input | |
| type="time" | |
| value={value[day]?.close_time || '18:00'} | |
| onChange={(e) => onChange(day, 'close_time', e.target.value)} | |
| /> | |
| </> | |
| )} | |
| </div> | |
| ))} | |
| </div> | |
| ) | |
| } | |
| ``` | |
| This prompt provides comprehensive guidance for building a production-ready UI that integrates seamlessly with your hierarchical merchant API system. |