Skip to content

chore: fix more linter issues#47

Merged
izadoesdev merged 11 commits into
databuddy-analytics:stagingfrom
AyanavaKarmakar:chore/lint-fixes-2
Jul 31, 2025
Merged

chore: fix more linter issues#47
izadoesdev merged 11 commits into
databuddy-analytics:stagingfrom
AyanavaKarmakar:chore/lint-fixes-2

Conversation

@AyanavaKarmakar

@AyanavaKarmakar AyanavaKarmakar commented Jul 30, 2025

Copy link
Copy Markdown
Contributor

Description

  • add 'chrome' to globals in biome config to suppress linter issue in extension
  • fix more linter issues

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

Summary by CodeRabbit

  • Refactor

    • Numerous files updated to use consistent code formatting, including explicit block braces for conditional statements and improved naming conventions for unused variables.
    • Unused imports and components were removed across various modules to enhance code clarity.
    • Several functions and components were renamed for clarity, with no changes to their behavior.
    • Improved import ordering and formatting consistency across components and hooks.
  • Bug Fixes

    • Improved type safety and validation in payment and security event handling for enhanced reliability.
    • Enhanced numeric validation and error handling in some data processing and formatting utilities.
  • Chores

    • Removed deprecated or unused middleware and logging utilities.
    • Updated type annotations and interface definitions for better maintainability.
    • Standardized error handling blocks and conditional statement formatting for consistency.
  • Tests

    • Optimized test execution by parallelizing asynchronous calls in geo-location tests.
  • Documentation

    • Improved code comments and formatting for readability in select components and utilities.

No user-facing features or functionality were changed.

@vercel

vercel Bot commented Jul 30, 2025

Copy link
Copy Markdown

@AyanavaKarmakar is attempting to deploy a commit to the Databuddy Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Jul 30, 2025

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

This update consists of widespread stylistic and consistency changes across the codebase, primarily converting single-line conditional statements into explicit block statements with braces. Numerous unused imports and variables are removed or renamed, and some function or parameter names are adjusted to clarify intentional non-use. Several files receive improved type annotations or parameter typings, particularly in Stripe webhook handling. No core logic, error handling, or control flow is altered; all modifications aim to enhance readability, maintainability, and type safety.

Changes

Cohort / File(s) Change Summary
Stylistic: Braces for Conditionals
apps/api/src/agent/handlers/metric-handler.ts, apps/api/src/agent/utils/sql-validator.ts, apps/api/src/query/utils.ts, apps/basket/src/polyfills/compression.js, apps/dashboard/app/(auth)/login/page.tsx, apps/dashboard/app/(main)/settings/_components/password-form.tsx, apps/dashboard/app/(main)/settings/_components/two-factor-form.tsx, apps/dashboard/app/(main)/websites/[id]/_components/utils/analytics-helpers.tsx, apps/dashboard/app/(main)/websites/[id]/_components/utils/code-generators.ts, apps/dashboard/app/(main)/websites/[id]/_components/utils/technology-helpers.tsx, apps/dashboard/app/(main)/websites/[id]/_components/utils/ui-components.tsx, apps/dashboard/app/(main)/websites/[id]/_components/tabs/performance-tab.tsx, apps/dashboard/app/(main)/websites/[id]/_components/tabs/overview-tab.tsx, apps/dashboard/app/(main)/websites/[id]/sessions/_components/session-utils.tsx, apps/dashboard/app/(main)/websites/[id]/sessions/_components/sessions-list.tsx, apps/dashboard/app/(main)/websites/[id]/funnels/_components/empty-state.tsx, apps/dashboard/app/(main)/websites/[id]/goals/_components/empty-state.tsx, apps/dashboard/app/(main)/websites/[id]/profiles/_components/profiles-list.tsx, apps/dashboard/app/(main)/websites/[id]/revenue/_components/revenue-chart.tsx, apps/dashboard/app/(main)/websites/[id]/revenue/page.tsx, apps/dashboard/app/(main)/websites/[id]/sessions/page.tsx, apps/dashboard/app/(main)/websites/[id]/sessions/_components/session-row.tsx, apps/dashboard/app/(main)/websites/[id]/test/components/minimal-table.tsx, apps/dashboard/app/(main)/websites/_components/website-card.tsx, apps/dashboard/app/actions/preferences.ts, apps/dashboard/app/actions/users.ts, apps/dashboard/components/analytics/animated-loading.tsx, apps/dashboard/components/charts/distribution-chart.tsx, apps/dashboard/components/charts/metrics-chart.tsx, apps/dashboard/components/date-range-picker.tsx, apps/dashboard/components/error-boundary.tsx, apps/dashboard/components/ui/calendar.tsx, apps/dashboard/components/ui/carousel.tsx, apps/dashboard/components/ui/closable-alert.tsx, apps/dashboard/components/ui/sidebar.tsx, apps/dashboard/components/ui/spinner.tsx, apps/database/app/page.tsx, apps/database/app/sql/page.tsx, apps/database/components/data-table-view.tsx, apps/database/components/data-table.tsx, apps/database/components/database-stats.tsx, apps/database/components/sql-editor.tsx, apps/database/components/table-card.tsx, apps/database/components/table-topbar.tsx, apps/database/components/ui/calendar.tsx, apps/database/components/ui/carousel.tsx
Converts single-line conditional statements into multi-line blocks with braces for clarity and consistency; logic remains unchanged. Also replaces some string concatenations with template literals for readability.
Parameter and Variable Renaming for Unused Values
apps/api/src/agent/prompts/agent.ts, apps/basket/src/routes/basket.ts, apps/dashboard/app/(main)/websites/[id]/revenue/_components/revenue-chart.tsx, apps/dashboard/app/(main)/websites/[id]/errors/_components/errors-page-content.tsx, apps/dashboard/app/(main)/websites/[id]/page.tsx, apps/dashboard/stores/jotai/chartAtoms.ts, apps/dashboard/stores/jotai/filterAtoms.ts, apps/dashboard/app/(auth)/login/forgot/page.tsx, apps/dashboard/app/(auth)/login/magic-sent/page.tsx, apps/dashboard/app/(auth)/login/magic/page.tsx, apps/dashboard/app/(auth)/login/verification-needed/page.tsx, apps/dashboard/app/(main)/organizations/[slug]/components/invitation-list.tsx, apps/dashboard/app/(main)/organizations/[slug]/components/invite-member-dialog.tsx, apps/dashboard/app/(main)/organizations/[slug]/components/member-list.tsx, apps/dashboard/app/(main)/organizations/[slug]/components/settings-tab.tsx, apps/dashboard/app/(main)/organizations/[slug]/components/teams-tab.tsx, apps/dashboard/app/(main)/organizations/[slug]/components/transfer-assets.tsx, apps/dashboard/app/(main)/organizations/components/organizations-tab.tsx, apps/dashboard/app/(main)/sandbox/reddit-mentions/hooks/use-reddit-mentions.ts, apps/dashboard/app/(main)/sandbox/reddit-mentions/page.tsx, apps/dashboard/app/(main)/settings/_components/timezone-preferences.tsx, apps/dashboard/app/(main)/websites/[id]/assistant/hooks/use-chat.ts, apps/dashboard/app/(main)/websites/[id]/profiles/page.tsx, apps/dashboard/app/(main)/websites/[id]/revenue/_components/revenue-chart.tsx, apps/dashboard/components/notifications/notification-item.tsx, apps/dashboard/components/ui/sidebar.tsx, apps/dashboard/stores/jotai/chartAtoms.ts, apps/dashboard/stores/jotai/filterAtoms.ts
Renames parameters or variables to underscore-prefixed versions to indicate intentional non-use (e.g., error_error, get_get, index_index).
Unused Import and Export Removal
apps/api/src/middleware/logging.ts, apps/dashboard/app/(main)/organizations/page.tsx, apps/dashboard/app/demo/layout.tsx, apps/dashboard/app/layout.tsx, apps/dashboard/components/analytics/animated-loading.tsx, apps/dashboard/components/charts/metrics-constants.ts, apps/dashboard/components/layout/logo.tsx, apps/dashboard/components/ui/spinner.tsx, apps/dashboard/components/ui/pagination.tsx, apps/dashboard/components/ui/sidebar.tsx, apps/database/app/api/database/stats/route.ts, apps/database/components/database-stats.tsx, apps/database/components/table-topbar.tsx, apps/database/components/sql-editor.tsx, apps/database/components/data-table.tsx, apps/database/components/data-table-view.tsx, apps/database/app/page.tsx, apps/database/app/sql/page.tsx, apps/database/components/table-card.tsx, apps/database/components/ui/calendar.tsx, apps/database/components/ui/carousel.tsx
Removes unused imports, deleted files, or components to clean up the codebase.
Type and Interface Improvements
apps/basket/src/routes/stripe.ts, apps/dashboard/lib/autumn/pricing-table-content.tsx, apps/dashboard/lib/geo.ts
Adds or refines TypeScript interfaces, type annotations, and function signatures for improved type safety and clarity, especially in Stripe webhook handling and geo data structures.
Naming and Formatting Adjustments
apps/dashboard/app/(main)/sandbox/reddit-mentions/page.tsx, apps/dashboard/app/(main)/websites/[id]/test/components/minimal-table.tsx, apps/database/components/data-table-view.tsx, apps/database/components/sql-editor.tsx, apps/dashboard/app/(main)/organizations/[slug]/components/team-view.tsx, apps/dashboard/app/(main)/websites/[id]/profiles/_components/profile-row.tsx, apps/dashboard/app/(main)/websites/[id]/profiles/page.tsx, apps/dashboard/app/(main)/websites/[id]/sessions/_components/session-row.tsx, apps/dashboard/app/(main)/websites/[id]/sessions/page.tsx, apps/dashboard/app/(main)/websites/[id]/funnels/_components/delete-funnel-dialog.tsx, apps/dashboard/app/(main)/websites/[id]/journeys/page.tsx, apps/dashboard/app/(main)/organizations/[slug]/components/invitation-list.tsx, apps/dashboard/app/(main)/organizations/[slug]/components/invite-member-dialog.tsx, apps/dashboard/app/(main)/organizations/[slug]/components/member-list.tsx, apps/dashboard/app/(main)/organizations/[slug]/components/settings-tab.tsx, apps/dashboard/app/(main)/organizations/[slug]/components/teams-tab.tsx, apps/dashboard/app/(main)/organizations/[slug]/components/transfer-assets.tsx, apps/dashboard/app/(main)/organizations/components/organizations-tab.tsx, apps/dashboard/app/(main)/organizations/page.tsx, apps/dashboard/app/(auth)/login/magic-sent/page.tsx, apps/dashboard/app/(auth)/login/forgot/page.tsx, apps/dashboard/app/(auth)/login/magic/page.tsx, apps/dashboard/app/(auth)/login/verification-needed/page.tsx, apps/dashboard/app/(main)/settings/page.tsx, apps/dashboard/app/(main)/billing/hooks/use-billing.ts, apps/dashboard/app/(main)/settings/_components/timezone-preferences.tsx, apps/dashboard/app/(main)/settings/_components/two-factor-form.tsx, apps/dashboard/app/(main)/websites/[id]/assistant/components/chat-section.tsx, apps/dashboard/app/(main)/websites/[id]/assistant/hooks/use-chat.ts
Renames functions or variables for clarity, reformats code for readability, adjusts JSX or utility function formatting, and reorders imports for consistency.
Dependency Array and Memoization Updates
apps/dashboard/app/(main)/websites/[id]/assistant/components/chat-section.tsx, apps/dashboard/app/(main)/websites/[id]/assistant/hooks/use-chat.ts, apps/dashboard/app/(main)/websites/[id]/journeys/page.tsx, apps/dashboard/components/ui/sidebar.tsx
Updates dependency arrays in hooks and memoized values to ensure correct reactivity and avoid stale closures.
Test Optimization
apps/basket/src/utils/ip-geo.test.ts
Parallelizes asynchronous test calls using Promise.all for improved test execution speed.
Stripe Webhook Typing Refactor
apps/basket/src/routes/stripe.ts
Introduces new interfaces and refactors function signatures for Stripe webhook handling, improving type safety without changing logic.
Accessibility and Attribute Adjustments
apps/dashboard/app/(main)/websites/[id]/test/components/minimal-table.tsx, apps/dashboard/components/ui/pagination.tsx
Removes or adjusts ARIA roles and attributes for improved accessibility semantics.

Sequence Diagram(s)

No sequence diagrams generated as changes are primarily stylistic, involve type/interface improvements, or minor refactoring without affecting control flow.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~18 minutes

Possibly related PRs

  • Fix lint issues in dashboard. #43: The main PR and the retrieved PR both focus on stylistic changes that convert single-line conditional returns into explicit multi-line blocks with braces, improving code clarity and consistency without altering logic or control flow; thus, their changes are related in nature and style though applied to different files and components.

Poem

A hop, a skip, a curly brace—
The codebase wears a tidy face!
Unused imports, gone with glee,
Types are crisp as they should be.
With every _error and _get in sight,
This bunny’s code now feels just right.
🐇✨

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@AyanavaKarmakar
AyanavaKarmakar changed the base branch from main to staging July 30, 2025 12:17

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 15

🔭 Outside diff range comments (14)
apps/database/components/sql-editor.tsx (2)

76-93: Potential stale-state bug in _addToHistory

_addToHistory closes over queryHistory from the render in which the function was created.
If the callback is executed after queryHistory has already been updated by another render, the slice will operate on a stale array and silently drop newer entries.

A simple, React-safe pattern is to pass an updater function to setQueryHistory:

-const _addToHistory = (query: string, success: boolean, duration?: number, error?: string) => {
-  const newEntry: QueryHistory = { … };
-  const updatedHistory = [newEntry, ...queryHistory.slice(0, 49)];
-  saveQueryHistory(updatedHistory);
-};
+const _addToHistory = (query: string, success: boolean, duration?: number, error?: string) => {
+  const newEntry: QueryHistory = { … };
+  setQueryHistory(prev => {
+    const next = [newEntry, ...prev.slice(0, 49)];
+    localStorage.setItem('sql-query-history', JSON.stringify(next));
+    return next;
+  });
+};

76-81: lucide icons violate project icon-set policy

Like other components, this file still imports many icons from lucide-react (CheckCircle, Clock, Copy, etc.).
Guidelines mandate using Phosphor icons instead. Please replace them across the file for consistency.

apps/dashboard/components/ui/carousel.tsx (1)

6-6: Icon library violation: Use Phosphor icons instead of Lucide.

The file imports from lucide-react which violates the coding guidelines. According to the project standards, only Phosphor icons should be used.

Consider updating in a future PR:

-import { ArrowLeft, ArrowRight } from 'lucide-react';
+import { ArrowLeftIcon, ArrowRightIcon } from '@phosphor-icons/react';

And update the usage:

-<ArrowLeft />
+<ArrowLeftIcon weight="fill" />
-<ArrowRight />  
+<ArrowRightIcon weight="fill" />
apps/dashboard/stores/jotai/filterAtoms.ts (1)

1-3: Replace date-fns with Dayjs to honour project guidelines

The repo’s coding-guidelines explicitly forbid date-fns and mandate Dayjs. All four helpers imported here (differenceInDays, format, isValid, subDays) have direct Dayjs equivalents or simple one-liners.

-import { differenceInDays, format, isValid, subDays } from 'date-fns';
+import dayjs from 'dayjs';
+import isBetween from 'dayjs/plugin/isBetween';
+dayjs.extend(isBetween);

Then:

-const initialStartDate = subDays(new Date(), 30);
-const diffDays = differenceInDays(newRange.endDate, newRange.startDate);
-format(startDate, 'yyyy-MM-dd')
+const initialStartDate = dayjs().subtract(30, 'day').toDate();
+const diffDays = dayjs(newRange.endDate).diff(dayjs(newRange.startDate), 'day');
+dayjs(startDate).format('YYYY-MM-DD')

Keeping date-fns here violates the style-lint checks and will re-introduce warnings next run.

apps/dashboard/app/(auth)/login/verification-needed/page.tsx (2)

4-4: Replace lucide-react with Phosphor icons.

Project guidelines explicitly forbid lucide-react.
Switch to @phosphor-icons/react and use Icon-suffixed names:

-import { AlertCircle, ChevronLeft, Loader2 } from 'lucide-react';
+import { WarningCircleIcon, CaretLeftIcon, SpinnerIcon } from '@phosphor-icons/react';

Update the JSX usages accordingly (<WarningCircleIcon …/>, <CaretLeftIcon …/>, <SpinnerIcon …/>).
Doing this consistently avoids future lint failures and keeps visual consistency.


42-60: Tailwind radius variants violate the “always rounded” rule.

rounded-xl (Line 42) and rounded-lg (Line 60) contradict the coding-guideline: “always use rounded, never rounded-xl/-md”.

-<div className="… rounded-xl border …">
+<div className="… rounded border …">

-<div className="rounded-lg border border-amber-200 …">
+<div className="rounded border border-amber-200 …">

Please sweep the file (and neighbouring ones) for variant-suffixes to avoid repetitive churn later.

apps/dashboard/app/(auth)/login/forgot/page.tsx (2)

4-4: lucide-react must be removed.

Same policy breach as in the verification page. Replace with Phosphor equivalents:

-import { ChevronLeft, Loader2 } from 'lucide-react';
+import { CaretLeftIcon, SpinnerIcon } from '@phosphor-icons/react';

Adjust JSX accordingly.


44-70: Radius variants conflict with styling guideline.

rounded-xl (Line 44) and rounded-lg (Line 70) should be plain rounded.

-… overflow-hidden rounded-xl border …
+… overflow-hidden rounded border …

-<div className="rounded-lg border border-blue-100 …">
+<div className="rounded border border-blue-100 …">

Refactor before styles diverge further.

apps/dashboard/app/(main)/organizations/[slug]/components/settings-tab.tsx (2)

40-42: Avoid any; define a proper organization type.

Using any defeats type-safety and violates the TS guideline. Create an explicit interface and import it here, e.g.:

export interface Organization {
  id: string;
  name: string;
  slug: string;
  // …other fields…
}

interface SettingsTabProps {
  organization: Organization;
}

72-93: updateOrganization is not awaited → optimistic toast could fire on failure.

handleSave is synchronous but calls the (presumably async) updateOrganization without await, yet shows a success toast immediately. If the mutation rejects, the user still sees “updated successfully”.

-const handleSave = () => {
+const handleSave = async () => {-  try {
-    updateOrganization({
+  try {
+    await updateOrganization({

Ensure the hook actually returns a promise or expose a callback to capture success/error.

apps/dashboard/app/(auth)/login/magic-sent/page.tsx (1)

45-45: rounded-xl radius must be plain rounded.

-<div className="relative mx-auto … rounded-xl border …">
+<div className="relative mx-auto … rounded border …">

Please align with the styling guideline.

apps/dashboard/app/(main)/websites/[id]/revenue/page.tsx (1)

69-73: Index used as React key – leads to unstable reconciliation

React keys must be stable between renders; using i breaks that rule and defeats list diffing.

-{[...new Array(4)].map((_, i) => (
+{Array.from({ length: 4 }, (_, idx) => `metric-skel-${idx}`).map((id) => (
 ...
-  key={`${i + 1}-metrics-skeleton`}
+  key={id}

(The switch to new Array is a no-op; the original [...Array(4)] was fine.)

apps/dashboard/app/(main)/websites/[id]/page.tsx (1)

137-144: Remove the dead _handleDateRangeChange callback

The logic is duplicated inline in the <DateRangePicker onChange={…}> below, so this memoised callback is never invoked. Keeping it around just increases bundle size.

-const _handleDateRangeChange = useCallback(
-  (range: DayPickerRange | undefined) => {
-    if (range?.from && range?.to) {
-      setDateRangeAction({ startDate: range.from, endDate: range.to });
-    }
-  },
-  [setDateRangeAction]
-);

Either wire it up to the picker or delete it.

apps/database/components/data-table-view.tsx (1)

16-30: Critical: Replace Lucide icons with Phosphor icons.

This file extensively uses Lucide icons, which violates the project's coding guidelines. According to the retrieved learnings, the project should "Don't use lucide for icons, ONLY use phosphor icons, use width='duotone' for most, but for arrows use fill, for plus icons don't add width".

All Lucide icon imports should be replaced with their Phosphor equivalents:

-import {
-	ArrowUpDown,
-	Binary,
-	Calendar,
-	Columns,
-	Edit,
-	Eye,
-	EyeOff,
-	Hash,
-	MoreHorizontal,
-	SortAsc,
-	SortDesc,
-	Trash2,
-	Type,
-} from 'lucide-react';
+import {
+	ArrowsDownUpIcon,
+	BinaryIcon,
+	CalendarIcon,
+	ColumnsIcon,
+	PencilIcon,
+	EyeIcon,
+	EyeSlashIcon,
+	HashIcon,
+	DotsThreeIcon,
+	SortAscendingIcon,
+	SortDescendingIcon,
+	TrashIcon,
+	TextTIcon,
+} from '@phosphor-icons/react';

And update all icon usages throughout the component accordingly.

🧹 Nitpick comments (18)
apps/basket/src/hooks/auth.ts (2)

18-20: Centralising regexes is 👍 — add the i flag for full case-insensitivity
Both constants are a welcome readability & perf win. However, callers may invoke isValidDomainFormat() with a mixed-case string (it’s exported). Adding the i flag keeps the match correct without relying on callers to lowercase first.

-const REGEX_WWW_PREFIX = /^www\./;
-const REGEX_DOMAIN_LABEL = /^[a-zA-Z0-9-]+$/;
+const REGEX_WWW_PREFIX = /^www\./i;
+const REGEX_DOMAIN_LABEL = /^[a-z0-9-]+$/i;

165-168: hostname.replace(REGEX_WWW_PREFIX, '') ignores numeric “www” prefixes
www2.example.com, www01.example.com, etc., are fairly common and semantically the same as www.. Consider broadening the pattern to strip any www\d*. prefix:

-const REGEX_WWW_PREFIX = /^www\./i;
+const REGEX_WWW_PREFIX = /^www\d*\./i;

This keeps behaviour unchanged for plain www. while covering additional real-world cases.

apps/dashboard/lib/canvas-utils.ts (1)

30-31: Remove the now-superfluous _centerX / _centerY constants

These constants are still computed but never referenced, so they only add byte-code and keep the “unused-var” suppression hack around. Deleting them is the cleanest option and keeps the function free of dead code.

-	const _centerX = image.naturalWidth / 2;
-	const _centerY = image.naturalHeight / 2;
apps/dashboard/components/charts/metrics-constants.ts (1)

1-1: Consider migrating away from lucide-react for future consistency

Throughout the dashboard, .tsx components are already switching to Phosphor icons per guidelines. Even though this is a .ts helper, it still couples downstream components to Lucide. When you next touch the chart primitives, consider exporting Phosphor equivalents so the icon stack stays uniform.

apps/dashboard/components/layout/user-menu.tsx (1)

30-32: Duplicate initials logic – extract to shared util

The initials-building code now appears both here and in components/auth/user-button.tsx. Extracting it to lib/get-user-initials.ts (or similar) removes duplication and centralises future tweaks (e.g., handling middle names).

apps/dashboard/lib/performance-utils.ts (1)

35-39: fastPages threshold off-by-one compared to scoring logic

fastPages is incremented when loadTime < FAST, whereas the score treats loadTime <= FAST as a perfect score (Lines 42-44).
For consistency the equality case should be counted as fast:

-if (loadTime < SCORE_THRESHOLDS.FAST) {
+if (loadTime <= SCORE_THRESHOLDS.FAST) {

Otherwise a page loading exactly at the FAST threshold is “perfect” for the score but not for the fast-page count.

apps/dashboard/lib/utils.ts (1)

18-34: Minor: guard negative durations

formatDuration doesn’t guard against negative seconds. A quick defensive check avoids odd output:

+if (seconds <= 0) return '0s';
apps/database/components/table-card.tsx (1)

51-51: Minor perf nit: avoid the extra parseFloat.

Number.parseFloat(x.toFixed(2)) converts a string back to a number only to string-interpolate it again. Drop the round-trip:

-return `${Number.parseFloat((bytes / k ** i).toFixed(2))} ${sizes[i]}`;
+return `${(bytes / k ** i).toFixed(2)} ${sizes[i]}`;
apps/dashboard/app/(main)/websites/[id]/_components/utils/code-generators.ts (2)

15-18: Remove unused _apiUrl variable

The variable is dead-code after renaming; keeping it around only to silence the unused-var rule adds noise.

- const _apiUrl = isLocalhost
-   ? 'http://localhost:4000'
-   : 'https://basket.databuddy.cc';

20-30: Duplication in option-filtering logic

The three nearly identical .filter() blocks can be extracted into a small helper to keep these generators DRY:

+function buildMeaningfulOptions(opts: TrackingOptions) {
+  return Object.entries(opts).filter(([k, v]) => {
+    const def = ACTUAL_LIBRARY_DEFAULTS[k as keyof TrackingOptions];
+    return v !== def && !(typeof v === 'boolean' && !v && !def);
+  });
+}

Then reuse in all three generators.

Also applies to: 55-65, 100-110

apps/dashboard/app/(main)/websites/[id]/errors/_components/errors-page-content.tsx (1)

55-69: Remove unused helper functions

_removeFilter and _clearFilters are no longer referenced after the linter rename. Keeping dead code adds noise and risks it drifting out of sync with the actual filter logic.

-	// Remove a filter
-	const _removeFilter = (filterToRemove: DynamicQueryFilter) => {
-		setActiveFilters((prev) =>
-			prev.filter(
-				(f) =>
-					!(
-						f.field === filterToRemove.field && f.value === filterToRemove.value
-					)
-			)
-		);
-	};
-
-	// Clear all filters
-	const _clearFilters = () => {
-		setActiveFilters([]);
-	};
apps/dashboard/app/(main)/sandbox/reddit-mentions/hooks/use-reddit-mentions.ts (1)

152-160: Centralise the repetitive result.error checks

Each API handler repeats the same 3-line pattern:

const result = await apiRequest<>();
if (result.error) {
  throw new Error(result.error);
}
return result.data || 

Extracting a small helper (e.g. assertSuccess(result)) trims ~20 lines, prevents copy-paste divergence, and keeps each handler focused on its own mapping logic.

Also applies to: 181-187, 195-202, 234-239

apps/dashboard/app/(main)/sandbox/reddit-mentions/page.tsx (1)

239-242: Delete unused _handleExport

_handleExport is defined but never called (export is performed inline in the button handler). Safely remove to avoid unused-symbol linter noise.

apps/dashboard/app/(main)/organizations/[slug]/components/settings-tab.tsx (1)

138-156: Multiple rounded-lg classes conflict with the “always rounded” rule.

Replace all rounded-lg occurrences with rounded to stay consistent.
A codemod across the component (and repository) will prevent repetitive manual edits.

Also applies to: 164-181, 282-289

apps/dashboard/app/(main)/revenue/_components/tabs/settings-tab.tsx (1)

53-53: Consider optimizing the dependency array for better performance.

While adding isMaskedSecret to the dependency array is correct since the function is used within the effect, this will cause the effect to re-run on every render because the function is recreated each time.

Consider one of these optimizations:

Option 1: Move the function outside the component

+const isMaskedSecret = (secret: string) => secret.includes('*');
+
 export function RevenueSettingsTab({
   revenueConfig,
 }: {
   revenueConfig: ReturnType<typeof useRevenueConfig>;
 }) {
   const [webhookSecret, setWebhookSecret] = useState('');
   const [isLiveMode, setIsLiveMode] = useState(revenueConfig.isLiveMode);

-  // Check if the webhook secret is masked (contains asterisks)
-  const isMaskedSecret = (secret: string) => secret.includes('*');

Option 2: Wrap in useCallback

+import { useEffect, useState, useCallback } from 'react';

   // Check if the webhook secret is masked (contains asterisks)
-  const isMaskedSecret = (secret: string) => secret.includes('*');
+  const isMaskedSecret = useCallback((secret: string) => secret.includes('*'), []);
apps/dashboard/app/(main)/websites/[id]/_components/utils/ui-components.tsx (1)

176-179: Guard clause reads clearer than nested return

Tiny readability nit – invert the condition to shorten indentation:

-if (!showTooltip) {
-  return content;
-}
+if (showTooltip) {
+
+}
+return content;

Feel free to ignore if you prefer the current style.

apps/database/components/data-table.tsx (1)

210-218: Minor nit – single-letter power operator is clearer

-return `${Number.parseFloat((bytes / k ** i).toFixed(2))} ${sizes[i]}`;
+return `${Number.parseFloat((bytes / (k ** i)).toFixed(2))} ${sizes[i]}`;

Adds parentheses to silence potential precedence lint complaints.

apps/dashboard/app/(main)/websites/[id]/assistant/components/chat-section.tsx (1)

116-126: Potential redundancy in scroll effects.

Both useEffect hooks (lines 116-120 and 122-126) now have empty dependency arrays and perform similar scrolling behavior. The first scrolls with behavior: 'auto' and the second with behavior: 'smooth'. Consider if both are necessary or if they can be consolidated.

 useEffect(() => {
   if (bottomRef.current) {
     bottomRef.current.scrollIntoView({ behavior: 'auto' });
   }
 }, []);

-useEffect(() => {
-  if (bottomRef.current) {
-    bottomRef.current.scrollIntoView({ behavior: 'smooth' });
-  }
-}, []);

Comment thread apps/dashboard/app/(auth)/login/magic-sent/page.tsx
Comment thread apps/dashboard/app/(auth)/register/page.tsx Outdated
Comment thread apps/dashboard/app/(main)/organizations/[slug]/components/teams-tab.tsx Outdated
Comment thread apps/dashboard/app/(main)/organizations/components/organizations-tab.tsx Outdated
Comment thread apps/dashboard/lib/autumn/pricing-table-content.tsx Outdated
Comment thread apps/dashboard/lib/geo.ts Outdated
Comment thread apps/database/app/page.tsx Outdated
Comment thread apps/database/components/database-stats.tsx
Comment thread apps/database/components/table-card.tsx
@izadoesdev

Copy link
Copy Markdown
Member

@ me when it's all done

@coderabbitai

coderabbitai Bot commented Jul 30, 2025

Copy link
Copy Markdown
Contributor
✅ Actions performed

Full review triggered.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🔭 Outside diff range comments (3)
apps/dashboard/components/bits/Iridiscence.tsx (1)

57-63: Component name ≠ filename → import failures on case-sensitive systems

export default function Iridescence (with an “e”) lives in a file named Iridiscence.tsx (without the “e”).
On macOS/Linux this mismatch will break import Iridiscence from './Iridiscence' or vice-versa, depending on which spelling callers choose.

-// Option A – keep filename, fix component
-export default function Iridescence({
+export default function Iridiscence({

or rename the file to Iridescence.tsx (preferred for correct spelling).

Failing to align the two will surface as a “module not found” error at runtime / build time.

apps/dashboard/app/(main)/revenue/_components/onboarding/configuration-summary.tsx (1)

20-32: CheckCircleIcon should default to duotone weight per icon rules

Team convention (see “01-MUST-DO”) says: “use weight='duotone' for most icons; use fill only for arrows; do not specify width for plus icons”.
CheckCircleIcon is currently rendered with fill in both places.

-<CheckCircleIcon
-  className="h-5 w-5 text-green-500"
-  size={20}
-  weight="fill"
-/>
+<CheckCircleIcon
+  className="h-5 w-5 text-green-500"
+  size={20}
+  weight="duotone"
+/>
...
-<CheckCircleIcon className="h-4 w-4" size={16} weight="fill" />
+<CheckCircleIcon className="h-4 w-4" size={16} weight="duotone" />

Switching to duotone keeps us 100 % compliant with the house iconography spec.

Also applies to: 74-76

apps/dashboard/app/(main)/billing/hooks/use-billing.ts (1)

19-35: _isActionLoading is written but never read – consider removing or exposing it

_isActionLoading is toggled via setIsActionLoading, but the state value itself is never consumed or returned by the hook.
Either:

  1. Expose it to consumers of useBilling so they can render a spinner, or
  2. Drop the state entirely if the UI no longer needs it.
-const [_isActionLoading, setIsActionLoading] = useState(false);
+const [isActionLoading, setIsActionLoading] = useState(false);
...
 return {
   isLoading,
+  isActionLoading,          // make it available to callers
   onUpgrade: handleUpgrade,
   ...
 }
♻️ Duplicate comments (15)
apps/dashboard/lib/geo.ts (1)

17-19: Avoid any in public coordinate types

any[][][] drops compile-time checks and violates the project guideline against any.
Use a concrete numeric type or introduce a reusable alias:

-			coordinates: any[][][];
+			coordinates: number[][][];

(or)

export type Coordinates3D = number[][][];
// …
coordinates: Coordinates3D;

Same change applies to both Subdivisions.geometry and Country.geometry.

Also applies to: 33-36

apps/dashboard/app/not-found.tsx (1)

3-3: Replace lucide-react icons with Phosphor icons as per project guidelines.
The project’s “01-MUST-DO” rules explicitly forbid lucide-react; use Phosphor with the prescribed weights instead. This was already pointed out in an earlier review and remains unresolved.

-import { ArrowLeft, Home } from 'lucide-react';
+import { ArrowLeftIcon, HouseIcon } from '@phosphor-icons/react';

Icon usage updates later in the file:

-  <Home className="mr-2 h-4 w-4" />
+  <HouseIcon className="mr-2 h-4 w-4" weight="duotone" />-  <ArrowLeft className="mr-2 h-4 w-4" />
+  <ArrowLeftIcon className="mr-2 h-4 w-4" weight="fill" />
apps/dashboard/components/layout/theme-toggle.tsx (2)

20-22: Stylistic improvement looks good, but the critical browser compatibility bug remains unfixed.

The expansion from single-line to multi-line if statement with braces improves code consistency and readability, which aligns with the linting improvements in this PR.

However, the critical logic bug identified in the previous review still exists: execution continues to line 23 even when document.startViewTransition is undefined, causing a TypeError in unsupported browsers.


19-24: Critical: Browser fallback still broken - execution falls through to undefined API call.

The logic bug from the previous review remains unfixed. When document.startViewTransition is not available, the code calls switchTheme() but continues executing document.startViewTransition(switchTheme) on line 23, causing a TypeError.

Apply this fix to prevent the fallthrough:

 const toggleTheme = () => {
 	if (!document.startViewTransition) {
 		switchTheme();
+		return;
 	}
 	document.startViewTransition(switchTheme);
 };
apps/dashboard/app/(main)/websites/[id]/map/page.tsx (1)

180-191: Previous key-related concern still unaddressed.

While the array instantiation was updated from Array(6).fill(0) to new Array(6).fill(0), the previously identified issue with using array indices in React keys (Line 183: key={country-skeleton-${i + 1}}) remains unresolved. Using array indices can break React's reconciliation when list lengths change.

Consider the previously suggested improvements:

  • Use Array.from({ length: 6 }) for cleaner array creation
  • Replace index-based keys with constant strings since these are static placeholders
apps/dashboard/app/(main)/organizations/[slug]/components/teams-tab.tsx (1)

12-12: Address the type safety issue with organization: any.

This issue was previously flagged but remains unresolved. The component still uses any type for the organization prop, which reduces type safety. Based on the database schema, consider using a proper type:

-export function TeamsTab({ organization }: { organization: any }) {
+export function TeamsTab({ organization }: { organization?: { id?: string } }) {
apps/dashboard/components/error-boundary.tsx (1)

3-3: Replace lucide icons with phosphor icons per project guidelines

This file still uses AlertTriangle and RefreshCw from lucide-react, violating the project guideline that requires using only phosphor icons.

Replace the imports and usage:

-import { AlertTriangle, RefreshCw } from 'lucide-react';
+import { WarningCircleIcon, ArrowClockwiseIcon } from '@phosphor-icons/react';
-<AlertTriangle className="h-5 w-5" />
+<WarningCircleIcon size={20} weight="duotone" />
-<RefreshCw className="h-3.5 w-3.5" />
+<ArrowClockwiseIcon size={14} weight="duotone" />

Also applies to: 44-44, 69-69

apps/dashboard/lib/autumn/pricing-table-content.tsx (1)

1-1: Replace any with a proper product interface

product is typed as any, which defeats type-safety and violates the repo guideline: "Don't use any type".
Create a shared Product interface (or import an existing one) and use it here.

apps/dashboard/app/(main)/websites/[id]/page.tsx (1)

88-88: Drop the unused setter instead of prefixing with "_"

As noted in previous reviews, _setCurrentDateRangeState is never referenced. Destructure only what you actually use:

-const [currentDateRange, _setCurrentDateRangeState] = useAtom(dateRangeAtom);
+const [currentDateRange] = useAtom(dateRangeAtom);
apps/dashboard/app/(main)/organizations/[slug]/components/invite-member-dialog.tsx (1)

33-35: Style improvement aligns with codebase consistency.

Expanding the single-line conditional to a multi-line block statement improves readability and aligns with the consistent formatting pattern applied across the codebase.

However, the previous review concerns about type safety and user feedback remain unaddressed:

  1. Component props still use any type (Line 24) instead of a proper interface
  2. Silent return provides no user feedback when email validation fails
apps/dashboard/app/(auth)/login/magic-sent/page.tsx (1)

4-4: Replace lucide icons with Phosphor equivalents.

Based on the project's coding guidelines, lucide icons should be replaced with Phosphor icons. The existing past review comment about this change is still applicable.

apps/dashboard/app/(auth)/register/page.tsx (1)

97-97: Error parameter renaming follows established pattern.

The renaming of error parameters to _error in all three catch blocks is consistent with the pattern used across other authentication pages and properly signals intentional non-use to the linter.

Also applies to: 121-121, 147-147

apps/database/components/table-card.tsx (1)

3-3: Replace lucide icons with Phosphor equivalents.

The existing past review comment about replacing lucide icons with Phosphor icons is still applicable. All the imported lucide icons should be replaced with their Phosphor counterparts according to the project guidelines.

apps/dashboard/app/(main)/organizations/components/organizations-tab.tsx (1)

72-72: Preserve error context when deletion fails.

This change only renames the error variable but doesn't address the underlying issue of losing error context for debugging organization deletion failures.

apps/database/app/page.tsx (1)

48-48: Potential infinite re-render issue with useEffect dependency.

Adding loadData to the dependency array could cause infinite re-renders since loadData is redefined on every component render. Consider wrapping loadData with useCallback to prevent this issue.

+ import { useCallback } from 'react';

- const loadData = async () => {
+ const loadData = useCallback(async () => {
    setLoading(true);
    // ... rest of the function
- };
+ }, []);
🧹 Nitpick comments (20)
apps/basket/src/utils/ip-geo.test.ts (2)

367-367: Avoid the double type-cast workaround

null as unknown as string side-steps the type system and makes the intent harder to read. If the goal is simply to exercise the “invalid input” branch, consider one of the options below instead of the two-step cast:

-const result = await getGeoLocation(null as unknown as string);
+// @ts-expect-error – deliberately passing null to verify defensive handling
+const result = await getGeoLocation(null);

or expose getGeoLocation with the broader type (ip: string | null | undefined) so the test doesn’t need casts at all.


439-447: Minor: guard against a single rejected promise

Because Promise.all rejects as soon as one promise fails, a transient network/database glitch in getGeoLocation could fail the entire test suite even when the other IPs succeed.

If you want the test to proceed and collect all results, Promise.allSettled is safer:

-const geoResults = await Promise.all(testIPs.map((ip) => getGeoLocation(ip)));
+const geoResults = await Promise.allSettled(
+  testIPs.map((ip) => getGeoLocation(ip))
+);
+for (const r of geoResults) {
+  expect(r.status).toBe('fulfilled');
+}

Not critical, but worth considering.

apps/database/app/api/database/stats/route.ts (1)

7-40: Run the four ClickHouse queries in parallel to cut response latency.

The tableStats, databases, systemInfo, and (best-effort) memoryInfo queries are completely independent yet execute serially, so the route waits for the slowest sum of their runtimes. Issuing them concurrently can slash p95 latency, especially on busy DB nodes.

-// Get table statistics
-const tableStats = await chQuery(`...`);
-
-// Get database list with sizes
-const databases = await chQuery(`...`);
-
-// Get system information
-const systemInfo = await chQuery(`...`);
-
-// Try to get memory usage (may not be available in all versions)
-let memoryInfo: unknown[] = [];
-try {
-  memoryInfo = await chQuery(`...`);
-} catch (error) {
-  console.warn('Memory metrics not available:', error);
-}
+const [
+  tableStats,
+  databases,
+  systemInfo,
+] = await Promise.all([
+  chQuery(`/* tables */`),
+  chQuery(`/* databases */`),
+  chQuery(`/* system */`),
+]);
+
+// Try to get memory usage (may not be available in all versions)
+let memoryInfo: unknown[] = [];
+try {
+  memoryInfo = await chQuery(`/* memory */`);
+} catch (error) {
+  console.warn('Memory metrics not available:', error);
+}

No behavioural change—just better throughput.

apps/dashboard/app/(main)/revenue/_components/onboarding/configuration-summary.tsx (2)

21-26: Add aria-hidden or aria-label for better a11y

The icons convey status but already have adjacent text. Without an accessible name screen-readers may announce the raw component name. Two options:

  1. Treat them as decorative:
-<CheckCircleIcon … />
+<CheckCircleIcon aria-hidden="true" focusable="false" … />
  1. Provide an explicit label:
-<WarningCircleIcon … />
+<WarningCircleIcon aria-label="Configuration warning" role="img" … />

Pick one approach and apply consistently.

Also applies to: 27-32, 74-76


43-47: Potential secret leakage – consider masking the webhook token

Rendering the raw webhookToken exposes the full secret in the DOM and browser history (copy-paste, screenshots). If operators only need to verify existence rather than the full string, show a masked “••••abcd” version instead.

-<p className="font-mono">{webhookToken || 'Not configured'}</p>
+<p className="font-mono">
+  {webhookToken ? `${webhookToken.slice(0, 4)}•••${webhookToken.slice(-4)}` : 'Not configured'}
+</p>

Helps prevent accidental credential leaks during demos or screen-sharing.

apps/dashboard/app/(main)/websites/[id]/test/components/minimal-table.tsx (1)

225-238: Guard against state updates after unmount by clearing the timeout

handleTabChange schedules a setTimeout that calls several setState functions.
If the component unmounts (or activeTab changes again) before the 150 ms timer fires, React will emit a “state update on unmounted component” warning and may cause a memory leak in DEV builds.

A lightweight fix is to store the timer id in a ref and clear it in an effect cleanup.

@@
 const [expandedRows, setExpandedRows] = useState<Set<string>>(new Set());
+const transitionTimer = useRef<NodeJS.Timeout>();

@@
   (tabId: string) => {
     if (tabId === activeTab) {
       return;
     }
-    setIsTransitioning(true);
-    setTimeout(() => {
+    setIsTransitioning(true);
+    if (transitionTimer.current) clearTimeout(transitionTimer.current);
+    transitionTimer.current = setTimeout(() => {
       setActiveTab(tabId);
       …
       setIsTransitioning(false);
-    }, 150);
+    }, 150);
   },
   [activeTab]
 );

+useEffect(() => {
+  return () => {
+    if (transitionTimer.current) clearTimeout(transitionTimer.current);
+  };
+}, []);

This prevents orphaned timers and keeps dev-mode noise down.

apps/database/app/sql/page.tsx (1)

35-49: Minor: avoid double-trimming and send a clean query string to the API.

query.trim() is computed three separate times (early-return, disabled, and in fetch).
It’s inexpensive but still redundant; more importantly, the raw (possibly whitespace-padded) string is what gets posted to /api/database/query.

-	const executeQuery = async () => {
-		if (!query.trim()) {
-			return;
-		}
+	const executeQuery = async () => {
+		const trimmedQuery = query.trim();
+		if (!trimmedQuery) {
+			return;
+		}-				body: JSON.stringify({ query }),
+				body: JSON.stringify({ query: trimmedQuery }),

This single trimmedQuery variable prevents accidental “ \n ” submissions and removes duplicated calls.
Impact is low but it tightens the UI-API contract.

apps/basket/src/hooks/auth.ts (3)

18-20: Broaden the “www” prefix regex for edge-cases

REGEX_WWW_PREFIX only matches the literal www.. Hosts such as www1.example.com or www2.—often used behind load-balancers/CDNs—will slip through and fail normalisation. A one-line tweak makes the rule more tolerant while remaining anchored to the start of the hostname:

-const REGEX_WWW_PREFIX = /^www\./;
+// Accepts "www.", "www1.", "www2.", … but still only at the very beginning
+const REGEX_WWW_PREFIX = /^www\d*\./;

165-168: Consider trimming a trailing dot after hostname extraction

Rarely, a fully-qualified domain arrives with a trailing dot (example.com.).
new URL().hostname preserves that dot, so the subsequent replace(REGEX_WWW_PREFIX, '') leaves it intact and the value fails later validation.

A tiny post-processing step keeps normalizeDomain resilient:

const hostname = new URL(urlString).hostname;
-const finalDomain = hostname.replace(REGEX_WWW_PREFIX, '');
+const finalDomain = hostname
+  .replace(REGEX_WWW_PREFIX, '')
+  .replace(/\.$/, ''); // strip trailing dot if present

219-223: Consolidate label checks into a single regex for clarity & speed

isValidDomainFormat first applies REGEX_DOMAIN_LABEL, then performs two extra string checks to forbid leading/trailing hyphens.
Those constraints can live inside the regex itself, eliminating the extra branches:

-const REGEX_DOMAIN_LABEL = /^[a-zA-Z0-9-]+$/;
+// Disallow leading/trailing hyphens while still permitting internal ones
+const REGEX_DOMAIN_LABEL = /^(?!-)[a-zA-Z0-9-]{1,63}(?<!-)$/;
...
-if (
-  !REGEX_DOMAIN_LABEL.test(label) ||
-  label.startsWith('-') ||
-  label.endsWith('-')
-) {
+if (!REGEX_DOMAIN_LABEL.test(label)) {
   return false;
 }

Besides being marginally faster, the intent is captured in one place.
Feel free to ignore if you prefer the current explicit checks for readability.

apps/dashboard/components/charts/metrics-constants.ts (1)

109-110: Move late import to the top for consistency

The formatDuration import appears after executable code. While top-level imports are hoisted, keeping all imports grouped at the beginning improves readability and avoids churn from auto-import tools.

-...
-];
-
-import { formatDuration } from '@/lib/utils';
+];
+
+// utilities
+import { formatDuration } from '@/lib/utils';
apps/dashboard/lib/canvas-utils.ts (1)

30-31: Consider removing unused variables entirely.

The underscore prefix correctly indicates these variables are intentionally unused. However, since _centerX and _centerY are calculated but never referenced, consider removing them entirely to reduce code complexity.

-	const _centerX = image.naturalWidth / 2;
-	const _centerY = image.naturalHeight / 2;
apps/database/components/sql-editor.tsx (1)

76-76: Consider removing unused function instead of prefixing with underscore.

While prefixing with underscore indicates the function is unused, consider removing the entire _addToHistory function if it's not needed. This would reduce code bloat and improve maintainability.

-	const _addToHistory = (
-		query: string,
-		success: boolean,
-		duration?: number,
-		error?: string
-	) => {
-		const newEntry: QueryHistory = {
-			id: Date.now().toString(),
-			query: query.trim(),
-			timestamp: new Date(),
-			duration,
-			success,
-			error,
-		};
-
-		const updatedHistory = [newEntry, ...queryHistory.slice(0, 49)]; // Keep last 50 queries
-		saveQueryHistory(updatedHistory);
-	};
apps/dashboard/app/(main)/websites/[id]/page.tsx (1)

137-144: Remove unused callback function

The _handleDateRangeChange function is defined but never used. The DateRangePicker on line 355 uses an inline callback instead. Consider removing this unused function entirely:

-const _handleDateRangeChange = useCallback(
-	(range: DayPickerRange | undefined) => {
-		if (range?.from && range?.to) {
-			setDateRangeAction({ startDate: range.from, endDate: range.to });
-		}
-	},
-	[setDateRangeAction]
-);
apps/dashboard/app/(main)/sandbox/reddit-mentions/page.tsx (1)

239-241: Good practice: Indicating unused function.

Prefixing the unused function with underscore clearly indicates intentional non-use. Consider removing this function if it's no longer needed, or implement the export functionality if it should be used.

apps/dashboard/app/(main)/revenue/_components/tabs/settings-tab.tsx (1)

53-53: Consider optimizing function placement and dependencies.

While adding isMaskedSecret to the dependency array is technically correct, since it's defined inside the component, it could cause unnecessary effect re-runs. Consider moving isMaskedSecret outside the component since it's a pure utility function, or wrap it in useCallback to stabilize its reference.

+// Move outside component since it's a pure utility function
+const isMaskedSecret = (secret: string) => secret.includes('*');
+
 export function RevenueSettingsTab({
   revenueConfig,
 }: {
   revenueConfig: ReturnType<typeof useRevenueConfig>;
 }) {
   const [webhookSecret, setWebhookSecret] = useState('');
   const [isLiveMode, setIsLiveMode] = useState(revenueConfig.isLiveMode);

-  // Check if the webhook secret is masked (contains asterisks)
-  const isMaskedSecret = (secret: string) => secret.includes('*');

   // Initialize webhook secret only if it's not masked
   useEffect(() => {
     const currentSecret = revenueConfig.webhookSecret || '';
     if (!isMaskedSecret(currentSecret)) {
       setWebhookSecret(currentSecret);
     }
-  }, [revenueConfig.webhookSecret, isMaskedSecret]);
+  }, [revenueConfig.webhookSecret]);
apps/dashboard/hooks/use-dynamic-query.ts (2)

291-323: Unused loop index – remove _index param for clarity

The map callback receives _index that is not referenced.
Drop the parameter to avoid misleading “unused” identifiers and reduce linter noise.

-return query.data.results.map((result, _index) => {
+return query.data.results.map((result) => {

393-397: Bubble fetch failure details to caller

You convert non-OK responses to a generic Error('Failed to fetch query options').
Consider including res.status or server-supplied message to aid debugging:

-throw new Error('Failed to fetch query options');
+throw new Error(`Failed to fetch query options – ${res.status} ${res.statusText}`);
apps/dashboard/public/databuddy.js (2)

892-897: Same compatibility concern for entries.at(-1)

PerformanceEntry[] does not guarantee Array.prototype.at support in all browsers.
Use entries[entries.length - 1] for wider compatibility.


440-448: Superfluous empty catch blocks – consider logging behind a debug flag

Several catch (_e) {} blocks swallow unexpected errors silently, making field debugging hard.
At minimum, log when process.env.NODE_ENV === 'development' to aid diagnosis.

Comment thread apps/dashboard/components/charts/metrics-constants.ts
Comment thread apps/dashboard/public/databuddy.js
Comment thread apps/database/app/sql/page.tsx
@coderabbitai

coderabbitai Bot commented Jul 30, 2025

Copy link
Copy Markdown
Contributor
✅ Actions performed

Full review triggered.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🔭 Outside diff range comments (2)
apps/dashboard/app/(main)/websites/[id]/_components/tabs/tracking-setup-tab.tsx (1)

92-105: Single shared copied state causes wrong visual feedback across multiple CodeBlocks
Because every CodeBlock receives the same copied boolean, copying one snippet flips the icon for all code blocks for 2 seconds. Users viewing another tab (npm vs script) will see an incorrect green checkmark.

Consider scoping the copied state per snippet instead of globally:

-const [copied, setCopied] = useState(false);
+const [copiedId, setCopiedId] = useState<string | null>(null);-const handleCopyCode = (code: string) => {
-  navigator.clipboard.writeText(code);
-  setCopied(true);
+const handleCopyCode = (id: string, code: string) => {
+  navigator.clipboard.writeText(code);
+  setCopiedId(id);
   toast.success('Tracking code copied to clipboard');
-  setTimeout(() => setCopied(false), 2000);
+  setTimeout(() => setCopiedId(null), 2000);
 };

Pass a stable id (e.g. 'tracking-script', 'npm-install', …) to each CodeBlock and derive its copied prop via copied={copiedId === id}.
This avoids confusing UX and keeps the component fully self-contained.

apps/dashboard/components/analytics/animated-loading.tsx (1)

3-9: Replace remaining lucide icons with phosphor icons

The file still imports multiple lucide icons (ActivitySquare, ArrowRight, Loader2, Server, Users) which violates project guidelines requiring phosphor icons exclusively. While the unused Database import was removed, the remaining icons need to be replaced with their phosphor equivalents.

Replace the lucide imports with phosphor equivalents:

-import {
-	ActivitySquare,
-	ArrowRight,
-	Loader2,
-	Server,
-	Users,
-} from 'lucide-react';
+import {
+	Activity,
+	ArrowRightIcon,
+	SpinnerIcon,
+	ServerIcon,
+	UsersIcon,
+} from '@phosphor-icons/react';

And update the corresponding JSX usage to use proper phosphor icon props with weight="duotone" or weight="fill" for arrows.

♻️ Duplicate comments (19)
apps/dashboard/components/charts/metrics-constants.ts (1)

1-1: The lucide-react import issue remains unresolved

While LineChart was removed, the core issue identified in previous reviews persists: the project guidelines mandate using Phosphor icons instead of lucide-react. The remaining imports (Eye, MousePointer, TrendingUp, Users) still violate the established icon standards.

apps/dashboard/components/error-boundary.tsx (1)

3-3: Replace lucide icons with phosphor icons per project guidelines

This issue was previously identified but remains unresolved. The project guidelines require using phosphor icons exclusively.

apps/dashboard/app/not-found.tsx (1)

3-3: Replace lucide-react with phosphor icons.

This file still violates the coding guidelines by using lucide-react icons. The guidelines explicitly state: "Don't use lucide for icons, ONLY use phosphor icons, use width='duotone' for most, but for arrows use fill".

Replace the lucide-react imports with phosphor icons:

-import { ArrowLeft, Home } from 'lucide-react';
+import { ArrowLeftIcon, HouseIcon } from '@phosphor-icons/react';

And update the icon usage in the JSX:

-<Home className="mr-2 h-4 w-4" />
+<HouseIcon className="mr-2 h-4 w-4" weight="duotone" />
-<ArrowLeft className="mr-2 h-4 w-4" />
+<ArrowLeftIcon className="mr-2 h-4 w-4" weight="fill" />
apps/dashboard/components/layout/theme-toggle.tsx (1)

20-24: Critical bug still present - missing return statement.

While the stylistic change to use block braces is good, the critical issue identified in previous reviews remains unfixed. When document.startViewTransition is unavailable, execution continues to line 23, causing a TypeError in browsers without View Transition API support.

Add the missing return statement:

 		if (!document.startViewTransition) {
 			switchTheme();
+			return;
 		}
 		document.startViewTransition(switchTheme);
apps/dashboard/lib/geo.ts (1)

18-18: LGTM! Improved type safety addresses previous feedback.

The change from any[][][] to number[][][] for coordinate arrays enhances type safety and directly addresses the previous review comment about avoiding any in public types. This provides compile-time safety for coordinate data which should indeed be numeric.

Also applies to: 35-35

apps/dashboard/public/databuddy.js (1)

893-896: Browser compatibility concern with entries.at(-1)

The use of .at(-1) may cause issues in older browsers. This is a known concern from previous reviews.

apps/dashboard/app/(auth)/login/magic-sent/page.tsx (1)

4-4: Icon migration from Lucide to Phosphor remains incomplete.

The imports still use lucide-react icons (ChevronLeft, Loader2, MailCheck) which should be replaced with Phosphor icons according to project guidelines.

apps/database/app/sql/page.tsx (1)

3-3: Replace lucide-react icons with Phosphor icons.

This is a duplicate of a previous comment - the project rules require using Phosphor icons instead of lucide-react.

apps/dashboard/app/(main)/websites/[id]/map/page.tsx (1)

180-191: Avoid using array index for React keys.

This duplicates a previous review comment - using array indices in React keys can break reconciliation when the list changes.

apps/dashboard/app/(auth)/register/page.tsx (1)

122-122: Consider logging errors for better observability.

This relates to a previous review comment - while renaming to _error satisfies linting, these catch blocks still discard valuable debugging information that could help with troubleshooting.

Also applies to: 148-148

apps/dashboard/app/(main)/organizations/components/organizations-tab.tsx (1)

72-75: Error context partially preserved but user still sees generic message.

While logging the error to console is helpful for debugging, the past review comment specifically requested forwarding the actual error message to the user via toast.error. The current implementation still shows a generic message to users.

apps/database/components/table-card.tsx (1)

3-3: Settings import removed, but lucide icons still need replacement.

Good cleanup removing the unused Settings import. However, the existing issue with lucide icons remains unaddressed.

apps/dashboard/lib/autumn/pricing-table-content.tsx (1)

3-3: Excellent type safety improvement

The change from any to Product type significantly improves type safety and addresses the previous review feedback about avoiding any types. This will provide compile-time checking and help prevent property access errors.

apps/dashboard/app/(main)/organizations/[slug]/components/invite-member-dialog.tsx (2)

24-32: Excellent type safety improvement

The replacement of any with a properly defined inline interface significantly improves type safety and addresses the previous review feedback. The interface clearly defines the expected props with appropriate types.


41-43: Formatting improved, but UX issue remains

The expansion to explicit block statement follows the PR's consistent formatting pattern. However, the underlying UX concern from the previous review persists - the silent return provides no user feedback when the email field is empty. Consider disabling the "Send Invitation" button when inviteEmail.trim().length === 0 or showing validation feedback.

apps/dashboard/app/(main)/sandbox/reddit-mentions/hooks/use-reddit-mentions.ts (4)

155-157: Guard against success === false, not only error

The conditional formatting improvement is good, but this still has the same critical error handling issue flagged in previous reviews. The code should check !result.success instead of only result.error to handle cases where apiRequest returns { success: false, error: undefined }.

-if (result.error) {
+if (!result.success) {
   throw new Error(result.error ?? 'Request failed');
 }

182-184: Same error handling issue as noted above.

Good formatting improvement, but the same !result.success check should be applied here for consistent error handling.


198-200: Consistent formatting with same error handling concern.

The block statement formatting is an improvement, but the error handling logic should also be updated per the previous review comments.


235-237: Final instance of the same error handling pattern.

Good stylistic improvement, but this also needs the !result.success check for consistency with proper error handling.

🧹 Nitpick comments (7)
apps/dashboard/app/(main)/websites/[id]/_components/tabs/tracking-setup-tab.tsx (1)

146-158: Refresh button triggers toast without visual loading state
handleRefresh invalidates the TRPC query and immediately shows “Checking tracking status…”. If the network is slow or errors out, the user has no indication of progress/failure.

Optional polish:

  1. Maintain a local isRefreshing flag that disables the button and spins the icon while the query refetches.
  2. Catch errors from invalidate (returns a promise) and surface them via toast.error.

This improves perceived responsiveness and accessibility for screen-reader users.

apps/basket/src/polyfills/compression.js (1)

32-40: Factor out duplicated format-selection logic

Both constructors repeat the same if‒else chain. Extracting a shared helper (or lookup table) removes duplication and guarantees the two classes stay consistent.

+const compressionFactories = {
+  'deflate':      () => zlib.createDeflate(),
+  'deflate-raw':  () => zlib.createDeflateRaw(),
+  'gzip':         () => zlib.createGzip(),
+};
+
+function getCompressionHandle(format) {
+  const factory = compressionFactories[format];
+  if (!factory) throw new TypeError(`Unsupported format: ${format}`);
+  return factory();
+}
-		let handle;
-		if (format === 'deflate') {
-			handle = zlib.createDeflate();
-		} else if (format === 'gzip') {
-			handle = zlib.createGzip();
-		} else if (format === 'deflate-raw') {
-			handle = zlib.createDeflateRaw();
-		} else {
-			throw new TypeError(`Unsupported CompressionStream format: ${format}`);
-		}
-		make(this, handle);
+		make(this, getCompressionHandle(format));

The same approach can be mirrored for DecompressionStream.

apps/database/components/sql-editor.tsx (1)

76-93: Consider removing unused function entirely.

The function _addToHistory is prefixed with an underscore to indicate it's unused, but it's never called anywhere in the component. Consider removing it entirely rather than keeping dead code.

-	// Add query to history
-	const _addToHistory = (
-		query: string,
-		success: boolean,
-		duration?: number,
-		error?: string
-	) => {
-		const newEntry: QueryHistory = {
-			id: Date.now().toString(),
-			query: query.trim(),
-			timestamp: new Date(),
-			duration,
-			success,
-			error,
-		};
-
-		const updatedHistory = [newEntry, ...queryHistory.slice(0, 49)]; // Keep last 50 queries
-		saveQueryHistory(updatedHistory);
-	};
apps/dashboard/app/(main)/revenue/_components/tabs/settings-tab.tsx (1)

53-53: Consider optimizing the dependency array.

Adding isMaskedSecret to the dependency array will cause the effect to run on every render since the function reference changes each time. Since isMaskedSecret is a pure function that doesn't depend on props or state, consider either:

  1. Moving it outside the component:
+const isMaskedSecret = (secret: string) => secret.includes('*');
+
export function RevenueSettingsTab({
-	// Check if the webhook secret is masked (contains asterisks)
-	const isMaskedSecret = (secret: string) => secret.includes('*');
  1. Or wrapping it in useCallback:
-	const isMaskedSecret = (secret: string) => secret.includes('*');
+	const isMaskedSecret = useCallback((secret: string) => secret.includes('*'), []);

Then remove it from the dependency array since it won't change.

apps/dashboard/app/(auth)/login/magic/page.tsx (1)

41-44: Consider logging the error for better observability.

While renaming to _error satisfies linting requirements, it discards valuable debugging information. Consider logging the error before showing the user-friendly toast message.

-} catch (_error) {
+} catch (error) {
+  console.error('Magic link login error:', error);
   setIsLoading(false);
   toast.error('Failed to send magic link. Please try again.');
 }
apps/dashboard/app/(main)/organizations/[slug]/components/teams-tab.tsx (1)

12-12: Type safety improved but may not match database schema.

Good improvement over the any type! However, according to the database schema in packages/db/src/drizzle/schema.ts (lines 594-611), the organization.id field is defined as a non-null primary key. Consider using { id: string } instead of optional properties to better reflect the actual data structure.

-export function TeamsTab({ organization }: { organization?: { id?: string } }) {
+export function TeamsTab({ organization }: { organization?: { id: string } }) {
apps/dashboard/app/(main)/sandbox/reddit-mentions/page.tsx (1)

239-241: Consider removing unused function or refactoring inline export

The _handleExport function is defined but never used. The export functionality is implemented inline at line 313. Consider either:

  1. Removing this unused function entirely
  2. Refactoring the inline export call to use this helper function

This would eliminate dead code and improve maintainability.

Comment thread apps/basket/src/polyfills/compression.js
@AyanavaKarmakar

Copy link
Copy Markdown
Contributor Author

@izadoesdev ready for review

@izadoesdev

Copy link
Copy Markdown
Member

mind fixing the last of the conflicts? @AyanavaKarmakar

@coderabbitai

coderabbitai Bot commented Jul 30, 2025

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Jul 30, 2025

Copy link
Copy Markdown
Contributor
✅ Actions performed

Full review triggered.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🔭 Outside diff range comments (6)
apps/dashboard/app/(main)/websites/[id]/test/components/minimal-table.tsx (1)

335-338: Potential accessibility regression: missing role="tablist"

The removal of role="tablist" from the nav element may impact accessibility. ARIA best practices recommend that elements with role="tab" should be contained within a parent element with role="tablist" to properly establish the tab navigation structure for assistive technologies.

Consider restoring the role attribute:

 <nav
   aria-label="Data view options"
   className="flex gap-0.5 rounded-lg bg-muted/40 p-0.5"
+  role="tablist"
 >

This ensures screen readers can properly announce the tab group and provides the expected keyboard navigation context.

apps/dashboard/components/analytics/animated-loading.tsx (1)

3-9: Replace lucide-react icons with phosphor icons per project guidelines.

The retrieved learnings indicate this project should "ONLY use phosphor icons" and not use lucide icons. This file imports multiple icons from lucide-react which violates the established guidelines.

Consider replacing the lucide imports:

-import {
-	ActivitySquare,
-	ArrowRight,
-	Loader2,
-	Server,
-	Users,
-} from 'lucide-react';
+import {
+	Activity,
+	ArrowRight,
+	CircleNotch,
+	Server,
+	Users,
+} from '@phosphor-icons/react';

Note: You may need to adjust the icon names to match phosphor equivalents and add appropriate weight props (typically "duotone" except for arrows which use "fill").

apps/dashboard/app/(main)/sandbox/reddit-mentions/hooks/use-reddit-mentions.ts (1)

78-87: headers built with User-Agent are overwritten by the later spread of options

Because ...options is spread after the explicit headers object, any headers
property inside options will overwrite the one that contains User-Agent,
dropping the custom header silently.

-      headers: {
-        'Content-Type': 'application/json',
-        'User-Agent': 'Databuddy-Dashboard/1.0',
-        ...options.headers,
-      },
-      signal: controller.signal,
-      ...options,
+      signal: controller.signal,
+      ...options,
+      headers: {
+        'Content-Type': 'application/json',
+        'User-Agent': 'Databuddy-Dashboard/1.0',
+        ...(options.headers ?? {}),
+      },
apps/dashboard/app/(main)/websites/[id]/page.tsx (1)

137-144: Remove the unused function entirely instead of prefixing.

The _handleDateRangeChange function is never used in this component. The DateRangePicker on lines 351-364 has its own inline onChange handler. Consider removing this dead code entirely.

-	const _handleDateRangeChange = useCallback(
-		(range: DayPickerRange | undefined) => {
-			if (range?.from && range?.to) {
-				setDateRangeAction({ startDate: range.from, endDate: range.to });
-			}
-		},
-		[setDateRangeAction]
-	);
apps/dashboard/app/(auth)/login/page.tsx (1)

26-35: Remove unused function or integrate it into the component.

The _handleLastUsed function is never called in the component, making it dead code. Either remove it entirely or integrate it into the component's functionality (perhaps call it in a useEffect after lastUsed is loaded).

-	const _handleLastUsed = () => {
-		if (lastUsed === 'github') {
-			handleGithubLogin();
-		} else if (lastUsed === 'google') {
-			handleGoogleLogin();
-		} else if (lastUsed === 'email') {
-			// Focus email input
-			document.getElementById('email')?.focus();
-		}
-	};

Alternatively, if this function should be used, add it to a useEffect:

	useEffect(() => {
		setLastUsed(localStorage.getItem('lastUsedLogin'));
+		// Auto-trigger last used method after loading
+		const lastMethod = localStorage.getItem('lastUsedLogin');
+		if (lastMethod) {
+			// Add logic here or call the function
+		}
	}, []);
apps/dashboard/app/(main)/websites/[id]/assistant/components/chat-section.tsx (1)

122-126: Ensure the chat auto-scrolls when new messages arrive

The two existing useEffect hooks both use an empty dependency array ([]), so they only run once on mount. That means incoming messages won’t trigger another scroll to bottom, degrading the UX. Update the effect that calls scrollIntoView to depend on your message list (e.g. messages or messages.length).

• File: apps/dashboard/app/(main)/websites/[id]/assistant/components/chat-section.tsx
• Around lines 122–126

Suggested change:

- useEffect(() => {
-   if (bottomRef.current) {
-     bottomRef.current.scrollIntoView({ behavior: 'smooth' });
-   }
- }, []);
+ useEffect(() => {
+   if (bottomRef.current) {
+     bottomRef.current.scrollIntoView({ behavior: 'smooth' });
+   }
+ }, [messages]);

Optionally you can use [messages.length] if you only care about additions.

♻️ Duplicate comments (13)
apps/basket/src/polyfills/compression.js (1)

14-23: Unsupported format values still silently fall back to raw deflate

The earlier review (see past comments) already pointed out that defaulting to zlib.createDeflateRaw()/createInflateRaw() when the caller supplies an invalid format violates the WHATWG Streams Compression spec and masks bugs.
The refactor kept the same behaviour; the constructors should reject anything other than "gzip" | "deflate" | "deflate-raw" with a TypeError.

 		} else if (format === 'gzip') {
 			handle = zlib.createGzip();
-		} else {
-			handle = zlib.createDeflateRaw();
+		} else if (format === 'deflate-raw') {
+			handle = zlib.createDeflateRaw();
+		} else {
+			throw new TypeError(
+				`Unsupported CompressionStream format: ${format}`
+			);
 		}

Apply the analogous change to the DecompressionStream constructor (replace createInflateRaw() / createGunzip() accordingly).
Until this is fixed, unknown formats will be processed with the wrong algorithm, potentially corrupting data.

Also applies to: 31-40

apps/dashboard/components/charts/metrics-constants.ts (1)

1-1: lucide-react import violates repo icon guidelines – switch to Phosphor icons

Long-term rules for this repository forbid lucide-react and require Phosphor React icons (…Icon, correct weight). Please migrate the imports (and downstream usages) accordingly and drop the lucide-react dependency.

-import { Eye, MousePointer, TrendingUp, Users } from 'lucide-react';
+import {
+  EyeIcon,
+  CursorIcon,
+  TrendingUpIcon,
+  UsersIcon,
+} from '@phosphor-icons/react';

After updating the import, adjust each icon usage:

• EyeIcon & UsersIcon → add weight="duotone"
• CursorIcon & TrendingUpIcon (arrow icons) → add weight="fill"

(Tagging as duplicate because this was raised in the previous review round and remains unresolved.)

apps/dashboard/lib/geo.ts (1)

18-18: Excellent type safety improvement!

The change from any[][][] to number[][][] for coordinates properly addresses the previous review feedback and aligns with project guidelines for type safety. Geographic coordinates are indeed numeric values, making this type annotation both accurate and meaningful.

Also applies to: 35-35

apps/dashboard/components/error-boundary.tsx (1)

3-3: Lucide icons still need to be replaced with phosphor icons.

This file still imports AlertTriangle and RefreshCw from lucide-react, which violates project guidelines requiring the use of phosphor icons only.

apps/database/app/sql/page.tsx (1)

3-3: The Lucide icons import issue remains unresolved.

The import from 'lucide-react' still violates the project rule requiring Phosphor icons. This should be replaced with '@phosphor-icons/react' imports using names ending with 'Icon'.

apps/dashboard/app/(main)/websites/[id]/errors/_components/errors-page-content.tsx (1)

55-64: Remove unused functions entirely.

These functions are still unused after being renamed with underscore prefixes. As identified in previous reviews, both _removeFilter and _clearFilters are never invoked and should be removed entirely to clean up dead code.

-	// Remove a filter
-	const _removeFilter = (filterToRemove: DynamicQueryFilter) => {
-		setActiveFilters((prev) =>
-			prev.filter(
-				(f) =>
-					!(
-						f.field === filterToRemove.field && f.value === filterToRemove.value
-					)
-			)
-		);
-	};
-
-	// Clear all filters
-	const _clearFilters = () => {
-		setActiveFilters([]);
-	};

Also applies to: 67-69

apps/dashboard/app/(main)/sandbox/reddit-mentions/hooks/use-reddit-mentions.ts (1)

152-158: Still guarding only on error instead of generic success === false
This was raised in a previous review and remains unresolved.

When the backend returns { success: false, error: undefined } the current check
treats the call as success and propagates undefined data.

-if (result.error) {
-  throw new Error(result.error);
-}
+if (!result.success) {
+  throw new Error(result.error ?? 'Request failed');
+}

Apply the same change to getHealth, refresh, and getAnalytics.

Also applies to: 181-184, 198-200, 235-237

apps/dashboard/public/databuddy.js (1)

1358-1359: Browser compatibility concern with biome-ignore comment.

The comment indicates awareness of browser compatibility issues with the .at() method. Based on past review feedback, this method is not supported in all target browsers and can cause TypeError in older Safari/Firefox versions.

The current implementation correctly uses the backward-compatible approach scripts[scripts.length - 1], which is good. However, verify that other uses of .at(-1) in this file (like line 893) are intentional and have appropriate fallbacks if needed.

apps/dashboard/app/(auth)/login/magic-sent/page.tsx (1)

4-4: Still using lucide-react icons instead of Phosphor icons.

This file continues to import and use icons from lucide-react (ChevronLeft, Loader2, MailCheck) despite the coding guidelines requiring Phosphor icons exclusively. This was flagged in previous reviews but remains unaddressed.

The retrieved learnings clearly state: "Don't use lucide for icons, ONLY use phosphor icons, use weight='duotone' for most, but for arrows use fill, for plus icons don't add weight"

-import { ChevronLeft, Loader2, MailCheck } from 'lucide-react';
+import { CaretLeftIcon, SpinnerIcon, EnvelopeSimpleOpenIcon } from '@phosphor-icons/react';

And update the JSX usage accordingly:

  • ChevronLeftCaretLeftIcon with weight="fill"
  • Loader2SpinnerIcon with weight="duotone"
  • MailCheckEnvelopeSimpleOpenIcon with weight="duotone"
apps/dashboard/app/(main)/organizations/[slug]/components/invite-member-dialog.tsx (1)

44-46: Stylistic improvement but silent return issue persists.

The explicit block formatting is good for consistency. However, the silent return when email is empty still provides no user feedback, as noted in previous reviews.

apps/dashboard/app/not-found.tsx (1)

3-3: Good cleanup but coding guideline violation remains.

Removing the unused BarChart import is good. However, the file still violates coding guidelines by using lucide-react icons instead of phosphor icons, as noted in previous reviews.

apps/dashboard/app/(auth)/register/page.tsx (1)

122-122: Inconsistent error handling pattern.

These catch blocks still swallow errors by renaming to _error, while line 98 properly logs them. Apply the same error logging pattern for consistency and better observability.

-} catch (_error) {
+} catch (error) {
+  console.error('resend-verification-email', error);
   toast.error('Failed to send verification email. Please try again later.');
-} catch (_error) {
+} catch (error) {
+  console.error('social-login', error);  
   toast.error('Something went wrong');

Also applies to: 148-148

apps/dashboard/app/(main)/websites/[id]/map/page.tsx (1)

180-191: Array index still used in React keys despite previous feedback.

The array creation syntax change is fine, but the existing issue with using array index in React keys remains unaddressed from previous reviews.

Using i as part of the key breaks React's reconciliation when list length changes. Consider using a constant string or UUID for these static skeleton elements:

-{new Array(6).fill(0).map((_, i) => (
+{Array.from({ length: 6 }, (_, idx) => (
   <div
     className="flex items-center justify-between p-3"
-    key={`country-skeleton-${i + 1}`}
+    key={`country-skeleton-${idx}`}
   >
🧹 Nitpick comments (10)
apps/dashboard/app/(main)/websites/[id]/revenue/page.tsx (1)

69-69: Consider standardizing array instantiation patterns throughout the file.

While this change is good, there's inconsistency within the same file:

  • Line 69: [...new Array(4)] (updated)
  • Line 92: Array.from({ length: 4 }) (different pattern)
  • Line 334: [...new Array(5)] (already using new Array)

Consider standardizing to one approach for consistency.

apps/database/app/api/database/stats/route.ts (2)

7-32: Run the three read-only queries in parallel to shave off latency

The three independent chQuery calls (tableStats, databases, systemInfo) plus the optional memoryInfo and recentQueries can be executed concurrently.
With the current sequential awaits, total latency ≈ Σ(query RTT). Using Promise.all makes it ≈ max(query RTT) which is a big win for an edge API route.

-// Get table statistics
-const tableStats = await chQuery(`...`);
-
-// Get database list with sizes
-const databases = await chQuery(`...`);
-
-// Get system information
-const systemInfo = await chQuery(`...`);
+const [tableStats, databases, systemInfo] = await Promise.all([
+  chQuery(`...table statistics query...`),
+  chQuery(`...database list query...`),
+  chQuery(`...system info query...`),
+]);

You can wrap the optional parts as well:

-try {
-  memoryInfo = await chQuery(`...`);
-} catch (error) {
-  ...
-}
+const [memoryInfo = [], recentQueries = defaultRecent] = await Promise.allSettled([
+  chQuery(`...memory...`),
+  chQuery(`...recent queries...`)
+]).then(r =>
+  r.map(p => (p.status === 'fulfilled' ? p.value : []))
+);

This keeps the same error-handling semantics while delivering a faster endpoint.

Also applies to: 41-77


79-98: Add explicit result typing & runtime guards

The object literals assume the ClickHouse column names and types never change. If the query or DB version drifts, this handler could throw at runtime (e.g., tableStats[0] is undefined). Add a small helper for safe extraction and strong typing:

interface OverviewRow {
  total_tables: number;
  total_rows: bigint;
  total_bytes: bigint;
}

function firstOrDefault<T>(rows: unknown[], fallback: T): T {
  return (Array.isArray(rows) && rows.length > 0 ? rows[0] : fallback) as T;
}

// usage
const overview = firstOrDefault<OverviewRow>(tableStats, {
  total_tables: 0,
  total_rows: 0n,
  total_bytes: 0n,
});

Benefits:
• Compile-time checks on field names
• Fewer optional-chaining / default-value fallbacks scattered through the body
• Early detection of schema drift during CI type-checks.

apps/dashboard/app/layout.tsx (1)

134-137: Load external script over HTTPS and pin with SRI

Protocol-relative URLs (//…) fall back to plain HTTP when the dev server itself is served over http://, which opens a MITM window. Switching to an explicit https:// URL (and ideally adding an integrity hash) eliminates the risk and avoids mixed-content warnings. A light performance win can also be gained by deferring the load with strategy="lazyOnload".

-				<Script
-					crossOrigin="anonymous"
-					src="//unpkg.com/react-scan/dist/auto.global.js"
-				/>
+				<Script
+					src="https://unpkg.com/react-scan/dist/auto.global.js"
+					integrity="sha384-<computed-hash>"
+					crossOrigin="anonymous"
+					strategy="lazyOnload"
+				/>
apps/dashboard/components/ui/sidebar.tsx (1)

90-94: Drop the meaningless return for clearer intent

toggleSidebar currently returns the (undefined) result of a state-setter. Returning this value serves no purpose and may confuse readers into thinking the return value is used.

-const toggleSidebar = React.useCallback(() => {
-  return isMobile ? setOpenMobile((open) => !open) : setOpen((open) => !open);
-}, [isMobile, setOpen]);
+const toggleSidebar = React.useCallback(() => {
+  if (isMobile) {
+    setOpenMobile((prev) => !prev);
+  } else {
+    setOpen((prev) => !prev);
+  }
+}, [isMobile, setOpen]);
apps/dashboard/app/(main)/websites/[id]/_components/utils/code-generators.ts (1)

15-17: Misleading variable name with underscore prefix.

The variable apiUrl was renamed to _apiUrl, but the underscore prefix typically indicates an unused variable. This could be misleading if the variable is actually used elsewhere in the code or will be used in the future.

Consider using a more descriptive name without the underscore prefix if this variable serves a purpose, or remove it entirely if it's truly unused.

apps/dashboard/app/(main)/billing/hooks/use-billing.ts (1)

26-30: Remove the unused _result variable to avoid dead-code warnings

_result is never read after await attach().
Either remove the assignment or handle the returned session URL.

-      const _result = await attach({
+      await attach({
apps/dashboard/app/(main)/sandbox/reddit-mentions/page.tsx (1)

239-241: Unused _handleExport helper

The helper wraps exportMutation.mutate but is never invoked. Delete it or wire
it to the “Export CSV” button to avoid dead code and future confusion.

apps/dashboard/hooks/use-dynamic-query.ts (1)

291-293: No-op underscore rename only silences the linter

Renaming index to _index without removing it from the parameter list keeps
creating the array element but the variable is unused. Consider dropping the
parameter entirely:

-return query.data.results.map((result, _index) => {
+return query.data.results.map((result) => {
apps/dashboard/app/(auth)/login/magic/page.tsx (1)

41-41: Good naming convention for unused parameter.

The underscore prefix correctly indicates the error parameter is intentionally unused. Consider logging the error for debugging purposes:

} catch (_error) {
+	console.error('Magic link error:', _error);
	setIsLoading(false);
	toast.error('Failed to send magic link. Please try again.');
}

Comment thread apps/dashboard/app/(main)/billing/hooks/use-billing.ts
Comment thread apps/dashboard/app/(main)/revenue/_components/tabs/settings-tab.tsx
@AyanavaKarmakar

Copy link
Copy Markdown
Contributor Author

@izadoesdev should be good now

@izadoesdev
izadoesdev merged commit 3bb1a66 into databuddy-analytics:staging Jul 31, 2025
1 check failed
@AyanavaKarmakar
AyanavaKarmakar deleted the chore/lint-fixes-2 branch July 31, 2025 09:26
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.

2 participants