diff --git a/platforms/eCurrency-api/src/services/TransactionNotificationService.ts b/platforms/eCurrency-api/src/services/TransactionNotificationService.ts index 39f3a7d4..265f4c0f 100644 --- a/platforms/eCurrency-api/src/services/TransactionNotificationService.ts +++ b/platforms/eCurrency-api/src/services/TransactionNotificationService.ts @@ -257,7 +257,7 @@ Transaction for your ${accountText} has been processed. ${isSender ? 'sent amount' : 'received amount'}: ${formattedAmount} currency: ${currency.name} (${currency.ename}) -time: ${formattedTime} +time: ${formattedTime} UTC ${otherPartyLabel}: ${otherPartyName}`; } diff --git a/platforms/eCurrency-api/src/services/UserService.ts b/platforms/eCurrency-api/src/services/UserService.ts index c680df34..3b4e4339 100644 --- a/platforms/eCurrency-api/src/services/UserService.ts +++ b/platforms/eCurrency-api/src/services/UserService.ts @@ -48,9 +48,27 @@ export class UserService { } async searchUsers(query: string, limit: number = 10): Promise { + const q = query.trim().toLowerCase(); + const patternPartial = `%${q}%`; + const patternPrefix = `${q}%`; + return await this.userRepository .createQueryBuilder("user") - .where("user.name ILIKE :query OR user.handle ILIKE :query", { query: `%${query}%` }) + .where("(user.name ILIKE :patternPartial OR user.handle ILIKE :patternPartial)", { + patternPartial, + }) + .addSelect( + `CASE ` + + `WHEN LOWER(COALESCE(user.name, '')) = :exact OR LOWER(COALESCE(user.handle, '')) = :exact THEN 0 ` + + `WHEN LOWER(COALESCE(user.name, '')) LIKE :patternPrefix OR LOWER(COALESCE(user.handle, '')) LIKE :patternPrefix THEN 1 ` + + `ELSE 2 ` + + `END`, + "relevance", + ) + .setParameter("exact", q) + .setParameter("patternPrefix", patternPrefix) + .orderBy("relevance", "ASC") + .addOrderBy("user.name", "ASC", "NULLS LAST") .limit(limit) .getMany(); } diff --git a/platforms/eCurrency/client/src/pages/currency-detail.tsx b/platforms/eCurrency/client/src/pages/currency-detail.tsx index 3b63fe78..995a4106 100644 --- a/platforms/eCurrency/client/src/pages/currency-detail.tsx +++ b/platforms/eCurrency/client/src/pages/currency-detail.tsx @@ -108,7 +108,7 @@ export default function CurrencyDetail() { if (!user) return; const adminGroups = groups?.filter((g: any) => g.isAdmin) || []; - + // If no context is set, default to user account if (!accountContext) { const defaultContext = { type: "user" as const, id: user.id }; @@ -119,16 +119,18 @@ export default function CurrencyDetail() { // Validate the saved context let isValid = false; - + if (accountContext.type === "user") { - // User context must match current user ID isValid = accountContext.id === user.id; } else if (accountContext.type === "group") { - // Group context must be in admin groups list - isValid = adminGroups.some((g: any) => g.id === accountContext.id); + // Do not reset group context while groups are still loading (preserves selection across refresh) + if (groups === undefined) { + isValid = true; + } else { + isValid = adminGroups.some((g: any) => g.id === accountContext.id); + } } - // If invalid, reset to user account if (!isValid) { const defaultContext = { type: "user" as const, id: user.id }; setAccountContext(defaultContext); @@ -141,22 +143,26 @@ export default function CurrencyDetail() { // If null is passed, default to user account const finalContext = context || (user ? { type: "user" as const, id: user.id } : null); - // Check if context actually changed - const contextChanged = !accountContext || - accountContext.type !== finalContext?.type || - accountContext.id !== finalContext?.id; - + // Check if context actually changed (semantic comparison) + const contextChanged = + finalContext === null && accountContext === null + ? false + : !accountContext || + !finalContext || + accountContext.type !== finalContext.type || + accountContext.id !== finalContext.id; + + // Only update state and storage when context meaningfully changed (avoids clearing transaction history when re-selecting same account) + if (!contextChanged) return; + setAccountContext(finalContext); if (finalContext) { localStorage.setItem("ecurrency_account_context", JSON.stringify(finalContext)); } else { localStorage.removeItem("ecurrency_account_context"); } - - // Navigate to dashboard when context changes - if (contextChanged) { - setLocation("/"); - } + + setLocation("/"); }; const { data: totalSupplyData, isLoading: totalSupplyLoading } = useQuery({ @@ -423,9 +429,9 @@ export default function CurrencyDetail() { {/* Transactions */}
-
+

Transactions

-
+
{isAdminOfCurrency && accountContext?.type === "group" && accountContext.id === currency.groupId && ( <>