Conversation
|
Warning Review limit reached
More reviews will be available in 54 minutes and 57 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more credits in the billing tab to continue. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (17)
WalkthroughThis PR introduces a sidebar navigation system with cookie-backed state persistence, breadcrumb routing from the current route, and updates the dashboard shell layout. Legacy header navigation is removed, pages are standardized to simpler container layouts, callback-based component interactions are refactored to use ChangesDashboard Sidebar Navigation Migration
Possibly Related PRs
🚥 Pre-merge checks | ✅ 3 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 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 |
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/app/dashboard/`(active)/layout.tsx:
- Around line 9-12: The layout reads a client-controlled cookie into cookie and
directly JSON.parse's it into DSCategoryState which can throw on malformed
input; wrap the parse in a safe guard (try/catch) or use a safeJsonParse helper
around the cookie value and fall back to an empty object on error so
layout.tsx’s DSCategoryState is always an object and parsing failures are
logged/ignored; update the code that references cookieStore, cookie and
DSCategoryState to use this safe parse.
In `@src/app/dashboard/`(active)/telegram/groups/page.tsx:
- Line 26: The column header text "Hide" in the groups listing is misleading
because the last column in GroupRow (component/group-row.tsx,
functions/rendering around the hide toggle and leave-chat actions) contains both
the hide toggle and leave-chat controls; update the header in page.tsx (where
the <p>Hide</p> is defined) to a more accurate label such as "Actions" or
"Controls" (or "Hide / Leave" if you prefer explicitness) and adjust any
associated aria-labels/tooltip text to match so the header aligns with the
actual controls rendered by GroupRow.
In `@src/components/dashboard-sidebar/data.tsx`:
- Around line 27-37: flattenNavigation currently only maps first-level items
from DSData so nested route titles are missing in NAV_MAP; update
flattenNavigation (and its inner traverse) to recursively walk child arrays
(e.g., items with a children or items property) and add every node with a url to
the map, ensuring NAV_MAP contains entries for nested routes used by
breadcrumb.tsx; locate flattenNavigation, DSData, traverse, and NAV_MAP and make
traverse call itself for child lists and/or child properties until all nested
nodes are added.
In `@src/components/dashboard-sidebar/main-nav.tsx`:
- Around line 21-27: DSMenuCategory currently creates its own
useCookieStorage(COOKIES.SIDEBAR_CATEGORY_STATE) per instance which causes
concurrent writes to clobber each other and also mutates state in place;
instead, move the single useCookieStorage(COOKIES.SIDEBAR_CATEGORY_STATE) call
up into DSMainNav (call it once to get shared categoryState and
setCategoryState) and pass the state and setter down to DSMenuCategory as props;
ensure DSMenuCategory updates use an immutable setter (no in-place mutation of
the state object—use a new object like {...state, [title]: newValue}) so toggles
for one category won’t overwrite others.
- Around line 77-79: The nav highlighting uses exact equality (const path =
usePathname(); const isActive = path === item.url) so nested/detail routes don't
mark the parent active; change the logic in the component that computes isActive
(where usePathname(), path and item.url are referenced) to treat the item as
active when the current path startsWith the item.url (and normalize trailing
slashes or handle the root "/" case) so parent menu items remain highlighted for
nested routes.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 11cd920e-0253-4982-bc61-5efb30ca7cd4
📒 Files selected for processing (30)
src/app/dashboard/(active)/account/page.tsxsrc/app/dashboard/(active)/azure/members/page.tsxsrc/app/dashboard/(active)/azure/page.tsxsrc/app/dashboard/(active)/breadcrumb.tsxsrc/app/dashboard/(active)/layout.tsxsrc/app/dashboard/(active)/page.tsxsrc/app/dashboard/(active)/telegram/grants/page.tsxsrc/app/dashboard/(active)/telegram/groups/group-row.tsxsrc/app/dashboard/(active)/telegram/groups/page.tsxsrc/app/dashboard/(active)/telegram/page.tsxsrc/app/dashboard/(active)/telegram/user-details/page.tsxsrc/app/dashboard/(active)/telegram/user-details/remove-role.tsxsrc/app/dashboard/(active)/telegram/user-list/page.tsxsrc/app/dashboard/layout.tsxsrc/app/layout.tsxsrc/app/page.tsxsrc/components/admin-header/index.tsxsrc/components/admin-header/right-nav.tsxsrc/components/dashboard-sidebar/data.tsxsrc/components/dashboard-sidebar/index.tsxsrc/components/dashboard-sidebar/main-nav.tsxsrc/components/dashboard-sidebar/user-nav.tsxsrc/components/ui/sidebar.tsxsrc/constants.tssrc/hooks/use-cookie-storage.tsxsrc/hooks/use-session-storage.tsxsrc/index.csssrc/lib/i18n.tssrc/utils/cookies.tstsconfig.json
💤 Files with no reviewable changes (4)
- src/lib/i18n.ts
- src/components/admin-header/index.tsx
- src/app/dashboard/(active)/telegram/page.tsx
- src/components/admin-header/right-nav.tsx
|
ci sono dei bug nella persistence degli stati open dei collapsible che devo fixare |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
src/app/dashboard/(active)/breadcrumb.tsx (1)
63-66: ⚡ Quick winReplace hard-coded breadcrumb index rule with route-aware link eligibility.
Line 65 hard-codes
i !== 1, which couples behavior to the current URL depth. Prefer deriving linkability fromNAV_MAPso future route changes don’t break breadcrumb behavior.Suggested diff
- breadcrumbs.push({ title, url: i !== 1 ? currentPath : undefined }) + const isNavigable = navMap.has(currentPath) + breadcrumbs.push({ title, url: isNavigable ? currentPath : undefined }) i++🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/dashboard/`(active)/breadcrumb.tsx around lines 63 - 66, The breadcrumb logic currently uses a hard-coded index check (i !== 1) when building breadcrumb objects in breadcrumb.tsx; replace this with route-aware link eligibility by consulting NAV_MAP (or the existing route metadata) instead of relying on the iteration index. Locate where breadcrumbs.push({ title, url: i !== 1 ? currentPath : undefined }) is used and change it to compute a boolean like isLinkable = NAV_MAP[currentPath]?.linkable || NAV_MAP[currentPath]?.isPage (or whatever metadata key denotes navigable pages) and then push { title, url: isLinkable ? currentPath : undefined }; remove dependence on the variable i/current depth so future route structure changes won’t break breadcrumb link behavior.src/hooks/use-cookie-storage.tsx (1)
28-46: ⚡ Quick winConsider using functional setState to stabilize the
setValuecallback.The current implementation includes
storedValueinsetValue's dependencies, causing a new callback reference on every state update. This can trigger unnecessary re-renders in components that receivesetValueas a prop, and functional updates read from the closure rather than React's state queue.♻️ Refactor to use functional setState
const setValue: Dispatch<SetStateAction<T>> = useCallback( (value) => { - try { - const valueToStore = value instanceof Function ? value(storedValue) : value - setStoredValue(valueToStore) - - if (typeof document !== "undefined") { - if (valueToStore === null || valueToStore === undefined) { - deleteCookie(key, { path: mergedOptions.path, domain: mergedOptions.domain }) - } else { - setCookie(key, JSON.stringify(valueToStore), mergedOptions) - } - } - } catch (error) { - console.warn(`Error setting cookie "${key}":`, error) - } + try { + setStoredValue((prev) => { + const valueToStore = value instanceof Function ? value(prev) : value + + if (typeof document !== "undefined") { + if (valueToStore === null || valueToStore === undefined) { + deleteCookie(key, { path: mergedOptions.path, domain: mergedOptions.domain }) + } else { + setCookie(key, JSON.stringify(valueToStore), mergedOptions) + } + } + + return valueToStore + }) + } catch (error) { + console.warn(`Error setting cookie "${key}":`, error) + } }, - [key, storedValue, mergedOptions] + [key, mergedOptions] )🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/hooks/use-cookie-storage.tsx` around lines 28 - 46, The setValue callback closes over storedValue causing it to change identity on every state update; change it to use the functional form of setStoredValue: inside useCallback call setStoredValue(prev => { const valueToStore = value instanceof Function ? value(prev) : value; /* update cookie/delete based on valueToStore */ return valueToStore }); then remove storedValue from the useCallback dependency array and keep key and mergedOptions, and continue using deleteCookie/setCookie with mergedOptions and key; ensure cookie updates use the computed valueToStore rather than the closed-over storedValue.src/hooks/use-session-storage.tsx (1)
22-36: ⚡ Quick winConsider using functional setState to stabilize the
setValuecallback.Same issue as in
use-cookie-storage.tsx: includingstoredValuein the dependencies array creates a newsetValuereference on every state change. Using functional setState removes this dependency and ensures successive updates are properly chained through React's state queue.♻️ Refactor to use functional setState
const setValue: Dispatch<SetStateAction<T>> = useCallback( (value) => { - try { - const valueToStore = value instanceof Function ? value(storedValue) : value - setStoredValue(valueToStore) - - if (typeof window !== "undefined") { - window.sessionStorage.setItem(key, JSON.stringify(valueToStore)) - } - } catch (error) { - console.warn(`Error setting sessionStorage key "${key}":`, error) - } + try { + setStoredValue((prev) => { + const valueToStore = value instanceof Function ? value(prev) : value + + if (typeof window !== "undefined") { + window.sessionStorage.setItem(key, JSON.stringify(valueToStore)) + } + + return valueToStore + }) + } catch (error) { + console.warn(`Error setting sessionStorage key "${key}":`, error) + } }, - [key, storedValue] + [key] )🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/hooks/use-session-storage.tsx` around lines 22 - 36, The setValue callback currently closes over storedValue and lists it in the useCallback deps which recreates setValue on every state change; change setValue (the function passed to useCallback) to use functional setState with setStoredValue(prev => { const valueToStore = typeof value === "function" ? value(prev) : value; /* persist to sessionStorage using key */ return valueToStore; }) so you compute valueToStore from the previous state instead of reading storedValue, then remove storedValue from the dependency array so useCallback only depends on key; keep the sessionStorage write (window.sessionStorage.setItem(key, JSON.stringify(valueToStore))) and the existing try/catch and warning behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/app/dashboard/`(active)/breadcrumb.tsx:
- Line 69: Remove the debug logging statement that prints route breadcrumbs to
the client: delete the console.log(breadcrumbs) call in
src/app/dashboard/(active)/breadcrumb.tsx (the place where the breadcrumbs
variable is used/rendered) so that user-facing code no longer outputs route
details; if needed for development replace it with a guarded debug logger that's
disabled in production or move logging behind a NODE_ENV check in the Breadcrumb
rendering logic.
---
Nitpick comments:
In `@src/app/dashboard/`(active)/breadcrumb.tsx:
- Around line 63-66: The breadcrumb logic currently uses a hard-coded index
check (i !== 1) when building breadcrumb objects in breadcrumb.tsx; replace this
with route-aware link eligibility by consulting NAV_MAP (or the existing route
metadata) instead of relying on the iteration index. Locate where
breadcrumbs.push({ title, url: i !== 1 ? currentPath : undefined }) is used and
change it to compute a boolean like isLinkable = NAV_MAP[currentPath]?.linkable
|| NAV_MAP[currentPath]?.isPage (or whatever metadata key denotes navigable
pages) and then push { title, url: isLinkable ? currentPath : undefined };
remove dependence on the variable i/current depth so future route structure
changes won’t break breadcrumb link behavior.
In `@src/hooks/use-cookie-storage.tsx`:
- Around line 28-46: The setValue callback closes over storedValue causing it to
change identity on every state update; change it to use the functional form of
setStoredValue: inside useCallback call setStoredValue(prev => { const
valueToStore = value instanceof Function ? value(prev) : value; /* update
cookie/delete based on valueToStore */ return valueToStore }); then remove
storedValue from the useCallback dependency array and keep key and
mergedOptions, and continue using deleteCookie/setCookie with mergedOptions and
key; ensure cookie updates use the computed valueToStore rather than the
closed-over storedValue.
In `@src/hooks/use-session-storage.tsx`:
- Around line 22-36: The setValue callback currently closes over storedValue and
lists it in the useCallback deps which recreates setValue on every state change;
change setValue (the function passed to useCallback) to use functional setState
with setStoredValue(prev => { const valueToStore = typeof value === "function" ?
value(prev) : value; /* persist to sessionStorage using key */ return
valueToStore; }) so you compute valueToStore from the previous state instead of
reading storedValue, then remove storedValue from the dependency array so
useCallback only depends on key; keep the sessionStorage write
(window.sessionStorage.setItem(key, JSON.stringify(valueToStore))) and the
existing try/catch and warning behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 20b31a27-f364-49fd-9b2a-70d335ddc6c2
📒 Files selected for processing (8)
src/app/dashboard/(active)/account/page.tsxsrc/app/dashboard/(active)/azure/page.tsxsrc/app/dashboard/(active)/breadcrumb.tsxsrc/components/dashboard-sidebar/data.tsxsrc/components/dashboard-sidebar/main-nav.tsxsrc/hooks/use-cookie-storage.tsxsrc/hooks/use-session-storage.tsxsrc/index.css
💤 Files with no reviewable changes (1)
- src/app/dashboard/(active)/azure/page.tsx
✅ Files skipped from review due to trivial changes (1)
- src/app/dashboard/(active)/account/page.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
- src/components/dashboard-sidebar/data.tsx
- src/components/dashboard-sidebar/main-nav.tsx
There was a problem hiding this comment.
Actionable comments posted: 8
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/server/actions/users.ts (1)
19-29:⚠️ Potential issue | 🟠 Major | ⚡ Quick winAdd error handling for tRPC calls.
The function chains multiple async tRPC calls without try/catch blocks. If any call fails (network issues, backend errors, authorization failures), the function will throw an unhandled exception that bubbles to the caller. Consider wrapping the calls in try/catch to provide graceful error handling and logging.
🛡️ Proposed error handling pattern
export async function getUserDetails(userId: number) { + try { const { user } = await trpc.tg.users.get.query({ userId }) if (!user) return null const { roles, groupAdmin } = await trpc.tg.permissions.getRoles.query({ userId: user.id }) const { messages } = await trpc.tg.messages.getLastByUser.query({ userId: user.id, limit: 15 }) const audits = await trpc.tg.auditLog.getById.query({ targetId: user.id }) const { grant } = await getUserGrant(user.id) return { roles, groupAdmin, user, messages, audits, grant } + } catch (error) { + console.error('Failed to fetch user details:', error) + throw error // or return null, depending on desired behavior + } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/server/actions/users.ts` around lines 19 - 29, getUserDetails currently calls multiple async tRPC endpoints (trpc.tg.users.get.query, trpc.tg.permissions.getRoles.query, trpc.tg.messages.getLastByUser.query, trpc.tg.auditLog.getById.query) and getUserGrant without any error handling; wrap the entire sequence in a try/catch inside getUserDetails, log the caught error via your logging utility (or processLogger) with context (e.g., "getUserDetails failed for userId: ..."), and return a safe fallback (null or a structured error object) so callers don’t receive unhandled exceptions; ensure you still return existing successful results when possible or short-circuit if the primary user fetch fails.
🧹 Nitpick comments (6)
src/app/dashboard/(active)/telegram/grants/delete-grant.tsx (1)
22-28: ⚡ Quick winRemove commented code.
Instead of leaving the
onDeleteprop and its invocation as comments, remove them entirely. Commented code can create confusion and maintenance burden.🧹 Proposed cleanup
-export function DeleteGrant({ - userId, - // onDelete -}: { - userId: number - // onDelete(): void -}) { +export function DeleteGrant({ userId }: { userId: number }) { const router = useRouter() const [open, setOpen] = useState(false)And remove the commented call:
else { toast.success("Grant interrupted successfully") router.refresh() - // onDelete() }Also applies to: 42-42
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/dashboard/`(active)/telegram/grants/delete-grant.tsx around lines 22 - 28, Remove the leftover commented prop and invocation from the DeleteGrant component: delete the commented onDelete prop declaration in the component signature and remove any commented call to onDelete inside the component (references around the DeleteGrant function and its JSX). Keep only the actual userId prop and related logic so no commented code remains.src/app/dashboard/(active)/telegram/users/[id]/card-user-grant.tsx (1)
8-16: ⚡ Quick winRemove commented code.
Similar to
DeleteGrant, the commentedonDeleteprop should be removed entirely rather than left as a comment.🧹 Proposed cleanup
-export function UserGrantCard({ - user, - grant, - //onDelete -}: { - user: TgUser - grant: TgGrant - //onDelete(): void -}) { +export function UserGrantCard({ user, grant }: { user: TgUser; grant: TgGrant }) { return (🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/dashboard/`(active)/telegram/users/[id]/card-user-grant.tsx around lines 8 - 16, Remove the leftover commented prop from the UserGrantCard component: delete the commented onDelete prop in both the function signature and the TypeScript props type so the component signature is clean (refer to UserGrantCard and its props block where "//onDelete" and "//onDelete(): void" are present), mirroring the cleanup done in DeleteGrant.src/app/dashboard/(active)/telegram/users/page.tsx (1)
1-1: ⚡ Quick winRemove unused import
ViewIcon.The
ViewIconimport is unused; onlyEyeis referenced in the component.♻️ Proposed fix
-import { Eye, ViewIcon } from "lucide-react" +import { Eye } from "lucide-react"🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/dashboard/`(active)/telegram/users/page.tsx at line 1, The import line currently imports both Eye and ViewIcon but ViewIcon is never used; update the import statement that references Eye and ViewIcon to only import Eye (remove ViewIcon from the named imports) and verify there are no remaining references to ViewIcon elsewhere in the module (e.g., in the component rendering) before committing.src/server/actions/users.ts (2)
20-20: ⚡ Quick winSimplify redundant object property shorthand.
The object property
userId: userIdcan be simplified to justuserIdusing ES6 shorthand.♻️ Proposed simplification
- const { user } = await trpc.tg.users.get.query({ userId: userId }) + const { user } = await trpc.tg.users.get.query({ userId })🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/server/actions/users.ts` at line 20, Replace the redundant object property in the trpc call: in the invocation of trpc.tg.users.get.query (the expression "const { user } = await trpc.tg.users.get.query({ userId: userId })"), use ES6 shorthand and pass { userId } instead of { userId: userId } to simplify the object literal.
19-19: 💤 Low valueConsider adding explicit return type annotation.
While TypeScript infers the return type correctly, adding an explicit return type improves code documentation and catches potential type mismatches earlier.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/server/actions/users.ts` at line 19, Add an explicit return type annotation to the getUserDetails function declaration (export async function getUserDetails(userId: number): Promise<...>) that matches the actual resolved value returned by the function (e.g., Promise<User> or Promise<User | null>); inspect the function's return statements or awaited calls to determine the correct concrete type or union, import or reference the appropriate User/UserDetails type if needed, and update the declaration so TypeScript enforces and documents the expected return shape.src/app/dashboard/(active)/telegram/users/[id]/remove-role.tsx (1)
37-37: ⚡ Quick winRemove commented code.
The commented
onDeleteprop and its invocation should be removed entirely for consistency with the refactoring pattern.🧹 Proposed cleanup
export function RemoveRole({ user, alreadyRoles, - // onDelete, }: { user: TgUser alreadyRoles: TgUserRole[] - // onDelete(): void }) {And remove the commented call:
else { toast.success("Role removed!") router.refresh() - // onDelete() }Also applies to: 41-41, 73-73
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/dashboard/`(active)/telegram/users/[id]/remove-role.tsx at line 37, Remove the leftover commented prop and call for onDelete in the RemoveRole component: delete the commented "onDelete," in the component props (the commented prop near the top) and remove any commented invocation of onDelete (the commented call around where the delete handler is invoked, including the one at lines ~41 and ~73). Ensure you only remove the commented references to onDelete and leave the rest of the component JSX and logic unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/app/dashboard/`(active)/account/loading.tsx:
- Around line 28-30: The loading fallback currently renders an interactive
NewPasskeyButton in loading.tsx which can trigger auth.passkey.addPasskey(...)
and cause duplicate creations; remove NewPasskeyButton from the fallback and
replace it with a non-interactive placeholder (e.g., a Skeleton or static
disabled UI) so no write actions or router.refresh() can occur while the page is
loading; locate the JSX in loading.tsx that renders <NewPasskeyButton /> and
remove or substitute it with a harmless, non-interactive element.
In `@src/app/dashboard/`(active)/layout.tsx:
- Around line 46-47: The code trusts parseCookie(...) for
sidebarCategoryStateCookie and sidebarOpenCookie but needs runtime validation;
update the layout to validate and coerce values: for sidebarOpenCookie use
parseCookie(sidebarOpenCookie) then convert to a boolean (true if value === true
or value === "true") and default to true for invalid values before assigning to
open, and for sidebarCategoryStateCookie use
parseCookie(sidebarCategoryStateCookie) then ensure it's a Record<string,
boolean> by iterating keys and only keeping keys with boolean values (or
coercing truthy/falsy to booleans) and defaulting to {} for invalid results
before assigning to state so SidebarProvider always receives the expected
shapes.
In `@src/app/dashboard/`(active)/telegram/users/[id]/page.tsx:
- Line 41: The displayed comment "Last messages (max 12):" is inconsistent with
the server action that fetches messages with limit: 15; update the UI text in
the JSX paragraph (the element rendering "Last messages (max 12):") to match the
query limit (e.g., "Last messages (max 15):") or alternatively change the server
action's fetch limit to 12 so both sides agree—locate the paragraph in the page
component and the server action where messages are fetched with limit: 15 and
make them consistent.
- Around line 10-12: TgUserDetails currently calls getUserDetails(parseInt(id,
10)) without validating the parsed id; add validation after extracting params
(in TgUserDetails) to detect non-numeric or NaN IDs (e.g., const userId =
parseInt(id, 10); if (!Number.isInteger(userId) || Number.isNaN(userId)) ...).
On invalid IDs, stop calling getUserDetails and return a clear fallback (render
an error message/invalid-ID UI, throw Next.js notFound(), or redirect) so the
page doesn't render an empty container when getUserDetails would be passed NaN.
- Line 25: The alreadyIn prop passed to NewGroupAdmin is built from
data.groupAdmin but uses g?.group.id ?? 0 which injects 0 for missing ids and
the outer ?? [] is unnecessary; update the expression that computes alreadyIn
(the value passed into NewGroupAdmin in page.tsx) to first filter out entries
with nullish group or group.id (e.g., data.groupAdmin.filter(g => g?.group?.id
!= null).map(g => g.group.id)) so only real group ids are included and remove
the redundant ?? [].
- Around line 16-68: The page currently only renders content when data is
truthy, so when getUserDetails returns null users see a blank page; update the
component in page.tsx to explicitly handle data === null and render a clear
"User not found" (or similar) message/UI instead of nothing. Locate the
rendering block that checks {data && (...)} and add an explicit branch (e.g., if
data === null) that returns a styled paragraph or card informing the user the
requested user does not exist; keep the existing rendering for when data is
present (UserInfoCard, UserGrantCard, GroupAdminCard, MessageCard, AuditLogCard)
unchanged.
- Around line 57-59: Remove the unnecessary React Suspense wrapper around
AuditLogCard in the render loop: AuditLogCard (export function in
src/app/.../card-audit-log.tsx) is synchronous and will never suspend, so delete
the <Suspense fallback={null} key={`${m.id}-${m.type}`}> ... </Suspense> wrapper
around AuditLogCard in page.tsx and render <AuditLogCard log={m} /> directly
(preserve the key on the list item/parent element if needed).
In `@src/app/dashboard/`(active)/telegram/users/page.tsx:
- Around line 41-43: The icon-only Button containing the Eye icon lacks
accessible text; update the Button usage in page.tsx so screen readers get
context by adding an aria-label (e.g., aria-label="View user" or similar) to the
Button component or include a visually-hidden span with descriptive text next to
the Eye icon; ensure you modify the Button element where Eye is rendered (the
Button and Eye usage) so the accessible label matches the button action.
---
Outside diff comments:
In `@src/server/actions/users.ts`:
- Around line 19-29: getUserDetails currently calls multiple async tRPC
endpoints (trpc.tg.users.get.query, trpc.tg.permissions.getRoles.query,
trpc.tg.messages.getLastByUser.query, trpc.tg.auditLog.getById.query) and
getUserGrant without any error handling; wrap the entire sequence in a try/catch
inside getUserDetails, log the caught error via your logging utility (or
processLogger) with context (e.g., "getUserDetails failed for userId: ..."), and
return a safe fallback (null or a structured error object) so callers don’t
receive unhandled exceptions; ensure you still return existing successful
results when possible or short-circuit if the primary user fetch fails.
---
Nitpick comments:
In `@src/app/dashboard/`(active)/telegram/grants/delete-grant.tsx:
- Around line 22-28: Remove the leftover commented prop and invocation from the
DeleteGrant component: delete the commented onDelete prop declaration in the
component signature and remove any commented call to onDelete inside the
component (references around the DeleteGrant function and its JSX). Keep only
the actual userId prop and related logic so no commented code remains.
In `@src/app/dashboard/`(active)/telegram/users/[id]/card-user-grant.tsx:
- Around line 8-16: Remove the leftover commented prop from the UserGrantCard
component: delete the commented onDelete prop in both the function signature and
the TypeScript props type so the component signature is clean (refer to
UserGrantCard and its props block where "//onDelete" and "//onDelete(): void"
are present), mirroring the cleanup done in DeleteGrant.
In `@src/app/dashboard/`(active)/telegram/users/[id]/remove-role.tsx:
- Line 37: Remove the leftover commented prop and call for onDelete in the
RemoveRole component: delete the commented "onDelete," in the component props
(the commented prop near the top) and remove any commented invocation of
onDelete (the commented call around where the delete handler is invoked,
including the one at lines ~41 and ~73). Ensure you only remove the commented
references to onDelete and leave the rest of the component JSX and logic
unchanged.
In `@src/app/dashboard/`(active)/telegram/users/page.tsx:
- Line 1: The import line currently imports both Eye and ViewIcon but ViewIcon
is never used; update the import statement that references Eye and ViewIcon to
only import Eye (remove ViewIcon from the named imports) and verify there are no
remaining references to ViewIcon elsewhere in the module (e.g., in the component
rendering) before committing.
In `@src/server/actions/users.ts`:
- Line 20: Replace the redundant object property in the trpc call: in the
invocation of trpc.tg.users.get.query (the expression "const { user } = await
trpc.tg.users.get.query({ userId: userId })"), use ES6 shorthand and pass {
userId } instead of { userId: userId } to simplify the object literal.
- Line 19: Add an explicit return type annotation to the getUserDetails function
declaration (export async function getUserDetails(userId: number): Promise<...>)
that matches the actual resolved value returned by the function (e.g.,
Promise<User> or Promise<User | null>); inspect the function's return statements
or awaited calls to determine the correct concrete type or union, import or
reference the appropriate User/UserDetails type if needed, and update the
declaration so TypeScript enforces and documents the expected return shape.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: a2828203-168d-400b-8137-e82afcc9f628
📒 Files selected for processing (31)
src/app/dashboard/(active)/account/loading.tsxsrc/app/dashboard/(active)/azure/members/loading.tsxsrc/app/dashboard/(active)/complete-profile.tsxsrc/app/dashboard/(active)/layout.tsxsrc/app/dashboard/(active)/page.tsxsrc/app/dashboard/(active)/telegram/grants/delete-grant.tsxsrc/app/dashboard/(active)/telegram/grants/loading.tsxsrc/app/dashboard/(active)/telegram/grants/page.tsxsrc/app/dashboard/(active)/telegram/groups/loading.tsxsrc/app/dashboard/(active)/telegram/groups/page.tsxsrc/app/dashboard/(active)/telegram/user-details/page.tsxsrc/app/dashboard/(active)/telegram/users/[id]/add-role.tsxsrc/app/dashboard/(active)/telegram/users/[id]/card-audit-log.tsxsrc/app/dashboard/(active)/telegram/users/[id]/card-group-admin.tsxsrc/app/dashboard/(active)/telegram/users/[id]/card-message.tsxsrc/app/dashboard/(active)/telegram/users/[id]/card-user-grant.tsxsrc/app/dashboard/(active)/telegram/users/[id]/card-user-info.tsxsrc/app/dashboard/(active)/telegram/users/[id]/delete-group-admin.tsxsrc/app/dashboard/(active)/telegram/users/[id]/loading.tsxsrc/app/dashboard/(active)/telegram/users/[id]/new-group-admin.tsxsrc/app/dashboard/(active)/telegram/users/[id]/page.tsxsrc/app/dashboard/(active)/telegram/users/[id]/remove-role.tsxsrc/app/dashboard/(active)/telegram/users/loading.tsxsrc/app/dashboard/(active)/telegram/users/page.tsxsrc/components/dashboard-sidebar/data.tsxsrc/components/dashboard-sidebar/main-nav.tsxsrc/components/ui/sidebar.tsxsrc/constants.tssrc/hooks/use-cookie-storage.tsxsrc/index.csssrc/server/actions/users.ts
💤 Files with no reviewable changes (1)
- src/app/dashboard/(active)/telegram/user-details/page.tsx
✅ Files skipped from review due to trivial changes (6)
- src/app/dashboard/(active)/azure/members/loading.tsx
- src/app/dashboard/(active)/telegram/groups/loading.tsx
- src/app/dashboard/(active)/telegram/grants/loading.tsx
- src/app/dashboard/(active)/telegram/users/[id]/loading.tsx
- src/app/dashboard/(active)/telegram/groups/page.tsx
- src/app/dashboard/(active)/telegram/users/loading.tsx
🚧 Files skipped from review as they are similar to previous changes (7)
- src/constants.ts
- src/app/dashboard/(active)/telegram/grants/page.tsx
- src/index.css
- src/hooks/use-cookie-storage.tsx
- src/components/dashboard-sidebar/data.tsx
- src/components/ui/sidebar.tsx
- src/components/dashboard-sidebar/main-nav.tsx
No description provided.