// Admin Vendor Creation Component function vendorCreation() { return { currentUser: {}, formData: { vendor_code: '', name: '', subdomain: '', description: '', owner_email: '', business_phone: '', website: '', business_address: '', tax_number: '' }, loading: false, errors: {}, showCredentials: false, credentials: null, init() { if (!this.checkAuth()) { return; } }, checkAuth() { if (!Auth.isAuthenticated()) { window.location.href = '/static/admin/login.html'; return false; } const user = Auth.getCurrentUser(); if (!user || user.role !== 'admin') { Utils.showToast('Access denied. Admin privileges required.', 'error'); Auth.logout(); window.location.href = '/static/admin/login.html'; return false; } this.currentUser = user; return true; }, async handleLogout() { const confirmed = await Utils.confirm( 'Are you sure you want to logout?', 'Confirm Logout' ); if (confirmed) { Auth.logout(); Utils.showToast('Logged out successfully', 'success', 2000); setTimeout(() => { window.location.href = '/static/admin/login.html'; }, 500); } }, // Auto-format vendor code (uppercase) formatVendorCode() { this.formData.vendor_code = this.formData.vendor_code .toUpperCase() .replace(/[^A-Z0-9_-]/g, ''); }, // Auto-format subdomain (lowercase) formatSubdomain() { this.formData.subdomain = this.formData.subdomain .toLowerCase() .replace(/[^a-z0-9-]/g, ''); }, clearErrors() { this.errors = {}; }, validateForm() { this.clearErrors(); let isValid = true; // Required fields validation if (!this.formData.vendor_code.trim()) { this.errors.vendor_code = 'Vendor code is required'; isValid = false; } if (!this.formData.name.trim()) { this.errors.name = 'Vendor name is required'; isValid = false; } if (!this.formData.subdomain.trim()) { this.errors.subdomain = 'Subdomain is required'; isValid = false; } if (!this.formData.owner_email.trim()) { this.errors.owner_email = 'Owner email is required'; isValid = false; } // Email validation const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (this.formData.owner_email && !emailRegex.test(this.formData.owner_email)) { this.errors.owner_email = 'Invalid email format'; isValid = false; } // Subdomain validation (must start and end with alphanumeric) const subdomainRegex = /^[a-z0-9][a-z0-9-]*[a-z0-9]$/; if (this.formData.subdomain && this.formData.subdomain.length > 1 && !subdomainRegex.test(this.formData.subdomain)) { this.errors.subdomain = 'Subdomain must start and end with a letter or number'; isValid = false; } return isValid; }, async handleSubmit() { if (!this.validateForm()) { Utils.showToast('Please fix validation errors', 'error'); window.scrollTo({ top: 0, behavior: 'smooth' }); return; } this.loading = true; try { // Prepare data (remove empty fields) const submitData = {}; for (const [key, value] of Object.entries(this.formData)) { if (value !== '' && value !== null && value !== undefined) { submitData[key] = value; } } console.log('Submitting vendor data:', submitData); const response = await apiClient.post('/admin/vendors', submitData); console.log('Vendor creation response:', response); // Store credentials - be flexible with response structure this.credentials = { vendor_code: response.vendor_code || this.formData.vendor_code, subdomain: response.subdomain || this.formData.subdomain, name: response.name || this.formData.name, owner_username: response.owner_username || `${this.formData.subdomain}_owner`, owner_email: response.owner_email || this.formData.owner_email, temporary_password: response.temporary_password || 'PASSWORD_NOT_RETURNED', login_url: response.login_url || `http://localhost:8000/vendor/${this.formData.subdomain}/login` || `${this.formData.subdomain}.platform.com/vendor/login` }; console.log('Stored credentials:', this.credentials); // Check if password was returned if (!response.temporary_password) { console.warn('⚠️ Warning: temporary_password not returned from API'); console.warn('Full API response:', response); Utils.showToast('Vendor created but password not returned. Check server logs.', 'warning', 5000); } // Show credentials display this.showCredentials = true; // Success notification Utils.showToast('Vendor created successfully!', 'success'); // Scroll to top to see credentials window.scrollTo({ top: 0, behavior: 'smooth' }); } catch (error) { console.error('Error creating vendor:', error); // Check for specific validation errors if (error.message.includes('vendor_code') || error.message.includes('Vendor code')) { this.errors.vendor_code = 'Vendor code already exists'; } else if (error.message.includes('subdomain')) { this.errors.subdomain = 'Subdomain already exists'; } else if (error.message.includes('email')) { this.errors.owner_email = 'Email already in use'; } Utils.showToast( error.message || 'Failed to create vendor', 'error' ); } finally { this.loading = false; } }, resetForm() { this.formData = { vendor_code: '', name: '', subdomain: '', description: '', owner_email: '', business_phone: '', website: '', business_address: '', tax_number: '' }; this.clearErrors(); this.showCredentials = false; this.credentials = null; }, copyToClipboard(text, label) { if (!text) { Utils.showToast('Nothing to copy', 'error'); return; } navigator.clipboard.writeText(text).then(() => { Utils.showToast(`${label} copied to clipboard`, 'success', 2000); }).catch((err) => { console.error('Failed to copy:', err); // Fallback for older browsers const textArea = document.createElement('textarea'); textArea.value = text; textArea.style.position = 'fixed'; textArea.style.left = '-999999px'; document.body.appendChild(textArea); textArea.select(); try { document.execCommand('copy'); Utils.showToast(`${label} copied to clipboard`, 'success', 2000); } catch (err) { Utils.showToast('Failed to copy to clipboard', 'error'); } document.body.removeChild(textArea); }); } } }