Conversation
WalkthroughRefactored 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
Sequence DiagramssequenceDiagram
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
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
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
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
|
There was a problem hiding this comment.
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.
filterByActivecan 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
undefinedcomparator/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
initfunction returns a Promise and awaits operations likeviewport.mount()that can reject. Without.catch(), initialization errors will silently fail anduseBackButton()won't be called.Note:
initis auto-imported via Nuxt's default mechanism (located inutils/), 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 showNaN. 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
localeComparecan yieldundefined. 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
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis 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/cuid2via"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.
| const totalBalance = computed(() => partnerStore.partners.reduce((acc, partner) => acc + partner.balance, 0)) | ||
|
|
There was a problem hiding this comment.
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.
| 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.



Summary by CodeRabbit
Release Notes
New Features
Improvements
Chores