Add claims pages
This commit is contained in:
@@ -1,8 +1,12 @@
|
||||
import { Routes } from '@angular/router';
|
||||
import { HomepageComponent } from './features/homepage/homepage.component';
|
||||
import { InsuranceDetailComponent } from './features/insurance-detail/insurance-detail.component';
|
||||
import { ClaimComponent } from './features/claim/claim.component';
|
||||
import { ClaimNewComponent } from './features/claim-new/claim-new.component';
|
||||
|
||||
export const routes: Routes = [
|
||||
{ path: '', component: HomepageComponent },
|
||||
{ path: 'plan/:id', component: InsuranceDetailComponent }
|
||||
{ path: 'plan/:id', component: InsuranceDetailComponent },
|
||||
{ path: 'claims', component: ClaimComponent },
|
||||
{ path: 'claims/new', component: ClaimNewComponent }
|
||||
];
|
||||
|
||||
0
src/app/features/claim-new/claim-new.component.css
Normal file
0
src/app/features/claim-new/claim-new.component.css
Normal file
27
src/app/features/claim-new/claim-new.component.html
Normal file
27
src/app/features/claim-new/claim-new.component.html
Normal file
@@ -0,0 +1,27 @@
|
||||
<div class="container mt-4">
|
||||
<h2>New Claim Submission</h2>
|
||||
|
||||
<form [formGroup]="claimForm" (ngSubmit)="onSubmit()">
|
||||
<div class="mb-2">
|
||||
<label>Name</label>
|
||||
<input type="text" class="form-control" formControlName="name" />
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label>Policy ID</label>
|
||||
<input type="text" class="form-control" formControlName="policyID" />
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label>Reason</label>
|
||||
<input type="text" class="form-control" formControlName="claimReason" />
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label>Amount</label>
|
||||
<input type="number" class="form-control" formControlName="claimAmount" />
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-success" [disabled]="claimForm.invalid">
|
||||
Submit
|
||||
</button>
|
||||
<button type="button" class="btn btn-secondary ms-2" (click)="cancel()">Cancel</button>
|
||||
</form>
|
||||
</div>
|
||||
45
src/app/features/claim-new/claim-new.component.ts
Normal file
45
src/app/features/claim-new/claim-new.component.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators, ReactiveFormsModule } from '@angular/forms';
|
||||
import { Router, RouterModule } from '@angular/router';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { ClaimService } from '../../shared/services/claim.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-claim-new',
|
||||
standalone: true,
|
||||
imports: [CommonModule, ReactiveFormsModule, RouterModule], // ✅ RouterModule is required
|
||||
templateUrl: './claim-new.component.html',
|
||||
styleUrls: ['./claim-new.component.css']
|
||||
})
|
||||
export class ClaimNewComponent {
|
||||
claimForm: FormGroup;
|
||||
|
||||
constructor(
|
||||
private fb: FormBuilder,
|
||||
private claimService: ClaimService,
|
||||
private router: Router
|
||||
) {
|
||||
this.claimForm = this.fb.group({
|
||||
name: ['', Validators.required],
|
||||
policyID: ['', Validators.required],
|
||||
claimReason: ['', Validators.required],
|
||||
claimAmount: [0, [Validators.required, Validators.min(1)]],
|
||||
status: ['PENDING']
|
||||
});
|
||||
}
|
||||
|
||||
// ✅ Submit with alert and redirect
|
||||
onSubmit(): void {
|
||||
if (this.claimForm.valid) {
|
||||
this.claimService.addClaim(this.claimForm.value).subscribe(() => {
|
||||
alert('✅ Claim submitted successfully!');
|
||||
setTimeout(() => this.router.navigate(['/claims']));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// ✅ Cancel button redirect
|
||||
cancel(): void {
|
||||
this.router.navigate(['/claims']);
|
||||
}
|
||||
}
|
||||
0
src/app/features/claim/claim.component.css
Normal file
0
src/app/features/claim/claim.component.css
Normal file
69
src/app/features/claim/claim.component.html
Normal file
69
src/app/features/claim/claim.component.html
Normal file
@@ -0,0 +1,69 @@
|
||||
<div class="container mt-4">
|
||||
<h2>Claims</h2>
|
||||
|
||||
<!-- Add Button -->
|
||||
<a routerLink="/claims/new" class="btn btn-primary mb-3">
|
||||
Add Claim
|
||||
</a>
|
||||
|
||||
<!-- Claims Table -->
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Name</th>
|
||||
<th>Policy ID</th>
|
||||
<th>Reason</th>
|
||||
<th>Amount</th>
|
||||
<th>Status</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let claim of claims">
|
||||
<td>{{ claim.id }}</td>
|
||||
<td>{{ claim.name }}</td>
|
||||
<td>{{ claim.policyID }}</td>
|
||||
<td>{{ claim.claimReason }}</td>
|
||||
<td>{{ claim.claimAmount }}</td>
|
||||
<td>{{ claim.status }}</td>
|
||||
<td>
|
||||
<button class="btn btn-sm btn-success me-1"
|
||||
(click)="updateStatus(claim.id, 'APPROVED')"
|
||||
[disabled]="claim.status === 'APPROVED'">
|
||||
Approve
|
||||
</button>
|
||||
<button class="btn btn-sm btn-danger"
|
||||
(click)="updateStatus(claim.id, 'REJECTED')"
|
||||
[disabled]="claim.status === 'REJECTED'">
|
||||
Reject
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Pagination -->
|
||||
<div class="d-flex justify-content-center mt-3">
|
||||
<button class="btn btn-outline-primary me-1"
|
||||
(click)="prevPage()"
|
||||
[disabled]="page === 0">
|
||||
Previous
|
||||
</button>
|
||||
|
||||
<ng-container *ngFor="let p of pageNumbers">
|
||||
<button class="btn me-1"
|
||||
[ngClass]="{'btn-primary': page === p, 'btn-outline-primary': page !== p}"
|
||||
(click)="goToPage(p)">
|
||||
{{ p + 1 }}
|
||||
</button>
|
||||
</ng-container>
|
||||
|
||||
<button class="btn btn-outline-primary ms-1"
|
||||
(click)="nextPage()"
|
||||
[disabled]="page + 1 >= totalPages">
|
||||
Next
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
64
src/app/features/claim/claim.component.ts
Normal file
64
src/app/features/claim/claim.component.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Claim, ClaimService, PageResponse } from '../../shared/services/claim.service';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'app-claim',
|
||||
standalone: true,
|
||||
imports: [CommonModule, RouterModule],
|
||||
templateUrl: './claim.component.html',
|
||||
styleUrls: ['./claim.component.css']
|
||||
})
|
||||
export class ClaimComponent implements OnInit {
|
||||
claims: Claim[] = [];
|
||||
page = 0;
|
||||
size = 5;
|
||||
totalElements = 0;
|
||||
|
||||
constructor(private claimService: ClaimService) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.loadClaims();
|
||||
}
|
||||
|
||||
loadClaims(): void {
|
||||
this.claimService.getClaims(this.page, this.size).subscribe((res: PageResponse<Claim>) => {
|
||||
this.claims = res.content;
|
||||
this.totalElements = res.totalElements;
|
||||
});
|
||||
}
|
||||
|
||||
nextPage(): void {
|
||||
if ((this.page + 1) * this.size < this.totalElements) {
|
||||
this.page++;
|
||||
this.loadClaims();
|
||||
}
|
||||
}
|
||||
|
||||
prevPage(): void {
|
||||
if (this.page > 0) {
|
||||
this.page--;
|
||||
this.loadClaims();
|
||||
}
|
||||
}
|
||||
|
||||
get totalPages(): number {
|
||||
return Math.ceil(this.totalElements / this.size);
|
||||
}
|
||||
|
||||
get pageNumbers(): number[] {
|
||||
return Array.from({ length: this.totalPages }, (_, i) => i);
|
||||
}
|
||||
|
||||
goToPage(page: number): void {
|
||||
this.page = page;
|
||||
this.loadClaims();
|
||||
}
|
||||
|
||||
updateStatus(id: number, status: string): void {
|
||||
this.claimService.updateStatus(id, status).subscribe(() => {
|
||||
this.loadClaims();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -28,4 +28,11 @@
|
||||
<div *ngIf="!loading && !errorMessage && cards.length === 0" class="text-center text-muted fs-5 mt-4">
|
||||
No insurances found.
|
||||
</div>
|
||||
|
||||
<div class="text-center mb-4">
|
||||
<button class="btn btn-success btn-lg" (click)="navigateToClaims()">
|
||||
Claims
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -59,4 +59,9 @@ export class HomepageComponent implements OnInit {
|
||||
navigate(link: string): void {
|
||||
this.router.navigate([link]);
|
||||
}
|
||||
|
||||
navigateToClaims(): void {
|
||||
this.router.navigate(['/claims']); // ✅ redirect to claim page
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
55
src/app/shared/services/claim.service.ts
Normal file
55
src/app/shared/services/claim.service.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient, HttpErrorResponse, HttpParams } from '@angular/common/http';
|
||||
import { Observable, throwError } from 'rxjs';
|
||||
import { catchError } from 'rxjs/operators';
|
||||
import { environment } from '../../../environments/environment';
|
||||
|
||||
export interface Claim {
|
||||
id: number;
|
||||
name: string;
|
||||
policyID: string;
|
||||
claimReason: string;
|
||||
claimAmount: number;
|
||||
status: string;
|
||||
}
|
||||
|
||||
export interface PageResponse<T> {
|
||||
content: T[];
|
||||
totalElements: number;
|
||||
totalPages: number;
|
||||
size: number;
|
||||
number: number;
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ClaimService {
|
||||
private apiUrl = `${environment.apiUrl}/api/claim`;
|
||||
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
// ✅ Get pageable claims
|
||||
getClaims(page: number, size: number): Observable<PageResponse<Claim>> {
|
||||
let params = new HttpParams().set('page', page).set('size', size);
|
||||
return this.http.get<PageResponse<Claim>>(this.apiUrl, { params })
|
||||
.pipe(catchError(this.handleError));
|
||||
}
|
||||
|
||||
// ✅ Create a new claim
|
||||
addClaim(claim: Claim): Observable<Claim> {
|
||||
return this.http.post<Claim>(`${this.apiUrl}/add`, claim)
|
||||
.pipe(catchError(this.handleError));
|
||||
}
|
||||
|
||||
// ✅ Update status (Approve / Reject)
|
||||
updateStatus(id: number, status: string): Observable<Claim> {
|
||||
return this.http.put<Claim>(`${this.apiUrl}/${id}/status?status=${status}`, {})
|
||||
.pipe(catchError(this.handleError));
|
||||
}
|
||||
|
||||
private handleError(error: HttpErrorResponse) {
|
||||
console.error('An error occurred:', error.message);
|
||||
return throwError(() => new Error('Something went wrong; please try again later.'));
|
||||
}
|
||||
}
|
||||
@@ -27,16 +27,17 @@ export interface InsuranceDetail {
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class InsuranceService {
|
||||
private apiUrl = environment.apiUrl;
|
||||
private apiUrl = `${environment.apiUrl}/api/insurance`;
|
||||
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
getInsurances(): Observable<Insurance[]> {
|
||||
return this.http.post<Insurance[]>(`${this.apiUrl}/all`, {}).pipe(
|
||||
return this.http.get<Insurance[]>(`${this.apiUrl}/all`).pipe(
|
||||
catchError(this.handleError)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
getInsuranceById(id: number | string): Observable<InsuranceDetail> {
|
||||
return this.http.get<InsuranceDetail>(`${this.apiUrl}/detail/${id}`)
|
||||
.pipe(catchError(this.handleError));
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export const environment = {
|
||||
production: true,
|
||||
apiUrl: 'https://insurance.hzwnrw.my/api/insurance'
|
||||
apiUrl: 'https://insurance.hzwnrw.my'
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export const environment = {
|
||||
production: false,
|
||||
apiUrl: 'http://localhost:1204/api/insurance'
|
||||
apiUrl: 'http://localhost:1204'
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user