Compare commits

...

3 Commits

10 changed files with 44 additions and 33 deletions

View File

@@ -3,19 +3,19 @@
<div class="fields"> <div class="fields">
<app-form-field <app-form-field
[errorsDictionary]="companyAndNameErrorsDictionary" [errorsDictionary]="companyAndNameErrorsDictionary()"
formControlName="name" formControlName="name"
[label]="(languageManager.strings.name|upperfirst) + ':'" [label]="(languageManager.strings.name|upperfirst) + ':'"
[placeholder]="languageManager.strings.contactsName|upperfirst" [placeholder]="languageManager.strings.contactsName|upperfirst"
/> />
<app-form-field <app-form-field
[errorsDictionary]="companyAndNameErrorsDictionary" [errorsDictionary]="companyAndNameErrorsDictionary()"
formControlName="company" formControlName="company"
[label]="(languageManager.strings.company|upperfirst) + ':'" [label]="(languageManager.strings.company|upperfirst) + ':'"
[placeholder]="languageManager.strings.contactsCompany|upperfirst" [placeholder]="languageManager.strings.contactsCompany|upperfirst"
/> />
<app-form-field <app-form-field
[errorsDictionary]="phoneErrorsDictionary" [errorsDictionary]="phoneErrorsDictionary()"
formControlName="phone" formControlName="phone"
[label]="(languageManager.strings.phone|upperfirst) +':'" [label]="(languageManager.strings.phone|upperfirst) +':'"
[placeholder]="languageManager.strings.contactsPhone|upperfirst" [placeholder]="languageManager.strings.contactsPhone|upperfirst"

View File

@@ -12,7 +12,10 @@ describe('ContactForm', () => {
let languageManager: jasmine.SpyObj<LanguageManager>; let languageManager: jasmine.SpyObj<LanguageManager>;
beforeEach(async () => { beforeEach(async () => {
languageManager = jasmine.createSpyObj(LanguageManager.name, [], { strings: strings.en }); languageManager = jasmine.createSpyObj(LanguageManager.name, [], {
strings: strings.en,
selectedLanguage$: () => 'en',
});
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
imports: [ContactForm], imports: [ContactForm],

View File

@@ -12,7 +12,7 @@
<div> <div>
@for(error of errorsDictionary()|keyvalue; track error.key) { @for(error of errorsDictionary()|keyvalue; track error.key) {
@if(control.hasError(error.key) && isDirty){ @if(control.hasError(error.key) && isDirty){
<p class="error-text">• {{error.value}}</p> <p class="error-text">• {{error.value|upperfirst}}</p>
} }
} }
</div> </div>

View File

@@ -1,10 +1,11 @@
import { KeyValuePipe } from '@angular/common'; import { KeyValuePipe } from '@angular/common';
import { Component, computed, input, Optional, Self, signal } from '@angular/core'; import { Component, computed, input, Optional, Self, signal } from '@angular/core';
import { ControlValueAccessor, NgControl, ReactiveFormsModule } from '@angular/forms'; import { ControlValueAccessor, NgControl, ReactiveFormsModule } from '@angular/forms';
import { UpperfirstPipe } from '../../pipes/upperfirst-pipe';
@Component({ @Component({
selector: 'app-form-field', selector: 'app-form-field',
imports: [ReactiveFormsModule, KeyValuePipe], imports: [ReactiveFormsModule, KeyValuePipe, UpperfirstPipe],
templateUrl: './form-field.html', templateUrl: './form-field.html',
styleUrl: './form-field.scss', styleUrl: './form-field.scss',
}) })

View File

@@ -1,18 +1,17 @@
import { inject } from '@angular/core'; import { computed, inject, Signal, signal } from '@angular/core';
import { Dictionary } from '../interfaces/dictionary.interface'; import { Dictionary } from '../interfaces/dictionary.interface';
import { LanguageManager } from '../services/language-manager'; import { LanguageManager } from '../services/language-manager';
export class NameAndCompanyFieldsErrorsDictionary implements Dictionary { export class NameAndCompanyFieldsErrorsDictionary implements Dictionary {
private readonly languageManager = inject(LanguageManager); private readonly languageManager = inject(LanguageManager);
private readonly maxlen: string;
private readonly required = this.languageManager.strings.errorMessageRequired;
constructor() { getDictionary(): Signal<{ [key: string]: string }> {
this.maxlen = this.languageManager.strings.errorMessageMaxLength(120); return computed(
} () =>
this.languageManager.selectedLanguage$() && {
getDictionary(): { [key: string]: string } { maxlen: this.languageManager.strings.errorMessageMaxLength(120),
const { maxlen, required } = this; required: this.languageManager.strings.errorMessageRequired,
return { maxlen, required }; }
);
} }
} }

View File

@@ -1,14 +1,17 @@
import { inject } from '@angular/core'; import { computed, inject, Signal } from '@angular/core';
import { Dictionary } from '../interfaces/dictionary.interface'; import { Dictionary } from '../interfaces/dictionary.interface';
import { LanguageManager } from '../services/language-manager'; import { LanguageManager } from '../services/language-manager';
export class PhoneFieldErroresDictionary implements Dictionary { export class PhoneFieldErroresDictionary implements Dictionary {
languageManager = inject(LanguageManager); languageManager = inject(LanguageManager);
pattern = this.languageManager.strings.errorMessagePhonePattern;
required = this.languageManager.strings.errorMessageRequired;
getDictionary(): { [key: string]: string } { getDictionary(): Signal<{ [key: string]: string }> {
const { required, pattern } = this; return computed(
return { required, pattern }; () =>
this.languageManager.selectedLanguage$() && {
pattern: this.languageManager.strings.errorMessagePhonePattern,
required: this.languageManager.strings.errorMessageRequired,
}
);
} }
} }

View File

@@ -1,3 +1,5 @@
import { Signal } from '@angular/core';
export interface Dictionary { export interface Dictionary {
getDictionary(): { [key: string]: string }; getDictionary(): Signal<{ [key: string]: string }>;
} }

View File

@@ -26,7 +26,10 @@ describe('Edit', () => {
data: of({ contact: CONTACT_MOCK }), data: of({ contact: CONTACT_MOCK }),
}); });
contactService = jasmine.createSpyObj(ContactService.name, ['update']); contactService = jasmine.createSpyObj(ContactService.name, ['update']);
languageManager = jasmine.createSpyObj(LanguageManager.name, [], { strings: strings.en }); languageManager = jasmine.createSpyObj(LanguageManager.name, [], {
strings: strings.en,
selectedLanguage$: () => 'en',
});
router = jasmine.createSpyObj(Router.name, ['navigate']); router = jasmine.createSpyObj(Router.name, ['navigate']);
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({

View File

@@ -15,15 +15,15 @@ export const strings = Object.freeze({
editContact: 'edit contact', editContact: 'edit contact',
editContactSuccessNotification: 'contact edited successfully', editContactSuccessNotification: 'contact edited successfully',
editTheContact: 'edit the contact', editTheContact: 'edit the contact',
errorMessageMaxLength: (maxLen: number) => `Must be ${maxLen} characters or fewer.`, errorMessageMaxLength: (maxLen: number) => `must be ${maxLen} characters or fewer`,
errorMessagePhonePattern: `Valid format: + (optional) plus 12 to 15 digits`, errorMessagePhonePattern: `valid format: + (optional) plus 12 to 15 digits`,
errorMessageRequired: 'This field is required.', errorMessageRequired: 'this field is required',
errorNotification: 'Oops, there was an error', errorNotification: 'oops, there was an error',
goBack: 'go back', goBack: 'go back',
name: 'name', name: 'name',
phone: 'phone', phone: 'phone',
save: 'save', save: 'save',
searchContactPlaceholder: 'Search contact...', searchContactPlaceholder: 'search contact...',
}, },
es: { es: {
actions: 'acciones', actions: 'acciones',
@@ -41,9 +41,9 @@ export const strings = Object.freeze({
editContact: 'editar contacto', editContact: 'editar contacto',
editContactSuccessNotification: 'contacto editado correctamente', editContactSuccessNotification: 'contacto editado correctamente',
editTheContact: 'edite el contacto. ', editTheContact: 'edite el contacto. ',
errorMessageMaxLength: (maxLen: number) => `Debe contener ${maxLen} caracteres or menos.`, errorMessageMaxLength: (maxLen: number) => `debe contener ${maxLen} caracteres or menos`,
errorMessagePhonePattern: `Formato: + (opcional) y 12 a 15 digitos`, errorMessagePhonePattern: `formato: + (opcional) y 12 a 15 digitos`,
errorMessageRequired: 'este campo es requerido.', errorMessageRequired: 'este campo es requerido',
errorNotification: 'hubo un error', errorNotification: 'hubo un error',
goBack: 'volver', goBack: 'volver',
name: 'nombre', name: 'nombre',

View File

@@ -1,4 +1,4 @@
export const environment = { export const environment = {
prod: false, prod: false,
apiUrl: 'http://192.168.1.3:4444', apiUrl: 'http://192.168.1.3:8080',
}; };