@@ -8,7 +8,12 @@ import {
88 OnDestroy ,
99} from '@angular/core' ;
1010import { DatePipe } from '@angular/common' ;
11- import type { Customer , PaymentIntent } from '@zoneless/shared-types' ;
11+ import type {
12+ Customer ,
13+ Invoice ,
14+ PaymentIntent ,
15+ Subscription as SubscriptionType ,
16+ } from '@zoneless/shared-types' ;
1217import { GetPaymentIntentListStatus } from '@zoneless/shared-types' ;
1318import { CustomerService } from '../../../../../data' ;
1419import { CustomerActionsService } from '../../services/customer-actions.service' ;
@@ -25,6 +30,18 @@ import { EventsListComponent } from '../../../components';
2530import { MetadataToArray } from '../../../util/metadata' ;
2631import { MetaService } from '../../../../../core' ;
2732import { Subscription } from 'rxjs' ;
33+ import {
34+ FormatInvoiceFrequency ,
35+ FormatInvoiceNumber ,
36+ } from '../../../invoices/util/invoice-display' ;
37+ import {
38+ FormatShortDate ,
39+ FormatSubscriptionBillingFrequency ,
40+ FormatSubscriptionNextInvoice ,
41+ FormatSubscriptionProduct ,
42+ GetSubscriptionListStatus ,
43+ GetSubscriptionPeriodProgress ,
44+ } from '../../../subscriptions/util/subscription-display' ;
2845
2946@Component ( {
3047 selector : 'app-customer-detail' ,
@@ -52,9 +69,21 @@ export class CustomerDetailComponent implements OnInit, OnDestroy {
5269 loading : WritableSignal < boolean > = signal ( false ) ;
5370 detailsExpanded : WritableSignal < boolean > = signal ( false ) ;
5471
72+ subscriptionColumns : PaginatedListColumn [ ] = [ ] ;
73+ subscriptionQueryParams : WritableSignal < Record < string , string > > = signal ( { } ) ;
74+ subscriptionExpand : WritableSignal < string [ ] > = signal ( [
75+ 'items.data.price.product' ,
76+ ] ) ;
77+
5578 paymentColumns : PaginatedListColumn [ ] = [ ] ;
5679 paymentQueryParams : WritableSignal < Record < string , string > > = signal ( { } ) ;
5780
81+ invoiceColumns : PaginatedListColumn [ ] = [ ] ;
82+ invoiceQueryParams : WritableSignal < Record < string , string > > = signal ( { } ) ;
83+ invoiceExpand : WritableSignal < string [ ] > = signal ( [
84+ 'subscription.items.data.price' ,
85+ ] ) ;
86+
5887 private sub ?: Subscription ;
5988
6089 customerActions : PopupMenuAction [ ] = [
@@ -73,7 +102,9 @@ export class CustomerDetailComponent implements OnInit, OnDestroy {
73102 if ( ! id ) return ;
74103 await this . LoadCustomer ( id ) ;
75104 this . metaService . SetMetaTitle ( this . customer ( ) ?. name ?? 'Customer' ) ;
105+ this . InitSubscriptionList ( id ) ;
76106 this . InitPaymentList ( id ) ;
107+ this . InitInvoiceList ( id ) ;
77108 this . sub = this . actions . events$ . subscribe ( ( event ) => {
78109 if ( event . type === 'deleted' && event . customerId === id ) {
79110 this . router . navigate ( [ '/account/customers' ] ) ;
@@ -96,6 +127,58 @@ export class CustomerDetailComponent implements OnInit, OnDestroy {
96127 }
97128 }
98129
130+ private InitSubscriptionList ( customerId : string ) : void {
131+ this . subscriptionColumns = [
132+ {
133+ header : 'Product' ,
134+ field : 'product' ,
135+ type : 'text' ,
136+ bolded : true ,
137+ progressGetter : ( item : unknown ) =>
138+ GetSubscriptionPeriodProgress ( item as SubscriptionType ) ,
139+ formatter : ( item : unknown ) =>
140+ FormatSubscriptionProduct ( item as SubscriptionType ) ,
141+ } ,
142+ {
143+ header : '' ,
144+ field : 'status' ,
145+ type : 'status' ,
146+ formatter : ( item : unknown ) =>
147+ GetSubscriptionListStatus ( item as SubscriptionType ) ,
148+ } ,
149+ {
150+ header : 'Frequency' ,
151+ field : 'frequency' ,
152+ type : 'text' ,
153+ dimmed : true ,
154+ formatter : ( item : unknown ) =>
155+ FormatSubscriptionBillingFrequency ( item as SubscriptionType ) ,
156+ } ,
157+ {
158+ header : 'Next invoice' ,
159+ field : 'next_invoice' ,
160+ type : 'text' ,
161+ dimmed : true ,
162+ formatter : ( item : unknown ) =>
163+ FormatSubscriptionNextInvoice ( item as SubscriptionType ) ,
164+ } ,
165+ {
166+ header : '' ,
167+ field : 'actions' ,
168+ type : 'actions' ,
169+ actions : [
170+ {
171+ title : 'Copy subscription ID' ,
172+ action : ( item : SubscriptionType ) => {
173+ void navigator . clipboard . writeText ( item . id ) ;
174+ } ,
175+ } ,
176+ ] ,
177+ } ,
178+ ] ;
179+ this . subscriptionQueryParams . set ( { customer : customerId } ) ;
180+ }
181+
99182 private InitPaymentList ( customerId : string ) : void {
100183 this . paymentColumns = [
101184 {
@@ -131,8 +214,79 @@ export class CustomerDetailComponent implements OnInit, OnDestroy {
131214 this . paymentQueryParams . set ( { customer : customerId } ) ;
132215 }
133216
217+ private InitInvoiceList ( customerId : string ) : void {
218+ this . invoiceColumns = [
219+ {
220+ header : 'Total' ,
221+ field : 'total' ,
222+ type : 'currency-with-code' ,
223+ currencyField : 'currency' ,
224+ bolded : true ,
225+ } ,
226+ {
227+ header : '' ,
228+ field : 'status' ,
229+ type : 'status' ,
230+ formatter : ( item : unknown ) => ( item as Invoice ) . status ?? '' ,
231+ } ,
232+ {
233+ header : 'Frequency' ,
234+ field : 'parent' ,
235+ type : 'text' ,
236+ dimmed : true ,
237+ formatter : ( item : unknown ) => FormatInvoiceFrequency ( item as Invoice ) ,
238+ } ,
239+ {
240+ header : 'Invoice number' ,
241+ field : 'number' ,
242+ type : 'text' ,
243+ dimmed : true ,
244+ formatter : ( item : unknown ) => FormatInvoiceNumber ( item as Invoice ) ,
245+ } ,
246+ {
247+ header : 'Due' ,
248+ field : 'due_date' ,
249+ type : 'text' ,
250+ dimmed : true ,
251+ formatter : ( item : unknown ) => {
252+ const dueDate = ( item as Invoice ) . due_date ;
253+ return dueDate ? FormatShortDate ( dueDate ) : '—' ;
254+ } ,
255+ } ,
256+ {
257+ header : 'Created' ,
258+ field : 'created' ,
259+ type : 'date' ,
260+ dimmed : true ,
261+ dateFormat : 'd MMM, HH:mm' ,
262+ } ,
263+ {
264+ header : '' ,
265+ field : '' ,
266+ type : 'actions' ,
267+ actions : [
268+ {
269+ title : 'Copy invoice ID' ,
270+ action : ( item : Invoice ) => {
271+ void navigator . clipboard . writeText ( item . id ) ;
272+ } ,
273+ } ,
274+ ] ,
275+ } ,
276+ ] ;
277+ this . invoiceQueryParams . set ( { customer : customerId } ) ;
278+ }
279+
280+ OnSubscriptionClick ( subscription : SubscriptionType ) : void {
281+ void this . router . navigate ( [ '/account/subscriptions' , subscription . id ] ) ;
282+ }
283+
134284 OnPaymentClick ( paymentIntent : PaymentIntent ) : void {
135- this . router . navigate ( [ '/account/payments' , paymentIntent . id ] ) ;
285+ void this . router . navigate ( [ '/account/payments' , paymentIntent . id ] ) ;
286+ }
287+
288+ OnInvoiceClick ( invoice : Invoice ) : void {
289+ void this . router . navigate ( [ '/account/invoices' , invoice . id ] ) ;
136290 }
137291
138292 OnEdit ( ) : void {
0 commit comments