feat: refactor forms to use Angular Material components for improved consistency and user experience
This commit is contained in:
1 parent
9a3e90ac74
commit
c133c4cc89
17 files changed
+174
-205
No files matched your search
@@ -59,8 +59,7 @@ dd {
|
||||
padding-block-start: 1.25rem;
|
||||
border-block-start: 1px solid var(--border, #dfe3e6);
|
||||
}
|
||||
fieldset,
|
||||
label {
|
||||
fieldset {
|
||||
display: grid;
|
||||
gap: 0.5rem;
|
||||
min-width: 0;
|
||||
@@ -74,16 +73,9 @@ legend {
|
||||
margin-block-end: 0.75rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
input,
|
||||
textarea {
|
||||
mat-form-field {
|
||||
min-width: 0;
|
||||
min-height: 2.75rem;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
input:focus-visible,
|
||||
textarea:focus-visible {
|
||||
outline: 2px solid var(--accent, #236b5d);
|
||||
outline-offset: 0.15rem;
|
||||
width: 100%;
|
||||
}
|
||||
.operation-error {
|
||||
color: var(--danger, #b42318);
|
||||
|
||||
@@ -137,8 +137,8 @@
|
||||
</button>
|
||||
</div>
|
||||
@if (notice().evidenceVersions.length) {
|
||||
<label>
|
||||
<span>Raison de la nouvelle version</span>
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Raison de la nouvelle version</mat-label>
|
||||
<input
|
||||
matInput
|
||||
type="text"
|
||||
@@ -146,7 +146,7 @@
|
||||
[value]="evidenceReason()"
|
||||
(input)="updateEvidenceReason($event)"
|
||||
/>
|
||||
</label>
|
||||
</mat-form-field>
|
||||
}
|
||||
@if (evidenceError() || evidenceOperationError()) {
|
||||
<p class="operation-error" role="alert">
|
||||
@@ -168,8 +168,8 @@
|
||||
>
|
||||
<fieldset [disabled]="withdrawalPending()">
|
||||
<legend>Accepter un retrait</legend>
|
||||
<label>
|
||||
<span>Date d’acceptation</span>
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Date d’acceptation</mat-label>
|
||||
<input
|
||||
matInput
|
||||
id="withdrawal-date"
|
||||
@@ -177,7 +177,7 @@
|
||||
[formField]="withdrawalForm.acceptedOn"
|
||||
(input)="withdrawalFieldChanged.emit('acceptedOn')"
|
||||
/>
|
||||
</label>
|
||||
</mat-form-field>
|
||||
@if (withdrawalDateError()) {
|
||||
<p class="operation-error" role="alert">{{ withdrawalDateError() }}</p>
|
||||
}
|
||||
@@ -186,16 +186,16 @@
|
||||
{{ serverError(withdrawalFieldErrors(), 'acceptedOn') }}
|
||||
</p>
|
||||
}
|
||||
<label
|
||||
><span>Raison</span
|
||||
><textarea
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Raison</mat-label>
|
||||
<textarea
|
||||
matInput
|
||||
id="withdrawal-reason"
|
||||
rows="2"
|
||||
[formField]="withdrawalForm.reason"
|
||||
(input)="withdrawalFieldChanged.emit('reason')"
|
||||
></textarea>
|
||||
</label>
|
||||
</mat-form-field>
|
||||
@if (withdrawalReasonError()) {
|
||||
<p class="operation-error" role="alert">
|
||||
{{ withdrawalReasonError() }}
|
||||
@@ -223,8 +223,8 @@
|
||||
>
|
||||
<fieldset [disabled]="invalidationPending()">
|
||||
<legend>Invalider administrativement</legend>
|
||||
<label>
|
||||
<span>Date d’invalidation</span>
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Date d’invalidation</mat-label>
|
||||
<input
|
||||
matInput
|
||||
id="invalidation-date"
|
||||
@@ -232,7 +232,7 @@
|
||||
[formField]="invalidationForm.invalidatedOn"
|
||||
(input)="invalidationFieldChanged.emit('invalidatedOn')"
|
||||
/>
|
||||
</label>
|
||||
</mat-form-field>
|
||||
@if (invalidationDateError()) {
|
||||
<p class="operation-error" role="alert">
|
||||
{{ invalidationDateError() }}
|
||||
@@ -243,16 +243,16 @@
|
||||
{{ serverError(invalidationFieldErrors(), 'invalidatedOn') }}
|
||||
</p>
|
||||
}
|
||||
<label
|
||||
><span>Raison</span
|
||||
><textarea
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Raison</mat-label>
|
||||
<textarea
|
||||
matInput
|
||||
id="invalidation-reason"
|
||||
rows="2"
|
||||
[formField]="invalidationForm.reason"
|
||||
(input)="invalidationFieldChanged.emit('reason')"
|
||||
></textarea>
|
||||
</label>
|
||||
</mat-form-field>
|
||||
@if (invalidationReasonError()) {
|
||||
<p class="operation-error" role="alert">
|
||||
{{ invalidationReasonError() }}
|
||||
|
||||
@@ -28,16 +28,9 @@ fieldset {
|
||||
grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr));
|
||||
gap: 1rem;
|
||||
}
|
||||
label:not(.confirmation-field) {
|
||||
display: grid;
|
||||
gap: 0.4rem;
|
||||
mat-form-field {
|
||||
min-width: 0;
|
||||
}
|
||||
input,
|
||||
select {
|
||||
min-width: 0;
|
||||
min-height: 2.75rem;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
}
|
||||
.confirmation-field {
|
||||
display: flex;
|
||||
@@ -57,11 +50,6 @@ select {
|
||||
margin-block-start: 0;
|
||||
color: var(--text-muted, #5f6368);
|
||||
}
|
||||
input:focus-visible,
|
||||
select:focus-visible {
|
||||
outline: 2px solid var(--accent, #236b5d);
|
||||
outline-offset: 0.15rem;
|
||||
}
|
||||
.operation-error {
|
||||
color: var(--danger, #b42318);
|
||||
}
|
||||
@@ -8,8 +8,8 @@
|
||||
>
|
||||
<fieldset [disabled]="submitting()">
|
||||
<div class="form-grid field-grid">
|
||||
<label>
|
||||
<span>Date de réception</span>
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Date de réception</mat-label>
|
||||
<input
|
||||
matInput
|
||||
id="notice-received-on"
|
||||
@@ -17,15 +17,15 @@
|
||||
[formField]="noticeForm.receivedOn"
|
||||
(input)="fieldWasChanged('receivedOn')"
|
||||
/>
|
||||
@if (receivedOnError()) {
|
||||
<p class="operation-error" role="alert">{{ receivedOnError() }}</p>
|
||||
}
|
||||
@if (serverError('receivedOn')) {
|
||||
<p class="operation-error" role="alert">{{ serverError('receivedOn') }}</p>
|
||||
}
|
||||
</label>
|
||||
<label>
|
||||
<span>Départ demandé</span>
|
||||
</mat-form-field>
|
||||
@if (receivedOnError()) {
|
||||
<p class="operation-error" role="alert">{{ receivedOnError() }}</p>
|
||||
}
|
||||
@if (serverError('receivedOn')) {
|
||||
<p class="operation-error" role="alert">{{ serverError('receivedOn') }}</p>
|
||||
}
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Départ demandé</mat-label>
|
||||
<input
|
||||
matInput
|
||||
id="notice-requested-departure-on"
|
||||
@@ -33,38 +33,37 @@
|
||||
[formField]="noticeForm.requestedDepartureOn"
|
||||
(input)="fieldWasChanged('requestedDepartureOn')"
|
||||
/>
|
||||
@if (requestedDepartureOnError()) {
|
||||
<p class="operation-error" role="alert">
|
||||
{{ requestedDepartureOnError() }}
|
||||
</p>
|
||||
}
|
||||
@if (serverError('requestedDepartureOn')) {
|
||||
<p class="operation-error" role="alert">
|
||||
{{ serverError('requestedDepartureOn') }}
|
||||
</p>
|
||||
}
|
||||
</label>
|
||||
</mat-form-field>
|
||||
@if (requestedDepartureOnError()) {
|
||||
<p class="operation-error" role="alert">
|
||||
{{ requestedDepartureOnError() }}
|
||||
</p>
|
||||
}
|
||||
@if (serverError('requestedDepartureOn')) {
|
||||
<p class="operation-error" role="alert">
|
||||
{{ serverError('requestedDepartureOn') }}
|
||||
</p>
|
||||
}
|
||||
</div>
|
||||
<label>
|
||||
<span>Mode de remise</span>
|
||||
<select
|
||||
matNativeControl
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Mode de remise</mat-label>
|
||||
<mat-select
|
||||
id="notice-delivery-mode"
|
||||
[formField]="noticeForm.deliveryMode"
|
||||
(change)="fieldWasChanged('deliveryMode')"
|
||||
(selectionChange)="fieldWasChanged('deliveryMode')"
|
||||
>
|
||||
<option value="">Choisissez un mode</option>
|
||||
<mat-option value="">Choisissez un mode</mat-option>
|
||||
@for (mode of deliveryModes; track mode.value) {
|
||||
<option [value]="mode.value">{{ mode.label }}</option>
|
||||
<mat-option [value]="mode.value">{{ mode.label }}</mat-option>
|
||||
}
|
||||
</select>
|
||||
@if (deliveryModeError()) {
|
||||
<p class="operation-error" role="alert">{{ deliveryModeError() }}</p>
|
||||
}
|
||||
</label>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
@if (deliveryModeError()) {
|
||||
<p class="operation-error" role="alert">{{ deliveryModeError() }}</p>
|
||||
}
|
||||
@if (model().deliveryMode === 'OTHER') {
|
||||
<label>
|
||||
<span>Mode de remise utilisé</span>
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Mode de remise utilisé</mat-label>
|
||||
<input
|
||||
matInput
|
||||
id="notice-other-delivery-mode"
|
||||
@@ -72,15 +71,15 @@
|
||||
[formField]="noticeForm.otherDeliveryMode"
|
||||
(input)="fieldWasChanged('otherDeliveryMode')"
|
||||
/>
|
||||
@if (otherDeliveryModeError()) {
|
||||
<p class="operation-error" role="alert">{{ otherDeliveryModeError() }}</p>
|
||||
}
|
||||
@if (serverError('otherDeliveryMode')) {
|
||||
<p class="operation-error" role="alert">
|
||||
{{ serverError('otherDeliveryMode') }}
|
||||
</p>
|
||||
}
|
||||
</label>
|
||||
</mat-form-field>
|
||||
@if (otherDeliveryModeError()) {
|
||||
<p class="operation-error" role="alert">{{ otherDeliveryModeError() }}</p>
|
||||
}
|
||||
@if (serverError('otherDeliveryMode')) {
|
||||
<p class="operation-error" role="alert">
|
||||
{{ serverError('otherDeliveryMode') }}
|
||||
</p>
|
||||
}
|
||||
<mat-checkbox
|
||||
class="confirmation-field"
|
||||
[formField]="noticeForm.nonStandardDeliveryConfirmed"
|
||||
|
||||
@@ -14,6 +14,7 @@ import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
import { NoticeDeliveryMode, RecordNoticeRequest } from '../../services/lease-end.service';
|
||||
import { FieldValidationError } from '../../services/http-error-message';
|
||||
|
||||
@@ -46,6 +47,7 @@ const serverMessages: Record<string, Record<string, string>> = {
|
||||
MatCheckboxModule,
|
||||
MatFormFieldModule,
|
||||
MatInputModule,
|
||||
MatSelectModule,
|
||||
],
|
||||
templateUrl: './lease-end-notice-form.html',
|
||||
styleUrl: './lease-end-notice-form.css',
|
||||
|
||||
+3
-11
@@ -20,8 +20,7 @@
|
||||
h2 {
|
||||
margin-block-start: 0;
|
||||
}
|
||||
fieldset,
|
||||
label:not(.confirmation-field) {
|
||||
fieldset {
|
||||
display: grid;
|
||||
gap: 0.75rem;
|
||||
min-width: 0;
|
||||
@@ -31,11 +30,9 @@ fieldset {
|
||||
padding: 0;
|
||||
border: 0;
|
||||
}
|
||||
input,
|
||||
textarea {
|
||||
mat-form-field {
|
||||
min-width: 0;
|
||||
min-height: 2.75rem;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
}
|
||||
.confirmation-field {
|
||||
display: flex;
|
||||
@@ -54,11 +51,6 @@ textarea {
|
||||
.report-date span {
|
||||
color: var(--text-muted, #5f6368);
|
||||
}
|
||||
input:focus-visible,
|
||||
textarea:focus-visible {
|
||||
outline: 2px solid var(--accent, #236b5d);
|
||||
outline-offset: 0.15rem;
|
||||
}
|
||||
.operation-error {
|
||||
color: var(--danger, #b42318);
|
||||
}
|
||||
+6
-6
@@ -8,8 +8,8 @@
|
||||
(submit)="submitAgreement(); $event.preventDefault()"
|
||||
>
|
||||
<fieldset [disabled]="agreementPending()">
|
||||
<label>
|
||||
<span>Date de fin convenue</span>
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Date de fin convenue</mat-label>
|
||||
<input
|
||||
matInput
|
||||
id="agreement-end-on"
|
||||
@@ -17,7 +17,7 @@
|
||||
[formField]="agreementForm.endOn"
|
||||
(input)="agreementFieldChanged.emit('endOn')"
|
||||
/>
|
||||
</label>
|
||||
</mat-form-field>
|
||||
@if (agreementDateError()) {
|
||||
<p class="operation-error" role="alert">{{ agreementDateError() }}</p>
|
||||
}
|
||||
@@ -26,8 +26,8 @@
|
||||
{{ serverError(agreementFieldErrors(), 'endOn') }}
|
||||
</p>
|
||||
}
|
||||
<label>
|
||||
<span>Raison de l’accord</span>
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Raison de l’accord</mat-label>
|
||||
<textarea
|
||||
matInput
|
||||
id="agreement-reason"
|
||||
@@ -35,7 +35,7 @@
|
||||
[formField]="agreementForm.reason"
|
||||
(input)="agreementFieldChanged.emit('reason')"
|
||||
></textarea>
|
||||
</label>
|
||||
</mat-form-field>
|
||||
@if (agreementReasonError()) {
|
||||
<p class="operation-error" role="alert">{{ agreementReasonError() }}</p>
|
||||
}
|
||||
|
||||
+1
-10
@@ -38,17 +38,8 @@ form label {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
select,
|
||||
input[type='file'] {
|
||||
box-sizing: border-box;
|
||||
mat-form-field {
|
||||
width: 100%;
|
||||
min-height: 2.75rem;
|
||||
max-width: 100%;
|
||||
border: 1px solid var(--border-strong, #aebbb4);
|
||||
border-radius: var(--radius-sm, 0.5rem);
|
||||
background: var(--surface, #fff);
|
||||
color: var(--text, #17211e);
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
.attestation {
|
||||
|
||||
+11
-12
@@ -11,23 +11,22 @@
|
||||
(submit)="submit(); $event.preventDefault()"
|
||||
>
|
||||
<fieldset [disabled]="pending()">
|
||||
<label>
|
||||
<span>Mode d’envoi</span>
|
||||
<select
|
||||
matNativeControl
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Mode d’envoi</mat-label>
|
||||
<mat-select
|
||||
class="delivery-method"
|
||||
[formField]="applicationForm.deliveryMethod"
|
||||
(change)="clearFieldError('deliveryMethod')"
|
||||
(selectionChange)="clearFieldError('deliveryMethod')"
|
||||
>
|
||||
<option value="">Choisissez un mode</option>
|
||||
<mat-option value="">Choisissez un mode</mat-option>
|
||||
@for (method of deliveryMethods; track method.value) {
|
||||
<option [value]="method.value">{{ method.label }}</option>
|
||||
<mat-option [value]="method.value">{{ method.label }}</mat-option>
|
||||
}
|
||||
</select>
|
||||
@if (fieldError('deliveryMethod')) {
|
||||
<small class="field-error">{{ fieldError('deliveryMethod') }}</small>
|
||||
}
|
||||
</label>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
@if (fieldError('deliveryMethod')) {
|
||||
<small class="field-error">{{ fieldError('deliveryMethod') }}</small>
|
||||
}
|
||||
<div>
|
||||
<span>Preuve d’envoi PDF (facultative)</span>
|
||||
<input
|
||||
|
||||
+12
-8
@@ -1,6 +1,8 @@
|
||||
import { provideHttpClient } from '@angular/common/http';
|
||||
import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing';
|
||||
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { MatSelectHarness } from '@angular/material/select/testing';
|
||||
import { vi } from 'vitest';
|
||||
import { RentRevisionResponse } from '../../services/lease.service';
|
||||
import { RentRevisionApplicationComponent } from './rent-revision-application';
|
||||
@@ -65,10 +67,11 @@ describe('RentRevisionApplicationComponent', () => {
|
||||
expect(fixture.nativeElement.textContent).toContain('Choisissez le mode d’envoi.');
|
||||
http.expectNone((request) => request.method === 'POST');
|
||||
|
||||
const delivery: HTMLSelectElement = fixture.nativeElement.querySelector('.delivery-method');
|
||||
delivery.value = 'EMAIL';
|
||||
delivery.dispatchEvent(new Event('input'));
|
||||
await fixture.whenStable();
|
||||
const loader = TestbedHarnessEnvironment.loader(fixture);
|
||||
const delivery = await loader.getHarness(
|
||||
MatSelectHarness.with({ selector: '.delivery-method' }),
|
||||
);
|
||||
await delivery.clickOptions({ text: 'Courriel' });
|
||||
fixture.detectChanges();
|
||||
fixture.nativeElement.querySelector('.apply-submit').click();
|
||||
fixture.detectChanges();
|
||||
@@ -82,10 +85,11 @@ describe('RentRevisionApplicationComponent', () => {
|
||||
const fixture = createComponent();
|
||||
const applied = vi.fn();
|
||||
fixture.componentInstance.applied.subscribe(applied);
|
||||
const delivery: HTMLSelectElement = fixture.nativeElement.querySelector('.delivery-method');
|
||||
delivery.value = 'REGISTERED_LETTER';
|
||||
delivery.dispatchEvent(new Event('input'));
|
||||
await fixture.whenStable();
|
||||
const loader = TestbedHarnessEnvironment.loader(fixture);
|
||||
const delivery = await loader.getHarness(
|
||||
MatSelectHarness.with({ selector: '.delivery-method' }),
|
||||
);
|
||||
await delivery.clickOptions({ text: 'Lettre recommandée' });
|
||||
fixture.nativeElement.querySelector('.delivery-confirmed input').click();
|
||||
const proof = new File(['pdf'], 'preuve-envoi.pdf', { type: 'application/pdf' });
|
||||
const proofInput: HTMLInputElement =
|
||||
|
||||
@@ -6,6 +6,7 @@ import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
import { finalize } from 'rxjs';
|
||||
import {
|
||||
ApplyRentRevisionResponse,
|
||||
@@ -32,6 +33,7 @@ const frenchDate = new Intl.DateTimeFormat('fr-FR', {
|
||||
MatCheckboxModule,
|
||||
MatFormFieldModule,
|
||||
MatInputModule,
|
||||
MatSelectModule,
|
||||
],
|
||||
templateUrl: './rent-revision-application.html',
|
||||
styleUrl: './rent-revision-application.css',
|
||||
|
||||
@@ -21,19 +21,18 @@
|
||||
>
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Nouvelle série officielle</mat-label>
|
||||
<select
|
||||
matNativeControl
|
||||
<mat-select
|
||||
class="series-override"
|
||||
[formField]="requestForm.seriesIdOverride"
|
||||
(change)="onSeriesChanged()"
|
||||
(selectionChange)="onSeriesChanged()"
|
||||
>
|
||||
<option value="">Série prévue dans le bail</option>
|
||||
<option value="001515333">Métropole — 001515333</option>
|
||||
<option value="010760507">Corse — 010760507</option>
|
||||
<option value="010760509">
|
||||
<mat-option value="">Série prévue dans le bail</mat-option>
|
||||
<mat-option value="001515333">Métropole — 001515333</mat-option>
|
||||
<mat-option value="010760507">Corse — 010760507</mat-option>
|
||||
<mat-option value="010760509">
|
||||
Départements d’outre-mer (article 73) — 010760509
|
||||
</option>
|
||||
</select>
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
@if (fieldError('seriesIdOverride')) {
|
||||
<small class="field-error">{{ fieldError('seriesIdOverride') }}</small>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { provideHttpClient } from '@angular/common/http';
|
||||
import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing';
|
||||
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { MatSelectHarness } from '@angular/material/select/testing';
|
||||
import { RentRevisionPreview } from '../../services/lease.service';
|
||||
import { WorkspaceService } from '../../services/workspace.service';
|
||||
import { RentRevisionPreviewComponent } from './rent-revision-preview';
|
||||
@@ -148,19 +150,20 @@ describe('RentRevisionPreviewComponent', () => {
|
||||
|
||||
it('requires an attestation before overriding the INSEE series', async () => {
|
||||
const fixture = createComponent();
|
||||
const series: HTMLSelectElement = fixture.nativeElement.querySelector('.series-override');
|
||||
expect([...series.options].map((option) => option.value)).toEqual([
|
||||
'',
|
||||
'001515333',
|
||||
'010760507',
|
||||
'010760509',
|
||||
const loader = TestbedHarnessEnvironment.loader(fixture);
|
||||
const series = await loader.getHarness(
|
||||
MatSelectHarness.with({ selector: '.series-override' }),
|
||||
);
|
||||
await series.open();
|
||||
const options = await series.getOptions();
|
||||
expect(await Promise.all(options.map((option) => option.getText()))).toEqual([
|
||||
'Série prévue dans le bail',
|
||||
'Métropole — 001515333',
|
||||
'Corse — 010760507',
|
||||
'Départements d’outre-mer (article 73) — 010760509',
|
||||
]);
|
||||
expect(series.textContent).toContain('Métropole — 001515333');
|
||||
expect(series.textContent).toContain('Corse — 010760507');
|
||||
expect(series.textContent).toContain('Départements d’outre-mer (article 73) — 010760509');
|
||||
series.value = '001515333';
|
||||
series.dispatchEvent(new Event('input'));
|
||||
await fixture.whenStable();
|
||||
await series.close();
|
||||
await series.clickOptions({ text: 'Métropole — 001515333' });
|
||||
fixture.detectChanges();
|
||||
|
||||
fixture.nativeElement.querySelector('.preview-submit').click();
|
||||
|
||||
@@ -7,6 +7,7 @@ import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||
import { MatExpansionModule } from '@angular/material/expansion';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
import { finalize } from 'rxjs';
|
||||
import {
|
||||
LeaseService,
|
||||
@@ -42,6 +43,7 @@ const indexFormatter = new Intl.NumberFormat('fr-FR', { maximumFractionDigits: 4
|
||||
MatExpansionModule,
|
||||
MatFormFieldModule,
|
||||
MatInputModule,
|
||||
MatSelectModule,
|
||||
RentRevisionProposalsComponent,
|
||||
],
|
||||
templateUrl: './rent-revision-preview.html',
|
||||
|
||||
@@ -36,28 +36,15 @@
|
||||
gap: var(--space-3, 0.75rem);
|
||||
}
|
||||
|
||||
.field-grid label,
|
||||
.proposal-field,
|
||||
.proposal-warnings,
|
||||
.attestation {
|
||||
display: grid;
|
||||
gap: var(--space-2, 0.5rem);
|
||||
}
|
||||
|
||||
.field-grid label {
|
||||
font-size: 0.78rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.field-grid input {
|
||||
box-sizing: border-box;
|
||||
mat-form-field {
|
||||
width: 100%;
|
||||
min-height: 2.75rem;
|
||||
padding-inline: var(--space-3, 0.75rem);
|
||||
border: 1px solid var(--border-strong, #aebbb4);
|
||||
border-radius: var(--radius-sm, 0.5rem);
|
||||
background: var(--surface, #fff);
|
||||
color: var(--text, #17211e);
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
.bounds,
|
||||
|
||||
@@ -22,50 +22,56 @@
|
||||
<fieldset [disabled]="creating()">
|
||||
<h4>Créer la proposition et sa lettre</h4>
|
||||
<div class="field-grid">
|
||||
<label>
|
||||
<span>Date de la demande</span>
|
||||
<input
|
||||
matInput
|
||||
type="date"
|
||||
class="requested-on"
|
||||
[formField]="proposalForm.requestedOn"
|
||||
(input)="clearFieldError('requestedOn')"
|
||||
/>
|
||||
<div class="proposal-field">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Date de la demande</mat-label>
|
||||
<input
|
||||
matInput
|
||||
type="date"
|
||||
class="requested-on"
|
||||
[formField]="proposalForm.requestedOn"
|
||||
(input)="clearFieldError('requestedOn')"
|
||||
/>
|
||||
</mat-form-field>
|
||||
@if (fieldError('requestedOn')) {
|
||||
<small class="field-error">{{ fieldError('requestedOn') }}</small>
|
||||
}
|
||||
</label>
|
||||
<label>
|
||||
<span>Nouveau loyer choisi</span>
|
||||
<input
|
||||
matInput
|
||||
type="number"
|
||||
step="0.01"
|
||||
class="chosen-rent"
|
||||
[formField]="proposalForm.chosenRent"
|
||||
(input)="clearFieldError('chosenRent')"
|
||||
/>
|
||||
@if (fieldError('chosenRent')) {
|
||||
<small class="field-error">{{ fieldError('chosenRent') }}</small>
|
||||
}
|
||||
</label>
|
||||
@if (currentPreview.chargeCeiling !== null) {
|
||||
<label>
|
||||
<span>Nouvelles charges choisies</span>
|
||||
</div>
|
||||
<div class="proposal-field">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Nouveau loyer choisi</mat-label>
|
||||
<input
|
||||
matInput
|
||||
type="number"
|
||||
step="0.01"
|
||||
class="chosen-charges"
|
||||
[formField]="proposalForm.chosenCharges"
|
||||
(input)="clearFieldError('chosenCharges')"
|
||||
class="chosen-rent"
|
||||
[formField]="proposalForm.chosenRent"
|
||||
(input)="clearFieldError('chosenRent')"
|
||||
/>
|
||||
</mat-form-field>
|
||||
@if (fieldError('chosenRent')) {
|
||||
<small class="field-error">{{ fieldError('chosenRent') }}</small>
|
||||
}
|
||||
</div>
|
||||
@if (currentPreview.chargeCeiling !== null) {
|
||||
<div class="proposal-field">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Nouvelles charges choisies</mat-label>
|
||||
<input
|
||||
matInput
|
||||
type="number"
|
||||
step="0.01"
|
||||
class="chosen-charges"
|
||||
[formField]="proposalForm.chosenCharges"
|
||||
(input)="clearFieldError('chosenCharges')"
|
||||
/>
|
||||
</mat-form-field>
|
||||
@if (fieldError('chosenCharges')) {
|
||||
<small class="field-error">{{
|
||||
fieldError('chosenCharges')
|
||||
}}</small>
|
||||
}
|
||||
</label>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<p class="bounds">
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { provideHttpClient } from '@angular/common/http';
|
||||
import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing';
|
||||
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { MatSelectHarness } from '@angular/material/select/testing';
|
||||
import { vi } from 'vitest';
|
||||
import {
|
||||
RentRevisionPreview,
|
||||
@@ -258,10 +260,11 @@ describe('RentRevisionProposalsComponent', () => {
|
||||
fixture.nativeElement.querySelectorAll('app-rent-revision-application'),
|
||||
).toHaveLength(2);
|
||||
expect(fixture.nativeElement.querySelector('.proposal-form')).not.toBeNull();
|
||||
const delivery: HTMLSelectElement = fixture.nativeElement.querySelector('.delivery-method');
|
||||
delivery.value = 'EMAIL';
|
||||
delivery.dispatchEvent(new Event('input'));
|
||||
await fixture.whenStable();
|
||||
const loader = TestbedHarnessEnvironment.loader(fixture);
|
||||
const delivery = await loader.getHarness(
|
||||
MatSelectHarness.with({ selector: '.delivery-method' }),
|
||||
);
|
||||
await delivery.clickOptions({ text: 'Courriel' });
|
||||
fixture.nativeElement.querySelector('.delivery-confirmed input').click();
|
||||
fixture.detectChanges();
|
||||
fixture.nativeElement.querySelector('.apply-submit').click();
|
||||
|
||||
Reference in new issue
Block a user