Skip to content

Commit

Permalink
Merge pull request #79 from Kleostro/feat/tu-01-15/carriage-configura…
Browse files Browse the repository at this point in the history
…tion-form

feat(tu-01-15): carriage configuration form
Kleostro authored Aug 19, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
2 parents 201f2a5 + 2869b54 commit 3075f94
Showing 28 changed files with 618 additions and 33 deletions.
10 changes: 9 additions & 1 deletion src/app/admin/components/carriage/carriage.component.html
Original file line number Diff line number Diff line change
@@ -3,7 +3,15 @@
<div class="car-top">
<strong class="title">{{ carriage.name | uppercase }}</strong>
<span class="seats-count">{{ (carriage.leftSeats + carriage.rightSeats) * carriage.rows }} seats</span>
<p-button [rounded]="true" class="edit-btn" severity="success" icon="pi pi-pencil" />
@if (isEditable()) {
<p-button
[rounded]="true"
class="edit-btn"
severity="success"
icon="pi pi-pencil"
(click)="openEditModal.emit(carriage)"
/>
}
</div>

<div class="car-bottom">
9 changes: 7 additions & 2 deletions src/app/admin/components/carriage/carriage.component.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { UpperCasePipe } from '@angular/common';
import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';
import { ChangeDetectionStrategy, Component, computed, EventEmitter, inject, input, Output } from '@angular/core';

import { ButtonModule } from 'primeng/button';
import { RippleModule } from 'primeng/ripple';

import { Carriage } from '@/app/api/models/carriage';

import { ModalService } from '../../../shared/services/modal/modal.service';
import createSeatsSchema from '../../utils/createSeatsSchema';
import { SeatComponent } from '../seat/seat.component';

@@ -19,5 +20,9 @@ import { SeatComponent } from '../seat/seat.component';
})
export class CarriageComponent {
public carriage = input<Carriage | null>(null);
public seatsSchema = computed(() => createSeatsSchema(this.carriage()!));
public isEditable = input(false);
public seatsSchema = computed(() => createSeatsSchema(this.carriage()));
public modalService = inject(ModalService);

@Output() public openEditModal: EventEmitter<Carriage> = new EventEmitter<Carriage>();
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
<div class="wrapper">
@for (carriage of allCarriages(); track carriage) {
<app-carriage [carriage]="carriage"></app-carriage>
<app-carriage
[carriage]="carriage"
[isEditable]="true"
(openEditModal)="handleOpenEditModal($event)"
></app-carriage>
}
</div>

<ng-template #editContent>
<app-update-carriage-form [carriage]="editCarriage()"></app-update-carriage-form>
</ng-template>
Original file line number Diff line number Diff line change
@@ -1,17 +1,28 @@
import { ChangeDetectionStrategy, Component, input } from '@angular/core';
import { ChangeDetectionStrategy, Component, inject, input, signal, TemplateRef, ViewChild } from '@angular/core';

import { Carriage } from '@/app/api/models/carriage';
import { ModalService } from '@/app/shared/services/modal/modal.service';

import { CarriageComponent } from '../carriage/carriage.component';
import { UpdateCarriageFormComponent } from '../update-carriage-form/update-carriage-form.component';

@Component({
selector: 'app-carriages-list',
standalone: true,
imports: [CarriageComponent],
imports: [CarriageComponent, UpdateCarriageFormComponent],
templateUrl: './carriages-list.component.html',
styleUrl: './carriages-list.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CarriagesListComponent {
public modalService = inject(ModalService);
public allCarriages = input<Carriage[]>([]);
public editCarriage = signal<Carriage | null>(null);

@ViewChild('editContent') public editContent!: TemplateRef<unknown>;

public handleOpenEditModal(carriage: Carriage): void {
this.editCarriage.set(carriage);
this.modalService.openModal(this.editContent, 'Edit carriage');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<form class="form" [formGroup]="carriageForm" (ngSubmit)="submit()">
<div class="controls">
<div class="control">
<label for="name"> Carriage name:</label>
<input pInputText type="text" id="name" formControlName="name" />
</div>
<div class="control">
<label for="rows"> Rows count:</label>
<p-inputNumber inputId="rows" formControlName="rows" />
</div>
<div class="control">
<label for="rightSeats"> Right seats count:</label>
<p-inputNumber inputId="rightSeats" formControlName="rightSeats" />
</div>
<div class="control">
<label for="leftSeats"> Left seats count:</label>
<p-inputNumber inputId="leftSeats" formControlName="leftSeats" />
</div>
<button
pButton
pRipple
type="submit"
class="p-button-success submit"
label="Save"
[disabled]="carriageForm.invalid"
[loading]="isCreated()"
></button>
</div>

@if (newCarriage(); as newCarriage) {
<app-carriage [carriage]="newCarriage"></app-carriage>
}
</form>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
.controls {
display: flex;
gap: 0.5rem;
margin: 1rem 0;
}

.control {
display: flex;
flex-direction: column;
gap: 0.2rem;
}

.submit {
align-self: end;
padding: 0.5rem 1rem;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { provideHttpClient } from '@angular/common/http';
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { MessageService } from 'primeng/api';

import { CreateCarriageFormComponent } from './create-carriage-form.component';

describe('CreateCarriageFormComponent', () => {
let component: CreateCarriageFormComponent;
let fixture: ComponentFixture<CreateCarriageFormComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [CreateCarriageFormComponent],
providers: [{ provide: MessageService, useValue: {} }, provideHttpClient()],
}).compileComponents();

fixture = TestBed.createComponent(CreateCarriageFormComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
inject,
OnDestroy,
OnInit,
signal,
} from '@angular/core';
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';

import { ButtonModule } from 'primeng/button';
import { InputNumberModule } from 'primeng/inputnumber';
import { InputTextModule } from 'primeng/inputtext';
import { RippleModule } from 'primeng/ripple';
import { debounceTime, distinctUntilChanged, map, Subscription } from 'rxjs';

import { CarriageService } from '@/app/api/carriagesService/carriage.service';
import { Carriage } from '@/app/api/models/carriage';
import { ModalService } from '@/app/shared/services/modal/modal.service';
import { USER_MESSAGE } from '@/app/shared/services/userMessage/constants/user-messages';
import { UserMessageService } from '@/app/shared/services/userMessage/user-message.service';

import { CarriageComponent } from '../carriage/carriage.component';

@Component({
selector: 'app-create-carriage-form',
standalone: true,
imports: [ReactiveFormsModule, InputNumberModule, ButtonModule, RippleModule, CarriageComponent, InputTextModule],
templateUrl: './create-carriage-form.component.html',
styleUrl: './create-carriage-form.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CreateCarriageFormComponent implements OnInit, OnDestroy {
private fb = inject(FormBuilder);
private cdr = inject(ChangeDetectorRef);
private modalService = inject(ModalService);
private userMessageService = inject(UserMessageService);
private carriageService = inject(CarriageService);
public newCarriage = signal<Carriage>({ name: '', rows: 0, leftSeats: 0, rightSeats: 0, code: '' });
public isCreated = signal(false);
private subsciption = new Subscription();
public carriageForm = this.fb.nonNullable.group({
name: ['', [Validators.required.bind(this)]],
rows: [0, [Validators.required.bind(this), Validators.min(1)]],
leftSeats: [0, [Validators.required.bind(this), Validators.min(1)]],
rightSeats: [0, [Validators.required.bind(this), Validators.min(1)]],
});

public redrawCurrentCarriage(formValue: Partial<Carriage>): void {
const { name, rows, leftSeats, rightSeats } = formValue;

const currentCarriage = this.newCarriage();
if (currentCarriage) {
currentCarriage.name = name ?? currentCarriage.name;
currentCarriage.rows = rows ?? currentCarriage.rows;
currentCarriage.leftSeats = leftSeats ?? currentCarriage.leftSeats;
currentCarriage.rightSeats = rightSeats ?? currentCarriage.rightSeats;
this.newCarriage.set({ ...currentCarriage });
this.cdr.detectChanges();
}

this.cdr.detectChanges();
}

public submit(): void {
this.carriageForm.markAsTouched();
this.carriageForm.updateValueAndValidity();
const updatedCarriage = {
name: this.carriageForm.controls.name.value ?? '',
rows: this.carriageForm.controls.rows.value,
leftSeats: this.carriageForm.controls.leftSeats.value,
rightSeats: this.carriageForm.controls.rightSeats.value,
};

if (this.carriageForm.valid) {
this.isCreated.set(true);
this.carriageService.createCarriage(updatedCarriage).subscribe({
next: () => this.submitSuccessHandler(),
});
}
}

private submitSuccessHandler(): void {
this.carriageService.getCarriages().subscribe((carriages) => {
this.carriageService.allCarriages.next([carriages[carriages.length - 1], ...carriages]);
});
this.isCreated.set(false);
this.modalService.closeModal();
this.userMessageService.showSuccessMessage(USER_MESSAGE.CARRIAGE_CREATED_SUCCESSFULLY);
}

public ngOnInit(): void {
this.subsciption.add(
this.carriageForm.valueChanges
.pipe(
debounceTime(500),
distinctUntilChanged(),
map((value) => this.redrawCurrentCarriage(value)),
)
.subscribe(),
);
}

public ngOnDestroy(): void {
this.subsciption.unsubscribe();
}
}
2 changes: 2 additions & 0 deletions src/app/admin/components/sidebar/sidebar.component.scss
Original file line number Diff line number Diff line change
@@ -25,6 +25,8 @@
}

.links {
position: sticky;
top: 0;
display: flex;
flex-direction: column;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<form class="form" [formGroup]="carriageForm" (ngSubmit)="submit()">
<div class="controls">
<div class="control">
<label for="rows"> Rows count:</label>
<p-inputNumber inputId="rows" formControlName="rows" />
</div>
<div class="control">
<label for="rightSeats"> Right seats count:</label>
<p-inputNumber inputId="rightSeats" formControlName="rightSeats" />
</div>
<div class="control">
<label for="leftSeats"> Left seats count:</label>
<p-inputNumber inputId="leftSeats" formControlName="leftSeats" />
</div>
<button
pButton
pRipple
type="submit"
class="p-button-success submit"
label="Save"
[disabled]="carriageForm.invalid"
[loading]="isUpdating()"
></button>
</div>

@if (currentCarriage(); as currentCarriage) {
<app-carriage [carriage]="currentCarriage"></app-carriage>
}
</form>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
.controls {
display: flex;
gap: 0.5rem;
margin: 1rem 0;
}

.control {
display: flex;
flex-direction: column;
gap: 0.2rem;
}

.submit {
align-self: end;
padding: 0.5rem 1rem;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { provideHttpClient } from '@angular/common/http';
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { MessageService } from 'primeng/api';

import { UpdateCarriageFormComponent } from './update-carriage-form.component';

describe('UpdateCarriageFormComponent', () => {
let component: UpdateCarriageFormComponent;
let fixture: ComponentFixture<UpdateCarriageFormComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [UpdateCarriageFormComponent],
providers: [{ provide: MessageService, useValue: {} }, provideHttpClient()],
}).compileComponents();

fixture = TestBed.createComponent(UpdateCarriageFormComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Loading

0 comments on commit 3075f94

Please sign in to comment.