UNPKG

ondc-campaign-sdk

Version:

[![npm version](https://img.shields.io/npm/v/ondc-campaign-sdk.svg)](https://www.npmjs.com/package/ondc-campaign-sdk) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) [![Made with ❤️](https://img.shields.io/badge/Made%20with-%

1,043 lines (1,042 loc) 44.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CampaignCreateComponent = void 0; const core_1 = require("@angular/core"); const forms_1 = require("@angular/forms"); const operators_1 = require("rxjs/operators"); const rxjs_1 = require("rxjs"); const common_1 = require("@angular/common"); const light_template_component_1 = require("../../shared/components/light-template/light-template.component"); const dark_template_component_1 = require("../../shared/components/dark-template/dark-template.component"); @(0, core_1.Component)({ selector: 'app-campaign-create', templateUrl: './campaign-create.component.html', styleUrls: ['./campaign-create.component.scss'], standalone: true, imports: [ common_1.CurrencyPipe, forms_1.ReactiveFormsModule, forms_1.FormsModule, common_1.NgIf, common_1.NgFor, common_1.NgClass, common_1.DatePipe, common_1.TitleCasePipe, light_template_component_1.LightTemplateComponent, dark_template_component_1.DarkTemplateComponent, ], }) class CampaignCreateComponent { fb; apiService; authService; router; activatedRoute; toastrService; // Form campaignForm; formChanged = false; initialFormValue; // Products availableProducts = []; filteredProducts = []; paginatedProducts = []; // Products for current page selectedProductIds = new Set(); searchTerm = ''; showSelectedOnly = false; // Filters showAdvancedFilters = true; selectedCategory = ''; selectedVendor = ''; selectedRating = null; availableCategories = []; availableVendors = []; activeFiltersCount = 0; // Pagination currentPage = 1; itemsPerPage = 50; totalPages = 1; totalProducts = 0; Math = Math; // For using Math in template // Helper methods for template parseFloat = parseFloat; // Add this for use in the template // Categories selectedCategoryIds = []; // Samhita Shop Categories samhitaShopCategories = []; selectedSamhitaCategories = []; isLoadingCategories = false; // Component state isSubmitting = false; isLoading = false; // Add loading state campaignToEdit; // Template selection selectedTemplate = 'light'; // Default to light template showTemplateModal = false; showPreviewModal = false; // Add preview modal state previewTemplateId = ''; // Add preview template ID // Template options templateOptions = [ { id: 'light', name: 'Modern Light', description: 'Clean and bright design perfect for modern brands', preview: 'src/app/assets/test-output/modern-elegant.html', bgColor: '#ffffff', textColor: '#1a1a1a', }, { id: 'dark', name: 'Luxury Dark', description: 'Premium dark theme ideal for luxury products', preview: 'src/app/assets/test-output/luxury-premium.html', bgColor: '#1a1a1a', textColor: '#ffffff', }, ]; // Lifecycle destroy$ = new rxjs_1.Subject(); campaignId; categories; // Stepper properties currentStep = 1; // Customization panel showCustomizationPanel = false; constructor(fb, apiService, authService, router, activatedRoute, toastrService) { this.fb = fb; this.apiService = apiService; this.authService = authService; this.router = router; this.activatedRoute = activatedRoute; this.toastrService = toastrService; } ngOnInit() { this.initForm(); this.loadSamhitaShopCategories(); // this.getCategories(); this.loadProducts(); this.checkEditMode(); this.trackFormChanges(); } ngOnDestroy() { this.destroy$.next(); this.destroy$.complete(); } // Toggle advanced filters toggleAdvancedFilters() { this.showAdvancedFilters = !this.showAdvancedFilters; } // Filter by category filterByCategory(event) { const select = event.target; this.selectedCategory = select.value; this.updateActiveFiltersCount(); this.applyProductFilters(); this.resetPagination(); } // Filter by vendor filterByVendor(event) { const select = event.target; this.selectedVendor = select.value; this.updateActiveFiltersCount(); this.applyProductFilters(); this.resetPagination(); } // Filter by rating filterByRating(rating) { this.selectedRating = rating; this.updateActiveFiltersCount(); this.applyProductFilters(); this.resetPagination(); } // Clear rating filter clearRatingFilter() { this.selectedRating = null; this.updateActiveFiltersCount(); this.applyProductFilters(); this.resetPagination(); } // Update filters count updateActiveFiltersCount() { this.activeFiltersCount = 0; if (this.selectedCategory) this.activeFiltersCount++; if (this.selectedVendor) this.activeFiltersCount++; if (this.selectedRating !== null) this.activeFiltersCount++; } // Clear all filters clearAllFilters() { this.selectedCategory = ''; this.selectedVendor = ''; this.selectedRating = null; this.searchTerm = ''; this.activeFiltersCount = 0; this.showSelectedOnly = false; // Load products from scratch instead of filtering this.loadProductsPage(1); } // Pagination methods goToPage(page) { if (page < 1 || page > this.totalPages) return; this.currentPage = page; // Store current selection state to prevent unwanted form updates const currentSelections = new Set(this.selectedProductIds); // Call API with new page instead of just updating from local array this.loadProductsPage(page); // Restore selections after loading if in edit mode if (this.campaignId) { setTimeout(() => { this.selectedProductIds = currentSelections; }, 100); } } resetPagination() { this.currentPage = 1; this.calculateTotalPages(); this.loadProductsPage(1); } calculateTotalPages() { // Use totalProducts instead of filteredProducts.length for pagination this.totalPages = Math.ceil(this.totalProducts / this.itemsPerPage); // If we're filtering products, we need to recalculate based on filtered count if (this.searchTerm || this.showSelectedOnly || this.selectedCategory || this.selectedVendor || this.selectedRating !== null) { this.totalPages = Math.ceil(this.filteredProducts.length / this.itemsPerPage); } // Debug log console.log(`Pagination: totalProducts=${this.totalProducts}, filteredCount=${this.filteredProducts.length}, itemsPerPage=${this.itemsPerPage}, totalPages=${this.totalPages}, currentPage=${this.currentPage}`); } updatePaginatedProducts() { const startIndex = (this.currentPage - 1) * this.itemsPerPage; const endIndex = startIndex + this.itemsPerPage; this.paginatedProducts = this.filteredProducts.slice(startIndex, endIndex); } getPageNumbers() { const pageNumbers = []; const maxVisiblePages = 5; if (this.totalPages <= maxVisiblePages) { // Show all pages if there are less than maxVisiblePages for (let i = 1; i <= this.totalPages; i++) { pageNumbers.push(i); } } else { // Show a subset of pages let startPage = Math.max(1, this.currentPage - Math.floor(maxVisiblePages / 2)); let endPage = startPage + maxVisiblePages - 1; if (endPage > this.totalPages) { endPage = this.totalPages; startPage = Math.max(1, endPage - maxVisiblePages + 1); } for (let i = startPage; i <= endPage; i++) { pageNumbers.push(i); } } return pageNumbers; } // Get product category getProductCategory(product) { if (product.categoryName && product.categoryName.length > 0) { return product.categoryName[0] || ''; } return ''; } // Form initialization initForm() { this.campaignForm = this.fb.group({ campaignName: ['', [forms_1.Validators.required, forms_1.Validators.minLength(3)]], description: ['', [forms_1.Validators.required, forms_1.Validators.minLength(3)]], banner: [''], backgroundColor: ['#3b82f6'], isActive: [false], products: [[]], categories: [[]], template_id: [this.selectedTemplate], // Title customization controls - fixed sizes titleColor: ['#ffffff'], titleFontWeight: ['bold'], // Description customization controls - fixed sizes descriptionColor: ['#e2e8f0'], // Banner template and layout controls - simplified options bannerTemplate: ['centered'], // Button customization controls - fixed sizes showButton: [true], buttonText: ['Shop Now'], buttonBgColor: ['#3b82f6'], buttonTextColor: ['#ffffff'], buttonBorderRadius: [8], }); // Save initial form state for new campaign this.initialFormValue = { ...this.campaignForm.value }; this.formChanged = false; } // Check if we're in edit mode checkEditMode() { this.activatedRoute.queryParams .pipe((0, operators_1.takeUntil)(this.destroy$)) .subscribe((params) => { this.campaignId = params.campaignId; if (this.campaignId) { this.loadCampaign(); } }); } // Track form changes trackFormChanges() { this.campaignForm.valueChanges .pipe((0, operators_1.takeUntil)(this.destroy$), (0, operators_1.debounceTime)(300)) .subscribe(() => { if (this.initialFormValue) { this.formChanged = !this.isSameFormValue(this.campaignForm.value, this.initialFormValue); } }); } // Compare form values isSameFormValue(val1, val2) { // Check if the selected products count has changed if (this.selectedProductIds.size !== (this.initialFormValue?.products?.length || 0)) { return false; } // Simple comparison of primitive form values return (val1.campaignName === val2.campaignName && val1.description === val2.description && val1.banner === val2.banner && val1.isActive === val2.isActive && val1.titleColor === val2.titleColor && val1.titleFontWeight === val2.titleFontWeight && val1.descriptionColor === val2.descriptionColor && val1.bannerTemplate === val2.bannerTemplate && val1.buttonText === val2.buttonText && val1.buttonBgColor === val2.buttonBgColor && val1.buttonTextColor === val2.buttonTextColor && val1.buttonBorderRadius === val2.buttonBorderRadius && val1.showButton === val2.showButton); } // Load campaign data loadCampaign() { this.apiService .getCampaignById(this.campaignId) .pipe((0, operators_1.takeUntil)(this.destroy$)) .subscribe({ next: (campaign) => { this.campaignToEdit = campaign; this.patchFormWithCampaignData(); }, error: (error) => { console.error('Error loading campaign:', error); // Show error notification }, }); } // Update form with campaign data patchFormWithCampaignData() { if (!this.campaignToEdit) return; const campaignStyle = this.campaignToEdit.campaign_style; // Patch basic form fields this.campaignForm.patchValue({ campaignName: this.campaignToEdit.campaignName, description: this.campaignToEdit.description, banner: this.campaignToEdit.banner, isActive: this.campaignToEdit.isActive, template_id: this.campaignToEdit.template_id || 'light', // Default to light if not set // Title customization fields with defaults titleColor: campaignStyle.titleColor || '#1a1a1a', titleFontWeight: campaignStyle.titleFontWeight || 'bold', // Description customization fields with defaults descriptionColor: campaignStyle.descriptionColor || '#6b7280', // Banner template and layout fields with defaults bannerTemplate: campaignStyle.bannerTemplate || 'centered', // Button customization fields with defaults if not present showButton: campaignStyle.showButton !== undefined ? campaignStyle.showButton : true, buttonText: campaignStyle.buttonText || 'Shop Now', buttonBgColor: campaignStyle.buttonBgColor || '#3b82f6', buttonTextColor: campaignStyle.buttonTextColor || '#ffffff', buttonBorderRadius: campaignStyle.buttonBorderRadius || 8, }); // Update selected template this.selectedTemplate = this.campaignToEdit.template_id || 'light'; // Clear previous selections this.selectedProductIds.clear(); // Add products from campaign to selected set if (this.campaignToEdit.products && this.campaignToEdit.products.length > 0) { this.campaignToEdit.products.forEach((product) => { const productId = product.productId || product.id; if (productId) { this.selectedProductIds.add(productId); } }); // Update the products in the form value as well this.campaignForm.patchValue({ products: this.campaignToEdit.products, }); } // Set selected categories if they exist if (this.campaignToEdit.categories && this.campaignToEdit.categories.length > 0) { this.selectedCategoryIds = this.campaignToEdit.categories.map((cat) => cat._id); } // Set selected Samhita categories if they exist if (this.campaignToEdit.categories && this.campaignToEdit.categories.length > 0) { this.selectedSamhitaCategories = this.campaignToEdit.categories; } // Save initial form state this.initialFormValue = { ...this.campaignForm.value }; this.formChanged = false; } // Search products from API searchProducts() { if (!this.searchTerm.trim()) { // If search is empty, load regular products this.loadProductsPage(1); return; } this.isLoading = true; this.apiService .getSamhitaStore1ProductsBySearch(1, this.itemsPerPage, this.searchTerm.trim()) .pipe((0, operators_1.takeUntil)(this.destroy$)) .subscribe({ next: (products) => { this.availableProducts = products?.d?.products || []; this.totalProducts = products.d?.totalProducts || this.availableProducts.length; // Process products to normalize data this.availableProducts = this.processProducts(this.availableProducts); // Update category and vendor lists this.updateCategoriesAndVendors(); // Update filtered and paginated products this.filteredProducts = [...this.availableProducts]; this.paginatedProducts = [...this.availableProducts]; this.isLoading = false; this.calculateTotalPages(); }, error: (error) => { console.error('Error searching products:', error); this.isLoading = false; this.toastrService.error('Failed to search products', 'Error'); }, }); } // Clear search and reset to default products clearSearch() { this.searchTerm = ''; this.loadProductsPage(1); // If other filters are active, keep them applied if (this.showSelectedOnly || this.selectedCategory || this.selectedVendor || this.selectedRating !== null) { this.applyProductFilters(); } } // Helper method to process products and ensure consistent format processProducts(products) { return products.map((product) => { // Ensure product has an ID - if not, generate one if (!product.productId && product.id) { product.productId = product.id.toString(); } // Ensure product has a name if (!product.productName && product.name) { product.productName = product.name; } // Make sure we have the image URL // For Samhita store products, imgUrl might be a path needing a base URL if (product.imgUrl && product.imgUrl.startsWith('/')) { product.imgUrl = `https://cdnaz.plotch.io/image/upload/w_300,h_450${product.imgUrl}?product_id=${product.productId}&s=1&tf=vt`; } // For backward compatibility with older schema if (product.base_image && product.base_image.original_image_url && !product.imgUrl) { product.imgUrl = product.base_image.original_image_url; } // Normalize prices for consistency if (typeof product.regularPrice === 'undefined' && product.prices?.regular?.price) { product.regularPrice = parseFloat(product.prices.regular.price); } if (typeof product.discountedPrice === 'undefined' && product.prices?.final?.price) { product.discountedPrice = parseFloat(product.prices.final.price); } // Calculate discount percentage if not provided if (typeof product.discountPercentage === 'undefined' && product.regularPrice && product.discountedPrice && product.regularPrice > product.discountedPrice) { const discount = product.regularPrice - product.discountedPrice; product.discountPercentage = Math.round((discount / product.regularPrice) * 100); } // Normalize ratings if (typeof product.productRatings === 'undefined' && product.ratings?.average) { product.productRatings = parseFloat(product.ratings.average); } return product; }); } // Update categories and vendors from available products updateCategoriesAndVendors() { const categorySet = new Set(); const vendorSet = new Set(); this.availableProducts.forEach((product) => { if (product.categoryName && product.categoryName.length) { product.categoryName.forEach((category) => { if (category) { categorySet.add(category); } }); } if (product.vendorName) { vendorSet.add(product.vendorName); } }); this.availableCategories = Array.from(categorySet).sort(); this.availableVendors = Array.from(vendorSet).sort(); } // Method to load products with pagination parameters loadProductsPage(page) { // If we have active filters except search term, we'll do client-side pagination if (this.showSelectedOnly || this.selectedCategory || this.selectedVendor || this.selectedRating !== null) { this.updatePaginatedProducts(); return; } // If we have a search term, use the search API if (this.searchTerm.trim()) { this.isLoading = true; this.apiService .getSamhitaStore1ProductsBySearch(page, this.itemsPerPage, this.searchTerm.trim()) .pipe((0, operators_1.takeUntil)(this.destroy$)) .subscribe({ next: (products) => { this.availableProducts = products?.d?.products || []; this.totalProducts = products.d?.totalProducts || this.availableProducts.length; // Process products this.availableProducts = this.processProducts(this.availableProducts); // Update filtered and paginated products this.filteredProducts = [...this.availableProducts]; this.paginatedProducts = [...this.availableProducts]; this.isLoading = false; this.calculateTotalPages(); }, error: (error) => { console.error('Error loading products:', error); this.isLoading = false; }, }); return; } // Otherwise, use the regular API this.isLoading = true; this.apiService .getSamhitaStore1Products(page, this.itemsPerPage) .pipe((0, operators_1.takeUntil)(this.destroy$)) .subscribe({ next: (products) => { this.availableProducts = products?.d?.products || []; // Set total products from API response metadata this.totalProducts = products.d?.totalProducts || this.availableProducts.length; // Process products this.availableProducts = this.processProducts(this.availableProducts); // Update categories and vendors this.updateCategoriesAndVendors(); // With server-side pagination, the filtered products are the same as availableProducts this.filteredProducts = [...this.availableProducts]; this.paginatedProducts = [...this.availableProducts]; this.isLoading = false; this.calculateTotalPages(); }, error: (error) => { console.error('Error loading products:', error); this.isLoading = false; }, }); } // Load initial products loadProducts() { this.loadProductsPage(1); } // Filter products based on search term filterProducts(event) { const term = event ? event.target.value.toLowerCase() : this.searchTerm.toLowerCase(); this.searchTerm = term; this.applyProductFilters(); this.resetPagination(); } // Toggle selected products filter toggleSelectedFilter() { this.showSelectedOnly = !this.showSelectedOnly; this.applyProductFilters(); this.resetPagination(); } // Apply all filters to products applyProductFilters() { let filtered = [...this.availableProducts]; let isFiltering = false; // Apply search filter if (this.searchTerm) { isFiltering = true; filtered = filtered.filter((product) => (product.productName || product.name || '') .toLowerCase() .includes(this.searchTerm.toLowerCase()) || (product.brandName || '') .toLowerCase() .includes(this.searchTerm.toLowerCase())); } // Apply selected only filter if (this.showSelectedOnly) { isFiltering = true; filtered = filtered.filter((product) => this.selectedProductIds.has(product.productId || product.id || '')); } // Apply category filter if (this.selectedCategory) { isFiltering = true; filtered = filtered.filter((product) => product.categoryName && product.categoryName.some((cat) => cat === this.selectedCategory)); } // Apply vendor filter if (this.selectedVendor) { isFiltering = true; filtered = filtered.filter((product) => product.vendorName === this.selectedVendor); } // Apply rating filter if (this.selectedRating !== null) { isFiltering = true; filtered = filtered.filter((product) => { const rating = product.productRatings || (product.ratings ? parseFloat(product.ratings.average || '0') : 0); return rating >= this.selectedRating; }); } this.filteredProducts = filtered; // Always reset to page 1 when filters change this.currentPage = 1; this.calculateTotalPages(); this.updatePaginatedProducts(); } // Toggle product selection onProductToggle(event, product) { const isChecked = event.target.checked; const productId = product.productId || product.id || ''; if (isChecked) { this.selectedProductIds.add(productId); } else { this.selectedProductIds.delete(productId); } // Update form value and change status const selectedProducts = this.filteredProducts.filter((p) => this.selectedProductIds.has(p.productId || p.id || '')); this.campaignForm.patchValue({ products: selectedProducts }); // Force update of form changed status this.formChanged = this.selectedProductIds.size !== (this.initialFormValue?.products?.length || 0) || !this.isSameFormValue(this.campaignForm.value, this.initialFormValue); // Update filters if showing selected only if (this.showSelectedOnly) { this.applyProductFilters(); } } // Click on product item onProductItemClick(product) { const productId = product.productId || product.id || ''; const isSelected = this.selectedProductIds.has(productId); if (isSelected) { this.selectedProductIds.delete(productId); } else { this.selectedProductIds.add(productId); } // Update form value const selectedProducts = this.filteredProducts.filter((p) => this.selectedProductIds.has(p.productId || p.id || '')); this.campaignForm.patchValue({ products: selectedProducts }); // Force update of form changed status this.formChanged = this.selectedProductIds.size !== (this.initialFormValue?.products?.length || 0) || !this.isSameFormValue(this.campaignForm.value, this.initialFormValue); // Update filters if showing selected only if (this.showSelectedOnly) { this.applyProductFilters(); } } // Check if product is selected isProductSelected(product) { const productId = product.productId || product.id || ''; return this.selectedProductIds.has(productId); } // Open media library for banner selection openMediaLibrary() { this.toastrService.warning('Browse is not available currently', 'Warning'); } // Remove banner image removeBanner() { this.campaignForm.patchValue({ banner: '' }); } // Handle image load errors handleImageError(event) { const img = event.target; img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUkAAACZCAMAAACVHTgBAAAAMFBMVEW+vr6UlJS7u7u0tLSXl5fBwcGZmZmkpKS5ubmpqamdnZ2srKyvr6+3t7enp6eSkpIpnIygAAACpUlEQVR4nO3X25KjIBCAYRAaOWne/223GzQxs3O7SZX7f1WZKAcpehowzgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOA/tQzz6lp6XoUeFnm2W8bFq8Wi1fmtw+t5b12ehbcla1SpZrekeM5VSkzzOiTvfSwajDj4JsXrrcs+iZNu1X7VHrtvs289n6dNZpc+x4hp/coMP0VWX9c1aVyW5J9Zk3T+9p01TKFZMBYfq+nXSHbvS2jJr3KJpD2v+pStyegS5hhr1HZfmeNn6Cy7iNMoXnIyeI2HVVZfNPOCT27RjyjnipXNSFbt6+xfkK+R3MQCu0r2VUaXOYZsMX5rlp8wZmnzz69Ialmo4ybOohAsksdeV/y+5KzRlRHN0by9RdJZoKt9Zpc5hiwxfWWKH6KzLNtWor/ukylqvPpIvLOdru6kou6hc/uLSXO1juXa/P4zkk4Dn2eXJDrG2lobCX5fehrYoaFZ9YpkOJbmyKzDsU8mi2Td933VSPZj42v6/Wsk5z4p5xj15+C3MvOlZ3nlpB0Q+2rnjy1pK5mr+7JPip5ASbZjde9/r+5tru7nPlm2EOo4qm7r2CeVRnIWafqNFCp24rTfThx3nDjJB7GOeshYNEdvO3HsqfuPE8c9U/imbJbzSiPZeu8t64z1XXpsgsFHvU/jLSgV8/Y+2XzsWXOtjsO6G41k6X31mt/56NKPMW4fyccZyZmJj14fwe414Zy0UagnxeKnJOUxIvmIYnvmsf9psEbnpGk8mgVrMsuqjmFLPzzuvVFu4fkWOeUQjgr9nSJLLy3Lqza4PH8ejlaStXo0z2f1+DsOneUo2o4x9P7mPxgBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAf+4Pjk0UGusRbysAAAAASUVORK5CYII='; img.onerror = null; // Prevent infinite error loop } handleProductImageError(event) { const img = event.target; img.src = 'https://www.howmet.com/wp-content/themes/howmet/assets/build/images/placeholder-image.db2b4d5c.jpeg'; img.onerror = null; } // Check if form control has error hasError(controlName) { const control = this.campaignForm.get(controlName); return !!(control && control.invalid && (control.dirty || control.touched)); } // Submit form submit() { if (this.campaignForm.invalid || this.selectedProductIds.size === 0) return; this.isSubmitting = true; const selectedProducts = this.availableProducts.filter((product) => this.selectedProductIds.has(product.productId || product.id || '')); const selectedCategories = this.selectedSamhitaCategories; const payload = { ...(this.campaignId ? this.campaignToEdit : {}), ...this.campaignForm.value, products: selectedProducts, categories: selectedCategories, _id: this.campaignId ? this.campaignToEdit._id : undefined, createdAt: this.campaignId ? this.campaignToEdit.createdAt : new Date().toISOString(), __v: this.campaignId ? this.campaignToEdit.__v : 0, campaign_style: this.generateCampaignStyle(), }; const apiCall = this.campaignId ? this.apiService.updateCampaign(payload, this.campaignId) : this.apiService.createCampaign(payload); apiCall.subscribe({ next: (res) => { this.isSubmitting = false; this.formChanged = false; if (res?.message) this.toastrService.success(res?.message); // Navigate to campaigns list this.moveToDashboard(); }, error: (err) => { this.isSubmitting = false; console.error('Operation failed:', err); this.toastrService.error(err?.error?.message || 'Something went wrong', 'Failed'); }, }); } generateCampaignStyle() { return { // Title customization controls - fixed sizes titleColor: this.campaignForm.get('titleColor')?.value || '#ffffff', titleFontWeight: this.campaignForm.get('titleFontWeight')?.value || 'bold', // Description customization controls - fixed sizes descriptionColor: this.campaignForm.get('descriptionColor')?.value || '#e2e8f0', // Banner template and layout controls - simplified options bannerTemplate: this.campaignForm.get('bannerTemplate')?.value || 'centered', // Button customization controls - fixed sizes showButton: this.campaignForm.get('showButton')?.value !== false, buttonText: this.campaignForm.get('buttonText')?.value || 'Shop Now', buttonBgColor: this.campaignForm.get('buttonBgColor')?.value || '#3b82f6', buttonTextColor: this.campaignForm.get('buttonTextColor')?.value || '#ffffff', buttonBorderRadius: this.campaignForm.get('buttonBorderRadius')?.value || 8, }; } moveToDashboard() { this.router.navigate(['/dashboard']); } logout() { this.authService.logout(); } getCategories() { const categories = localStorage.getItem('categories'); if (categories && categories != 'undefined') { const parsedCategories = JSON.parse(categories); this.categories = parsedCategories; } else { this.apiService.getCategories().subscribe((res) => { this.categories = res.data .filter((item) => item.type === 'category') .map((item) => ({ ...item, image: item.category == 'agritech' ? 'src/app/assets/categories/Agritech.svg' : item.category == 'appliances' ? 'src/app/assets/categories/Appliances.svg' : item.category == 'beauty-and-personal-care' ? 'src/app/assets/categories/Beauty-Personal-Care.svg' : item.category == 'grocery' ? 'src/app/assets/categories/Grocery.svg' : item.category == 'food-and-beverages' ? 'src/app/assets/categories/Food-Beverages.svg' : item.category == 'fashion' ? 'src/app/assets/categories/Fashion.svg' : item.category == 'home-and-kitchen' ? 'src/app/assets/categories/Home-Decor.svg' : item.category == 'auto-components-and-accessories' ? 'src/app/assets/categories/Automotive.svg' : item.category == 'gift-card' ? 'src/app/assets/categories/Gift-Card.svg' : item.category == 'health-and-wellness' ? 'src/app/assets/categories/Health-Wellness.svg' : item.category == 'toys-and-games' ? 'src/app/assets/categories/ToysGames.svg' : item.category == 'electronics' ? 'src/app/assets/categories/Electronics.svg' : '', })); localStorage.setItem('categories', JSON.stringify(this.categories)); }); } console.log(this.categories); } // Get top attributes to display getTopAttributes(product) { if (!product.attrTag || !product.attrTag.length) { // If no attrTag, try to get attributes from groupAttributes if (product.groupAttributes) { const attributes = []; // Process the first 2 group attributes let count = 0; for (const group in product.groupAttributes) { if (count >= 2) break; // Limit to 2 attributes const groupData = product.groupAttributes[group]; for (const attrName in groupData) { if (count >= 2) break; // Limit to 2 attributes attributes.push({ code: attrName.toLowerCase(), value: groupData[attrName], }); count++; } } return attributes; } return []; } const attributeList = product.attrTag.find((tag) => tag.code === 'attribute')?.list || []; // Return the first 2 attributes for display return attributeList.slice(0, 2); } // View product details viewProductDetails(product) { // Implement product view details functionality console.log('View product details:', product); if (!product?.productName || !product?.productId) { this.toastrService.error('Product name or ID not found', 'Error'); return; } const productName = product.productName .toLowerCase() .replace(/[^a-z0-9\s-]/g, '') // Remove special chars except hyphen .replace(/\s+/g, '-') // Replace spaces with single hyphen .replace(/-+/g, '-') // Replace multiple hyphens with single hyphen .replace(/(\d+)\s*(kg|g|ml|l)\b/i, '$1$2'); // Join number and unit without space const url = `https://shop.samhita.org/product/${productName}/${product.productId}`; window.open(url, '_blank'); } // Category handling methods isCategorySelected(categoryId) { return this.selectedCategoryIds.includes(categoryId); } onCategoryToggle(event, categoryId) { const isChecked = event.target.checked; this.toggleCategorySelection(categoryId, isChecked); } toggleCategorySelection(categoryId, forcedState) { const isSelected = this.isCategorySelected(categoryId); const newState = forcedState !== undefined ? forcedState : !isSelected; if (newState && !isSelected) { this.selectedCategoryIds.push(categoryId); } else if (!newState && isSelected) { this.selectedCategoryIds = this.selectedCategoryIds.filter((id) => id !== categoryId); } // Update form value this.campaignForm.patchValue({ categories: this.categories.filter((cat) => this.selectedCategoryIds.includes(cat._id)), }); this.formChanged = true; } filterByItemsPerPage(event) { const selectedValue = event.target.value; if (selectedValue === 'All') { this.itemsPerPage = this.totalProducts; } else { this.itemsPerPage = parseInt(selectedValue); } this.loadProductsPage(1); } loadSamhitaShopCategories() { this.isLoadingCategories = true; this.apiService.getSamhitaShopCategory().subscribe({ next: (response) => { this.samhitaShopCategories = response.filtersData || []; this.isLoadingCategories = false; }, error: (error) => { console.error('Error loading Samhita shop categories:', error); this.isLoadingCategories = false; }, }); } // Samhita Shop Category handling methods isSamhitaCategorySelected(category) { return this.selectedSamhitaCategories.some((cat) => cat.filterItem === category.filterItem); } onSamhitaCategoryToggle(event, category) { event.stopPropagation(); const isChecked = event.target.checked; this.toggleSamhitaCategorySelection(category, isChecked); } toggleSamhitaCategorySelection(category, forcedState) { const isSelected = this.isSamhitaCategorySelected(category); const newState = forcedState !== undefined ? forcedState : !isSelected; if (newState && !isSelected) { this.selectedSamhitaCategories.push(category); } else if (!newState && isSelected) { this.selectedSamhitaCategories = this.selectedSamhitaCategories.filter((cat) => cat.filterItem !== category.filterItem); } this.formChanged = true; } onSamhitaCategoryClick(category) { this.toggleSamhitaCategorySelection(category); } // Template selection methods openTemplateModal() { this.showTemplateModal = true; } closeTemplateModal() { this.showTemplateModal = false; } selectTemplate(templateId) { this.selectedTemplate = templateId; this.campaignForm.patchValue({ template_id: templateId }); this.formChanged = true; this.closeTemplateModal(); } getCurrentTemplate() { return (this.templateOptions.find((template) => template.id === this.selectedTemplate) || this.templateOptions[0]); } // Preview modal methods openPreviewModal(templateId) { this.previewTemplateId = templateId; this.showPreviewModal = true; } closePreviewModal() { this.showPreviewModal = false; this.previewTemplateId = ''; } getPreviewTemplate() { return (this.templateOptions.find((template) => template.id === this.previewTemplateId) || this.templateOptions[0]); } selectTemplateFromPreview() { if (this.previewTemplateId) { this.selectTemplate(this.previewTemplateId); } this.closePreviewModal(); } // Stepper navigation methods goToStep(step) { if (step >= 1 && step <= 3) { this.currentStep = step; } } nextStep() { if (this.currentStep < 3) { this.currentStep++; } } previousStep() { if (this.currentStep > 1) { this.currentStep--; } } canProceedToNextStep() { switch (this.currentStep) { case 1: return !!(this.campaignForm.get('campaignName')?.valid && this.campaignForm.get('description')?.valid && this.campaignForm.get('banner')?.valid); case 2: return this.selectedSamhitaCategories.length > 0; case 3: return this.selectedProductIds.size > 0; default: return false; } } // Helper methods for UI tracking getTotalProductsFromCategories() { return this.selectedSamhitaCategories.reduce((total, category) => total + category.productCount, 0); } trackByCategory(index, category) { return category.filterItem; } trackByProduct(index, product) { return product.productId || product.id || index.toString(); } // Customization panel methods toggleCustomizationPanel() { this.showCustomizationPanel = !this.showCustomizationPanel; } selectBannerTemplate(template) { this.campaignForm.patchValue({ bannerTemplate: template, }); // Auto-adjust colors based on template const currentTitleColor = this.campaignForm.get('titleColor')?.value; const currentDescColor = this.campaignForm.get('descriptionColor')?.value; // For all templates, use light text by default if (currentTitleColor === '#1f2937' || !currentTitleColor || currentTitleColor === '#ffffff') { this.campaignForm.patchValue({ titleColor: '#ffffff' }); } if (currentDescColor === '#4b5563' || !currentDescColor || currentDescColor === '#e2e8f0') { this.campaignForm.patchValue({ descriptionColor: '#e2e8f0' }); } } // Fixed font size methods for campaign cards getTitleFontSize() { return '1.5rem'; // Fixed size for campaign cards } getDescriptionFontSize() { return '0.875rem'; // Fixed size for campaign cards } getButtonFontSize() { return '0.875rem'; // Fixed size for campaign cards } getButtonPadding() { return '0.5rem 1rem'; // Fixed padding for campaign cards } } exports.CampaignCreateComponent = CampaignCreateComponent;