feat: add establishment settings
This commit is contained in:
@@ -28,10 +28,13 @@
|
|||||||
"edit_chain": "edit chain"
|
"edit_chain": "edit chain"
|
||||||
},
|
},
|
||||||
"establishment": {
|
"establishment": {
|
||||||
"establishments":"establishments"
|
"establishments":"establishments",
|
||||||
|
"new_establishment": "new establishment",
|
||||||
|
"edit_establishment": "edit establishment"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"common": {
|
"common": {
|
||||||
|
"address":"address",
|
||||||
"name":"name",
|
"name":"name",
|
||||||
"save": "save",
|
"save": "save",
|
||||||
"update": "update",
|
"update": "update",
|
||||||
|
|||||||
@@ -28,10 +28,13 @@
|
|||||||
"edit_chain": "editar cadena"
|
"edit_chain": "editar cadena"
|
||||||
},
|
},
|
||||||
"establishment": {
|
"establishment": {
|
||||||
"establishments":"establecimientos"
|
"establishments":"establecimientos",
|
||||||
|
"new_establishment": "nuevo establecimiento",
|
||||||
|
"edit_establishment": "editar establecimiento"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"common": {
|
"common": {
|
||||||
|
"address":"dirección",
|
||||||
"name":"nombre",
|
"name":"nombre",
|
||||||
"no_file_yet": "Sin carga",
|
"no_file_yet": "Sin carga",
|
||||||
"save": "guardar",
|
"save": "guardar",
|
||||||
|
|||||||
@@ -28,10 +28,13 @@
|
|||||||
"edit_chain": "edit chain"
|
"edit_chain": "edit chain"
|
||||||
},
|
},
|
||||||
"establishment": {
|
"establishment": {
|
||||||
"establishments":"establishments"
|
"establishments":"establishments",
|
||||||
|
"new_establishment": "new establishment",
|
||||||
|
"edit_establishment": "edit establishment"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"common": {
|
"common": {
|
||||||
|
"address":"address",
|
||||||
"name":"name",
|
"name":"name",
|
||||||
"save": "save",
|
"save": "save",
|
||||||
"update": "update",
|
"update": "update",
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { EstablishmentAdd } from './establishment-add';
|
||||||
|
import { provideTranslateService } from '@ngx-translate/core';
|
||||||
|
import { Chain } from '../../models/Chain';
|
||||||
|
import { Establishment } from '../../models/Establishment';
|
||||||
|
import { EstablishmentSettings } from '../../services/establishment-settings';
|
||||||
|
import { EstablishmentForm } from '../../pages/settings/establishments/establishment-form/establishment-form';
|
||||||
|
|
||||||
|
describe('EstablishmentAdd', () => {
|
||||||
|
let component: EstablishmentAdd;
|
||||||
|
let fixture: ComponentFixture<EstablishmentAdd>;
|
||||||
|
|
||||||
|
let establishmentSettings: Partial<EstablishmentSettings>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
establishmentSettings = {
|
||||||
|
save: vi.fn(),
|
||||||
|
};
|
||||||
|
TestBed.overrideComponent(EstablishmentForm, {
|
||||||
|
set: { template: `` },
|
||||||
|
});
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [EstablishmentAdd],
|
||||||
|
providers: [
|
||||||
|
provideTranslateService(),
|
||||||
|
{ provide: EstablishmentSettings, useValue: establishmentSettings },
|
||||||
|
],
|
||||||
|
}).compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(EstablishmentAdd);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
await fixture.whenStable();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should save on valid form', async () => {
|
||||||
|
const SELECTED_CHAIN_MOCK = new Chain('Mock', 'mock_logo.png', 1);
|
||||||
|
const ADDRESS_MOCK = 'Mock street';
|
||||||
|
await component.submit();
|
||||||
|
//form is invalid so it doesnt call establishmenDAO save method
|
||||||
|
expect(establishmentSettings.save).not.toHaveBeenCalled();
|
||||||
|
//User chooses chain, form is valid
|
||||||
|
component['form'].patchValue({ chain: SELECTED_CHAIN_MOCK, address: ADDRESS_MOCK });
|
||||||
|
await component.submit();
|
||||||
|
const establishment = new Establishment(SELECTED_CHAIN_MOCK, ADDRESS_MOCK);
|
||||||
|
expect(establishmentSettings.save).toHaveBeenCalledExactlyOnceWith(establishment);
|
||||||
|
});
|
||||||
|
});
|
||||||
36
src/app/components/establishment-add/establishment-add.ts
Normal file
36
src/app/components/establishment-add/establishment-add.ts
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import { Component, inject } from '@angular/core';
|
||||||
|
|
||||||
|
import { EstablishmentSettings } from '../../services/establishment-settings';
|
||||||
|
import { Establishment } from '../../models/Establishment';
|
||||||
|
import { ActionBtn } from '../action-btn/action-btn';
|
||||||
|
import { TranslatePipe } from '@ngx-translate/core';
|
||||||
|
import { UpperfirstPipe } from '../../pipes/upperfirst-pipe';
|
||||||
|
import { EstablishmentFormGroup } from '../../pages/settings/establishments/establishment-formgroup';
|
||||||
|
import { SettingsBaseAddEdit } from '../settings-base-add-edit/settings-base-add-edit';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-establishment-add',
|
||||||
|
imports: [
|
||||||
|
ActionBtn,
|
||||||
|
TranslatePipe,
|
||||||
|
UpperfirstPipe,
|
||||||
|
],
|
||||||
|
templateUrl: './../settings-base-add-edit/settings-base-add-edit.html',
|
||||||
|
styleUrl: './../settings-base-add-edit/settings-base-add-edit.scss',
|
||||||
|
})
|
||||||
|
export class EstablishmentAdd extends SettingsBaseAddEdit {
|
||||||
|
private readonly establishmentSettings = inject(EstablishmentSettings);
|
||||||
|
|
||||||
|
readonly form = new EstablishmentFormGroup();
|
||||||
|
btnText = 'common.save';
|
||||||
|
title = 'settings.establishment.new_establishment';
|
||||||
|
|
||||||
|
async submit() {
|
||||||
|
const chain = this.form.controls.chain.value;
|
||||||
|
const address = this.form.controls.address.value;
|
||||||
|
if (chain?.id) {
|
||||||
|
const establishment = new Establishment(chain, address);
|
||||||
|
this.establishmentSettings.save(establishment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { EstablishmentEdit } from './establishment-edit';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import { BehaviorSubject } from 'rxjs';
|
||||||
|
import { Establishment } from '../../models/Establishment';
|
||||||
|
import { Chain } from '../../models/Chain';
|
||||||
|
import { EstablishmentSettings } from '../../services/establishment-settings';
|
||||||
|
import { provideTranslateService } from '@ngx-translate/core';
|
||||||
|
import { EstablishmentForm } from '../../pages/settings/establishments/establishment-form/establishment-form';
|
||||||
|
import { By } from '@angular/platform-browser';
|
||||||
|
|
||||||
|
describe('EstablishmentEdit', () => {
|
||||||
|
let component: EstablishmentEdit;
|
||||||
|
let fixture: ComponentFixture<EstablishmentEdit>;
|
||||||
|
|
||||||
|
let activatedRoute: Partial<ActivatedRoute>;
|
||||||
|
let establishmentSettings: Partial<EstablishmentSettings>;
|
||||||
|
|
||||||
|
const data = new BehaviorSubject({
|
||||||
|
establishment: new Establishment(new Chain('mock', 'logo_mock.jpg', 1), 'mock street', 1),
|
||||||
|
});
|
||||||
|
beforeEach(async () => {
|
||||||
|
activatedRoute = {
|
||||||
|
data,
|
||||||
|
};
|
||||||
|
establishmentSettings = {
|
||||||
|
update: vi.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
TestBed.overrideComponent(EstablishmentForm, {
|
||||||
|
set: { template: `` },
|
||||||
|
});
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [EstablishmentEdit],
|
||||||
|
providers: [
|
||||||
|
{ provide: ActivatedRoute, useValue: activatedRoute },
|
||||||
|
{ provide: EstablishmentSettings, useValue: establishmentSettings },
|
||||||
|
provideTranslateService(),
|
||||||
|
],
|
||||||
|
}).compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(EstablishmentEdit);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
await fixture.whenStable();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call establishmentSettings update', async () => {
|
||||||
|
const CHAIN_MOCK = new Chain('mock', 'logo_mock.png', 2);
|
||||||
|
const ADDRESS_MOCK = 'mock street';
|
||||||
|
//User selects chain
|
||||||
|
component['form'].patchValue({chain: CHAIN_MOCK, address: ADDRESS_MOCK});
|
||||||
|
const submitBtn = fixture.debugElement.query(By.css('app-action-btn'));
|
||||||
|
submitBtn.triggerEventHandler('click');
|
||||||
|
await fixture.whenStable()
|
||||||
|
expect(establishmentSettings.update).toHaveBeenCalledExactlyOnceWith(new Establishment(CHAIN_MOCK, ADDRESS_MOCK, component['establishment']!.id));
|
||||||
|
});
|
||||||
|
});
|
||||||
53
src/app/components/establishment-edit/establishment-edit.ts
Normal file
53
src/app/components/establishment-edit/establishment-edit.ts
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
import { Component, inject, OnInit } from '@angular/core';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import { UpperfirstPipe } from '../../pipes/upperfirst-pipe';
|
||||||
|
import { TranslatePipe } from '@ngx-translate/core';
|
||||||
|
import { Establishment } from '../../models/Establishment';
|
||||||
|
import { Observable, take, tap } from 'rxjs';
|
||||||
|
import { EstablishmentFormGroup } from '../../pages/settings/establishments/establishment-formgroup';
|
||||||
|
import { ActionBtn } from '../action-btn/action-btn';
|
||||||
|
import { EstablishmentSettings } from '../../services/establishment-settings';
|
||||||
|
import { SettingsBaseAddEdit } from '../settings-base-add-edit/settings-base-add-edit';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-establishment-edit',
|
||||||
|
imports: [UpperfirstPipe, TranslatePipe, ActionBtn],
|
||||||
|
templateUrl: './../settings-base-add-edit/settings-base-add-edit.html',
|
||||||
|
styleUrl: './../settings-base-add-edit/settings-base-add-edit.scss',
|
||||||
|
})
|
||||||
|
export class EstablishmentEdit extends SettingsBaseAddEdit implements OnInit {
|
||||||
|
private readonly activatedRoute = inject(ActivatedRoute);
|
||||||
|
private readonly establishmentSettings = inject(EstablishmentSettings);
|
||||||
|
|
||||||
|
private establishment?: Establishment;
|
||||||
|
readonly form = new EstablishmentFormGroup();
|
||||||
|
btnText = 'common.update';
|
||||||
|
title = 'settings.establishment.edit_establishment'
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
(<Observable<{ establishment: Establishment }>>this.activatedRoute.data)
|
||||||
|
.pipe(
|
||||||
|
take(1),
|
||||||
|
tap((data) => (this.establishment = data.establishment)),
|
||||||
|
tap((data) => this.patchForm(data.establishment)),
|
||||||
|
)
|
||||||
|
.subscribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
patchForm(establishment: Establishment) {
|
||||||
|
this.form.patchValue({
|
||||||
|
chain: establishment.chain,
|
||||||
|
address: establishment.address,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async submit() {
|
||||||
|
const chain = this.form.controls.chain.value;
|
||||||
|
if (chain && this.establishment?.id) {
|
||||||
|
const address = this.form.controls.address.value;
|
||||||
|
const establishment = new Establishment(chain, address, this.establishment.id);
|
||||||
|
await this.establishmentSettings.update(establishment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
<app-establishment-add #e>
|
||||||
|
<app-establishment-form [form]="e.form"></app-establishment-form>
|
||||||
|
</app-establishment-add>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
:host {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { EstablishmentAddPage } from './establishment-add-page';
|
||||||
|
import { EstablishmentSettings } from '../../../../services/establishment-settings';
|
||||||
|
import { provideTranslateService } from '@ngx-translate/core';
|
||||||
|
import { ChainDAO } from '../../../../dao/ChainDAO';
|
||||||
|
|
||||||
|
describe('EstablishmentAddPage', () => {
|
||||||
|
let component: EstablishmentAddPage;
|
||||||
|
let fixture: ComponentFixture<EstablishmentAddPage>;
|
||||||
|
|
||||||
|
let chainDAO: Partial<ChainDAO>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
chainDAO = {
|
||||||
|
findAll: vi.fn(),
|
||||||
|
};
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [EstablishmentAddPage],
|
||||||
|
providers: [
|
||||||
|
{ provide: ChainDAO, useValue: chainDAO },
|
||||||
|
{ provide: EstablishmentSettings, useValue: {} },
|
||||||
|
provideTranslateService(),
|
||||||
|
],
|
||||||
|
}).compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(EstablishmentAddPage);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
await fixture.whenStable();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { EstablishmentAdd } from "../../../../components/establishment-add/establishment-add";
|
||||||
|
import { EstablishmentForm } from "../establishment-form/establishment-form";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-establishment-add-page',
|
||||||
|
imports: [EstablishmentAdd, EstablishmentForm],
|
||||||
|
templateUrl: './establishment-add-page.html',
|
||||||
|
styleUrl: './establishment-add-page.scss',
|
||||||
|
})
|
||||||
|
export class EstablishmentAddPage {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
<app-establishment-edit #e>
|
||||||
|
<app-establishment-form [form]="e.form"></app-establishment-form>
|
||||||
|
</app-establishment-edit>
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
:host {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { EstablishmentEditPage } from './establishment-edit-page';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import { of } from 'rxjs';
|
||||||
|
import { Establishment } from '../../../../models/Establishment';
|
||||||
|
import { Chain } from '../../../../models/Chain';
|
||||||
|
import { EstablishmentSettings } from '../../../../services/establishment-settings';
|
||||||
|
import { provideTranslateService } from '@ngx-translate/core';
|
||||||
|
import { ChainDAO } from '../../../../dao/ChainDAO';
|
||||||
|
|
||||||
|
describe('EstablishmentEditPage', () => {
|
||||||
|
let component: EstablishmentEditPage;
|
||||||
|
let fixture: ComponentFixture<EstablishmentEditPage>;
|
||||||
|
|
||||||
|
let activatedRoute: Partial<ActivatedRoute>;
|
||||||
|
let chainDAO: Partial<ChainDAO>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
activatedRoute = {
|
||||||
|
data: of({establishment: new Establishment(new Chain('mock', 'logo_mock.jpg', 1), 'mock street', 1)}),
|
||||||
|
};
|
||||||
|
chainDAO = {
|
||||||
|
findAll: vi.fn().mockResolvedValue([]),
|
||||||
|
};
|
||||||
|
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [EstablishmentEditPage],
|
||||||
|
providers: [
|
||||||
|
{ provide: ActivatedRoute, useValue: activatedRoute },
|
||||||
|
{ provide: ChainDAO, useValue: chainDAO },
|
||||||
|
{ provide: EstablishmentSettings, useValue: {} },
|
||||||
|
provideTranslateService(),
|
||||||
|
],
|
||||||
|
}).compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(EstablishmentEditPage);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
await fixture.whenStable();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { EstablishmentEdit } from "../../../../components/establishment-edit/establishment-edit";
|
||||||
|
import { EstablishmentForm } from "../establishment-form/establishment-form";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-establishment-edit-page',
|
||||||
|
imports: [EstablishmentEdit, EstablishmentForm],
|
||||||
|
templateUrl: './establishment-edit-page.html',
|
||||||
|
styleUrl: './establishment-edit-page.scss',
|
||||||
|
})
|
||||||
|
export class EstablishmentEditPage {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<form [formGroup]="form()">
|
||||||
|
<app-chain-select formControlName="chain"></app-chain-select>
|
||||||
|
<mat-form-field appearance="outline" class="full-width">
|
||||||
|
<mat-label>{{'common.address'|translate|upperfirst}}</mat-label>
|
||||||
|
<input matInput formControlName="address"/>
|
||||||
|
</mat-form-field>
|
||||||
|
</form>
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { EstablishmentForm } from './establishment-form';
|
||||||
|
import { ChainDAO } from '../../../../dao/ChainDAO';
|
||||||
|
import { provideTranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
|
describe('EstablishmentForm', () => {
|
||||||
|
let component: EstablishmentForm;
|
||||||
|
let fixture: ComponentFixture<EstablishmentForm>;
|
||||||
|
|
||||||
|
let chainDAO: Partial<ChainDAO>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
chainDAO = {
|
||||||
|
findAll: vi.fn().mockResolvedValue([]),
|
||||||
|
};
|
||||||
|
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [EstablishmentForm],
|
||||||
|
providers: [{ provide: ChainDAO, useValue: chainDAO }, provideTranslateService()],
|
||||||
|
}).compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(EstablishmentForm);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
await fixture.whenStable();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import { Component, input } from '@angular/core';
|
||||||
|
import { EstablishmentFormGroup } from '../establishment-formgroup';
|
||||||
|
import { ChainSelect } from '../../../../components/chain-select/chain-select';
|
||||||
|
import { ReactiveFormsModule } from '@angular/forms';
|
||||||
|
import { MatFormField, MatLabel } from '@angular/material/form-field';
|
||||||
|
import { MatInput } from '@angular/material/input';
|
||||||
|
import { TranslatePipe } from '@ngx-translate/core';
|
||||||
|
import { UpperfirstPipe } from "../../../../pipes/upperfirst-pipe";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-establishment-form',
|
||||||
|
imports: [ChainSelect, ReactiveFormsModule, MatFormField, MatInput, MatLabel, TranslatePipe, UpperfirstPipe],
|
||||||
|
templateUrl: './establishment-form.html',
|
||||||
|
styles: '',
|
||||||
|
})
|
||||||
|
export class EstablishmentForm {
|
||||||
|
form = input(new EstablishmentFormGroup());
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import { FormControl, FormGroup, Validators } from '@angular/forms';
|
||||||
|
import { Chain } from '../../../models/Chain';
|
||||||
|
|
||||||
|
export class EstablishmentFormGroup extends FormGroup<{
|
||||||
|
chain: FormControl<Chain | null>;
|
||||||
|
address: FormControl<string>;
|
||||||
|
}> {
|
||||||
|
constructor(
|
||||||
|
form = {
|
||||||
|
chain: new FormControl<Chain | null>(null, [Validators.required]),
|
||||||
|
address: new FormControl('', { nonNullable: true }),
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
super(form);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { EstablishmentList } from './establishment-list';
|
||||||
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
|
import { BehaviorSubject } from 'rxjs';
|
||||||
|
import { Establishment } from '../../../../models/Establishment';
|
||||||
|
import { Chain } from '../../../../models/Chain';
|
||||||
|
import { By } from '@angular/platform-browser';
|
||||||
|
|
||||||
|
const ADD_PATH = ['settings', 'establishments', 'add'];
|
||||||
|
describe('EstablishmentList', () => {
|
||||||
|
let component: EstablishmentList;
|
||||||
|
let fixture: ComponentFixture<EstablishmentList>;
|
||||||
|
|
||||||
|
let activatedRoute: Partial<ActivatedRoute>;
|
||||||
|
let router: Partial<Router>;
|
||||||
|
|
||||||
|
const activatedRouteData = new BehaviorSubject({
|
||||||
|
establishments: [new Establishment(new Chain('Mock', 'logo_mock.png', 1), 'Mock street', 1)],
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
activatedRoute = { data: activatedRouteData.asObservable() };
|
||||||
|
router = {
|
||||||
|
navigate: vi.fn(),
|
||||||
|
};
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [EstablishmentList],
|
||||||
|
providers: [
|
||||||
|
{ provide: ActivatedRoute, useValue: activatedRoute },
|
||||||
|
{ provide: Router, useValue: router },
|
||||||
|
],
|
||||||
|
}).compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(EstablishmentList);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
await fixture.whenStable();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should navigate to add on add btn click', () => {
|
||||||
|
const addBtn = fixture.debugElement.query(By.css('app-floating-big-btn'));
|
||||||
|
addBtn.triggerEventHandler('bigClick');
|
||||||
|
expect(router.navigate).toHaveBeenCalledExactlyOnceWith(ADD_PATH);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import { Component, inject } from '@angular/core';
|
||||||
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
|
import { SimpleListWActions } from '../../../../components/simple-list-w-actions/simple-list-w-actions';
|
||||||
|
import { FloatingBigBtn } from '../../../../components/floating-big-btn/floating-big-btn';
|
||||||
|
import { AsyncPipe } from '@angular/common';
|
||||||
|
import { map } from 'rxjs';
|
||||||
|
import { SimpleListItem } from '../../../../components/simple-list-w-actions/SimpleListItem';
|
||||||
|
import { SimpleListItemAction } from '../../../../components/simple-list-w-actions/SimpleListItemAction';
|
||||||
|
import { Establishment } from '../../../../models/Establishment';
|
||||||
|
import { SettingsBaseList } from '../../../../components/settings-base-list/settings-base-list';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-establishment-list',
|
||||||
|
imports: [SimpleListWActions, FloatingBigBtn, AsyncPipe],
|
||||||
|
templateUrl: './../../../../components/settings-base-list/settings-base-list.html',
|
||||||
|
styleUrl: './../../../../components/settings-base-list/settings-base-list.scss'
|
||||||
|
})
|
||||||
|
export class EstablishmentList extends SettingsBaseList{
|
||||||
|
activatedRoute = inject(ActivatedRoute);
|
||||||
|
router = inject(Router);
|
||||||
|
|
||||||
|
data$ = this.activatedRoute.data.pipe(
|
||||||
|
map((data) =>
|
||||||
|
(<Establishment[]>data['establishments']).map((e) => {
|
||||||
|
const itemName = e.chain.name + (e.address ? ` - ${e.address}` : '');
|
||||||
|
return new SimpleListItem(String(e.id), itemName ?? '', [
|
||||||
|
new SimpleListItemAction('edit', 'edit'),
|
||||||
|
]);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
edit(action: { action: string; subject: string }) {
|
||||||
|
this.router.navigate(['settings', 'establishments', 'edit', action.subject]);
|
||||||
|
}
|
||||||
|
|
||||||
|
add() {
|
||||||
|
this.router.navigate(['settings', 'establishments', 'add']);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
<app-simple-layout title="settings.establishment.establishments" [withBackBtn]="true" >
|
||||||
|
<router-outlet></router-outlet>
|
||||||
|
</app-simple-layout>
|
||||||
25
src/app/pages/settings/establishments/establishments.spec.ts
Normal file
25
src/app/pages/settings/establishments/establishments.spec.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { Establishments } from './establishments';
|
||||||
|
import { provideTranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
|
describe('Establishments', () => {
|
||||||
|
let component: Establishments;
|
||||||
|
let fixture: ComponentFixture<Establishments>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [Establishments],
|
||||||
|
providers: [provideTranslateService()]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(Establishments);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
await fixture.whenStable();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
13
src/app/pages/settings/establishments/establishments.ts
Normal file
13
src/app/pages/settings/establishments/establishments.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { SimpleLayout } from "../../../components/simple-layout/simple-layout";
|
||||||
|
import { RouterOutlet } from "@angular/router";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-establishments',
|
||||||
|
imports: [SimpleLayout, RouterOutlet],
|
||||||
|
templateUrl: './establishments.html',
|
||||||
|
styles: '',
|
||||||
|
})
|
||||||
|
export class Establishments {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -2,6 +2,9 @@ import { Route } from '@angular/router';
|
|||||||
import { chainsResolver } from '../../resolvers/chains-resolver';
|
import { chainsResolver } from '../../resolvers/chains-resolver';
|
||||||
import { ChainList } from './chains/chain-list/chain-list';
|
import { ChainList } from './chains/chain-list/chain-list';
|
||||||
import { chainResolver } from '../../resolvers/chain-resolver';
|
import { chainResolver } from '../../resolvers/chain-resolver';
|
||||||
|
import { EstablishmentList } from './establishments/establishment-list/establishment-list';
|
||||||
|
import { establishmentsResolver } from '../../resolvers/establishments-resolver';
|
||||||
|
import { establishmentResolver } from '../../resolvers/establishment-resolver';
|
||||||
|
|
||||||
export const routes: Route[] = [
|
export const routes: Route[] = [
|
||||||
{
|
{
|
||||||
@@ -32,4 +35,24 @@ export const routes: Route[] = [
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'establishments',
|
||||||
|
loadComponent: () => import('./establishments/establishments').then( c => c.Establishments ),
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: EstablishmentList,
|
||||||
|
resolve: {establishments: establishmentsResolver},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'add',
|
||||||
|
loadComponent: () => import('./establishments/establishment-add-page/establishment-add-page').then(c => c.EstablishmentAddPage)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'edit/:id',
|
||||||
|
loadComponent: () => import('./establishments/establishment-edit-page/establishment-edit-page').then(c => c.EstablishmentEditPage),
|
||||||
|
resolve: {establishment: establishmentResolver}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export class Settings {
|
|||||||
readonly menuItems = [
|
readonly menuItems = [
|
||||||
new IconNavListItem('translate', 'settings.nav.language', ['languages']),
|
new IconNavListItem('translate', 'settings.nav.language', ['languages']),
|
||||||
new IconNavListItem('warehouse', 'settings.nav.manage_chains', ['chains']),
|
new IconNavListItem('warehouse', 'settings.nav.manage_chains', ['chains']),
|
||||||
new IconNavListItem('store', 'settings.nav.manage_establishments', ['/']),
|
new IconNavListItem('store', 'settings.nav.manage_establishments', ['establishments']),
|
||||||
new IconNavListItem('shopping_bag', 'settings.nav.manage_products', ['/']),
|
new IconNavListItem('shopping_bag', 'settings.nav.manage_products', ['/']),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
68
src/app/resolvers/establishment-resolver.spec.ts
Normal file
68
src/app/resolvers/establishment-resolver.spec.ts
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
import { provideRouter, RedirectCommand, ResolveFn, Router } from '@angular/router';
|
||||||
|
|
||||||
|
import { establishmentResolver } from './establishment-resolver';
|
||||||
|
import { Establishment } from '../models/Establishment';
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { EstablishmentDAO } from '../dao/EstablishmentDAO';
|
||||||
|
import { Chain } from '../models/Chain';
|
||||||
|
|
||||||
|
const PATH_MOCK = 'mock/:id';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-mock',
|
||||||
|
template: ``,
|
||||||
|
styles: [],
|
||||||
|
})
|
||||||
|
class MockComponent {}
|
||||||
|
|
||||||
|
const ESTABLISHMENT_SETTINGS_PATH = 'settings/establishments';
|
||||||
|
describe('establishmentResolver', () => {
|
||||||
|
let establishmentDAO: Partial<EstablishmentDAO>;
|
||||||
|
let router: Router;
|
||||||
|
let ESTABLISHMENT_MOCK: Establishment;
|
||||||
|
const executeResolver: ResolveFn<Establishment | RedirectCommand> = (...resolverParameters) =>
|
||||||
|
TestBed.runInInjectionContext(() => establishmentResolver(...resolverParameters));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
ESTABLISHMENT_MOCK = new Establishment(new Chain('mock', 'logo_mock.png', 1), 'mock street');
|
||||||
|
establishmentDAO = {
|
||||||
|
findBy: vi.fn().mockResolvedValue([ESTABLISHMENT_MOCK]),
|
||||||
|
};
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [MockComponent],
|
||||||
|
providers: [
|
||||||
|
provideRouter([
|
||||||
|
{
|
||||||
|
path: 'mock/:id',
|
||||||
|
component: MockComponent,
|
||||||
|
resolve: { establishment: establishmentResolver },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: ESTABLISHMENT_SETTINGS_PATH,
|
||||||
|
component: MockComponent
|
||||||
|
}
|
||||||
|
]),
|
||||||
|
{ provide: EstablishmentDAO, useValue: establishmentDAO },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
router = TestBed.inject(Router);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(executeResolver).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fetch establishment by id', async () => {
|
||||||
|
const ESTABLISHMENT_ID_MOCK = 1;
|
||||||
|
await router.navigate(['mock', ESTABLISHMENT_ID_MOCK]);
|
||||||
|
expect(establishmentDAO.findBy).toHaveBeenCalledExactlyOnceWith({id: ESTABLISHMENT_ID_MOCK})
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should navigate back to settings if establishment is not found', async () => {
|
||||||
|
establishmentDAO.findBy = vi.fn().mockResolvedValue([]);
|
||||||
|
await router.navigate(['mock', 1]);
|
||||||
|
expect(router.url).toEqual('/'+ESTABLISHMENT_SETTINGS_PATH);
|
||||||
|
});
|
||||||
|
});
|
||||||
27
src/app/resolvers/establishment-resolver.ts
Normal file
27
src/app/resolvers/establishment-resolver.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import { inject } from '@angular/core';
|
||||||
|
import { RedirectCommand, ResolveFn, Router } from '@angular/router';
|
||||||
|
import { EstablishmentDAO } from '../dao/EstablishmentDAO';
|
||||||
|
import { Establishment } from '../models/Establishment';
|
||||||
|
|
||||||
|
export const establishmentResolver: ResolveFn<Establishment | RedirectCommand> = async (
|
||||||
|
route,
|
||||||
|
_,
|
||||||
|
) => {
|
||||||
|
const establishmentDAO = inject(EstablishmentDAO);
|
||||||
|
const router = inject(Router);
|
||||||
|
const establishmentID = (<{ id: string }>route.params).id;
|
||||||
|
let establishment: Establishment;
|
||||||
|
try {
|
||||||
|
const results = await establishmentDAO.findBy({ id: Number(establishmentID) });
|
||||||
|
if (!results[0]) {
|
||||||
|
throw new Error('The search for establishment on edit did not find any match');
|
||||||
|
}
|
||||||
|
establishment = results[0];
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
return new RedirectCommand(router.parseUrl('settings/establishments'), {
|
||||||
|
skipLocationChange: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return establishment;
|
||||||
|
};
|
||||||
52
src/app/resolvers/establishments-resolver.spec.ts
Normal file
52
src/app/resolvers/establishments-resolver.spec.ts
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
import { provideRouter, ResolveFn, Router } from '@angular/router';
|
||||||
|
|
||||||
|
import { establishmentsResolver } from './establishments-resolver';
|
||||||
|
import { Establishment } from '../models/Establishment';
|
||||||
|
import { EstablishmentDAO } from '../dao/EstablishmentDAO';
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-mock',
|
||||||
|
template: ``,
|
||||||
|
styles: ``,
|
||||||
|
})
|
||||||
|
class MockComponent {}
|
||||||
|
|
||||||
|
const PATH_MOCK = 'establishments';
|
||||||
|
describe('establishmentsResolver', () => {
|
||||||
|
let establishmentDAO: Partial<EstablishmentDAO>;
|
||||||
|
let router: Router;
|
||||||
|
const executeResolver: ResolveFn<Establishment[]> = (...resolverParameters) =>
|
||||||
|
TestBed.runInInjectionContext(() => establishmentsResolver(...resolverParameters));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
establishmentDAO = {
|
||||||
|
findAll: vi.fn().mockResolvedValue([]),
|
||||||
|
};
|
||||||
|
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
providers: [
|
||||||
|
{ provide: EstablishmentDAO, useValue: establishmentDAO },
|
||||||
|
provideRouter([
|
||||||
|
{
|
||||||
|
path: PATH_MOCK,
|
||||||
|
component: MockComponent,
|
||||||
|
resolve: { establishments: establishmentsResolver },
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
router = TestBed.inject(Router);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(executeResolver).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call establishmentDAO findAll method', async () => {
|
||||||
|
await router.navigate([PATH_MOCK]);
|
||||||
|
expect(establishmentDAO.findAll).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
16
src/app/resolvers/establishments-resolver.ts
Normal file
16
src/app/resolvers/establishments-resolver.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { inject } from '@angular/core';
|
||||||
|
import { ResolveFn } from '@angular/router';
|
||||||
|
import { EstablishmentDAO } from '../dao/EstablishmentDAO';
|
||||||
|
import { Establishment } from '../models/Establishment';
|
||||||
|
|
||||||
|
export const establishmentsResolver: ResolveFn<Establishment[]> = async (route, state) => {
|
||||||
|
const establishmentDAO = inject(EstablishmentDAO);
|
||||||
|
let establishments: Establishment[] = [];
|
||||||
|
try {
|
||||||
|
establishments = await establishmentDAO.findAll()
|
||||||
|
} catch(e) {
|
||||||
|
console.error(e);
|
||||||
|
//TODO: report error
|
||||||
|
}
|
||||||
|
return establishments;
|
||||||
|
};
|
||||||
44
src/app/services/establishment-settings.spec.ts
Normal file
44
src/app/services/establishment-settings.spec.ts
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { EstablishmentSettings } from './establishment-settings';
|
||||||
|
import { EstablishmentDAO } from '../dao/EstablishmentDAO';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
import { Chain } from '../models/Chain';
|
||||||
|
import { Establishment } from '../models/Establishment';
|
||||||
|
|
||||||
|
describe('EstablishmentSettings', () => {
|
||||||
|
let service: EstablishmentSettings;
|
||||||
|
|
||||||
|
let establishmentDAO: Partial<EstablishmentDAO>;
|
||||||
|
let router: Partial<Router>;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
establishmentDAO = {
|
||||||
|
insert: vi.fn().mockResolvedValue({ rows: [] }),
|
||||||
|
};
|
||||||
|
router = {
|
||||||
|
navigate: vi.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
providers: [
|
||||||
|
{ provide: EstablishmentDAO, useValue: establishmentDAO },
|
||||||
|
{ provide: Router, useValue: router },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
service = TestBed.inject(EstablishmentSettings);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should insert new establishment', async () => {
|
||||||
|
const CHAIN_MOCK = new Chain('Chain mock', 'logo_mock.png', 1);
|
||||||
|
const ADDRESS_MOCK = 'Mock street';
|
||||||
|
const ESTABLISHMENT_MOCK = new Establishment(CHAIN_MOCK, ADDRESS_MOCK);
|
||||||
|
await service.save(ESTABLISHMENT_MOCK);
|
||||||
|
expect(establishmentDAO.insert).toHaveBeenCalledExactlyOnceWith(ESTABLISHMENT_MOCK);
|
||||||
|
expect(router.navigate).toHaveBeenCalledExactlyOnceWith(['settings', 'establishments']);
|
||||||
|
});
|
||||||
|
});
|
||||||
37
src/app/services/establishment-settings.ts
Normal file
37
src/app/services/establishment-settings.ts
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import { inject, Injectable } from '@angular/core';
|
||||||
|
import { Location } from '@angular/common';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
|
import { EstablishmentDAO } from '../dao/EstablishmentDAO';
|
||||||
|
import { Establishment } from '../models/Establishment';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
|
export class EstablishmentSettings {
|
||||||
|
private readonly establishmentDAO = inject(EstablishmentDAO);
|
||||||
|
private readonly router = inject(Router);
|
||||||
|
private readonly location = inject(Location);
|
||||||
|
|
||||||
|
async save(establishment: Establishment) {
|
||||||
|
try {
|
||||||
|
await this.establishmentDAO.insert(establishment);
|
||||||
|
} catch(e) {
|
||||||
|
console.error(e)
|
||||||
|
//TODO: handle error
|
||||||
|
}
|
||||||
|
this.router.navigate(['settings', 'establishments']);
|
||||||
|
this.location.replaceState('settings');
|
||||||
|
}
|
||||||
|
|
||||||
|
async update(establishment: Establishment) {
|
||||||
|
try {
|
||||||
|
await this.establishmentDAO.update(establishment, {id: establishment.id});
|
||||||
|
}catch(e) {
|
||||||
|
console.error(e)
|
||||||
|
//TODO: handle error
|
||||||
|
}
|
||||||
|
this.router.navigate(['settings', 'establishments']);
|
||||||
|
this.location.replaceState('settings');
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user