@@ -3,88 +3,62 @@ import {
33 ChangeDetectionStrategy ,
44 signal ,
55 computed ,
6+ inject ,
7+ OnInit ,
68} from "@angular/core" ;
7- import { CommonModule , NgOptimizedImage } from "@angular/common" ;
8-
9- interface Service {
10- id : number ;
11- name : string ;
12- category : string ;
13- description : string ;
14- price : number ;
15- imageUrl : string ;
16- }
9+ import { CommonModule } from "@angular/common" ;
10+ import { AdminSettingsService } from "@entities/admin-settings" ;
11+ import { TreatmentsService } from "@entities/treatments" ;
12+ import { environment } from "@environments/environment" ;
13+ import { linkServerConvert } from "@shared/lib" ;
1714
1815@Component ( {
1916 selector : "app-services-catalog" ,
2017 standalone : true ,
21- imports : [ CommonModule , NgOptimizedImage ] ,
18+ imports : [ CommonModule ] ,
19+ providers : [ TreatmentsService ] ,
2220 changeDetection : ChangeDetectionStrategy . OnPush ,
2321 templateUrl : "./treatments-catalog.component.html" ,
2422 styleUrls : [ "./treatments-catalog.component.scss" ] ,
2523} )
26- export class ServicesCatalogComponent {
27- services = signal < Service [ ] > ( [
28- {
29- id : 1 ,
30- name : "Lip Neutralization" ,
31- category : "Medical Aesthetics" ,
32- description :
33- "Advanced pigmentation correction technique to restore natural color and definition. Ideal for correcting cool tones or asymmetry with minimal downtime." ,
34- price : 1200 ,
35- imageUrl :
36- "https://lh3.googleusercontent.com/aida-public/AB6AXuCnLA3tyCDcRymBx90wrQjtgGrWXr_0vKq72g14XO5LhCtxN0fIKkFn9IKD6M6rsiu2j-1__eQ3HJiho2vFk_lUHKNgfQNS64FGix2N4F6nBTaf3Rj8L6dICODAdpKFsPPMxMl_Pmvzxp-eFvAmxPVLjUW97KBGsfct4_5BDBksKXVjK3k0-dAiz7QQdGnsOy0tfeqFvOTrXr6fFz-G7dqpR1pQtskfaENZz1vQbsl1ShEaci5i8fDDN3Z_aU8hZQl4VkxlfL-rO07R" ,
37- } ,
38- {
39- id : 2 ,
40- name : "Evening Glamour" ,
41- category : "Professional Visage" ,
42- description :
43- "High-end evening makeup application using luxury cosmetics. Focused on longevity, photogenic finish, and enhancing your unique facial architecture." ,
44- price : 600 ,
45- imageUrl :
46- "https://lh3.googleusercontent.com/aida-public/AB6AXuD08o6hF5_pbFiIJqYs4VYYrPPviAtlB2PjR4z2lZYzuT3rcSqK7UbUQNiOic7Y-5L8OgQjXfDI3pcgi0scXP-E6zXsJwv5g2J3sX89thdN8QagJQQCwGJWt96_rVAjbhNezpl35TsKsDKDFcyUdrK2qT0yPcFM3kP0hOXpqC8ZB7OFulzRzNGWHZR0Hw2QbGd77Id8wWieXLWUC7eU1JKb3MgO6TXvXzAJQth53BY6a91dqAL2kuvJKelagAgLC2sRUWQy1FQ6Ul7i" ,
47- } ,
48- {
49- id : 3 ,
50- name : "HydraFacial Elite" ,
51- category : "Skin Therapy" ,
52- description :
53- "The ultimate skin detox. A multi-step treatment that cleanses, exfoliates, and extracts impurities while infusing skin with hydrating serums." ,
54- price : 850 ,
55- imageUrl :
56- "https://lh3.googleusercontent.com/aida-public/AB6AXuCN_i0UQ2DDBO3oiICvkDjAAQV4CBheKjtZbeV5zkQ3A3tngd9-v_70jN19UdyigQVFmmIJDEC6KKFrFXpRZnADtipZUJtbLTQrkC2elu6cCE8YLFAfsNR4Sy2SSAkC9vrYzA1VIzXnfpODZ7BB0sLbToeWMEeyWAB73l2Knzq96QXhRvBQlRlC3T7NRYn2TyQGjGmRmuoej4liuPk-DWB4caahTA2ZC7ui3ZRdGP1RwFDSRGLLzJclNcKQCbsaytClAoq-wBZgNMuu" ,
57- } ,
58- {
59- id : 4 ,
60- name : "Botulinum Therapy" ,
61- category : "Medical Aesthetics" ,
62- description :
63- "Medical-grade precision treatment to relax facial muscles, smoothing fine lines and wrinkles for a refreshed, youthful appearance." ,
64- price : 1500 ,
65- imageUrl :
66- "https://lh3.googleusercontent.com/aida-public/AB6AXuB34PkR8y1rYZNuLirjoa_FFY2CY_sTtk3E3D3TyDA3ETuKZbV1f8UE43MtJowMY1QOkYx7mK8J63t1ElZzHXCDnlJcQYrZMqn3_uOkUn73PcyqERAFxeNewueco1IiX_dN1plTcEHcp1rjm_S-F900peq3YKUrZ9edGuDoXDqmXhfYwwt_qDbLHdlaxqKvcczg_kPsJADCRIBk8kD3gHj-EZsWUO2PlGmKPvoLa2z6haQa_oPg1yQuDbLaUjPG84AAjlPmus3FpnTd" ,
67- } ,
68- ] ) ;
24+ export class ServicesCatalogComponent implements OnInit {
25+ private treatmentsService = inject ( TreatmentsService ) ;
26+ private adminSettingsService = inject ( AdminSettingsService ) ;
27+ private env = signal ( environment ) ;
28+
29+ // Live data from backend GET /treatments
30+ treatments = this . treatmentsService . treatments ;
31+
32+ // Dynamic filter list from AdminSettings
33+ filterOptions = computed < string [ ] > ( ( ) => {
34+ const cats = this . adminSettingsService . settings ( ) ?. treatmentCategories ;
35+ return [ "All Services" , ...( cats && cats . length > 0 ? cats : [ "Medical Aesthetics" , "Professional Visage" , "Skin Therapy" ] ) ] ;
36+ } ) ;
6937
70- filterOptions = [
71- "All Services" ,
72- "Medical Aesthetics" ,
73- "Professional Visage" ,
74- "Skin Therapy" ,
75- ] ;
7638 activeFilter = signal ( "All Services" ) ;
7739
7840 filteredServices = computed ( ( ) => {
79- const services = this . services ( ) ;
41+ const all = this . treatments ( ) ;
8042 const filter = this . activeFilter ( ) ;
43+ if ( filter === "All Services" ) return all ;
44+ return all . filter ( ( t ) => t . category === filter ) ;
45+ } ) ;
8146
82- if ( filter === "All Services" ) {
83- return services ;
47+ ngOnInit ( ) {
48+ if ( ! this . adminSettingsService . settings ( ) ) {
49+ this . adminSettingsService . getSettings ( ) . subscribe ( ) ;
8450 }
51+ this . treatmentsService . getTreatments ( ) . subscribe ( ) ;
52+ }
8553
86- return services . filter ( ( service ) => service . category === filter ) ;
87- } ) ;
54+ getImageUrl ( path : string | undefined ) : string {
55+ if ( ! path ) return "assets/placeholder-treatment.png" ;
56+ const isAbsolute =
57+ path . startsWith ( "http" ) ||
58+ path . startsWith ( "blob" ) ||
59+ path . includes ( this . env ( ) . apiUrl ) ;
60+ return isAbsolute ? path : linkServerConvert ( path ) ;
61+ }
8862
8963 setFilter ( filter : string ) {
9064 this . activeFilter . set ( filter ) ;
0 commit comments