diff --git a/app/templates/admin/vendor-create.html b/app/templates/admin/vendor-create.html index 566549bd..f21eabbc 100644 --- a/app/templates/admin/vendor-create.html +++ b/app/templates/admin/vendor-create.html @@ -1,10 +1,270 @@ - - - - - Title - - +{# app/templates/admin/vendor-create.html #} +{% extends "admin/base.html" %} - - \ No newline at end of file +{% block title %}Create Vendor{% endblock %} + +{% block alpine_data %}adminVendorCreate(){% endblock %} + +{% block content %} + +
+
+

+ Create New Vendor +

+

+ Create a vendor (storefront/brand) under an existing company +

+
+ + + + Back to Vendors + + +
+ + +
+
+ +
+

Vendor Created Successfully!

+ +
+
+
+ + +
+
+ +
+

Error Creating Vendor

+

+
+
+
+ + +
+
+ + Loading companies... +
+
+ + +
+
+ +
+

Parent Company

+
+

+ + Vendors are storefronts/brands under a company. Select the parent company for this vendor. +

+
+ +
+ + +

The company this vendor belongs to

+
+
+ + +
+

Vendor Information

+ +
+ +
+ + +

Unique identifier (uppercase, 2-50 chars)

+
+ + +
+ +
+ + .example.com +
+

Lowercase letters, numbers, and hyphens only

+
+
+ +
+ +
+ + +
+ + +
+ +
+
+ + +
+ + +
+
+ + +
+

Marketplace URLs (Optional)

+

+ CSV feed URLs for product import from Letzshop marketplace +

+ +
+ +
+ + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + +
+ + +
+
+
+{% endblock %} + +{% block extra_scripts %} + +{% endblock %} diff --git a/static/admin/js/vendor-create.js b/static/admin/js/vendor-create.js new file mode 100644 index 00000000..61d30ad1 --- /dev/null +++ b/static/admin/js/vendor-create.js @@ -0,0 +1,173 @@ +// static/admin/js/vendor-create.js +/** + * Admin Vendor Create Page + * Handles vendor creation form with company selection + */ + +// Use centralized logger +const vendorCreateLog = window.LogConfig.loggers.vendors; + +vendorCreateLog.info('Loading vendor create module...'); + +function adminVendorCreate() { + vendorCreateLog.debug('adminVendorCreate() called'); + + return { + // Inherit base layout functionality + ...data(), + + // Page identifier + currentPage: 'vendors', + + // Companies list for dropdown + companies: [], + loadingCompanies: true, + + // Form data matching VendorCreate schema + formData: { + company_id: '', + vendor_code: '', + subdomain: '', + name: '', + description: '', + letzshop_csv_url_fr: '', + letzshop_csv_url_en: '', + letzshop_csv_url_de: '' + }, + + // UI state + loading: false, + successMessage: false, + errorMessage: '', + createdVendor: null, + + // Initialize + async init() { + vendorCreateLog.info('Initializing vendor create page'); + await this.loadCompanies(); + }, + + // Load companies for dropdown + async loadCompanies() { + this.loadingCompanies = true; + try { + const response = await apiClient.get('/admin/companies?limit=1000'); + this.companies = response.companies || []; + vendorCreateLog.debug('Loaded companies:', this.companies.length); + } catch (error) { + vendorCreateLog.error('Failed to load companies:', error); + this.errorMessage = 'Failed to load companies. Please refresh the page.'; + } finally { + this.loadingCompanies = false; + } + }, + + // Auto-generate subdomain from vendor name + autoGenerateSubdomain() { + if (!this.formData.name) { + return; + } + + // Convert name to subdomain format + const subdomain = this.formData.name + .toLowerCase() + .replace(/[^a-z0-9\s-]/g, '') // Remove special chars + .replace(/\s+/g, '-') // Replace spaces with hyphens + .replace(/-+/g, '-') // Replace multiple hyphens with single + .replace(/^-|-$/g, ''); // Remove leading/trailing hyphens + + this.formData.subdomain = subdomain; + vendorCreateLog.debug('Auto-generated subdomain:', subdomain); + }, + + // Create vendor + async createVendor() { + this.loading = true; + this.errorMessage = ''; + this.successMessage = false; + this.createdVendor = null; + + try { + vendorCreateLog.info('Creating vendor:', { + company_id: this.formData.company_id, + vendor_code: this.formData.vendor_code, + name: this.formData.name + }); + + // Prepare payload - only include non-empty values + const payload = { + company_id: parseInt(this.formData.company_id), + vendor_code: this.formData.vendor_code.toUpperCase(), + subdomain: this.formData.subdomain.toLowerCase(), + name: this.formData.name + }; + + // Add optional fields if provided + if (this.formData.description) { + payload.description = this.formData.description; + } + if (this.formData.letzshop_csv_url_fr) { + payload.letzshop_csv_url_fr = this.formData.letzshop_csv_url_fr; + } + if (this.formData.letzshop_csv_url_en) { + payload.letzshop_csv_url_en = this.formData.letzshop_csv_url_en; + } + if (this.formData.letzshop_csv_url_de) { + payload.letzshop_csv_url_de = this.formData.letzshop_csv_url_de; + } + + const response = await apiClient.post('/admin/vendors', payload); + + vendorCreateLog.info('Vendor created successfully:', response.vendor_code); + + // Store created vendor details + this.createdVendor = { + vendor_code: response.vendor_code, + name: response.name, + subdomain: response.subdomain, + company_name: response.company_name + }; + + this.successMessage = true; + + // Reset form + this.formData = { + company_id: '', + vendor_code: '', + subdomain: '', + name: '', + description: '', + letzshop_csv_url_fr: '', + letzshop_csv_url_en: '', + letzshop_csv_url_de: '' + }; + + // Scroll to top to show success message + window.scrollTo({ top: 0, behavior: 'smooth' }); + + // Redirect after 3 seconds + setTimeout(() => { + window.location.href = `/admin/vendors/${response.vendor_code}`; + }, 3000); + + } catch (error) { + vendorCreateLog.error('Failed to create vendor:', error); + + // Parse error message + if (error.message) { + this.errorMessage = error.message; + } else if (error.detail) { + this.errorMessage = error.detail; + } else { + this.errorMessage = 'Failed to create vendor. Please try again.'; + } + + window.scrollTo({ top: 0, behavior: 'smooth' }); + } finally { + this.loading = false; + } + } + }; +} + +vendorCreateLog.info('Vendor create module loaded');