diff --git a/apps/your-burguer/project.json b/apps/your-burguer/project.json index 23f6363..063ef0d 100644 --- a/apps/your-burguer/project.json +++ b/apps/your-burguer/project.json @@ -13,7 +13,7 @@ "outputPath": "dist/apps/your-burguer", "index": "apps/your-burguer/src/index.html", "browser": "apps/your-burguer/src/main.ts", - "polyfills": ["zone.js"], + "polyfills": [], "tsConfig": "apps/your-burguer/tsconfig.app.json", "assets": [ { diff --git a/apps/your-burguer/public/images/burguer-type/classic.png b/apps/your-burguer/public/images/burguer-type/classic.png new file mode 100644 index 0000000..420e5c6 Binary files /dev/null and b/apps/your-burguer/public/images/burguer-type/classic.png differ diff --git a/apps/your-burguer/public/images/burguer-type/smash.png b/apps/your-burguer/public/images/burguer-type/smash.png new file mode 100644 index 0000000..a8b3091 Binary files /dev/null and b/apps/your-burguer/public/images/burguer-type/smash.png differ diff --git a/apps/your-burguer/public/images/burguer-type/vegan.png b/apps/your-burguer/public/images/burguer-type/vegan.png new file mode 100644 index 0000000..20d6eee Binary files /dev/null and b/apps/your-burguer/public/images/burguer-type/vegan.png differ diff --git a/apps/your-burguer/public/images/delivery/delivery.png b/apps/your-burguer/public/images/delivery/delivery.png new file mode 100644 index 0000000..3e0b28f Binary files /dev/null and b/apps/your-burguer/public/images/delivery/delivery.png differ diff --git a/apps/your-burguer/public/images/delivery/in-site.png b/apps/your-burguer/public/images/delivery/in-site.png new file mode 100644 index 0000000..34699bd Binary files /dev/null and b/apps/your-burguer/public/images/delivery/in-site.png differ diff --git a/apps/your-burguer/public/images/delivery/pick-up.png b/apps/your-burguer/public/images/delivery/pick-up.png new file mode 100644 index 0000000..b69659e Binary files /dev/null and b/apps/your-burguer/public/images/delivery/pick-up.png differ diff --git a/apps/your-burguer/src/app/app.component.css b/apps/your-burguer/src/app/_pages/choice-assistant/choice-assistant.page.component.css similarity index 100% rename from apps/your-burguer/src/app/app.component.css rename to apps/your-burguer/src/app/_pages/choice-assistant/choice-assistant.page.component.css diff --git a/apps/your-burguer/src/app/_pages/choice-assistant/choice-assistant.page.component.html b/apps/your-burguer/src/app/_pages/choice-assistant/choice-assistant.page.component.html new file mode 100644 index 0000000..de0a7b0 --- /dev/null +++ b/apps/your-burguer/src/app/_pages/choice-assistant/choice-assistant.page.component.html @@ -0,0 +1,19 @@ +
+
+ +
 {{ customerPreferencesState.snapshot | json }} 
+
+ + +
\ No newline at end of file diff --git a/apps/your-burguer/src/app/_pages/choice-assistant/choice-assistant.page.component.spec.ts b/apps/your-burguer/src/app/_pages/choice-assistant/choice-assistant.page.component.spec.ts new file mode 100644 index 0000000..f47e865 --- /dev/null +++ b/apps/your-burguer/src/app/_pages/choice-assistant/choice-assistant.page.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ChoiceAssistantPageComponent } from './choice-assistant.page.component'; + +describe('ChoiceAssistantPageComponent', () => { + let component: ChoiceAssistantPageComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ChoiceAssistantPageComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(ChoiceAssistantPageComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/apps/your-burguer/src/app/_pages/choice-assistant/choice-assistant.page.component.ts b/apps/your-burguer/src/app/_pages/choice-assistant/choice-assistant.page.component.ts new file mode 100644 index 0000000..3a2465e --- /dev/null +++ b/apps/your-burguer/src/app/_pages/choice-assistant/choice-assistant.page.component.ts @@ -0,0 +1,18 @@ +import { Component, inject } from '@angular/core'; +import { SimpleChoicePickerComponent } from '@choice-assistant/infra/ui/simple-choice-picker/simple-choice-picker.component'; +import { RouterModule } from '@angular/router'; +import { WorkflowNavigator } from '@workflow/domain/workflow-navigator'; +import { CustomerPreferencesState } from '@choice-assistant/domain/preference/customer-preferences-state'; +import { JsonPipe } from '@angular/common'; + +@Component({ + selector: 'app-choice-assistant-page', + standalone: true, + imports: [RouterModule, SimpleChoicePickerComponent, JsonPipe], + templateUrl: './choice-assistant.page.component.html', + styleUrl: './choice-assistant.page.component.css', +}) +export class ChoiceAssistantPageComponent { + public navigator = inject(WorkflowNavigator); + public customerPreferencesState = inject(CustomerPreferencesState); +} diff --git a/apps/your-burguer/src/app/_pages/choice-assistant/steps/_utils/map-ui-choices.ts b/apps/your-burguer/src/app/_pages/choice-assistant/steps/_utils/map-ui-choices.ts new file mode 100644 index 0000000..a9947c6 --- /dev/null +++ b/apps/your-burguer/src/app/_pages/choice-assistant/steps/_utils/map-ui-choices.ts @@ -0,0 +1,12 @@ +import { CustomerPreference } from '@choice-assistant/domain/preference/customer-preference'; +import { SimpleChoice } from '@choice-assistant/infra/ui/simple-choice-picker/simple-choice-picker.component'; + +export function mapToUiChoices( + preferences: CustomerPreference[] +): SimpleChoice[] { + return preferences.map((preference) => ({ + value: preference.name, + displayText: preference.name, + icon: 'images/burguer-type/classic.png', + })); +} diff --git a/apps/your-burguer/src/app/_pages/choice-assistant/steps/burguer-type.ts b/apps/your-burguer/src/app/_pages/choice-assistant/steps/burguer-type.ts new file mode 100644 index 0000000..e69de29 diff --git a/apps/your-burguer/src/app/_pages/choice-assistant/steps/burguer-type/adapter.ts b/apps/your-burguer/src/app/_pages/choice-assistant/steps/burguer-type/adapter.ts new file mode 100644 index 0000000..42eefde --- /dev/null +++ b/apps/your-burguer/src/app/_pages/choice-assistant/steps/burguer-type/adapter.ts @@ -0,0 +1,29 @@ +import { BurguerType } from '@choice-assistant/domain/preference/burguer-type/burguer-type'; +import { SimpleChoiceConfig } from '@choice-assistant/infra/ui/simple-choice-picker/simple-choice-picker.component'; + +export const BURGUER_TYPE_ICON_MAP = new Map([ + [BurguerType.CLASSIC, 'images/burguer-type/classic.png'], + [BurguerType.SMASH, 'images/burguer-type/smash.png'], + [BurguerType.VEGAN, 'images/burguer-type/vegan.png'], +]); + +export const BURGUER_TYPE_CHOICE_CONFIG: SimpleChoiceConfig = { + choices: [ + { + value: BurguerType.CLASSIC, + displayText: BurguerType.CLASSIC, + icon: BURGUER_TYPE_ICON_MAP.get(BurguerType.CLASSIC)!, + }, + { + value: BurguerType.SMASH, + displayText: BurguerType.SMASH, + icon: BURGUER_TYPE_ICON_MAP.get(BurguerType.SMASH)!, + }, + { + value: BurguerType.VEGAN, + displayText: BurguerType.VEGAN, + icon: BURGUER_TYPE_ICON_MAP.get(BurguerType.VEGAN)!, + }, + ], + default: '', +}; diff --git a/apps/your-burguer/src/app/_pages/choice-assistant/steps/burguer-type/burguer-type-step.component.css b/apps/your-burguer/src/app/_pages/choice-assistant/steps/burguer-type/burguer-type-step.component.css new file mode 100644 index 0000000..e69de29 diff --git a/apps/your-burguer/src/app/_pages/choice-assistant/steps/burguer-type/burguer-type-step.component.html b/apps/your-burguer/src/app/_pages/choice-assistant/steps/burguer-type/burguer-type-step.component.html new file mode 100644 index 0000000..013c946 --- /dev/null +++ b/apps/your-burguer/src/app/_pages/choice-assistant/steps/burguer-type/burguer-type-step.component.html @@ -0,0 +1,2 @@ + \ No newline at end of file diff --git a/apps/your-burguer/src/app/_pages/choice-assistant/steps/burguer-type/burguer-type-step.component.spec.ts b/apps/your-burguer/src/app/_pages/choice-assistant/steps/burguer-type/burguer-type-step.component.spec.ts new file mode 100644 index 0000000..ce0a19d --- /dev/null +++ b/apps/your-burguer/src/app/_pages/choice-assistant/steps/burguer-type/burguer-type-step.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { BurguerTypeStepComponent } from './burguer-type-step.component'; + +describe('BurguerTypeStepComponent', () => { + let component: BurguerTypeStepComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [BurguerTypeStepComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(BurguerTypeStepComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/apps/your-burguer/src/app/_pages/choice-assistant/steps/burguer-type/burguer-type-step.component.ts b/apps/your-burguer/src/app/_pages/choice-assistant/steps/burguer-type/burguer-type-step.component.ts new file mode 100644 index 0000000..c3c1a33 --- /dev/null +++ b/apps/your-burguer/src/app/_pages/choice-assistant/steps/burguer-type/burguer-type-step.component.ts @@ -0,0 +1,26 @@ +import { Component, inject } from '@angular/core'; +import { BURGUER_TYPE_CHOICE_CONFIG } from './adapter'; +import { + SimpleChoice, + SimpleChoicePickerComponent, +} from '@choice-assistant/infra/ui/simple-choice-picker/simple-choice-picker.component'; +import { CustomerPreferencesState } from '@choice-assistant/domain/preference/customer-preferences-state'; +import { BurguerType } from '@choice-assistant/domain/preference/burguer-type/burguer-type'; + +@Component({ + selector: 'app-burguer-type-step', + standalone: true, + imports: [SimpleChoicePickerComponent], + templateUrl: './burguer-type-step.component.html', + styleUrl: './burguer-type-step.component.css', +}) +export class BurguerTypeStepComponent { + private readonly customerPreferencesState = inject(CustomerPreferencesState); + config = BURGUER_TYPE_CHOICE_CONFIG; + + onChoiceChanged(choice: SimpleChoice) { + this.customerPreferencesState.patch({ + burguerType: choice.value as BurguerType, + }); + } +} diff --git a/apps/your-burguer/src/app/_pages/choice-assistant/steps/delivery/adapter.ts b/apps/your-burguer/src/app/_pages/choice-assistant/steps/delivery/adapter.ts new file mode 100644 index 0000000..88d0fc6 --- /dev/null +++ b/apps/your-burguer/src/app/_pages/choice-assistant/steps/delivery/adapter.ts @@ -0,0 +1,29 @@ +import { Delivery } from '@choice-assistant/domain/preference/delivery/delivery'; +import { SimpleChoiceConfig } from '@choice-assistant/infra/ui/simple-choice-picker/simple-choice-picker.component'; + +export const DELIVERY_ICON_MAP = new Map([ + [Delivery.IN_SITE, 'images/delivery/in-site.png'], + [Delivery.PICK_UP, 'images/delivery/pick-up.png'], + [Delivery.DELIVERY, 'images/delivery/delivery.png'], +]); + +export const DELIVERY_CHOICE_CONFIG: SimpleChoiceConfig = { + choices: [ + { + value: Delivery.IN_SITE, + displayText: Delivery.IN_SITE, + icon: DELIVERY_ICON_MAP.get(Delivery.IN_SITE)!, + }, + { + value: Delivery.PICK_UP, + displayText: Delivery.PICK_UP, + icon: DELIVERY_ICON_MAP.get(Delivery.PICK_UP)!, + }, + { + value: Delivery.DELIVERY, + displayText: Delivery.DELIVERY, + icon: DELIVERY_ICON_MAP.get(Delivery.DELIVERY)!, + }, + ], + default: '', +}; diff --git a/apps/your-burguer/src/app/_pages/choice-assistant/steps/delivery/delivery-step.component.css b/apps/your-burguer/src/app/_pages/choice-assistant/steps/delivery/delivery-step.component.css new file mode 100644 index 0000000..e69de29 diff --git a/apps/your-burguer/src/app/_pages/choice-assistant/steps/delivery/delivery-step.component.html b/apps/your-burguer/src/app/_pages/choice-assistant/steps/delivery/delivery-step.component.html new file mode 100644 index 0000000..7287c3e --- /dev/null +++ b/apps/your-burguer/src/app/_pages/choice-assistant/steps/delivery/delivery-step.component.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/your-burguer/src/app/_pages/choice-assistant/steps/delivery/delivery-step.component.spec.ts b/apps/your-burguer/src/app/_pages/choice-assistant/steps/delivery/delivery-step.component.spec.ts new file mode 100644 index 0000000..ff020b9 --- /dev/null +++ b/apps/your-burguer/src/app/_pages/choice-assistant/steps/delivery/delivery-step.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { DeliveryStepComponent } from './delivery-step.component'; + +describe('DeliveryStepComponent', () => { + let component: DeliveryStepComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [DeliveryStepComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(DeliveryStepComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/apps/your-burguer/src/app/_pages/choice-assistant/steps/delivery/delivery-step.component.ts b/apps/your-burguer/src/app/_pages/choice-assistant/steps/delivery/delivery-step.component.ts new file mode 100644 index 0000000..639ffba --- /dev/null +++ b/apps/your-burguer/src/app/_pages/choice-assistant/steps/delivery/delivery-step.component.ts @@ -0,0 +1,28 @@ +import { Component, inject } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { DELIVERY_CHOICE_CONFIG } from './adapter'; +import { + SimpleChoice, + SimpleChoicePickerComponent, +} from '@choice-assistant/infra/ui/simple-choice-picker/simple-choice-picker.component'; +import { CustomerPreferencesState } from '@choice-assistant/domain/preference/customer-preferences-state'; +import { Delivery } from '@choice-assistant/domain/preference/delivery/delivery'; + +@Component({ + selector: 'app-delivery-step', + standalone: true, + imports: [CommonModule, SimpleChoicePickerComponent], + templateUrl: './delivery-step.component.html', + styleUrl: './delivery-step.component.css', +}) +export class DeliveryStepComponent { + private readonly customerPreferencesState = inject(CustomerPreferencesState); + + config = DELIVERY_CHOICE_CONFIG; + + onChoiceChanged(choice: SimpleChoice) { + this.customerPreferencesState.patch({ + delivery: choice.value as Delivery, + }); + } +} diff --git a/apps/your-burguer/src/app/app.component.html b/apps/your-burguer/src/app/app.component.html deleted file mode 100644 index 0f4018b..0000000 --- a/apps/your-burguer/src/app/app.component.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/apps/your-burguer/src/app/app.component.spec.ts b/apps/your-burguer/src/app/app.component.spec.ts deleted file mode 100644 index c3174f4..0000000 --- a/apps/your-burguer/src/app/app.component.spec.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { TestBed } from '@angular/core/testing'; -import { AppComponent } from './app.component'; -import { NxWelcomeComponent } from './nx-welcome.component'; -import { RouterModule } from '@angular/router'; - -describe('AppComponent', () => { - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [AppComponent, NxWelcomeComponent, RouterModule.forRoot([])], - }).compileComponents(); - }); - - it('should render title', () => { - const fixture = TestBed.createComponent(AppComponent); - fixture.detectChanges(); - const compiled = fixture.nativeElement as HTMLElement; - expect(compiled.querySelector('h1')?.textContent).toContain( - 'Welcome your-burguer' - ); - }); - - it(`should have as title 'your-burguer'`, () => { - const fixture = TestBed.createComponent(AppComponent); - const app = fixture.componentInstance; - expect(app.title).toEqual('your-burguer'); - }); -}); diff --git a/apps/your-burguer/src/app/app.component.ts b/apps/your-burguer/src/app/app.component.ts index 791cb2a..bbb26c8 100644 --- a/apps/your-burguer/src/app/app.component.ts +++ b/apps/your-burguer/src/app/app.component.ts @@ -1,14 +1,10 @@ import { Component } from '@angular/core'; -import { RouterModule } from '@angular/router'; -import { NxWelcomeComponent } from './nx-welcome.component'; +import { ShellComponent } from './shell/shell.component'; @Component({ standalone: true, - imports: [NxWelcomeComponent, RouterModule], + imports: [ShellComponent], selector: 'app-root', - templateUrl: './app.component.html', - styleUrl: './app.component.css', + template: ``, }) -export class AppComponent { - title = 'your-burguer'; -} +export class AppComponent {} diff --git a/apps/your-burguer/src/app/app.config.ts b/apps/your-burguer/src/app/app.config.ts index bc2fc3c..5b63dc4 100644 --- a/apps/your-burguer/src/app/app.config.ts +++ b/apps/your-burguer/src/app/app.config.ts @@ -1,10 +1,20 @@ -import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; +import { + ApplicationConfig, + importProvidersFrom, + provideExperimentalZonelessChangeDetection, +} from '@angular/core'; import { provideRouter } from '@angular/router'; import { appRoutes } from './app.routes'; +import { WorkflowModule } from '@workflow/workflow.module'; +import { ChoiceAssistantModule } from '@choice-assistant/choice-assistant.module'; export const appConfig: ApplicationConfig = { providers: [ - provideZoneChangeDetection({ eventCoalescing: true }), + provideExperimentalZonelessChangeDetection(), provideRouter(appRoutes), + importProvidersFrom( + WorkflowModule.forRoot(), + ChoiceAssistantModule.forRoot() + ), ], }; diff --git a/apps/your-burguer/src/app/app.routes.ts b/apps/your-burguer/src/app/app.routes.ts index 8762dfe..18dffaf 100644 --- a/apps/your-burguer/src/app/app.routes.ts +++ b/apps/your-burguer/src/app/app.routes.ts @@ -1,3 +1,32 @@ import { Route } from '@angular/router'; -export const appRoutes: Route[] = []; +export const appRoutes: Route[] = [ + { + path: '', + redirectTo: 'choice-assistant/burguer-type', + pathMatch: 'full', + }, + { + path: 'choice-assistant', + loadComponent: () => + import('./_pages/choice-assistant/choice-assistant.page.component').then( + (c) => c.ChoiceAssistantPageComponent + ), + children: [ + { + path: 'burguer-type', + loadComponent: () => + import( + './_pages/choice-assistant/steps/burguer-type/burguer-type-step.component' + ).then((c) => c.BurguerTypeStepComponent), + }, + { + path: 'delivery', + loadComponent: () => + import( + './_pages/choice-assistant/steps/delivery/delivery-step.component' + ).then((c) => c.DeliveryStepComponent), + }, + ], + }, +]; diff --git a/apps/your-burguer/src/app/choice-assistant/choice-assistant.module.ts b/apps/your-burguer/src/app/choice-assistant/choice-assistant.module.ts new file mode 100644 index 0000000..7dbe936 --- /dev/null +++ b/apps/your-burguer/src/app/choice-assistant/choice-assistant.module.ts @@ -0,0 +1,12 @@ +import { ModuleWithProviders, NgModule } from '@angular/core'; +import { CustomerPreferencesState } from './domain/preference/customer-preferences-state'; + +@NgModule() +export class ChoiceAssistantModule { + static forRoot(): ModuleWithProviders { + return { + ngModule: ChoiceAssistantModule, + providers: [CustomerPreferencesState], + }; + } +} diff --git a/apps/your-burguer/src/app/choice-assistant/domain/choice-assistant.ts b/apps/your-burguer/src/app/choice-assistant/domain/choice-assistant.ts new file mode 100644 index 0000000..cfe99f8 --- /dev/null +++ b/apps/your-burguer/src/app/choice-assistant/domain/choice-assistant.ts @@ -0,0 +1,10 @@ +import { Choice } from './choice'; + +export class ChoiceAssistant { + async getChoice(): Promise { + return { + id: 'uuid', + burguer: 'GOIKO SMASH', + }; + } +} diff --git a/apps/your-burguer/src/app/choice-assistant/domain/choice.ts b/apps/your-burguer/src/app/choice-assistant/domain/choice.ts new file mode 100644 index 0000000..c442247 --- /dev/null +++ b/apps/your-burguer/src/app/choice-assistant/domain/choice.ts @@ -0,0 +1,4 @@ +export interface Choice { + id: string; + burguer: string; +} diff --git a/apps/your-burguer/src/app/choice-assistant/domain/preference/burguer-type/burguer-type-choices.ts b/apps/your-burguer/src/app/choice-assistant/domain/preference/burguer-type/burguer-type-choices.ts new file mode 100644 index 0000000..2863ba9 --- /dev/null +++ b/apps/your-burguer/src/app/choice-assistant/domain/preference/burguer-type/burguer-type-choices.ts @@ -0,0 +1,21 @@ +import { CustomerPreference } from '../customer-preference'; +import { PreferenceSegment } from '../preference-segment'; +import { BurguerType } from './burguer-type'; + +export const BURGUER_TYPE_CHOICES: CustomerPreference< + PreferenceSegment.BURGUER_TYPE, + BurguerType +>[] = [ + { + name: BurguerType.CLASSIC, + segment: PreferenceSegment.BURGUER_TYPE, + }, + { + name: BurguerType.SMASH, + segment: PreferenceSegment.BURGUER_TYPE, + }, + { + name: BurguerType.VEGAN, + segment: PreferenceSegment.BURGUER_TYPE, + }, +]; diff --git a/apps/your-burguer/src/app/choice-assistant/domain/preference/burguer-type/burguer-type.ts b/apps/your-burguer/src/app/choice-assistant/domain/preference/burguer-type/burguer-type.ts new file mode 100644 index 0000000..2cefa21 --- /dev/null +++ b/apps/your-burguer/src/app/choice-assistant/domain/preference/burguer-type/burguer-type.ts @@ -0,0 +1,5 @@ +export enum BurguerType { + CLASSIC = 'CLASSIC', + SMASH = 'SMASH', + VEGAN = 'VEGAN', +} diff --git a/apps/your-burguer/src/app/choice-assistant/domain/preference/customer-preference.ts b/apps/your-burguer/src/app/choice-assistant/domain/preference/customer-preference.ts new file mode 100644 index 0000000..83a00ad --- /dev/null +++ b/apps/your-burguer/src/app/choice-assistant/domain/preference/customer-preference.ts @@ -0,0 +1,9 @@ +import { PreferenceSegment } from './preference-segment'; + +export interface CustomerPreference< + Segment extends PreferenceSegment, + Choice extends string +> { + name: Choice; + segment: Segment; +} diff --git a/apps/your-burguer/src/app/choice-assistant/domain/preference/customer-preferences-state.ts b/apps/your-burguer/src/app/choice-assistant/domain/preference/customer-preferences-state.ts new file mode 100644 index 0000000..92e02fc --- /dev/null +++ b/apps/your-burguer/src/app/choice-assistant/domain/preference/customer-preferences-state.ts @@ -0,0 +1,43 @@ +import { BurguerType } from './burguer-type/burguer-type'; +import { Delivery } from './delivery/delivery'; +import { Garnish } from './garnish/garnish'; +import { Highlights } from './highlights/highlights'; +import { Intolerances } from './intolerances/intolerances'; +import { Mode } from './mode/mode'; +import { Pricing } from './pricing/pricing'; +import { SiteType } from './site-type/site-type'; + +export interface CustomerPreferencesProps { + burguerType?: BurguerType; + delivery?: Delivery; + pricing?: Pricing; + siteType?: SiteType; + intolerances?: Intolerances; + highlights?: Highlights; + garnish?: Garnish; + mode?: Mode; + location?: { + street?: string; + latitude?: number; + longitude?: number; + altitude?: number; + radius?: number; + }; +} + +const DEFAULT_CUSTOMER_PREFERENCES: CustomerPreferencesProps = {}; + +export class CustomerPreferencesState { + private state: CustomerPreferencesProps = DEFAULT_CUSTOMER_PREFERENCES; + + get snapshot() { + return this.state; + } + + patch(preferences: Partial) { + this.state = { + ...this.state, + ...preferences, + }; + } +} diff --git a/apps/your-burguer/src/app/choice-assistant/domain/preference/delivery/delivery-choices.ts b/apps/your-burguer/src/app/choice-assistant/domain/preference/delivery/delivery-choices.ts new file mode 100644 index 0000000..6f24a7e --- /dev/null +++ b/apps/your-burguer/src/app/choice-assistant/domain/preference/delivery/delivery-choices.ts @@ -0,0 +1,21 @@ +import { CustomerPreference } from '../customer-preference'; +import { PreferenceSegment } from '../preference-segment'; +import { Delivery } from './delivery'; + +export const DELIVERY_CHOICES: CustomerPreference< + PreferenceSegment.DELIVERY, + Delivery +>[] = [ + { + name: Delivery.IN_SITE, + segment: PreferenceSegment.DELIVERY, + }, + { + name: Delivery.PICK_UP, + segment: PreferenceSegment.DELIVERY, + }, + { + name: Delivery.DELIVERY, + segment: PreferenceSegment.DELIVERY, + }, +]; diff --git a/apps/your-burguer/src/app/choice-assistant/domain/preference/delivery/delivery.ts b/apps/your-burguer/src/app/choice-assistant/domain/preference/delivery/delivery.ts new file mode 100644 index 0000000..3feba1c --- /dev/null +++ b/apps/your-burguer/src/app/choice-assistant/domain/preference/delivery/delivery.ts @@ -0,0 +1,5 @@ +export enum Delivery { + IN_SITE = 'IN_SITE', + PICK_UP = 'PICK_UP', + DELIVERY = 'DELIVERY', +} diff --git a/apps/your-burguer/src/app/choice-assistant/domain/preference/garnish/garnish.ts b/apps/your-burguer/src/app/choice-assistant/domain/preference/garnish/garnish.ts new file mode 100644 index 0000000..c4be7e0 --- /dev/null +++ b/apps/your-burguer/src/app/choice-assistant/domain/preference/garnish/garnish.ts @@ -0,0 +1,7 @@ +export enum Garnish { + NONE = 'NONE', + REGULAR_POTATOES = 'REGULAR_POTATOES', + WEDGES_POTATOES = 'WEDGES_POTATOES', + SWEET_POTATOES = 'SWEET_POTATOES', + SALAD = 'SALAD', +} diff --git a/apps/your-burguer/src/app/choice-assistant/domain/preference/highlights/highlights.ts b/apps/your-burguer/src/app/choice-assistant/domain/preference/highlights/highlights.ts new file mode 100644 index 0000000..ec97ded --- /dev/null +++ b/apps/your-burguer/src/app/choice-assistant/domain/preference/highlights/highlights.ts @@ -0,0 +1,6 @@ +export enum Highlights { + NONE = 'NONE', + CHEESE = 'CHEESE', + SAUCE = 'SAUCE', + VEGETABLES = 'VEGETABLES', +} diff --git a/apps/your-burguer/src/app/choice-assistant/domain/preference/intolerances/intolerances.ts b/apps/your-burguer/src/app/choice-assistant/domain/preference/intolerances/intolerances.ts new file mode 100644 index 0000000..7201c8f --- /dev/null +++ b/apps/your-burguer/src/app/choice-assistant/domain/preference/intolerances/intolerances.ts @@ -0,0 +1,6 @@ +export enum Intolerances { + NONE = 'NONE', + GLUTEN = 'GLUTEN', + LACTOSE = 'LACTOSE', + OTHERS = 'OTHERS', +} diff --git a/apps/your-burguer/src/app/choice-assistant/domain/preference/mode/mode.ts b/apps/your-burguer/src/app/choice-assistant/domain/preference/mode/mode.ts new file mode 100644 index 0000000..6d869ad --- /dev/null +++ b/apps/your-burguer/src/app/choice-assistant/domain/preference/mode/mode.ts @@ -0,0 +1,4 @@ +export enum Mode { + PREFERENCE = 'PREFERENCE', + TRY_OUT = 'TRY_OUT', +} diff --git a/apps/your-burguer/src/app/choice-assistant/domain/preference/preference-segment.ts b/apps/your-burguer/src/app/choice-assistant/domain/preference/preference-segment.ts new file mode 100644 index 0000000..8fd2c97 --- /dev/null +++ b/apps/your-burguer/src/app/choice-assistant/domain/preference/preference-segment.ts @@ -0,0 +1,11 @@ +export enum PreferenceSegment { + BURGUER_TYPE = 'BURGUER_TYPE', + DELIVERY = 'DELIVERY', + LOCATION = 'LOCATION', + PRICING = 'PRICING', + SITE_TYPE = 'SITE_TYPE', + INTOLERANCES = 'INTOLERANCES', + HIGHLIGHTS = 'HIGHLIGHTS', + GARNISH = 'GARNISH', + MODE = 'MODE', +} diff --git a/apps/your-burguer/src/app/choice-assistant/domain/preference/pricing/pricing-choices.ts b/apps/your-burguer/src/app/choice-assistant/domain/preference/pricing/pricing-choices.ts new file mode 100644 index 0000000..b8a1d45 --- /dev/null +++ b/apps/your-burguer/src/app/choice-assistant/domain/preference/pricing/pricing-choices.ts @@ -0,0 +1,21 @@ +import { CustomerPreference } from '../customer-preference'; +import { PreferenceSegment } from '../preference-segment'; +import { Pricing } from './pricing'; + +export const PRICING_CHOICES: CustomerPreference< + PreferenceSegment.PRICING, + Pricing +>[] = [ + { + name: Pricing.LOW_COST, + segment: PreferenceSegment.PRICING, + }, + { + name: Pricing.REGULAR, + segment: PreferenceSegment.PRICING, + }, + { + name: Pricing.EXPENSIVE, + segment: PreferenceSegment.PRICING, + }, +]; diff --git a/apps/your-burguer/src/app/choice-assistant/domain/preference/pricing/pricing.ts b/apps/your-burguer/src/app/choice-assistant/domain/preference/pricing/pricing.ts new file mode 100644 index 0000000..190e265 --- /dev/null +++ b/apps/your-burguer/src/app/choice-assistant/domain/preference/pricing/pricing.ts @@ -0,0 +1,5 @@ +export enum Pricing { + LOW_COST = 'LOW_COST', + REGULAR = 'REGULAR', + EXPENSIVE = 'EXPENSIVE', +} diff --git a/apps/your-burguer/src/app/choice-assistant/domain/preference/site-type/site-type-choices.ts b/apps/your-burguer/src/app/choice-assistant/domain/preference/site-type/site-type-choices.ts new file mode 100644 index 0000000..33346bd --- /dev/null +++ b/apps/your-burguer/src/app/choice-assistant/domain/preference/site-type/site-type-choices.ts @@ -0,0 +1,17 @@ +import { CustomerPreference } from '../customer-preference'; +import { PreferenceSegment } from '../preference-segment'; +import { SiteType } from './site-type'; + +export const SITE_TYPE_CHOICES: CustomerPreference< + PreferenceSegment.SITE_TYPE, + SiteType +>[] = [ + { + name: SiteType.COOL_SITES, + segment: PreferenceSegment.SITE_TYPE, + }, + { + name: SiteType.FAST_FOOD, + segment: PreferenceSegment.SITE_TYPE, + }, +]; diff --git a/apps/your-burguer/src/app/choice-assistant/domain/preference/site-type/site-type.ts b/apps/your-burguer/src/app/choice-assistant/domain/preference/site-type/site-type.ts new file mode 100644 index 0000000..4a9fbc7 --- /dev/null +++ b/apps/your-burguer/src/app/choice-assistant/domain/preference/site-type/site-type.ts @@ -0,0 +1,4 @@ +export enum SiteType { + COOL_SITES = 'COOL_SITES', + FAST_FOOD = 'FAST_FOOD', +} diff --git a/apps/your-burguer/src/app/choice-assistant/infra/ui/simple-choice-picker/simple-choice-picker.component.css b/apps/your-burguer/src/app/choice-assistant/infra/ui/simple-choice-picker/simple-choice-picker.component.css new file mode 100644 index 0000000..fc8fb27 --- /dev/null +++ b/apps/your-burguer/src/app/choice-assistant/infra/ui/simple-choice-picker/simple-choice-picker.component.css @@ -0,0 +1,4 @@ +.selected { + background-color: #1d4ed8; /* Azul tailwind */ + color: white; +} diff --git a/apps/your-burguer/src/app/choice-assistant/infra/ui/simple-choice-picker/simple-choice-picker.component.html b/apps/your-burguer/src/app/choice-assistant/infra/ui/simple-choice-picker/simple-choice-picker.component.html new file mode 100644 index 0000000..fbe5464 --- /dev/null +++ b/apps/your-burguer/src/app/choice-assistant/infra/ui/simple-choice-picker/simple-choice-picker.component.html @@ -0,0 +1,17 @@ +
+

{{title()}}

+
+ @for (choice of config().choices; track $index) { + + } +
+
\ No newline at end of file diff --git a/apps/your-burguer/src/app/choice-assistant/infra/ui/simple-choice-picker/simple-choice-picker.component.spec.ts b/apps/your-burguer/src/app/choice-assistant/infra/ui/simple-choice-picker/simple-choice-picker.component.spec.ts new file mode 100644 index 0000000..f274ccf --- /dev/null +++ b/apps/your-burguer/src/app/choice-assistant/infra/ui/simple-choice-picker/simple-choice-picker.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { SimpleChoicePickerComponent } from './simple-choice-picker.component'; + +describe('SimpleChoicePickerComponent', () => { + let component: SimpleChoicePickerComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [SimpleChoicePickerComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(SimpleChoicePickerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/apps/your-burguer/src/app/choice-assistant/infra/ui/simple-choice-picker/simple-choice-picker.component.ts b/apps/your-burguer/src/app/choice-assistant/infra/ui/simple-choice-picker/simple-choice-picker.component.ts new file mode 100644 index 0000000..a17c9aa --- /dev/null +++ b/apps/your-burguer/src/app/choice-assistant/infra/ui/simple-choice-picker/simple-choice-picker.component.ts @@ -0,0 +1,44 @@ +import { Component, input, model, output } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { ReactiveFormsModule } from '@angular/forms'; + +export interface SimpleChoiceConfig { + choices: SimpleChoice[]; + default: string; +} + +export interface SimpleChoice { + displayText: string; + value: string; + icon: string; +} + +@Component({ + selector: 'app-simple-choice-picker', + standalone: true, + imports: [CommonModule, ReactiveFormsModule], + templateUrl: './simple-choice-picker.component.html', + styleUrl: './simple-choice-picker.component.css', +}) +export class SimpleChoicePickerComponent { + title = input.required(); + config = input.required(); + choiceChanged = output(); + + choicePicked = model(); + + pickChoice(choice: SimpleChoice) { + this.choicePicked.set(choice); + this.choiceChanged.emit(choice); + } + + isPicked(choice: SimpleChoice) { + return choice.value === this.choicePicked()?.value; + } + + selected = false; + + toggleSelection() { + this.selected = !this.selected; + } +} diff --git a/apps/your-burguer/src/app/nx-welcome.component.ts b/apps/your-burguer/src/app/nx-welcome.component.ts deleted file mode 100644 index 4572799..0000000 --- a/apps/your-burguer/src/app/nx-welcome.component.ts +++ /dev/null @@ -1,870 +0,0 @@ -import { Component, ViewEncapsulation } from '@angular/core'; -import { CommonModule } from '@angular/common'; - -@Component({ - selector: 'app-nx-welcome', - standalone: true, - imports: [CommonModule], - template: ` - - -
-
- -
-

- Hello there, - Welcome your-burguer 👋 -

-
- -
-
-

- - - - You're up and running -

- What's next? -
-
- - - -
-
- - - -
-

Next steps

-

Here are some things you can do with Nx:

-
- - - - - Build, test and lint your app - -
# Build
-nx build 
-# Test
-nx test 
-# Lint
-nx lint 
-# Run them together!
-nx run-many -t build test lint
-
-
- - - - - View project details - -
nx show project your-burguer
-
- -
- - - - - View interactive project graph - -
nx graph
-
- -
- - - - - Add UI library - -
# Generate UI lib
-nx g @nx/angular:lib ui
-# Add a component
-nx g @nx/angular:component ui/src/lib/button
-
-
-

- Carefully crafted with - - - -

-
-
- `, - styles: [], - encapsulation: ViewEncapsulation.None, -}) -export class NxWelcomeComponent {} diff --git a/apps/your-burguer/src/app/shell/navbar/navbar.component.css b/apps/your-burguer/src/app/shell/navbar/navbar.component.css new file mode 100644 index 0000000..e69de29 diff --git a/apps/your-burguer/src/app/shell/navbar/navbar.component.html b/apps/your-burguer/src/app/shell/navbar/navbar.component.html new file mode 100644 index 0000000..d2141e4 --- /dev/null +++ b/apps/your-burguer/src/app/shell/navbar/navbar.component.html @@ -0,0 +1,55 @@ + \ No newline at end of file diff --git a/apps/your-burguer/src/app/shell/navbar/navbar.component.spec.ts b/apps/your-burguer/src/app/shell/navbar/navbar.component.spec.ts new file mode 100644 index 0000000..b507306 --- /dev/null +++ b/apps/your-burguer/src/app/shell/navbar/navbar.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { NavbarComponent } from './navbar.component'; + +describe('NavbarComponent', () => { + let component: NavbarComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [NavbarComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(NavbarComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/apps/your-burguer/src/app/shell/navbar/navbar.component.ts b/apps/your-burguer/src/app/shell/navbar/navbar.component.ts new file mode 100644 index 0000000..2dcfb51 --- /dev/null +++ b/apps/your-burguer/src/app/shell/navbar/navbar.component.ts @@ -0,0 +1,11 @@ +import { Component } from '@angular/core'; +import { CommonModule } from '@angular/common'; + +@Component({ + selector: 'app-navbar', + standalone: true, + imports: [CommonModule], + templateUrl: './navbar.component.html', + styleUrl: './navbar.component.css', +}) +export class NavbarComponent {} diff --git a/apps/your-burguer/src/app/shell/shell.component.css b/apps/your-burguer/src/app/shell/shell.component.css new file mode 100644 index 0000000..e69de29 diff --git a/apps/your-burguer/src/app/shell/shell.component.html b/apps/your-burguer/src/app/shell/shell.component.html new file mode 100644 index 0000000..0c1a735 --- /dev/null +++ b/apps/your-burguer/src/app/shell/shell.component.html @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/apps/your-burguer/src/app/shell/shell.component.spec.ts b/apps/your-burguer/src/app/shell/shell.component.spec.ts new file mode 100644 index 0000000..ac41e51 --- /dev/null +++ b/apps/your-burguer/src/app/shell/shell.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ShellComponent } from './shell.component'; + +describe('ShellComponent', () => { + let component: ShellComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ShellComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(ShellComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/apps/your-burguer/src/app/shell/shell.component.ts b/apps/your-burguer/src/app/shell/shell.component.ts new file mode 100644 index 0000000..45ccc42 --- /dev/null +++ b/apps/your-burguer/src/app/shell/shell.component.ts @@ -0,0 +1,12 @@ +import { Component } from '@angular/core'; +import { NavbarComponent } from './navbar/navbar.component'; +import { RouterModule } from '@angular/router'; + +@Component({ + selector: 'app-shell', + standalone: true, + imports: [RouterModule, NavbarComponent], + templateUrl: './shell.component.html', + styleUrl: './shell.component.css', +}) +export class ShellComponent {} diff --git a/apps/your-burguer/src/app/workflow/domain/step/element/step-element-type.ts b/apps/your-burguer/src/app/workflow/domain/step/element/step-element-type.ts new file mode 100644 index 0000000..8e52040 --- /dev/null +++ b/apps/your-burguer/src/app/workflow/domain/step/element/step-element-type.ts @@ -0,0 +1,3 @@ +export enum StepElementType { + CHOICE, +} diff --git a/apps/your-burguer/src/app/workflow/domain/step/element/step-element.ts b/apps/your-burguer/src/app/workflow/domain/step/element/step-element.ts new file mode 100644 index 0000000..3bcbc35 --- /dev/null +++ b/apps/your-burguer/src/app/workflow/domain/step/element/step-element.ts @@ -0,0 +1,3 @@ +import { StepElementChoice } from './types/step-element-choice'; + +export type StepElement = StepElementChoice; diff --git a/apps/your-burguer/src/app/workflow/domain/step/element/types/step-element-choice.ts b/apps/your-burguer/src/app/workflow/domain/step/element/types/step-element-choice.ts new file mode 100644 index 0000000..ee17a23 --- /dev/null +++ b/apps/your-burguer/src/app/workflow/domain/step/element/types/step-element-choice.ts @@ -0,0 +1,11 @@ +import { StepElementType } from '../step-element-type'; + +export interface StepElementChoice { + type: StepElementType.CHOICE; + options: StepElementChoiceOption[]; +} + +interface StepElementChoiceOption { + value: string; + displayText: string; +} diff --git a/apps/your-burguer/src/app/workflow/domain/step/step-config.ts b/apps/your-burguer/src/app/workflow/domain/step/step-config.ts new file mode 100644 index 0000000..4aeb277 --- /dev/null +++ b/apps/your-burguer/src/app/workflow/domain/step/step-config.ts @@ -0,0 +1,5 @@ +import { StepElement } from './element/step-element'; + +export interface StepConfig { + components: StepElement[]; +} diff --git a/apps/your-burguer/src/app/workflow/domain/step/step.ts b/apps/your-burguer/src/app/workflow/domain/step/step.ts new file mode 100644 index 0000000..4fa5756 --- /dev/null +++ b/apps/your-burguer/src/app/workflow/domain/step/step.ts @@ -0,0 +1,7 @@ +import { StepConfig } from './step-config'; + +export interface Step { + name: string; + path: string; + config: StepConfig; +} diff --git a/apps/your-burguer/src/app/workflow/domain/workflow-navigator.ts b/apps/your-burguer/src/app/workflow/domain/workflow-navigator.ts new file mode 100644 index 0000000..b349c36 --- /dev/null +++ b/apps/your-burguer/src/app/workflow/domain/workflow-navigator.ts @@ -0,0 +1,39 @@ +import { Workflow } from './workflow'; +import { WorkflowState } from './workflow.state'; +import { DEFAULT_WORKFLOW } from './workflows/default'; + +export abstract class WorkflowNavigator { + protected state: WorkflowState = new WorkflowState({ + workflow: DEFAULT_WORKFLOW, + current: { + step: DEFAULT_WORKFLOW.steps[0], + index: 0, + hasNext: true, + hasPrevious: false, + }, + }); + + public setWorkflow(workflow: Workflow): void { + this.state.setState({ + workflow, + current: { + step: workflow.steps[0], + index: 0, + hasNext: true, + hasPrevious: false, + }, + }); + } + + public abstract next(): void; + + public hasNext(): boolean { + return this.state.hasNext(); + } + + public abstract previous(): void; + + public hasPrevious(): boolean { + return this.state.hasPrevious(); + } +} diff --git a/apps/your-burguer/src/app/workflow/domain/workflow.state.ts b/apps/your-burguer/src/app/workflow/domain/workflow.state.ts new file mode 100644 index 0000000..9641ad4 --- /dev/null +++ b/apps/your-burguer/src/app/workflow/domain/workflow.state.ts @@ -0,0 +1,75 @@ +import { Step } from './step/step'; +import { Workflow } from './workflow'; + +interface WorkflowStateProps { + workflow: Workflow; + current: { + step: Step; + index: number; + hasNext: boolean; + hasPrevious: boolean; + }; +} + +export class WorkflowState { + private _state: WorkflowStateProps; + + get state(): WorkflowStateProps { + return this._state; + } + + constructor(state: WorkflowStateProps) { + this._state = state; + } + + setState(state: Partial) { + this.patch(state); + } + + patch(state: Partial) { + this._state = { + ...this._state, + ...state, + current: { + ...this._state.current, + ...state.current, + }, + }; + } + + next(): void { + if (this.hasNext()) { + const nextIndex = this._state.current.index + 1; + this.patch({ + current: { + step: this._state.workflow.steps[nextIndex], + index: nextIndex, + hasNext: nextIndex < this._state.workflow.steps.length - 1, + hasPrevious: nextIndex > 0, + }, + }); + } + } + + hasNext(): boolean { + return this._state.current.index < this._state.workflow.steps.length - 1; + } + + previous(): void { + if (this.hasPrevious()) { + const prevIndex = this._state.current.index - 1; + this.patch({ + current: { + step: this._state.workflow.steps[prevIndex], + index: prevIndex, + hasNext: prevIndex < this._state.workflow.steps.length - 1, + hasPrevious: prevIndex > 0, + }, + }); + } + } + + hasPrevious(): boolean { + return this._state.current.index > 0; + } +} diff --git a/apps/your-burguer/src/app/workflow/domain/workflow.ts b/apps/your-burguer/src/app/workflow/domain/workflow.ts new file mode 100644 index 0000000..99ec953 --- /dev/null +++ b/apps/your-burguer/src/app/workflow/domain/workflow.ts @@ -0,0 +1,6 @@ +import { Step } from './step/step'; + +export interface Workflow { + name: string; + steps: Step[]; +} diff --git a/apps/your-burguer/src/app/workflow/domain/workflows/default.ts b/apps/your-burguer/src/app/workflow/domain/workflows/default.ts new file mode 100644 index 0000000..8976f94 --- /dev/null +++ b/apps/your-burguer/src/app/workflow/domain/workflows/default.ts @@ -0,0 +1,224 @@ +import { Delivery } from '@choice-assistant/domain/preference/delivery/delivery'; +import { BurguerType } from '../../../choice-assistant/domain/preference/burguer-type/burguer-type'; +import { StepElementType } from '../step/element/step-element-type'; +import { Workflow } from '../workflow'; +import { SiteType } from '@choice-assistant/domain/preference/site-type/site-type'; +import { Pricing } from '@choice-assistant/domain/preference/pricing/pricing'; +import { Intolerances } from '@choice-assistant/domain/preference/intolerances/intolerances'; +import { Highlights } from '@choice-assistant/domain/preference/highlights/highlights'; +import { Garnish } from '@choice-assistant/domain/preference/garnish/garnish'; +import { Mode } from '@choice-assistant/domain/preference/mode/mode'; + +export const DEFAULT_WORKFLOW: Workflow = { + name: 'default', + steps: [ + { + name: 'BURGUER_TYPE', + path: '/choice-assistant/burguer-type', + config: { + components: [ + { + type: StepElementType.CHOICE, + options: [ + { + value: BurguerType.CLASSIC, + displayText: 'burguerType.classic', + }, + { + value: BurguerType.SMASH, + displayText: 'burguerType.smash', + }, + { + value: BurguerType.VEGAN, + displayText: 'burguerType.vegan', + }, + ], + }, + ], + }, + }, + { + name: 'DELIVERY', + path: '/choice-assistant/delivery', + config: { + components: [ + { + type: StepElementType.CHOICE, + options: [ + { + value: Delivery.IN_SITE, + displayText: 'delivery.inSite', + }, + { + value: Delivery.PICK_UP, + displayText: 'delivery.pickUp', + }, + { + value: Delivery.DELIVERY, + displayText: 'delivery.delivery', + }, + ], + }, + ], + }, + }, + { + name: 'PRIGING', + path: '/choice-assistant/pricing', + config: { + components: [ + { + type: StepElementType.CHOICE, + options: [ + { + value: Pricing.LOW_COST, + displayText: 'pricing.lowCost', + }, + { + value: Pricing.REGULAR, + displayText: 'pricing.regular', + }, + { + value: Pricing.EXPENSIVE, + displayText: 'pricing.expensive', + }, + ], + }, + ], + }, + }, + { + name: 'SITE_TYPE', + path: '/choice-assistant/site-type', + config: { + components: [ + { + type: StepElementType.CHOICE, + options: [ + { + value: SiteType.COOL_SITES, + displayText: 'siteType.coolSites', + }, + { + value: SiteType.FAST_FOOD, + displayText: 'siteType.fastFood', + }, + ], + }, + ], + }, + }, + { + name: 'INTOLERANCES', + path: '/choice-assistant/intolerances', + config: { + components: [ + { + type: StepElementType.CHOICE, + options: [ + { + value: Intolerances.NONE, + displayText: 'intolerances.none', + }, + { + value: Intolerances.GLUTEN, + displayText: 'intolerances.gluten', + }, + { + value: Intolerances.LACTOSE, + displayText: 'intolerances.lactose', + }, + { + value: Intolerances.OTHERS, + displayText: 'intolerances.others', + }, + ], + }, + ], + }, + }, + { + name: 'HIGHLIGHTS', + path: '/choice-assistant/highlights', + config: { + components: [ + { + type: StepElementType.CHOICE, + options: [ + { + value: Highlights.NONE, + displayText: 'highlights.none', + }, + { + value: Highlights.CHEESE, + displayText: 'highlights.cheese', + }, + { + value: Highlights.SAUCE, + displayText: 'highlights.sauce', + }, + { + value: Highlights.VEGETABLES, + displayText: 'highlights.vegetables', + }, + ], + }, + ], + }, + }, + { + name: 'GARNISH', + path: '/choice-assistant/garnish', + config: { + components: [ + { + type: StepElementType.CHOICE, + options: [ + { + value: Garnish.NONE, + displayText: 'garnish.none', + }, + { + value: Garnish.REGULAR_POTATOES, + displayText: 'garnish.regularPotatoes', + }, + { + value: Garnish.WEDGES_POTATOES, + displayText: 'garnish.wedgesPotatoes', + }, + { + value: Garnish.SWEET_POTATOES, + displayText: 'garnish.sweetPotatoes', + }, + { + value: Garnish.SALAD, + displayText: 'garnish.salad', + }, + ], + }, + ], + }, + }, + { + name: 'MODE', + path: '/choice-assistant/mode', + config: { + components: [ + { + type: StepElementType.CHOICE, + options: [ + { + value: Mode.PREFERENCE, + displayText: 'mode.preference', + }, + { + value: Mode.TRY_OUT, + displayText: 'mode.tryOut', + }, + ], + }, + ], + }, + }, + ], +}; diff --git a/apps/your-burguer/src/app/workflow/infra/ng-workflow-navigator.ts b/apps/your-burguer/src/app/workflow/infra/ng-workflow-navigator.ts new file mode 100644 index 0000000..c036989 --- /dev/null +++ b/apps/your-burguer/src/app/workflow/infra/ng-workflow-navigator.ts @@ -0,0 +1,25 @@ +import { inject } from '@angular/core'; +import { Router } from '@angular/router'; +import { WorkflowNavigator } from '@workflow/domain/workflow-navigator'; + +export class NgWorkflowNavigator extends WorkflowNavigator { + private router = inject(Router); + + public override next(): void { + if (!this.state.hasNext()) { + throw new Error(`Current workflow has no next step`); + } + this.state.next(); + const { path } = this.state.state.current.step; + this.router.navigate([path]); + } + + public override previous(): void { + if (!this.state.hasPrevious()) { + throw new Error(`Current workflow has no previous step`); + } + this.state.previous(); + const { path } = this.state.state.current.step; + this.router.navigate([path]); + } +} diff --git a/apps/your-burguer/src/app/workflow/workflow.module.ts b/apps/your-burguer/src/app/workflow/workflow.module.ts new file mode 100644 index 0000000..b12cd01 --- /dev/null +++ b/apps/your-burguer/src/app/workflow/workflow.module.ts @@ -0,0 +1,23 @@ +import { ModuleWithProviders, NgModule } from '@angular/core'; +import { WorkflowNavigator } from './domain/workflow-navigator'; +import { NgWorkflowNavigator } from './infra/ng-workflow-navigator'; +import { DEFAULT_WORKFLOW } from './domain/workflows/default'; + +@NgModule({}) +export class WorkflowModule { + static forRoot(): ModuleWithProviders { + return { + ngModule: WorkflowModule, + providers: [ + { + provide: WorkflowNavigator, + useFactory: () => { + const navigator = new NgWorkflowNavigator(); + navigator.setWorkflow(DEFAULT_WORKFLOW); + return navigator; + }, + }, + ], + }; + } +} diff --git a/apps/your-burguer/src/styles.css b/apps/your-burguer/src/styles.css index 90d4ee0..844323d 100644 --- a/apps/your-burguer/src/styles.css +++ b/apps/your-burguer/src/styles.css @@ -1 +1,4 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; /* You can add global styles to this file, and also import other style files */ diff --git a/apps/your-burguer/tailwind.config.js b/apps/your-burguer/tailwind.config.js new file mode 100644 index 0000000..38183db --- /dev/null +++ b/apps/your-burguer/tailwind.config.js @@ -0,0 +1,14 @@ +const { createGlobPatternsForDependencies } = require('@nx/angular/tailwind'); +const { join } = require('path'); + +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html}'), + ...createGlobPatternsForDependencies(__dirname), + ], + theme: { + extend: {}, + }, + plugins: [], +}; diff --git a/apps/your-burguer/tsconfig.json b/apps/your-burguer/tsconfig.json index c147dd2..af00bd2 100644 --- a/apps/your-burguer/tsconfig.json +++ b/apps/your-burguer/tsconfig.json @@ -7,7 +7,11 @@ "noImplicitOverride": true, "noPropertyAccessFromIndexSignature": true, "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true + "noFallthroughCasesInSwitch": true, + "paths": { + "@choice-assistant/*": ["apps/your-burguer/src/app/choice-assistant/*"], + "@workflow/*": ["apps/your-burguer/src/app/workflow/*"] + } }, "files": [], "include": [], diff --git a/nx.json b/nx.json index dadeae8..f031366 100644 --- a/nx.json +++ b/nx.json @@ -67,6 +67,9 @@ "linter": "eslint", "style": "css", "unitTestRunner": "jest" + }, + "@nx/angular:component": { + "style": "css" } } } diff --git a/package-lock.json b/package-lock.json index ece4104..fe85ba7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,8 +17,7 @@ "@angular/platform-browser": "~18.2.0", "@angular/platform-browser-dynamic": "~18.2.0", "@angular/router": "~18.2.0", - "rxjs": "~7.8.0", - "zone.js": "~0.14.3" + "rxjs": "~7.8.0" }, "devDependencies": { "@angular-devkit/build-angular": "~18.2.0", @@ -46,6 +45,7 @@ "@types/node": "18.16.9", "@typescript-eslint/utils": "^7.16.0", "angular-eslint": "^18.3.0", + "autoprefixer": "^10.4.0", "eslint": "^9.8.0", "eslint-config-prettier": "^9.0.0", "eslint-plugin-playwright": "^1.6.2", @@ -53,7 +53,9 @@ "jest-environment-jsdom": "^29.7.0", "jest-preset-angular": "~14.1.0", "nx": "19.8.2", + "postcss": "^8.4.5", "prettier": "^2.6.2", + "tailwindcss": "^3.0.2", "ts-jest": "^29.1.0", "ts-node": "10.9.1", "tslib": "^2.3.0", @@ -68,6 +70,19 @@ "dev": true, "license": "MIT" }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", @@ -716,33 +731,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@angular-devkit/build-angular/node_modules/less": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/less/-/less-4.2.0.tgz", - "integrity": "sha512-P3b3HJDBtSzsXUl0im2L7gTO5Ubg8mEN6G8qoTS77iXxXX4Hvu4Qj540PZDvQ8V6DmX6iXo98k7Md0Cm1PrLaA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "copy-anything": "^2.0.1", - "parse-node-version": "^1.0.1", - "tslib": "^2.3.0" - }, - "bin": { - "lessc": "bin/lessc" - }, - "engines": { - "node": ">=6" - }, - "optionalDependencies": { - "errno": "^0.1.1", - "graceful-fs": "^4.1.2", - "image-size": "~0.5.0", - "make-dir": "^2.1.0", - "mime": "^1.4.1", - "needle": "^3.1.0", - "source-map": "~0.6.0" - } - }, "node_modules/@angular-devkit/build-angular/node_modules/less-loader": { "version": "12.2.0", "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-12.2.0.tgz", @@ -796,32 +784,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@angular-devkit/build-angular/node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/make-dir/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "license": "ISC", - "optional": true, - "bin": { - "semver": "bin/semver" - } - }, "node_modules/@angular-devkit/build-angular/node_modules/mini-css-extract-plugin": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.0.tgz", @@ -941,17 +903,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@angular-devkit/build-angular/node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=6" - } - }, "node_modules/@angular-devkit/build-angular/node_modules/piscina": { "version": "4.6.1", "resolved": "https://registry.npmjs.org/piscina/-/piscina-4.6.1.tgz", @@ -7081,6 +7032,35 @@ } } }, + "node_modules/@nx/js/node_modules/babel-plugin-macros": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz", + "integrity": "sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.7.2", + "cosmiconfig": "^6.0.0", + "resolve": "^1.12.0" + } + }, + "node_modules/@nx/js/node_modules/cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/@nx/js/node_modules/jsonc-parser": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", @@ -7381,6 +7361,81 @@ "webpack-subresource-integrity": "^5.1.0" } }, + "node_modules/@nx/webpack/node_modules/less": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/less/-/less-4.1.3.tgz", + "integrity": "sha512-w16Xk/Ta9Hhyei0Gpz9m7VS8F28nieJaL/VyShID7cYvP6IL5oHeL6p4TXSDJqZE/lNv0oJ2pGVjJsRkfwm5FA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "copy-anything": "^2.0.1", + "parse-node-version": "^1.0.1", + "tslib": "^2.3.0" + }, + "bin": { + "lessc": "bin/lessc" + }, + "engines": { + "node": ">=6" + }, + "optionalDependencies": { + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "make-dir": "^2.1.0", + "mime": "^1.4.1", + "needle": "^3.1.0", + "source-map": "~0.6.0" + } + }, + "node_modules/@nx/webpack/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@nx/webpack/node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@nx/webpack/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/@nx/webpack/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/@nx/workspace": { "version": "19.8.2", "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-19.8.2.tgz", @@ -9134,6 +9189,127 @@ "vite": "^3.0.0 || ^4.0.0 || ^5.0.0" } }, + "node_modules/@vitest/expect": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.1.tgz", + "integrity": "sha512-YeueunS0HiHiQxk+KEOnq/QMzlUuOzbU1Go+PgAsHvvv3tUkJPm9xWt+6ITNTlzsMXUjmgm5T+U7KBPK2qQV6w==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@vitest/spy": "2.1.1", + "@vitest/utils": "2.1.1", + "chai": "^5.1.1", + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.1.tgz", + "integrity": "sha512-LNN5VwOEdJqCmJ/2XJBywB11DLlkbY0ooDJW3uRX5cZyYCrc4PI/ePX0iQhE3BiEGiQmK4GE7Q/PqCkkaiPnrA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@vitest/spy": "^2.1.0-beta.1", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.11" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@vitest/spy": "2.1.1", + "msw": "^2.3.5", + "vite": "^5.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.1.tgz", + "integrity": "sha512-SjxPFOtuINDUW8/UkElJYQSFtnWX7tMksSGW0vfjxMneFqxVr8YJ979QpMbDW7g+BIiq88RAGDjf7en6rvLPPQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.1.tgz", + "integrity": "sha512-uTPuY6PWOYitIkLPidaY5L3t0JJITdGTSwBtwMjKzo5O6RCOEncz9PUN+0pDidX8kTHYjO0EwUIvhlGpnGpxmA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@vitest/utils": "2.1.1", + "pathe": "^1.1.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.1.tgz", + "integrity": "sha512-BnSku1WFy7r4mm96ha2FzN99AZJgpZOWrAhtQfoxjUU5YMRpq1zmHRq7a5K9/NjqonebO7iVDla+VvZS8BOWMw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@vitest/pretty-format": "2.1.1", + "magic-string": "^0.30.11", + "pathe": "^1.1.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.1.tgz", + "integrity": "sha512-ZM39BnZ9t/xZ/nF4UwRH5il0Sw93QnZXd9NAZGRpIgj0yvVwPpLd702s/Cx955rGaMlyBQkZJ2Ir7qyY48VZ+g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "tinyspy": "^3.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.1.tgz", + "integrity": "sha512-Y6Q9TsI+qJ2CC0ZKj6VBb+T8UPz593N113nnUykqwANqhgf3QkZeHFlusgKLTqrnVHbj/XDKZcDHol+dxVT+rQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@vitest/pretty-format": "2.1.1", + "loupe": "^3.1.1", + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, "node_modules/@webassemblyjs/ast": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", @@ -9625,6 +9801,13 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true, + "license": "MIT" + }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -9696,6 +9879,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + } + }, "node_modules/async": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", @@ -10014,15 +10208,21 @@ } }, "node_modules/babel-plugin-macros": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz", - "integrity": "sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { - "@babel/runtime": "^7.7.2", - "cosmiconfig": "^6.0.0", - "resolve": "^1.12.0" + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" } }, "node_modules/babel-plugin-polyfill-corejs2": { @@ -10431,9 +10631,20 @@ "node": ">= 0.8" } }, - "node_modules/cacache": { - "version": "18.0.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.4.tgz", + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cacache": { + "version": "18.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.4.tgz", "integrity": "sha512-B+L5iIa9mgcjLbliir2th36yEwPftrzteHYujzsx3dFP/31GCHcIeS8f5MGd80odLOjaOvSpU3EEAmRQptkxLQ==", "dev": true, "license": "ISC", @@ -10553,6 +10764,16 @@ "node": ">=6" } }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, "node_modules/caniuse-api": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", @@ -10587,6 +10808,24 @@ ], "license": "CC-BY-4.0" }, + "node_modules/chai": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.1.tgz", + "integrity": "sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -10621,6 +10860,17 @@ "dev": true, "license": "MIT" }, + "node_modules/check-error": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", + "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 16" + } + }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -11196,20 +11446,20 @@ } }, "node_modules/cosmiconfig": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", - "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", "dev": true, "license": "MIT", "dependencies": { "@types/parse-json": "^4.0.0", - "import-fresh": "^3.1.0", + "import-fresh": "^3.2.1", "parse-json": "^5.0.0", "path-type": "^4.0.0", - "yaml": "^1.7.2" + "yaml": "^1.10.0" }, "engines": { - "node": ">=8" + "node": ">=10" } }, "node_modules/create-jest": { @@ -11659,6 +11909,17 @@ } } }, + "node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, "node_modules/deep-equal": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", @@ -11860,6 +12121,13 @@ "node": ">= 4.0.0" } }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", @@ -11893,6 +12161,13 @@ "node": ">=8" } }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true, + "license": "MIT" + }, "node_modules/dns-packet": { "version": "5.6.1", "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", @@ -12781,6 +13056,17 @@ "node": ">=4.0" } }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/estree": "^1.0.0" + } + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -13381,23 +13667,6 @@ "concat-map": "0.0.1" } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/cosmiconfig": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/fork-ts-checker-webpack-plugin/node_modules/fs-extra": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", @@ -13619,6 +13888,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": "*" + } + }, "node_modules/get-intrinsic": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", @@ -16222,9 +16502,9 @@ } }, "node_modules/less": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/less/-/less-4.1.3.tgz", - "integrity": "sha512-w16Xk/Ta9Hhyei0Gpz9m7VS8F28nieJaL/VyShID7cYvP6IL5oHeL6p4TXSDJqZE/lNv0oJ2pGVjJsRkfwm5FA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/less/-/less-4.2.0.tgz", + "integrity": "sha512-P3b3HJDBtSzsXUl0im2L7gTO5Ubg8mEN6G8qoTS77iXxXX4Hvu4Qj540PZDvQ8V6DmX6iXo98k7Md0Cm1PrLaA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -16855,6 +17135,31 @@ "dev": true, "license": "MIT" }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/loupe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.1.tgz", + "integrity": "sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "get-func-name": "^2.0.1" + } + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -17429,6 +17734,18 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, "node_modules/nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", @@ -17988,6 +18305,26 @@ "dev": true, "license": "MIT" }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, "node_modules/object-inspect": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", @@ -18479,6 +18816,25 @@ "node": ">=8" } }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/pathval": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", + "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 14.16" + } + }, "node_modules/picocolors": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", @@ -18776,6 +19132,75 @@ "postcss": "^8.0.0" } }, + "node_modules/postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-load-config/node_modules/yaml": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/postcss-loader": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", @@ -18799,23 +19224,6 @@ "webpack": "^5.0.0" } }, - "node_modules/postcss-loader/node_modules/cosmiconfig": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/postcss-media-query-parser": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", @@ -18990,6 +19398,32 @@ "postcss": "^8.1.0" } }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, "node_modules/postcss-normalize-charset": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-6.0.2.tgz", @@ -19502,6 +19936,35 @@ "node": ">= 0.8" } }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, "node_modules/react-is": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", @@ -20107,6 +20570,17 @@ "node": ">=v12.22.7" } }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + } + }, "node_modules/schema-utils": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", @@ -20440,6 +20914,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC", + "peer": true + }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -20774,6 +21256,14 @@ "node": ">=8" } }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -20784,6 +21274,14 @@ "node": ">= 0.8" } }, + "node_modules/std-env": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", + "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/streamroller": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.5.tgz", @@ -21083,6 +21581,83 @@ "dev": true, "license": "ISC" }, + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/sucrase/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/sucrase/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sucrase/node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/sucrase/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -21152,6 +21727,109 @@ "dev": true, "license": "MIT" }, + "node_modules/tailwindcss": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.13.tgz", + "integrity": "sha512-KqjHOJKogOUt5Bs752ykCeiwvi0fKVkr5oqsFNt/8px/tA8scFPIlkygsf6jXrfCqGHz7VflA6+yytWuM+XhFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.0", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.0", + "lilconfig": "^2.1.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.23", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.1", + "postcss-nested": "^6.0.1", + "postcss-selector-parser": "^6.0.11", + "resolve": "^1.22.2", + "sucrase": "^3.32.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tailwindcss/node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tailwindcss/node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/tailwindcss/node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/tailwindcss/node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/tailwindcss/node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", @@ -21465,6 +22143,29 @@ "dev": true, "license": "MIT" }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/thingies": { "version": "1.21.0", "resolved": "https://registry.npmjs.org/thingies/-/thingies-1.21.0.tgz", @@ -21492,6 +22193,55 @@ "dev": true, "license": "MIT" }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/tinyexec": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.0.tgz", + "integrity": "sha512-tVGE0mVJPGb0chKhqmsoosjsS+qUnJVGJpZgsHYQcGoPlG3B51R3PouqTgEGH2Dc9jjFyOqOpix6ZHNMXp1FZg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/tinypool": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.1.tgz", + "integrity": "sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": "^18.0.0 || >=20.0.0" + } + }, + "node_modules/tinyrainbow": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz", + "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", + "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/tmp": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", @@ -21621,6 +22371,13 @@ "typescript": ">=4.2.0" } }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/ts-jest": { "version": "29.2.5", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.5.tgz", @@ -22264,6 +23021,29 @@ } } }, + "node_modules/vite-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.1.tgz", + "integrity": "sha512-N/mGckI1suG/5wQI35XeR9rsMsPqKXzq1CdUndzVstBj/HvyxxGctwnK6WX43NGt5L3Z5tcRf83g4TITKJhPrA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.3.6", + "pathe": "^1.1.2", + "vite": "^5.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, "node_modules/vite/node_modules/@esbuild/aix-ppc64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", @@ -22694,6 +23474,72 @@ "@esbuild/win32-x64": "0.21.5" } }, + "node_modules/vitest": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.1.tgz", + "integrity": "sha512-97We7/VC0e9X5zBVkvt7SGQMGrRtn3KtySFQG5fpaMlS+l62eeXRQO633AYhSTC3z7IMebnPPNjGXVGNRFlxBA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@vitest/expect": "2.1.1", + "@vitest/mocker": "2.1.1", + "@vitest/pretty-format": "^2.1.1", + "@vitest/runner": "2.1.1", + "@vitest/snapshot": "2.1.1", + "@vitest/spy": "2.1.1", + "@vitest/utils": "2.1.1", + "chai": "^5.1.1", + "debug": "^4.3.6", + "magic-string": "^0.30.11", + "pathe": "^1.1.2", + "std-env": "^3.7.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.0", + "tinypool": "^1.0.0", + "tinyrainbow": "^1.2.0", + "vite": "^5.0.0", + "vite-node": "2.1.1", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/node": "^18.0.0 || >=20.0.0", + "@vitest/browser": "2.1.1", + "@vitest/ui": "2.1.1", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, "node_modules/w3c-xmlserializer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", @@ -23226,6 +24072,24 @@ "which": "bin/which" } }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/wildcard": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", @@ -23446,7 +24310,8 @@ "version": "0.14.10", "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.14.10.tgz", "integrity": "sha512-YGAhaO7J5ywOXW6InXNlLmfU194F8lVgu7bRntUF3TiG8Y3nBK0x1UJJuHUP/e8IyihkjCYqhCScpSwnlaSRkQ==", - "license": "MIT" + "license": "MIT", + "peer": true } } } diff --git a/package.json b/package.json index d63a45c..34d1c3a 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,7 @@ "@angular/platform-browser": "~18.2.0", "@angular/platform-browser-dynamic": "~18.2.0", "@angular/router": "~18.2.0", - "rxjs": "~7.8.0", - "zone.js": "~0.14.3" + "rxjs": "~7.8.0" }, "devDependencies": { "@angular-devkit/build-angular": "~18.2.0", @@ -42,6 +41,7 @@ "@types/node": "18.16.9", "@typescript-eslint/utils": "^7.16.0", "angular-eslint": "^18.3.0", + "autoprefixer": "^10.4.0", "eslint": "^9.8.0", "eslint-config-prettier": "^9.0.0", "eslint-plugin-playwright": "^1.6.2", @@ -49,7 +49,9 @@ "jest-environment-jsdom": "^29.7.0", "jest-preset-angular": "~14.1.0", "nx": "19.8.2", + "postcss": "^8.4.5", "prettier": "^2.6.2", + "tailwindcss": "^3.0.2", "ts-jest": "^29.1.0", "ts-node": "10.9.1", "tslib": "^2.3.0",