From 8e3f14ac319ba2fbd72b73300a668095b3ac122c Mon Sep 17 00:00:00 2001 From: swoocn Date: Tue, 27 Feb 2024 12:41:03 -0500 Subject: [PATCH] Revisions to business configuration to prepare adding products; WIP. --- .../business-configuration.component.html | 59 ++- .../business-configuration.component.spec.ts | 47 +- .../business-configuration.component.ts | 413 +++++++++++++++--- 3 files changed, 407 insertions(+), 112 deletions(-) diff --git a/frontend/src/app/business/business-settings/business-configuration/business-configuration.component.html b/frontend/src/app/business/business-settings/business-configuration/business-configuration.component.html index 07ceaed3..35fe4977 100644 --- a/frontend/src/app/business/business-settings/business-configuration/business-configuration.component.html +++ b/frontend/src/app/business/business-settings/business-configuration/business-configuration.component.html @@ -1,30 +1,29 @@ -
-
- - - -
-
+
+ + + +
+
diff --git a/frontend/src/app/business/business-settings/business-configuration/business-configuration.component.spec.ts b/frontend/src/app/business/business-settings/business-configuration/business-configuration.component.spec.ts index 36561043..f314e7fa 100644 --- a/frontend/src/app/business/business-settings/business-configuration/business-configuration.component.spec.ts +++ b/frontend/src/app/business/business-settings/business-configuration/business-configuration.component.spec.ts @@ -1,5 +1,4 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { ReactiveFormsModule } from '@angular/forms'; import { BusinessConfigurationComponent } from './business-configuration.component'; describe('BusinessConfigurationComponent', () => { @@ -8,18 +7,12 @@ describe('BusinessConfigurationComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [ReactiveFormsModule] + imports: [BusinessConfigurationComponent] }).compileComponents(); fixture = TestBed.createComponent(BusinessConfigurationComponent); component = fixture.componentInstance; fixture.detectChanges(); - - component.businessConfigurationForm.setValue({ - menuEnabled: true, - orderEnabled: false, - paymentEnabled: true - }); }); it('should create', () => { @@ -27,10 +20,9 @@ describe('BusinessConfigurationComponent', () => { }); it('should initialize form with default values', () => { - expect(component.businessConfigurationForm).toBeDefined(); - expect(component.businessConfigurationForm.get('menuEnabled')?.value).toBe(true); - expect(component.businessConfigurationForm.get('orderEnabled')?.value).toBe(false); - expect(component.businessConfigurationForm.get('paymentEnabled')?.value).toBe(true); + expect(component.menuStatusLabel).toBe('on'); + expect(component.orderStatusLabel).toBe('off'); + expect(component.paymentStatusLabel).toBe('on'); }); it('should load toggle states and update form', () => { @@ -48,29 +40,28 @@ describe('BusinessConfigurationComponent', () => { }); it('should update toggle labels correctly', () => { - component.businessConfigurationForm.patchValue({ - orderEnabled: true, - paymentEnabled: false - }); + component.menuToggle.nativeElement.checked = true; + + component.orderToggleDiv.nativeElement.querySelector('input')!.checked = true; + component.paymentToggleDiv.nativeElement.querySelector('input')!.checked = false; component.updateToggleLabels(); - expect(component.menuStatusLabel.nativeElement.textContent).toEqual('on'); - expect(component.orderStatusLabel.nativeElement.textContent).toEqual('on'); - expect(component.paymentStatusLabel.nativeElement.textContent).toEqual('off'); + expect(component.menuStatusLabel).toEqual('on'); + expect(component.orderStatusLabel).toEqual('on'); + expect(component.paymentStatusLabel).toEqual('off'); }); - it('should hide appropriate sections when menuEnabled is false', () => { - component.businessConfigurationForm.patchValue({ - menuEnabled: false - }); + // it('should hide appropriate sections when menuEnabled is false', () => { + // component.menuToggle.nativeElement.checked = false; - component.loadToggleStates(); + // component.loadToggleStates(); + // fixture.detectChanges(); - expect(component.orderToggleDiv.nativeElement.classList.contains('hidden')).toBeTruthy(); - expect(component.paymentToggleDiv.nativeElement.classList.contains('hidden')).toBeTruthy(); - expect(component.floatingButtonSection.nativeElement.classList.contains('hidden')).toBeTruthy(); - }); + // expect(component.orderToggleDiv.nativeElement.classList.contains('hidden')).toBeTruthy(); + // expect(component.paymentToggleDiv.nativeElement.classList.contains('hidden')).toBeTruthy(); + // expect(component.floatingButtonSection.nativeElement.classList.contains('hidden')).toBeTruthy(); + // }); it('should call saveToggleStates on toggle change', () => { spyOn(component, 'saveToggleStates'); diff --git a/frontend/src/app/business/business-settings/business-configuration/business-configuration.component.ts b/frontend/src/app/business/business-settings/business-configuration/business-configuration.component.ts index 3a5815f2..cf9b5d83 100644 --- a/frontend/src/app/business/business-settings/business-configuration/business-configuration.component.ts +++ b/frontend/src/app/business/business-settings/business-configuration/business-configuration.component.ts @@ -1,37 +1,29 @@ -import { ChangeDetectionStrategy, Component, ElementRef, OnInit, ViewChild } from '@angular/core'; -import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { Component, AfterViewInit, ViewChild, ElementRef, ChangeDetectionStrategy } from '@angular/core'; @Component({ selector: 'app-business-configuration', standalone: true, - imports: [ReactiveFormsModule], templateUrl: './business-configuration.component.html', styleUrl: './business-configuration.component.scss', changeDetection: ChangeDetectionStrategy.OnPush }) -export class BusinessConfigurationComponent implements OnInit { - @ViewChild('menuToggleDiv') menuToggleDiv!: ElementRef; - @ViewChild('orderToggleDiv') orderToggleDiv!: ElementRef; - @ViewChild('paymentToggleDiv') paymentToggleDiv!: ElementRef; - @ViewChild('addItemButtonSection') addItemButtonSection!: ElementRef; - @ViewChild('floatingButtonSection') floatingButtonSection!: ElementRef; - @ViewChild('menuStatusLabel') menuStatusLabel!: ElementRef; - @ViewChild('orderStatusLabel') orderStatusLabel!: ElementRef; - @ViewChild('paymentStatusLabel') paymentStatusLabel!: ElementRef; - - businessConfigurationForm!: FormGroup; - - constructor(private formBuilder: FormBuilder) { } - - ngOnInit(): void { - this.businessConfigurationForm = this.formBuilder.group({ - menuEnabled: [true], - orderEnabled: [false], - paymentEnabled: [true] - }); +export class BusinessConfigurationComponent implements AfterViewInit { + @ViewChild('menuToggle') menuToggle!: ElementRef; + @ViewChild('orderToggleDiv') orderToggleDiv!: ElementRef; + @ViewChild('paymentToggleDiv') paymentToggleDiv!: ElementRef; + @ViewChild('addItemButtonSection') addItemButtonSection!: ElementRef; + @ViewChild('floatingButtonSection') floatingButtonSection!: ElementRef; + + menuStatusLabel: string = 'on'; + orderStatusLabel: string = 'off'; + paymentStatusLabel: string = 'on'; - this.loadToggleStates(); // Load toggle states on initialization + constructor() { } + + ngAfterViewInit(): void { + this.loadToggleStates(); + this.initializeToggles(); } /** @@ -52,6 +44,28 @@ export class BusinessConfigurationComponent implements OnInit { console.log('Loading toggle states...'); // Simulate fetching data from the backend // TODO: Make an API call to your backend to fetch saved states + const fetchedStates = { + menuEnabled: true, + orderEnabled: false, + paymentEnabled: true, + }; + + // Apply these states to your toggles + this.menuToggle.nativeElement.checked = fetchedStates.menuEnabled; + + if (this.orderToggleDiv.nativeElement) { + const orderToggleInput = this.orderToggleDiv.nativeElement.querySelector('input'); + if (orderToggleInput) { + orderToggleInput.checked = fetchedStates.orderEnabled; + } + } + + if (this.paymentToggleDiv.nativeElement) { + const paymentToggleInput = this.paymentToggleDiv.nativeElement.querySelector('input'); + if (paymentToggleInput) { + paymentToggleInput.checked = fetchedStates.paymentEnabled; + } + } // Update the UI based on these states this.updateToggleLabels(); @@ -66,33 +80,38 @@ export class BusinessConfigurationComponent implements OnInit { // Initial state update this.updateSliderAppearance(); - const menuEnabled = this.businessConfigurationForm.get('menuEnabled')?.value; - - if (this.orderToggleDiv && this.paymentToggleDiv && this.addItemButtonSection) { - if (menuEnabled) { - this.orderToggleDiv.nativeElement.classList.remove('hidden'); - this.paymentToggleDiv.nativeElement.classList.remove('hidden'); - this.addItemButtonSection.nativeElement.classList.remove('hidden'); - } else { - this.orderToggleDiv.nativeElement.classList.add('hidden'); - this.paymentToggleDiv.nativeElement.classList.add('hidden'); - this.addItemButtonSection.nativeElement.classList.add('hidden'); - } + console.log("menuToggle.nativeElement.checked: ", this.menuToggle.nativeElement.checked); + + if (this.menuToggle && this.menuToggle.nativeElement.checked) { + this.orderToggleDiv.nativeElement.classList.remove('hidden'); + this.paymentToggleDiv.nativeElement.classList.remove('hidden'); + } else { + this.orderToggleDiv.nativeElement.classList.add('hidden'); + this.paymentToggleDiv.nativeElement.classList.add('hidden'); + } + } + + updateToggleStates(): void { + // Handle the toggle logic for the menu checkbox + if (this.menuToggle.nativeElement.checked) { + // Show elements related to menu + this.orderToggleDiv.nativeElement.classList.remove('hidden'); + this.paymentToggleDiv.nativeElement.classList.remove('hidden'); + } else { + // Hide elements related to menu + this.orderToggleDiv.nativeElement.classList.add('hidden'); + this.paymentToggleDiv.nativeElement.classList.add('hidden'); } } /** - * Updates the visibility of the floating add item button based on the menu toggle state. - */ + * Updates the visibility of the floating add item button based on the menu toggle state. + */ updateFloatingButtonVisibility(): void { - const menuEnabled = this.businessConfigurationForm.get('menuEnabled')?.value; - - if (this.floatingButtonSection) { - if (menuEnabled) { - this.floatingButtonSection.nativeElement.classList.remove('hidden'); - } else { - this.floatingButtonSection.nativeElement.classList.add('hidden'); - } + if (this.menuToggle.nativeElement.checked) { + this.floatingButtonSection.nativeElement.classList.remove('hidden'); + } else { + this.floatingButtonSection.nativeElement.classList.add('hidden'); } } @@ -100,14 +119,18 @@ export class BusinessConfigurationComponent implements OnInit { * Updates the labels next to toggles to reflect their current state off/on. */ updateToggleLabels(): void { - const menuEnabled = this.businessConfigurationForm.get('menuEnabled')?.value; - const orderEnabled = this.businessConfigurationForm.get('orderEnabled')?.value; - const paymentEnabled = this.businessConfigurationForm.get('paymentEnabled')?.value; - - if (this.menuStatusLabel && this.orderStatusLabel && this.paymentStatusLabel) { - this.menuStatusLabel.nativeElement.textContent = menuEnabled ? 'on' : 'off'; - this.orderStatusLabel.nativeElement.textContent = orderEnabled ? 'on' : 'off'; - this.paymentStatusLabel.nativeElement.textContent = paymentEnabled ? 'on' : 'off'; + // Update label content based on checkbox state + if (this.menuToggle && this.orderToggleDiv && this.paymentToggleDiv) { + // Update menu toggle label + this.menuStatusLabel = this.menuToggle.nativeElement.checked ? 'on' : 'off'; + + // Update order toggle label + const orderToggleInput = this.orderToggleDiv.nativeElement.querySelector('input'); + this.orderStatusLabel = orderToggleInput ? (orderToggleInput.checked ? 'on' : 'off') : ''; + + // Update payment toggle label + const paymentToggleInput = this.paymentToggleDiv.nativeElement.querySelector('input'); + this.paymentStatusLabel = paymentToggleInput ? (paymentToggleInput.checked ? 'on' : 'off') : ''; } } @@ -132,8 +155,12 @@ export class BusinessConfigurationComponent implements OnInit { }); } + /** + * Utility function for toggle maangement. + */ onToggleChange(toggleId: string): void { if (toggleId === 'menu-toggle') { + this.initializeToggles(); this.updateFloatingButtonVisibility(); } this.updateSliderAppearance(); @@ -141,3 +168,281 @@ export class BusinessConfigurationComponent implements OnInit { this.saveToggleStates(); } } + +// // Updates the appearance of sliders to reflect their state. +// private updateSliderAppearance(): void { +// const toggles = document.querySelectorAll('.menu-settings__toggle input'); + +// toggles.forEach(toggle => { +// const slider = toggle.nextElementSibling; // Accurately select the slider span related to each toggle +// const sliderCircle = slider.querySelector('.menu-settings__slider:before'); // Assuming you want to target the pseudo-element (note: pseudo-elements cannot be directly manipulated via JS like this) + +// if (toggle.checked) { +// slider.classList.remove('menu-settings__slider--off'); +// } else { +// slider.classList.add('menu-settings__slider--off'); +// // If you have a specific class to indicate the "off" state that affects the appearance, toggle it here +// } +// }); +// } + +// import { CommonModule } from '@angular/common'; +// import { ChangeDetectionStrategy, Component, ElementRef, OnInit, ViewChild } from '@angular/core'; +// import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms'; + +// @Component({ +// selector: 'app-business-configuration', +// standalone: true, +// imports: [CommonModule, ReactiveFormsModule], +// templateUrl: './business-configuration.component.html', +// styleUrl: './business-configuration.component.scss', +// changeDetection: ChangeDetectionStrategy.OnPush +// }) + +// export class BusinessConfigurationComponent implements OnInit { +// @ViewChild('menuToggleDiv') menuToggleDiv!: ElementRef; +// @ViewChild('orderToggleDiv') orderToggleDiv!: ElementRef; +// @ViewChild('paymentToggleDiv') paymentToggleDiv!: ElementRef; +// @ViewChild('addItemButtonSection') addItemButtonSection!: ElementRef; +// @ViewChild('floatingButtonSection') floatingButtonSection!: ElementRef; +// @ViewChild('menuStatusLabel') menuStatusLabel!: ElementRef; +// @ViewChild('orderStatusLabel') orderStatusLabel!: ElementRef; +// @ViewChild('paymentStatusLabel') paymentStatusLabel!: ElementRef; + +// @ViewChild('itemsDisplayArea') itemsDisplayArea!: ElementRef; +// @ViewChild('addItemModal') addItemModal!: ElementRef; + +// businessProductsForm!: FormGroup; + +// menuEnabled: boolean = true; +// orderEnabled: boolean = false; +// paymentEnabled: boolean = true; + +// previewImageSrc: string | undefined; +// isPreviewImageVisible: boolean = false; + +// constructor(private formBuilder: FormBuilder) { } + +// ngOnInit(): void { +// this.businessProductsForm = this.formBuilder.group({ +// itemName: [''], +// itemPrice: [''], +// prepTime: [''], +// description: [''], +// }); + +// this.loadToggleStates(); // Load toggle states on initialization +// this.loadItems(); // Load items on initialization +// } + +// /** +// * Simulates saving the current states of toggle buttons. +// * Placeholder for backend API call. +// */ +// saveToggleStates(): void { +// // Placeholder for saving the current state of toggles to the backend +// console.log('Saving toggle states...'); +// // Make API call to the backend +// } + +// /** +// * Loads and applies the saved toggle states from the backend. +// */ +// loadToggleStates(): void { +// // Placeholder for loading saved toggle states from the backend +// console.log('Loading toggle states...'); +// // Simulate fetching data from the backend +// // TODO: Make an API call to your backend to fetch saved states + +// // Update the UI based on these states +// this.updateToggleLabels(); +// this.updateSliderAppearance(); +// this.updateFloatingButtonVisibility(); + +// // Initialize the toggles based on the menu setting +// this.initializeToggles(); +// } + +// initializeToggles(): void { +// // Initial state update +// this.updateSliderAppearance(); + +// const menuEnabled = this.menuEnabled; + +// if (this.orderToggleDiv && this.paymentToggleDiv && this.addItemButtonSection) { +// if (menuEnabled) { +// this.orderToggleDiv.nativeElement.classList.remove('hidden'); +// this.paymentToggleDiv.nativeElement.classList.remove('hidden'); +// this.addItemButtonSection.nativeElement.classList.remove('hidden'); +// } else { +// this.orderToggleDiv.nativeElement.classList.add('hidden'); +// this.paymentToggleDiv.nativeElement.classList.add('hidden'); +// this.addItemButtonSection.nativeElement.classList.add('hidden'); +// } +// } +// } + +// /** +// * Updates the visibility of the floating add item button based on the menu toggle state. +// */ +// updateFloatingButtonVisibility(): void { +// const menuEnabled = this.menuEnabled; + +// if (this.floatingButtonSection) { +// if (menuEnabled) { +// this.floatingButtonSection.nativeElement.classList.remove('hidden'); +// } else { +// this.floatingButtonSection.nativeElement.classList.add('hidden'); +// } +// } +// } + +// /** +// * Updates the labels next to toggles to reflect their current state off/on. +// */ +// updateToggleLabels(): void { +// const menuEnabled = this.menuEnabled; +// const orderEnabled = this.orderEnabled; +// const paymentEnabled = this.paymentEnabled; + +// if (this.menuStatusLabel && this.orderStatusLabel && this.paymentStatusLabel) { +// this.menuStatusLabel.nativeElement.textContent = menuEnabled ? 'on' : 'off'; +// this.orderStatusLabel.nativeElement.textContent = orderEnabled ? 'on' : 'off'; +// this.paymentStatusLabel.nativeElement.textContent = paymentEnabled ? 'on' : 'off'; +// } +// } + +// /** +// * Updates the appearance of sliders to reflect their state. +// */ +// updateSliderAppearance(): void { +// const toggles = document.querySelectorAll('.menu-settings__toggle input'); + +// toggles.forEach((toggle) => { +// if (toggle instanceof HTMLInputElement) { +// const slider = toggle.nextElementSibling as HTMLElement; // Accurately select the slider span related to each toggle + +// if (slider) { +// if (toggle.checked) { +// slider.classList.remove('menu-settings__slider--off'); +// } else { +// slider.classList.add('menu-settings__slider--off'); +// } +// } +// } +// }); +// } + +// onToggleChange(toggleId: string): void { +// if (toggleId === 'menu-toggle') { +// this.updateFloatingButtonVisibility(); +// } +// this.updateSliderAppearance(); +// this.updateToggleLabels(); +// this.saveToggleStates(); +// } + +// showModal(): void { +// const modal = this.addItemModal.nativeElement as HTMLElement; +// modal.style.display = 'block'; +// } + +// hideModal(event: Event): void { +// event.preventDefault(); +// const modal = this.addItemModal.nativeElement as HTMLElement; +// modal.style.display = 'none'; +// } + +// // Function to handle image file selection and display a preview +// handleImageUpload(event: any): void { +// const file = event.target.files[0]; +// const reader = new FileReader(); +// reader.onload = () => { +// this.previewImageSrc = reader.result as string; +// this.isPreviewImageVisible = true; +// }; +// reader.readAsDataURL(file); +// } + +// // Function to save items to localStorage +// saveItems(items: any[]): void { +// localStorage.setItem('items', JSON.stringify(items)); +// } + +// // Function to load items from localStorage and display them +// loadItems(): void { +// const storedItems = localStorage.getItem('items'); +// if (storedItems) { +// const items = JSON.parse(storedItems) || []; +// const itemsDisplayArea = this.itemsDisplayArea.nativeElement; +// itemsDisplayArea.innerHTML = ''; // Clear previous content +// items.forEach((item: any) => { +// this.addItemToDisplayArea(item); +// }); +// } +// this.adjustFloatingButtonPosition(); +// } + +// // Function to delete an item +// deleteItem(itemId: string): void { +// const storedItems = localStorage.getItem('items'); +// if (storedItems) { +// const items = JSON.parse(storedItems) || []; +// const updatedItems = items.filter((item: { id: string; }) => item.id !== itemId); +// localStorage.setItem('items', JSON.stringify(updatedItems)); +// this.loadItems(); // Reload items to update the display +// } +// this.adjustFloatingButtonPosition(); +// } + +// // Function to add an item to the display area +// addItemToDisplayArea(item: any): void { +// const itemsDisplayArea = this.itemsDisplayArea.nativeElement; +// const itemElement = document.createElement('div'); +// itemElement.classList.add('item'); +// itemElement.setAttribute('data-id', item.id); +// itemElement.innerHTML = ` +// ${item.itemName} +//
+//

${item.itemName}

+//

${item.itemDescription}

+// +//
`; +// itemsDisplayArea.appendChild(itemElement); +// } + +// // Function to adjust the floating button's position based on the items display area's height +// adjustFloatingButtonPosition(): void { +// const floatingButton = this.floatingButtonSection.nativeElement; +// const itemsDisplayArea = this.itemsDisplayArea.nativeElement; +// const displayAreaBottom = itemsDisplayArea.getBoundingClientRect().bottom; +// const viewportHeight = window.innerHeight; +// let newBottomPosition = viewportHeight - displayAreaBottom + -700; // Add a 20px offset from the bottom of the items display area + +// floatingButton.style.bottom = `${newBottomPosition}px`; +// } + +// clearPreviewImage(): void { +// this.previewImageSrc = undefined; +// this.isPreviewImageVisible = false; +// } + +// onModalConfirm(): void { +// const newItem = this.businessProductsForm.value; +// newItem.imagePreview = this.previewImageSrc; +// newItem.id = Date.now().toString(); + +// this.addItemToDisplayArea(newItem); + +// const storedItems = localStorage.getItem('items'); +// if (storedItems) { +// const items = JSON.parse(storedItems) || []; +// items.push(newItem); +// this.saveItems(items); +// this.businessProductsForm.reset(); +// this.previewImageSrc = ''; +// this.hideModal(new Event('click')); // Simulate click event to hide modal +// } +// this.adjustFloatingButtonPosition(); +// } +// }