diff --git a/public/i18n/en.json b/public/i18n/en.json
index f0f2329..84c8541 100644
--- a/public/i18n/en.json
+++ b/public/i18n/en.json
@@ -22,9 +22,13 @@
"portuguese": "portuguese"
},
"chain": {
+ "chain": "chain",
"chains": "chains",
"new_chain": "new chain",
"edit_chain": "edit chain"
+ },
+ "establishment": {
+ "establishments":"establishments"
}
},
"common": {
diff --git a/public/i18n/es.json b/public/i18n/es.json
index 49ce30e..e3ae7db 100644
--- a/public/i18n/es.json
+++ b/public/i18n/es.json
@@ -22,9 +22,13 @@
"portuguese": "portugués"
},
"chain": {
+ "chain": "cadena",
"chains": "cadenas",
"new_chain": "nueva cadena",
"edit_chain": "editar cadena"
+ },
+ "establishment": {
+ "establishments":"establecimientos"
}
},
"common": {
diff --git a/public/i18n/pt.json b/public/i18n/pt.json
index f0f2329..84c8541 100644
--- a/public/i18n/pt.json
+++ b/public/i18n/pt.json
@@ -22,9 +22,13 @@
"portuguese": "portuguese"
},
"chain": {
+ "chain": "chain",
"chains": "chains",
"new_chain": "new chain",
"edit_chain": "edit chain"
+ },
+ "establishment": {
+ "establishments":"establishments"
}
},
"common": {
diff --git a/src/app/components/chain-select/chain-select.html b/src/app/components/chain-select/chain-select.html
new file mode 100644
index 0000000..406884d
--- /dev/null
+++ b/src/app/components/chain-select/chain-select.html
@@ -0,0 +1,11 @@
+
+ {{'settings.chain.chain'|translate|upperfirst}}
+
+ @for(chain of chains$|async; track chain.id) {
+ {{chain.name}}
+ }
+
+
diff --git a/src/app/components/chain-select/chain-select.scss b/src/app/components/chain-select/chain-select.scss
new file mode 100644
index 0000000..53a4bc5
--- /dev/null
+++ b/src/app/components/chain-select/chain-select.scss
@@ -0,0 +1,3 @@
+mat-form-field {
+ width: 100%;
+}
\ No newline at end of file
diff --git a/src/app/components/chain-select/chain-select.spec.ts b/src/app/components/chain-select/chain-select.spec.ts
new file mode 100644
index 0000000..1b6f028
--- /dev/null
+++ b/src/app/components/chain-select/chain-select.spec.ts
@@ -0,0 +1,65 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { Component } from '@angular/core';
+import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
+import { By } from '@angular/platform-browser';
+import { MatSelect } from '@angular/material/select';
+import { provideTranslateService } from '@ngx-translate/core';
+import { Chain } from '../../models/Chain';
+import { ChainDAO } from '../../dao/ChainDAO';
+import { ChainSelect } from './chain-select';
+
+@Component({
+ selector: 'app-chain-select-mock',
+ imports: [
+ ChainSelect,
+ ReactiveFormsModule
+ ],
+ template: `
+
+
+ `,
+ styleUrl: './chain-select.scss',
+})
+class ChainSelectTestbed {
+ form = new FormGroup({mock: new FormControl()})
+}
+
+describe('ChainSelect', () => {
+ let component: ChainSelectTestbed;
+ let fixture: ComponentFixture;
+
+ let chainDAO: Partial;
+ let CHAINS_MOCK: Chain[];
+ beforeEach(async () => {
+ CHAINS_MOCK = [new Chain('Mock 1', '', 1)];
+
+ chainDAO = {
+ findAll: vi.fn().mockResolvedValue(CHAINS_MOCK),
+ };
+
+ await TestBed.configureTestingModule({
+ imports: [ChainSelectTestbed],
+ providers: [{ provide: ChainDAO, useValue: chainDAO }, provideTranslateService()],
+ }).compileComponents();
+
+ fixture = TestBed.createComponent(ChainSelectTestbed);
+ component = fixture.componentInstance;
+
+ });
+
+ it('should create', async () => {
+ await fixture.whenStable();
+ expect(component).toBeTruthy();
+ });
+
+ it('should match form chain with chain option', async () => {
+ component.form = new FormGroup({mock: new FormControl(CHAINS_MOCK[0])});
+ await fixture.whenStable();
+ const matSelect: MatSelect = fixture.debugElement.query(By.css('mat-select')).componentInstance;
+ expect(matSelect.value).toEqual(CHAINS_MOCK[0]);
+ });
+
+});
diff --git a/src/app/components/chain-select/chain-select.ts b/src/app/components/chain-select/chain-select.ts
new file mode 100644
index 0000000..f1b5f0c
--- /dev/null
+++ b/src/app/components/chain-select/chain-select.ts
@@ -0,0 +1,53 @@
+import { Component, inject, OnInit, Optional, Self } from '@angular/core';
+import { ChainDAO } from '../../dao/ChainDAO';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
+import { MatSelectModule } from '@angular/material/select';
+import { AsyncPipe } from '@angular/common';
+import { ControlValueAccessor, FormControl, NgControl, ReactiveFormsModule } from '@angular/forms';
+import { Chain } from '../../models/Chain';
+import { TranslatePipe } from '@ngx-translate/core';
+import { UpperfirstPipe } from "../../pipes/upperfirst-pipe";
+
+@Component({
+ selector: 'app-chain-select',
+ imports: [
+ AsyncPipe,
+ MatFormFieldModule,
+ MatInputModule,
+ MatSelectModule,
+ ReactiveFormsModule,
+ TranslatePipe,
+ UpperfirstPipe
+],
+ templateUrl: './chain-select.html',
+ styleUrl: './chain-select.scss',
+})
+export class ChainSelect implements ControlValueAccessor, OnInit {
+ private readonly chainDAO = inject(ChainDAO);
+ protected chains$ = this.chainDAO.findAll();
+ protected control = new FormControl();
+
+ constructor(@Self() @Optional() public controlDir: NgControl) {
+ if (this.controlDir) {
+ this.controlDir.valueAccessor = this;
+ }
+ }
+
+ ngOnInit() {
+ this.control = this.controlDir.control;
+ }
+
+ writeValue(obj: any): void {}
+
+ registerOnChange(onChange: any) {}
+
+ registerOnTouched(fn: any): void {}
+
+ setDisabledState?(isDisabled: boolean): void {}
+
+ compareFn(c1: Chain, c2: Chain) {
+ if (!c1 || !c2) return false;
+ return c1.id === c2.id;
+ }
+}