Skip to content

feat: filters on partner page#243

Merged
hmbanan666 merged 1 commit intomainfrom
partners
Oct 23, 2025
Merged

feat: filters on partner page#243
hmbanan666 merged 1 commit intomainfrom
partners

Conversation

@hmbanan666
Copy link
Copy Markdown
Collaborator

@hmbanan666 hmbanan666 commented Oct 23, 2025

Summary by CodeRabbit

Release Notes

  • New Features

    • Added total balance display with currency formatting on the partner page.
    • Introduced sorting controls (by name, ascending/descending balance) and filtering options (all or negative balance) for partner data.
  • Improvements

    • Enhanced CounterBadge component to support string and numeric values with updated visibility logic.
  • Chores

    • Dependency version updates for enhanced compatibility and stability.

@hmbanan666 hmbanan666 self-assigned this Oct 23, 2025
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Oct 23, 2025

Walkthrough

Refactored Telegram app initialization flow by simplifying isDev logic and chaining back-button setup within promise resolution; extended CounterBadge to accept string values; enhanced partner page with sorting and filtering controls; simplified agreement page computed logic; disabled fullscreen toggling; updated workspace dependencies.

Changes

Cohort / File(s) Summary
Initialization & App Setup
apps/atrium-telegram/app/app.vue, apps/atrium-telegram/app/utils/init.ts
Refactored init promise flow: removed launch-param-based debugging, replaced with environment-derived isDev flag; chained useBackButton() inside init promise resolution instead of after; removed back-button setup before init. Removed automatic fullscreen request/exit logic during viewport initialization.
Partner Page UI Enhancements
apps/atrium-telegram/app/pages/partner/index.vue
Added totalBalance display via CounterBadge with currency formatting in header; introduced USelect controls for sorting (name, balance asc/desc) and filtering (all, negativeBalance); added computed helpers for sort/filter functions and refactored filteredPartners computed to apply sort then filter sequentially.
Component Type Expansion
apps/atrium-telegram/app/components/CounterBadge.vue
Extended prop type from number | null to string | number | null; updated visibility condition to exclude both numeric zero and string "0" in addition to null.
Computed Logic Refactoring
apps/atrium-telegram/app/pages/agreement/index.vue
Inlined filter return in computed pipeline; removed intermediate variable while preserving filtering and sorting logic.
Workspace Dependencies
pnpm-workspace.yaml
Updated @paralleldrive/cuid2 to exact version 2.2.2; bumped @tma.js/sdk-vue to ^1.0.6, lint-staged to ^16.2.6, playwright to ^1.56.1, vite to ^7.1.12.

Sequence Diagrams

sequenceDiagram
    participant User
    participant App as app.vue
    participant Init as init.ts
    participant BackBtn as Back Button

    User->>App: App loads
    App->>App: Compute isDev from env
    App->>Init: Call init(isDev)
    Init->>Init: Initialize with debug/eruda flags
    Init-->>App: Promise resolves
    App->>BackBtn: Chain useBackButton()
    BackBtn-->>App: Back button ready
    App->>User: App ready
Loading
sequenceDiagram
    participant UI as Partner Page UI
    participant State as Component State
    participant Store as Partner Store
    participant Filters as Filter/Sort Logic

    UI->>State: User selects sort option
    State->>State: Update sortedBy ref
    State->>Filters: Compute filteredPartners
    Filters->>Filters: Apply selected sort function
    Filters->>Filters: Apply selected filter predicate
    Filters->>Filters: Apply search filter if needed
    Filters-->>UI: Return sorted & filtered list
    UI->>UI: Render updated partner list
    Note over UI: CounterBadge shows totalBalance
Loading

Estimated Code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

The changes span multiple files with varying complexity: initialization refactoring requires careful flow verification; partner page additions involve new state management and compute chains; dependency updates are straightforward; and simpler refactors like the agreement page computed logic are low-risk. Heterogeneous patterns across files increase review burden beyond homogeneous repetitive changes.

Possibly related PRs

Poem

🐰 Through midnight code, a rabbit hops with glee,
Init chains and filters dance in harmony,
CounterBadges stretch to hold the new,
Partner sorts and fullscreen says adieu,
Dependencies bump—the workspace blooms anew!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title Check ❓ Inconclusive The title "filters on partner page" refers to a real and significant aspect of the changeset—filtering controls were indeed added to the partner page component. However, the partner page changes also include sorting functionality (sortByNameAsc, sortByBalanceAsc, sortByBalanceDesc) and a new total balance display, which are equally prominent features but not mentioned in the title. Additionally, the PR encompasses other substantial changes across multiple files (app.vue changes with high review effort, CounterBadge.vue component enhancements, init.ts modifications, and dependency updates), making it unclear whether the partner page is the primary focus or one aspect of a broader changeset. The title captures one important feature but appears incomplete in representing the full scope of changes introduced. Consider whether the title should be expanded to reflect both filtering and sorting (e.g., "feat: add sorting and filtering to partner page"), or clarified to indicate whether the partner page enhancements are the primary focus or supporting changes. Ensure the title provides enough specificity that a team member scanning the history would understand the complete scope of partner page modifications without needing to open the PR details.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch partners

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@socket-security
Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updated@​tma.js/​sdk-vue@​1.0.4 ⏵ 1.0.6671006792 +2100

View full report

@sonarqubecloud
Copy link
Copy Markdown

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/atrium-telegram/app/pages/agreement/index.vue (1)

105-111: Ensure predicate returns a boolean.

filterByActive can return a non-boolean (truthy date/string). Make it explicit.

-function filterByActive(agreement: PartnerAgreementWithAllData) {
-  return agreement.concludedAt && agreement.isActive
-}
+function filterByActive(agreement: PartnerAgreementWithAllData) {
+  return Boolean(agreement.concludedAt) && agreement.isActive === true
+}
🧹 Nitpick comments (10)
apps/atrium-telegram/app/pages/agreement/index.vue (2)

113-120: “Ends soon” filter can go stale without a reactive clock.

This uses the current time inside a computed that won’t re-run unless store/inputs change. If nothing else changes, UI won’t update as time passes.

Option: add a small reactive tick used only when filteredBy === 'willEndSoon':

+const now = ref(Date.now())
+const tick = setInterval(() => (now.value = Date.now()), 60_000)
+onUnmounted(() => clearInterval(tick))
 
 function filterByWillEndSoon(agreement: PartnerAgreementWithAllData) {
   const SIX_MONTHS = 6 * 30 * 24 * 60 * 60 * 1000
   return (
     agreement.isActive
     && agreement.willEndAt
-    && new Date(agreement.willEndAt).getTime() - new Date().getTime() < SIX_MONTHS
+    && new Date(agreement.willEndAt).getTime() - now.value < SIX_MONTHS
   )
 }

86-97: Add default branches to selector functions.

Prevents undefined comparator/predicate if state ever gets out of sync.

 function chooseSortFunction() {
   switch (sortedBy.value) {
     case 'concludedAtDesc':
       return sortByConcludedAtDesc
     case 'concludedAtAsc':
       return sortByConcludedAtAsc
     case 'willEndAtDesc':
       return sortByWillEndAtDesc
     case 'willEndAtAsc':
       return sortByWillEndAtAsc
   }
+  return sortByConcludedAtDesc
 }
 
 function chooseFilterFunction() {
   switch (filteredBy.value) {
     case 'all':
       return filterByAll
     case 'active':
       return filterByActive
     case 'inactive':
       return filterByInactive
     case 'willEndSoon':
       return filterByWillEndSoon
   }
+  return filterByAll
 }

Also applies to: 122-133

apps/atrium-telegram/app/app.vue (2)

49-59: Theme sync is one‑way.

If Telegram theme changes at runtime, themeParams.isDark() won’t trigger updates. Optional: subscribe to theme param changes if SDK exposes an event.


37-46: Add error handling to prevent silent failures from init rejection.

The init function returns a Promise and awaits operations like viewport.mount() that can reject. Without .catch(), initialization errors will silently fail and useBackButton() won't be called.

Note: init is auto-imported via Nuxt's default mechanism (located in utils/), so no explicit import is needed.

 init({
   debug: isDev,
   eruda: isDev,
   mockForMacOS: false,
-}).then(() => {
+})
+.then(() => {
   useBackButton()
+})
+.catch((err) => {
+  console.error('[init] failed', err)
 })
apps/atrium-telegram/app/components/CounterBadge.vue (1)

1-10: Make zero detection robust for formatted strings (e.g., “0 ₽”).

Current guard misses values like "0 ₽" and may show NaN. Centralize visibility logic.

 <template>
   <UBadge
-    v-if="value != null && value !== '0' && value !== 0"
+    v-if="show"
     size="lg"
     color="secondary"
     variant="solid"
     :label="value"
     class="min-w-8 justify-center text-base/4 font-bold tracking-tight"
   />
 </template>

 <script setup lang="ts">
-defineProps<{ value?: string | number | null }>()
+const props = defineProps<{ value?: string | number | null }>()
+const show = computed(() => {
+  const v = props.value
+  if (v == null) return false
+  if (typeof v === 'number') return Number.isFinite(v) && v !== 0
+  const digits = Number(String(v).replace(/[^\d.-]/g, ''))
+  return Number.isFinite(digits) ? digits !== 0 : String(v).trim() !== '0'
+})
 </script>

If the desired UX is to always show the balance even when zero, skip this change and keep it as-is. Please confirm.

Also applies to: 12-14

apps/atrium-telegram/app/pages/partner/index.vue (5)

6-7: Confirm zero-balance display intent.

"0 ₽" will render (unlike numeric 0). If you prefer hiding zero totals, gate at usage:

-<CounterBadge :value="`${new Intl.NumberFormat().format(totalBalance)} ₽`" />
+<CounterBadge v-if="totalBalance !== 0" :value="`${new Intl.NumberFormat('ru-RU').format(totalBalance)} ₽`" />

Otherwise, keep as-is and ignore this.


73-75: Locale‑aware, resilient name sort.

Optional chaining around localeCompare can yield undefined. Normalize strings and pass locale/options.

-function sortByNameAsc(a: PartnerWithData, b: PartnerWithData): number {
-  return a.legalEntity?.name?.localeCompare(b.legalEntity?.name ?? '') ?? 0
-}
+function sortByNameAsc(a: PartnerWithData, b: PartnerWithData): number {
+  const an = a.legalEntity?.name ?? ''
+  const bn = b.legalEntity?.name ?? ''
+  return an.localeCompare(bn, 'ru', { sensitivity: 'base', numeric: true })
+}

77-83: Add tie‑breakers for stable numeric sorts.

Ensures deterministic order when balances are equal.

 function sortByBalanceAsc(a: PartnerWithData, b: PartnerWithData) {
-  return a.balance - b.balance
+  const d = a.balance - b.balance
+  return d !== 0 ? d : sortByNameAsc(a, b)
 }
 
 function sortByBalanceDesc(a: PartnerWithData, b: PartnerWithData) {
-  return b.balance - a.balance
+  const d = b.balance - a.balance
+  return d !== 0 ? d : sortByNameAsc(a, b)
 }

85-94: Default branches for selector functions.

Prevents undefined comparator/predicate in edge cases.

 function chooseSortFunction() {
   switch (sortedBy.value) {
     case 'nameAsc':
       return sortByNameAsc
     case 'balanceAsc':
       return sortByBalanceAsc
     case 'balanceDesc':
       return sortByBalanceDesc
   }
+  return sortByNameAsc
 }
 ...
 function chooseFilterFunction() {
   switch (filteredBy.value) {
     case 'all':
       return filterByAll
     case 'negativeBalance':
       return filterByNegativeBalance
   }
+  return filterByAll
 }

Also applies to: 108-115


121-129: Trim and precompute query for search.

Avoids false negatives from leading/trailing spaces and redundant lowercasing.

-  if (!search.value) {
+  const query = search.value.trim().toLowerCase()
+  if (!query) {
     // Show all
     return filtered
   }
 
-  return filtered.filter((partner) => {
-    return partner.legalEntity?.name?.toLowerCase().includes(search.value.toLowerCase()) ?? false
-  })
+  return filtered.filter((partner) =>
+    (partner.legalEntity?.name ?? '').toLowerCase().includes(query)
+  )
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c62e896 and 703b177.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (6)
  • apps/atrium-telegram/app/app.vue (2 hunks)
  • apps/atrium-telegram/app/components/CounterBadge.vue (2 hunks)
  • apps/atrium-telegram/app/pages/agreement/index.vue (1 hunks)
  • apps/atrium-telegram/app/pages/partner/index.vue (3 hunks)
  • apps/atrium-telegram/app/utils/init.ts (0 hunks)
  • pnpm-workspace.yaml (3 hunks)
💤 Files with no reviewable changes (1)
  • apps/atrium-telegram/app/utils/init.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (3)
apps/atrium-telegram/app/pages/agreement/index.vue (1)

135-138: LGTM on the inlined filter.

The pipeline is clear: sort then filter. Reads well and is non-mutating via toSorted.

apps/atrium-telegram/app/pages/partner/index.vue (1)

21-34: UI controls look good.

Items/values match the union types; classes and icons consistent with the design system.

Also applies to: 36-48

pnpm-workspace.yaml (1)

23-23: The original review comment is incorrect and should be disregarded.

The workspace uses pnpm's catalog mechanism, which ensures all packages reference @paralleldrive/cuid2 via "catalog:" pointers in their package.json files. This means the version is centrally defined in pnpm-workspace.yaml (2.2.2) and all consumers inherit it—preventing duplicate installs, not causing them. The concern about mixed versioning and duplicates does not apply here.

While there is a minor stylistic inconsistency (exact pin vs. caret ranges for other catalog entries), this is cosmetic and poses no technical risk to monorepo consistency or dependency resolution.

Likely an incorrect or invalid review comment.

Comment on lines +69 to +70
const totalBalance = computed(() => partnerStore.partners.reduce((acc, partner) => acc + partner.balance, 0))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Avoid NaN in total balance.

Guard against missing balances.

-const totalBalance = computed(() => partnerStore.partners.reduce((acc, partner) => acc + partner.balance, 0))
+const totalBalance = computed(() =>
+  partnerStore.partners.reduce((acc, partner) => acc + (partner.balance ?? 0), 0)
+)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const totalBalance = computed(() => partnerStore.partners.reduce((acc, partner) => acc + partner.balance, 0))
const totalBalance = computed(() =>
partnerStore.partners.reduce((acc, partner) => acc + (partner.balance ?? 0), 0)
)
🤖 Prompt for AI Agents
In apps/atrium-telegram/app/pages/partner/index.vue around lines 69-70, the
computed totalBalance can become NaN when partner.balance is missing or not a
number; update the reducer to coerce each partner.balance to a finite numeric
value (e.g. use Number(...) and fallback to 0, or parseFloat plus isFinite) and
ensure the reduce has an explicit initial accumulator of 0 so missing/invalid
balances are treated as 0 rather than producing NaN.

@hmbanan666 hmbanan666 merged commit e844770 into main Oct 23, 2025
8 checks passed
@hmbanan666 hmbanan666 deleted the partners branch October 23, 2025 13:43
This was referenced Oct 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant