ondc-campaign-sdk
Version:
[](https://www.npmjs.com/package/ondc-campaign-sdk) [](LICENSE) [ • 44.2 kB
JavaScript
"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;