@@ -345,9 +345,6 @@ <h2>Council login</h2>
345345 < button class ="btn small " id ="addCitizenBtn "> + Add</ button >
346346 < button class ="btn small ghost " id ="settingsBtn "> ⚙️</ button >
347347 </ div >
348- < div class ="action-grid " style ="grid-template-columns:1fr ">
349- < button class ="btn small ghost " id ="backupMenuBtn "> Backup / Restore</ button >
350- </ div >
351348 < div id ="pendingContainer " class ="hidden " style ="margin-bottom:12px; ">
352349 < div class ="panel " style ="background:var(--surface);border:1px solid #f0d99a; ">
353350 < h4 > Pending UPI payments < span id ="pendingCount " class ="pending-badge "> 0</ span > </ h4 >
@@ -401,16 +398,20 @@ <h4>Pending UPI payments <span id="pendingCount" class="pending-badge">0</span><
401398 return "due" ;
402399}
403400function getEffectiveBalance ( c ) {
401+ const cachedBalance = Number ( c . balance ?? 0 ) ;
402+ if ( typeof c . balance === "number" && ! excludedPeriods . length && ( ! c . ledger || ! c . ledger . some ( e => e . deferred ) ) ) {
403+ return cachedBalance ;
404+ }
404405 if ( ! c . ledger ) {
405- return Number ( c . balance ?? ( ( c . totalCharged || 0 ) - ( c . totalPaid || 0 ) ) ) ;
406+ return cachedBalance ;
406407 }
407408 let includedCharged = 0 ;
408409 for ( const e of c . ledger ) {
409410 if ( e . type === "charge" && e . note && ! excludedPeriods . includes ( e . note ) && ! e . deferred ) {
410- includedCharged += e . amount ;
411+ includedCharged += Number ( e . amount || 0 ) ;
411412 }
412413 }
413- return includedCharged - ( c . totalPaid || 0 ) ;
414+ return includedCharged - Number ( c . totalPaid || 0 ) ;
414415}
415416function getDeferredAmount ( c ) {
416417 if ( typeof c . deferredTotal === "number" ) return Number ( c . deferredTotal || 0 ) ;
@@ -839,15 +840,20 @@ <h4>Pending UPI payments <span id="pendingCount" class="pending-badge">0</span><
839840 const out = [ ] ;
840841 for ( const d of snap . docs ) {
841842 const c = d . data ( ) ;
843+ if ( ! excludedPeriods . length ) {
844+ const effBal = Number ( c . balance || 0 ) ;
845+ if ( effBal > 0 ) out . push ( { id :d . id , ...c , balance :effBal } ) ;
846+ continue ;
847+ }
842848 const ledSnap = await fs . getDocs ( fs . collection ( db , "citizens" , d . id , "ledger" ) ) ;
843849 let includedCharged = 0 ;
844850 ledSnap . docs . forEach ( doc => {
845851 const e = doc . data ( ) ;
846852 if ( e . type === "charge" && e . note && ! excludedPeriods . includes ( e . note ) && ! e . deferred ) {
847- includedCharged += e . amount ;
853+ includedCharged += Number ( e . amount || 0 ) ;
848854 }
849855 } ) ;
850- const effBal = includedCharged - ( c . totalPaid || 0 ) ;
856+ const effBal = includedCharged - Number ( c . totalPaid || 0 ) ;
851857 if ( effBal > 0 ) out . push ( { id :d . id , ...c , balance :effBal } ) ;
852858 }
853859 return out ;
@@ -1248,8 +1254,8 @@ <h4>Pending UPI payments <span id="pendingCount" class="pending-badge">0</span><
12481254}
12491255
12501256/* ---------- public list ---------- */
1251- let pubAll = [ ] , pubShown = 10 , backTarget = "list" ;
1252- const PUB_STEP = 10 ;
1257+ let pubAll = [ ] , pubShown = 6 , backTarget = "list" ;
1258+ const PUB_STEP = 6 ;
12531259
12541260function showList ( ) {
12551261 backTarget = "list" ;
@@ -1265,6 +1271,19 @@ <h4>Pending UPI payments <span id="pendingCount" class="pending-badge">0</span><
12651271 pubAll . sort ( byCardNo ) ;
12661272 pubShown = PUB_STEP ;
12671273 renderPubList ( ) ;
1274+ if ( pubAll . length > pubShown ) {
1275+ requestAnimationFrame ( ( ) => {
1276+ const more = pubAll . slice ( pubShown , Math . min ( pubShown + PUB_STEP , pubAll . length ) ) ;
1277+ if ( more . length ) {
1278+ const current = $ ( "citizenList" ) . innerHTML ;
1279+ const extra = more . map ( c => personCardHTML ( c . id , c ) ) . join ( "" ) ;
1280+ const marker = current . includes ( 'id="seeMore"' ) ? '<button class="btn block ghost small" id="seeMore" style="margin-top:12px">Show next 6</button>' : '' ;
1281+ $ ( "citizenList" ) . innerHTML = current . replace ( marker , marker + extra ) ;
1282+ document . querySelectorAll ( "#citizenList .result-card" ) . forEach ( b =>
1283+ b . addEventListener ( "click" , ( ) => openMatch ( b . dataset . id , true ) ) ) ;
1284+ }
1285+ } ) ;
1286+ }
12681287 } catch ( err ) { console . error ( err ) ; $ ( "citizenList" ) . innerHTML = `<div class="notice err">Couldn't load the list.</div>` ; }
12691288}
12701289function renderPubList ( ) {
@@ -1507,6 +1526,7 @@ <h4>Pending UPI payments <span id="pendingCount" class="pending-badge">0</span><
15071526 <div class="panel" style="margin-bottom:16px">
15081527 <h4>Quick Actions</h4>
15091528 <button class="btn block ghost" id="settingsPeriods">Manage periods</button>
1529+ <button class="btn block ghost" id="settingsRename" style="margin-top:8px">Rename period</button>
15101530 <button class="btn block ghost" id="settingsBackup" style="margin-top:8px">Backup / Restore</button>
15111531 <button class="btn block ghost" id="settingsImport" style="margin-top:8px">Import / Export</button>
15121532 </div>
@@ -1523,6 +1543,7 @@ <h4>App Info</h4>
15231543 </div>
15241544 ` ) ;
15251545 $ ( "settingsPeriods" ) . addEventListener ( "click" , ( ) => { closeSheet ( ) ; openPeriods ( ) ; } ) ;
1546+ $ ( "settingsRename" ) . addEventListener ( "click" , ( ) => { closeSheet ( ) ; openRenamePeriod ( ) ; } ) ;
15261547 $ ( "settingsBackup" ) . addEventListener ( "click" , ( ) => { closeSheet ( ) ; openBackup ( ) ; } ) ;
15271548 $ ( "settingsImport" ) . addEventListener ( "click" , ( ) => { closeSheet ( ) ; openImportExport ( ) ; } ) ;
15281549 $ ( "settingsLogout" ) . addEventListener ( "click" , doLogout ) ;
@@ -1570,7 +1591,6 @@ <h4>App Info</h4>
15701591/* ============================================================
15711592 ADMIN — import (unchanged, but included for completeness)
15721593 ============================================================ */
1573- $ ( "backupMenuBtn" ) . addEventListener ( "click" , openBackup ) ;
15741594let pendingImport = null , pendingMonthly = null , pendingBank = null , pendingUpload = null ;
15751595
15761596function openImportExport ( ) {
@@ -1599,11 +1619,6 @@ <h4>App Info</h4>
15991619 <p style="font-size:12.5px;color:var(--muted);margin:0 0 10px">If any balance looks wrong, this rebuilds every total from its history.</p>
16001620 <button class="btn block ghost" id="recalcBtn">Recalculate all balances</button>
16011621 </div>
1602- <div style="border-top:1px solid var(--border);padding-top:16px">
1603- <p style="font-size:12.5px;color:var(--muted);margin:0 0 10px">Bulk operations</p>
1604- <button class="btn block ghost" id="renamePeriodBtn">Rename period</button>
1605- <button class="btn block ghost" id="periodsBtn" style="margin-top:8px">Manage periods</button>
1606- </div>
16071622 <div style="border-top:1px solid var(--border);padding-top:16px">
16081623 <p style="font-size:12.5px;color:var(--muted);margin:0 0 10px">Danger zone - these actions cannot be undone.</p>
16091624 <button class="btn block ghost" id="deleteAllBtn" style="color:var(--due);border-color:var(--due)">Delete all data</button>
@@ -1614,8 +1629,6 @@ <h4>App Info</h4>
16141629 $ ( "restoreBtn" ) . addEventListener ( "click" , ( ) => $ ( "restoreFile" ) . click ( ) ) ;
16151630 $ ( "restoreFile" ) . addEventListener ( "change" , doRestore ) ;
16161631 $ ( "recalcBtn" ) . addEventListener ( "click" , doRecalcAll ) ;
1617- $ ( "renamePeriodBtn" ) . addEventListener ( "click" , openRenamePeriod ) ;
1618- $ ( "periodsBtn" ) . addEventListener ( "click" , openPeriods ) ;
16191632 $ ( "deleteAllBtn" ) . addEventListener ( "click" , doDeleteAll ) ;
16201633}
16211634async function doRecalcAll ( ) {
@@ -1685,20 +1698,19 @@ <h4>App Info</h4>
16851698 try {
16861699 const periods = await store . getAllPeriods ( ) ;
16871700 const excluded = await store . getExcludedPeriods ( ) ;
1688- console . log ( "Periods:" , periods , "Excluded:" , excluded ) ;
1689- const list = periods . map ( p => `
1690- <div class="brow" style="padding:8px 0;border-bottom:1px solid var(--border)">
1701+ const list = periods . map ( ( p , index ) => `
1702+ <label class="brow" style="padding:8px 0;border-bottom:1px solid var(--border);display:flex;justify-content:space-between;align-items:center;gap:10px">
16911703 <span>${ esc ( p ) } </span>
1692- <input type="checkbox" class="period-toggle" data- period="${ esc ( p ) } " ${ ! excluded . includes ( p ) ?"checked" :"" } >
1693- </div >
1704+ <input type="checkbox" class="period-toggle" name=" period-toggle" value ="${ esc ( p ) } " ${ ! excluded . includes ( p ) ?"checked" :"" } >
1705+ </label >
16941706 ` ) . join ( '' ) ;
16951707 $ ( "periodsList" ) . innerHTML = list || '<div style="color:var(--muted)">No periods found yet.</div>' ;
16961708 } catch ( err ) { console . error ( "Load periods error:" , err ) ; $ ( "periodsList" ) . innerHTML = `<div class="notice err">Failed to load periods: ${ err . message || err } </div>` ; }
16971709}
16981710async function savePeriods ( ) {
1699- const toggles = document . querySelectorAll ( ". period-toggle") ;
1711+ const toggles = document . querySelectorAll ( 'input[name=" period-toggle"]' ) ;
17001712 const excluded = [ ] ;
1701- toggles . forEach ( t => { if ( ! t . checked ) excluded . push ( t . dataset . period ) ; } ) ;
1713+ toggles . forEach ( t => { if ( ! t . checked ) excluded . push ( t . value ) ; } ) ;
17021714 const msg = $ ( "periodsMsg" ) ; const btn = $ ( "savePeriodsBtn" ) ; btn . disabled = true ;
17031715 msg . innerHTML = `<div class="notice info">Saving…</div>` ;
17041716 try {
0 commit comments