@@ -92,7 +92,7 @@ <h4>Pending UPI payments <span id="pendingCount" class="pending-badge">0</span><
9292</ main >
9393
9494< div id ="modalRoot "> </ div >
95- < footer > New Serchhip North Village Council · v1.29.3 </ footer >
95+ < footer > New Serchhip North Village Council · v1.29.4 </ footer >
9696
9797< script type ="module ">
9898/* ============================================================
@@ -2802,80 +2802,63 @@ <h4>Pending UPI payments <span id="pendingCount" class="pending-badge">0</span><
28022802 . filter ( c => getEffectiveBalance ( c ) > 0 ) ;
28032803 if ( ! list . length ) { toast ( "No owing households to export" ) ; return ; }
28042804
2805- const ledgers = ledgerCache . size ? Object . fromEntries ( ledgerCache ) : await store . getAllLedgers ( ) ;
2806- const rows = [ ] ;
28072805 let total = 0 ;
2808- for ( const c of list ) {
2806+ const rows = list . map ( c => {
28092807 const bal = getEffectiveBalance ( c ) ;
28102808 total += bal ;
2811- const entries = ledgers [ c . id ] || await store . getLedger ( c . id ) ;
2812- const payments = entries . filter ( e => e . type === "payment" ) . map ( e => `${ entryLabel ( e ) } ${ fmt ( e . amount ) } ` ) . join ( "; " ) ;
2813- rows . push ( [
2814- c . name || "—" ,
2815- c . jobCard || c . id ,
2816- fmt ( bal ) ,
2817- payments || "—"
2818- ] ) ;
2819- }
2809+ return { name : c . name || "—" , jobCard : c . jobCard || c . id , amount : fmt ( bal ) } ;
2810+ } ) ;
28202811
2821- const doc = new jsPDF ( { orientation : "landscape " , unit : "mm" , format : "a4" } ) ;
2812+ const doc = new jsPDF ( { orientation : "portrait " , unit : "mm" , format : "a4" } ) ;
28222813 const pageW = doc . internal . pageSize . getWidth ( ) ;
2823- const margin = 14 ;
2824- let y = 20 ;
2814+ const margin = 16 ;
2815+ const rightX = pageW - margin ;
2816+ let y = 22 ;
28252817
2826- doc . setFontSize ( 16 ) ;
2818+ doc . setFontSize ( 18 ) ;
28272819 doc . setFont ( undefined , "bold" ) ;
2828- doc . text ( "New Serchhip North Village Council" , margin , y ) ;
2829- y += 8 ;
2830- doc . setFontSize ( 12 ) ;
2831- doc . setFont ( undefined , "normal" ) ;
2832- doc . text ( `Owing List — ${ todayISO ( ) } ` , margin , y ) ;
2833- y += 6 ;
2834- doc . setFontSize ( 10 ) ;
2835- doc . text ( `Filter: ${ adminFilter . charAt ( 0 ) . toUpperCase ( ) + adminFilter . slice ( 1 ) } ${ periodFilter ?` · Period: ${ periodFilter } ` :"" } ` , margin , y ) ;
2820+ doc . text ( "Owing List" , margin , y ) ;
28362821 y += 10 ;
28372822
2838- // Table header
2839- const colX = [ margin , margin + 55 , margin + 110 , margin + 140 ] ;
2840- const colW = [ 55 , 55 , 30 , pageW - margin - colX [ 3 ] - 5 ] ;
2841- doc . setFillColor ( 26 , 77 , 62 ) ;
2842- doc . setTextColor ( 255 , 255 , 255 ) ;
2843- doc . rect ( margin , y - 5 , pageW - margin * 2 , 8 , "F" ) ;
2844- doc . setFont ( undefined , "bold" ) ;
2845- doc . text ( "Name" , colX [ 0 ] + 2 , y ) ;
2846- doc . text ( "Job Card" , colX [ 1 ] + 2 , y ) ;
2847- doc . text ( "Outstanding" , colX [ 2 ] + 2 , y ) ;
2848- doc . text ( "Payment History" , colX [ 3 ] + 2 , y ) ;
2849- y += 8 ;
2850-
2851- // Rows
2852- doc . setTextColor ( 0 , 0 , 0 ) ;
2823+ doc . setFontSize ( 10 ) ;
28532824 doc . setFont ( undefined , "normal" ) ;
2854- doc . setFontSize ( 9 ) ;
2825+ doc . text ( `${ todayISO ( ) } · ${ adminFilter . charAt ( 0 ) . toUpperCase ( ) + adminFilter . slice ( 1 ) } ${ periodFilter ?` · ${ periodFilter } ` :"" } ` , margin , y ) ;
2826+ y += 14 ;
2827+
2828+ doc . setDrawColor ( 230 , 230 , 230 ) ;
2829+ doc . setFontSize ( 11 ) ;
28552830 for ( const r of rows ) {
2856- if ( y > doc . internal . pageSize . getHeight ( ) - 20 ) { doc . addPage ( ) ; y = 20 ; }
2857- const linesName = doc . splitTextToSize ( r [ 0 ] , colW [ 0 ] - 4 ) ;
2858- const linesJob = doc . splitTextToSize ( r [ 1 ] , colW [ 1 ] - 4 ) ;
2859- const linesPay = doc . splitTextToSize ( r [ 3 ] , colW [ 3 ] - 4 ) ;
2860- const rowH = Math . max ( linesName . length , linesJob . length , 1 , linesPay . length ) * 4 + 3 ;
2861-
2862- doc . setDrawColor ( 220 , 220 , 220 ) ;
2863- doc . line ( margin , y + rowH - 1 , pageW - margin , y + rowH - 1 ) ;
2864- doc . text ( linesName , colX [ 0 ] + 2 , y + 4 ) ;
2865- doc . text ( linesJob , colX [ 1 ] + 2 , y + 4 ) ;
2866- doc . text ( r [ 2 ] , colX [ 2 ] + 2 , y + 4 ) ;
2867- doc . text ( linesPay , colX [ 3 ] + 2 , y + 4 ) ;
2868- y += rowH ;
2831+ if ( y > doc . internal . pageSize . getHeight ( ) - 24 ) { doc . addPage ( ) ; y = 20 ; }
2832+
2833+ doc . setFont ( undefined , "bold" ) ;
2834+ doc . setTextColor ( 40 , 40 , 40 ) ;
2835+ const nameLines = doc . splitTextToSize ( r . name , pageW - margin * 2 - 45 ) ;
2836+ doc . text ( nameLines , margin , y ) ;
2837+
2838+ const amountW = doc . getTextWidth ( r . amount ) ;
2839+ doc . setTextColor ( 180 , 40 , 40 ) ;
2840+ doc . text ( r . amount , rightX - amountW , y ) ;
2841+
2842+ doc . setFont ( undefined , "normal" ) ;
2843+ doc . setTextColor ( 120 , 120 , 120 ) ;
2844+ doc . setFontSize ( 9 ) ;
2845+ y += nameLines . length * 4.5 + 1 ;
2846+ doc . text ( r . jobCard , margin , y ) ;
2847+ doc . setFontSize ( 11 ) ;
2848+
2849+ y += 6 ;
2850+ doc . line ( margin , y , pageW - margin , y ) ;
2851+ y += 8 ;
28692852 }
28702853
2871- // Total row
2854+ // Total
28722855 if ( y > doc . internal . pageSize . getHeight ( ) - 20 ) { doc . addPage ( ) ; y = 20 ; }
2873- doc . setFillColor ( 240 , 240 , 240 ) ;
2874- doc . rect ( margin , y - 5 , pageW - margin * 2 , 8 , "F" ) ;
28752856 doc . setFont ( undefined , "bold" ) ;
2876- doc . setFontSize ( 10 ) ;
2877- doc . text ( "Total Outstanding" , colX [ 0 ] + 2 , y ) ;
2878- doc . text ( fmt ( total ) , colX [ 2 ] + 2 , y ) ;
2857+ doc . setTextColor ( 40 , 40 , 40 ) ;
2858+ doc . text ( "Total" , margin , y ) ;
2859+ const totalW = doc . getTextWidth ( fmt ( total ) ) ;
2860+ doc . setTextColor ( 180 , 40 , 40 ) ;
2861+ doc . text ( fmt ( total ) , rightX - totalW , y ) ;
28792862
28802863 doc . save ( `owing_${ todayISO ( ) } .pdf` ) ;
28812864 toast ( "PDF exported" ) ;
0 commit comments