feat: paginate customer orders and polish the dashboard hero
Add paged orders API and infinite scroll, short order numbers, and align the guest invite card with the logged-in hero shell. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -367,21 +367,26 @@ export class AccountingSyncService {
|
||||
select: { accountingGoldBalance: true, accountingRialBalance: true, accountingBalanceAt: true },
|
||||
});
|
||||
const stale = !c?.accountingBalanceAt || Date.now() - c.accountingBalanceAt.getTime() > BALANCE_FRESH_MS;
|
||||
if (stale) {
|
||||
try {
|
||||
const [b] = await a.provider.getBalances(
|
||||
{ ...a.settings, timeoutMs: Math.min(a.settings.timeoutMs, BALANCE_ON_DEMAND_TIMEOUT_MS) },
|
||||
[link.externalCode],
|
||||
|
||||
// Already have a stored figure: hand it back immediately and refresh in the
|
||||
// background. Waiting on Tahesab/Zarrin here blocked GET /customer/me for up
|
||||
// to BALANCE_ON_DEMAND_TIMEOUT_MS on almost every dashboard open (freshness
|
||||
// is only a few seconds), so the app painted the guest invite while the
|
||||
// token was still valid.
|
||||
if (c?.accountingBalanceAt && stale) {
|
||||
void this.refreshStoredBalance(a, customerId, link.externalCode).catch((err) => {
|
||||
this.logger.warn(
|
||||
`Background balance refresh for ${customerId} failed: ${(err as Error).message}`,
|
||||
);
|
||||
if (b) {
|
||||
c = await this.prisma.customer.update({
|
||||
where: { id: customerId },
|
||||
data: { accountingGoldBalance: b.goldGrams, accountingRialBalance: b.rial, accountingBalanceAt: new Date() },
|
||||
select: { accountingGoldBalance: true, accountingRialBalance: true, accountingBalanceAt: true },
|
||||
});
|
||||
}
|
||||
});
|
||||
} else if (stale) {
|
||||
// First read — nothing to show yet, so wait (with the short timeout).
|
||||
try {
|
||||
c = (await this.refreshStoredBalance(a, customerId, link.externalCode)) ?? c;
|
||||
} catch (err) {
|
||||
this.logger.warn(`On-demand balance for ${customerId} failed, serving the stored one: ${(err as Error).message}`);
|
||||
this.logger.warn(
|
||||
`On-demand balance for ${customerId} failed, serving the stored one: ${(err as Error).message}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
if (!c?.accountingBalanceAt) return null;
|
||||
@@ -393,6 +398,32 @@ export class AccountingSyncService {
|
||||
};
|
||||
}
|
||||
|
||||
/** Pull one linked customer's balance from the provider and persist it. */
|
||||
private async refreshStoredBalance(
|
||||
a: ActiveProvider,
|
||||
customerId: string,
|
||||
externalCode: string,
|
||||
) {
|
||||
const [b] = await a.provider.getBalances(
|
||||
{ ...a.settings, timeoutMs: Math.min(a.settings.timeoutMs, BALANCE_ON_DEMAND_TIMEOUT_MS) },
|
||||
[externalCode],
|
||||
);
|
||||
if (!b) return null;
|
||||
return this.prisma.customer.update({
|
||||
where: { id: customerId },
|
||||
data: {
|
||||
accountingGoldBalance: b.goldGrams,
|
||||
accountingRialBalance: b.rial,
|
||||
accountingBalanceAt: new Date(),
|
||||
},
|
||||
select: {
|
||||
accountingGoldBalance: true,
|
||||
accountingRialBalance: true,
|
||||
accountingBalanceAt: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// ════════════════════════════════════════════════════════════════════
|
||||
// Real-time: change poll + live reads
|
||||
|
||||
Reference in New Issue
Block a user