feat: add establishment settings
This commit is contained in:
@@ -28,10 +28,13 @@
|
||||
"edit_chain": "edit chain"
|
||||
},
|
||||
"establishment": {
|
||||
"establishments":"establishments"
|
||||
"establishments":"establishments",
|
||||
"new_establishment": "new establishment",
|
||||
"edit_establishment": "edit establishment"
|
||||
}
|
||||
},
|
||||
"common": {
|
||||
"address":"address",
|
||||
"name":"name",
|
||||
"save": "save",
|
||||
"update": "update",
|
||||
|
||||
@@ -28,10 +28,13 @@
|
||||
"edit_chain": "editar cadena"
|
||||
},
|
||||
"establishment": {
|
||||
"establishments":"establecimientos"
|
||||
"establishments":"establecimientos",
|
||||
"new_establishment": "nuevo establecimiento",
|
||||
"edit_establishment": "editar establecimiento"
|
||||
}
|
||||
},
|
||||
"common": {
|
||||
"address":"dirección",
|
||||
"name":"nombre",
|
||||
"no_file_yet": "Sin carga",
|
||||
"save": "guardar",
|
||||
|
||||
@@ -28,10 +28,13 @@
|
||||
"edit_chain": "edit chain"
|
||||
},
|
||||
"establishment": {
|
||||
"establishments":"establishments"
|
||||
"establishments":"establishments",
|
||||
"new_establishment": "new establishment",
|
||||
"edit_establishment": "edit establishment"
|
||||
}
|
||||
},
|
||||
"common": {
|
||||
"address":"address",
|
||||
"name":"name",
|
||||
"save": "save",
|
||||
"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 { ChainList } from './chains/chain-list/chain-list';
|
||||
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[] = [
|
||||
{
|
||||
@@ -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 = [
|
||||
new IconNavListItem('translate', 'settings.nav.language', ['languages']),
|
||||
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', ['/']),
|
||||
];
|
||||
}
|
||||
|
||||
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