Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/app/app.config.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';

import { provideHttpClient } from '@angular/common/http';
import { routes } from './app.routes';

export const appConfig: ApplicationConfig = {
providers: [provideRouter(routes)]
providers: [provideRouter(routes), provideHttpClient()],
};
12 changes: 6 additions & 6 deletions src/app/pages/pet-details/pet-details.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@
>
<div class="h-full w-full md:w-[35%]">
<img
[src]="pet?.image"
[alt]="pet?.name"
[src]="pet()?.image"
[alt]="pet()?.name"
class="object-contain w-full h-full"
/>
</div>
<div class="w-full md:w-[65%] h-full pt-[30px] flex flex-col p-3">
<h1>Name: {{ pet?.name }}</h1>
<h1>Type: {{ pet?.type }}</h1>
<h1>Adopted: {{ pet?.adopted ? "yes" : "no" }}</h1>
<h1>Name: {{ pet()?.name }}</h1>
<h1>Type: {{ pet()?.type }}</h1>
<h1>Adopted: {{ pet()?.adopted ? "yes" : "no" }}</h1>

@if (!pet?.adopted) {
@if (!pet()?.adopted) {
<button
class="w-[70px] border border-black rounded-md hover:bg-green-400 my-5"
>
Expand Down
36 changes: 25 additions & 11 deletions src/app/pages/pet-details/pet-details.component.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,40 @@
import { Component } from '@angular/core';
import { Component, effect, inject, signal } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Pet, pets } from '../../../data/pets';
import { PetService } from '../../shared/services/pet.service';
import { HttpClient } from '@angular/common/http';

@Component({
selector: 'app-pet-details',
standalone: true,
imports: [],
templateUrl: './pet-details.component.html',
styleUrl: './pet-details.component.css'
styleUrl: './pet-details.component.css',
})
export class PetDetailsComponent {
pet: Pet | null = null;
pets = pets;
pet = signal<Pet | undefined>(undefined);

constructor(private route: ActivatedRoute, private router: Router) {
private petService = inject(PetService);
pets = signal<Pet[]>([]);

constructor(
private route: ActivatedRoute,
private router: Router,
private http: HttpClient
) {
const id = Number(this.route.snapshot.paramMap.get('id'));
const foundPet = pets.find((p) => p.id === id);

if (!foundPet) {
this.router.navigate(['/pets']);
} else {
this.pet = foundPet;
}
effect(() => {
this.petService.getPetById(id).subscribe((response: Pet) => {
console.log(response); // log the response
this.pet.set(response); // ✅ Update signal
});
});

// if (!foundPet) {
// this.router.navigate(['/pets']);
// } else {
// this.pet = foundPet;
// }
}
}
23 changes: 18 additions & 5 deletions src/app/pages/pets/pets.component.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,38 @@
import { Component } from '@angular/core';
import { Component, effect, Inject, inject, signal } from '@angular/core';
import { PetsHeaderComponent } from '../../components/pets-header/pets-header.component';
import { PetsListComponent } from '../../components/pets-list/pets-list.component';
import { pets } from '../../../data/pets';
import { HttpClient, HttpClientModule } from '@angular/common/http';
import { PetService } from '../../shared/services/pet.service';
import { Pet } from '../../../data/pets';
// import { pets } from '../../../data/pets';

@Component({
selector: 'app-pets',
standalone: true,
imports: [PetsHeaderComponent, PetsListComponent],
imports: [PetsHeaderComponent, PetsListComponent, HttpClientModule],
templateUrl: './pets.component.html',
styleUrl: './pets.component.css',
})
export class PetsComponent {
query = '';
allPets = pets;
private petService = inject(PetService);
allPets = signal<Pet[]>([]);

setQuery(query: string) {
this.query = query;
}

constructor(private http: HttpClient) {
effect(() => {
this.petService.getPets().subscribe((response: Pet[]) => {
console.log(response); // log the response
this.allPets.set(response); // ✅ Update signal
});
});
}

get filteredPets() {
return this.allPets.filter((pet) =>
return this.allPets().filter((pet: { name: string }) =>
pet.name.toLowerCase().includes(this.query.toLowerCase())
);
}
Expand Down
31 changes: 29 additions & 2 deletions src/app/shared/services/modal.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,17 @@ import {
createComponent,
EnvironmentInjector,
ComponentRef,
ViewContainerRef
ViewContainerRef,
inject,
} from '@angular/core';
import { ModalHostComponent } from '../components/modal-host/modal-host.component';
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';

@Injectable({ providedIn: 'root' })
export class ModalService {
private hostRef?: ComponentRef<ModalHostComponent>;
private containerRef?: ViewContainerRef;

private readonly _http = inject(HttpClient);
constructor(
private appRef: ApplicationRef,
private envInjector: EnvironmentInjector
Expand Down Expand Up @@ -49,4 +51,29 @@ export class ModalService {
this.hostRef = undefined;
}
}

get<T>(url: string, params?: HttpParams, headers?: HttpHeaders) {
return this._http.get<T>(url, { params, headers });
}

/**
* Generic POST method to add new data
*/
post<T>(url: string, body: T, headers?: HttpHeaders) {
return this._http.post<T>(url, body, { headers });
}

/**
* Generic PUT method to update data
*/
put<T>(url: string, body: T, headers?: HttpHeaders) {
return this._http.put<T>(url, body, { headers });
}

/**
* Generic DELETE method to remove data
*/
delete<T>(url: string, params?: HttpParams, headers?: HttpHeaders) {
return this._http.delete<T>(url, { params, headers });
}
}
16 changes: 16 additions & 0 deletions src/app/shared/services/pet.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';

import { PetService } from './pet.service';

describe('PetService', () => {
let service: PetService;

beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(PetService);
});

it('should be created', () => {
expect(service).toBeTruthy();
});
});
34 changes: 34 additions & 0 deletions src/app/shared/services/pet.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// post.service.ts
import { Injectable } from '@angular/core';
// import { HttpClient } from '@angular/common/http';
import { ModalService } from './modal.service';
import { catchError, Observable, of } from 'rxjs';
import { Pet } from '../../../data/pets';

@Injectable({ providedIn: 'root' })
export class PetService extends ModalService {
private apiUrl = 'https://pets-react-query-backend.eapi.joincoded.com/pets';

// ✅ No need to inject HttpClient here — it's handled by BaseService via inject()
// constructor(_http: HttpClient) {
// super(_http);
// }

getPets(): Observable<Pet[]> {
return this.get<Pet[]>(this.apiUrl).pipe(
catchError((error) => {
console.error('Error fetching posts:', error); // Log the error for debugging
return of([]); // Return an empty array to prevent the app from breaking in case of an error
})
);
}

getPetById(id: number): Observable<Pet> {
return this.get<Pet>(this.apiUrl + `/${id}`).pipe(
catchError((error) => {
console.error('Error fetching posts:', error); // Log the error for debugging
return of(); // Return an empty array to prevent the app from breaking in case of an error
})
);
}
}