Skip to content
This repository was archived by the owner on Aug 24, 2025. It is now read-only.

Feat/report#15

Merged
ditto-11 merged 5 commits into
mainfrom
feat/report
Jun 20, 2025
Merged

Feat/report#15
ditto-11 merged 5 commits into
mainfrom
feat/report

Conversation

@ditto-11

@ditto-11 ditto-11 commented Jun 20, 2025

Copy link
Copy Markdown
Contributor

Closes #4

Summary by CodeRabbit

  • New Features
    • Introduced a comprehensive analytics and reporting dashboard with tabbed navigation for activity, ticket, and revenue reports.
    • Added interactive charts and tables for visualizing user, ticket, and revenue data, with filtering by year and month.
    • Enabled exporting of displayed report data to Excel files.
  • Enhancements
    • Added support for chart rendering and spreadsheet file processing.
  • Bug Fixes
    • Improved handling of loading, error, and empty data states in analytics reports.
  • Chores
    • Updated dependencies to support new charting and spreadsheet features.
    • Enhanced TypeScript configuration for better type support with new libraries.

@ditto-11 ditto-11 requested review from a team as code owners June 20, 2025 17:34
@coderabbitai

coderabbitai Bot commented Jun 20, 2025

Copy link
Copy Markdown

Walkthrough

The changes introduce charting and spreadsheet export capabilities to the analytics reports dashboard. New dependencies for chart rendering and Excel export are added. Several new TypeScript interfaces and React hooks standardize report data fetching. The analytics page is fully implemented with data aggregation, visualization, filtering, and exporting to Excel. Configuration files are updated accordingly.

Changes

File(s) Change Summary
.vscode/settings.json Added "chartjs" to spell checker custom words.
package.json, tsconfig.json Added charting and spreadsheet dependencies; updated TypeScript types for chart.js and node.
src/app/(dashboard)/analytics-reports/page.tsx Fully implemented analytics dashboard with data fetching, aggregation, charting, and export.
src/lib/hooks/useReport.ts Added hooks to fetch paginated activity, ticket, and revenue reports from APIs.
src/types/activity.d.ts, src/types/ticketReport.d.ts, src/types/revenue.d.ts Added TypeScript interfaces for activity, ticket, and revenue report data structures.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant AnalyticsPage
    participant useReportsActivity/useReportTicket/useRevenueTicket
    participant API
    participant XLSX

    User->>AnalyticsPage: Selects filters/views or navigates tabs
    AnalyticsPage->>useReportsActivity/useReportTicket/useRevenueTicket: Fetch report data (with params)
    useReportsActivity/useReportTicket/useRevenueTicket->>API: GET /reports/{type}
    API-->>useReportsActivity/useReportTicket/useRevenueTicket: Return paginated report data
    useReportsActivity/useReportTicket/useRevenueTicket-->>AnalyticsPage: Return parsed data
    AnalyticsPage->>AnalyticsPage: Aggregate/process data for charts/tables
    AnalyticsPage-->>User: Render charts, tables, and export buttons
    User->>AnalyticsPage: Clicks "Export to Excel"
    AnalyticsPage->>XLSX: Generate Excel file from current data
    XLSX-->>User: Download Excel file
Loading

Assessment against linked issues

Objective Addressed Explanation
Export report as Excel (#4)
Export report as PDF (#4) Only Excel export functionality is implemented; PDF export is not present.
Export report as Image (#4) Only Excel export functionality is implemented; image export is not present.

Poem

In the dashboard’s warren, new charts now gleam,
With rows and columns—an analyst’s dream!
Click export to Excel, watch data hop,
While rabbits in code make the numbers pop.
Chart.js and XLSX now join the show—
Analytics magic, in one bunny burrow! 🐇📊

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

npm error Exit handler never called!
npm error This is an error with npm itself. Please report this error at:
npm error https://github.com/npm/cli/issues
npm error A complete log of this run can be found in: /.npm/_logs/2025-06-20T17_35_02_652Z-debug-0.log

✨ Finishing Touches
  • 📝 Generate Docstrings

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

❤️ Share
🪧 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 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.

@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
4.2% Duplication on New Code (required ≤ 3%)
B Reliability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (5)
src/types/ticketReport.d.ts (1)

1-6: New interface TicketReportDto is well-defined.
Consider clarifying the date format or switching to a Date type if downstream code performs date operations.

src/types/activity.d.ts (1)

1-6: New interface ActivityDto is well-defined.
You may want to document the format of totalPrincipal or convert it to a numeric type for calculations if feasible.

.vscode/settings.json (1)

12-12: Custom spell-check words updated
Good catch adding chartjs and other terms. You might also include xlsx to avoid future spell-check flags when referencing spreadsheet exports.

src/app/(dashboard)/analytics-reports/page.tsx (1)

516-519: Remove redundant netIncome assignment

The netIncome property is being assigned redundantly. It's already correctly aggregated in line 512.

return Object.values(termAggregated).map((item) => ({
  ...item,
-  netIncome: item.netIncome,
}));
src/lib/hooks/useReport.ts (1)

53-137: Refactor duplicated hook logic to follow DRY principle

All three hooks share nearly identical logic. Consider extracting a generic hook factory to reduce code duplication and improve maintainability.

Create a generic hook factory:

function createReportHook<T extends { data: any[]; meta: any; links: any }>(
  endpoint: string
) {
  return (params: {
    page?: number;
    limit?: number;
    sortBy?: string[];
    nextUrl?: string;
  }) => {
    const query = new URLSearchParams();
    if (params.page) query.append('page', params.page.toString());
    if (params.limit) query.append('limit', params.limit.toString());
    if (params.sortBy) {
      for (const sort of params.sortBy) {
        query.append('sortBy', sort);
      }
    }

    const url = params.nextUrl || `${API_URL}${endpoint}?${query.toString()}`;
    const raw = useFetch<T>(url);

    return useMemo(() => {
      return {
        ...raw,
        reports: raw.data?.data,
        meta: raw.data?.meta,
        links: raw.data?.links,
      };
    }, [raw.data, raw.error, raw.isLoading, raw.isValidating, raw.mutate]);
  };
}

export const useReportsActivity = createReportHook<ReportActivityResponse>('/reports/activity');
export const useReportTicket = createReportHook<ReportTicketResponse>('/reports/ticket');
export const useRevenueTicket = createReportHook<ReportRevenueResponse>('/reports/revenue');
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2e3bf6d and 1a8ade9.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (8)
  • .vscode/settings.json (1 hunks)
  • package.json (1 hunks)
  • src/app/(dashboard)/analytics-reports/page.tsx (1 hunks)
  • src/lib/hooks/useReport.ts (1 hunks)
  • src/types/activity.d.ts (1 hunks)
  • src/types/revenue.d.ts (1 hunks)
  • src/types/ticketReport.d.ts (1 hunks)
  • tsconfig.json (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/app/(dashboard)/analytics-reports/page.tsx (4)
src/types/activity.d.ts (1)
  • ActivityDto (1-6)
src/types/ticketReport.d.ts (1)
  • TicketReportDto (1-6)
src/types/revenue.d.ts (1)
  • RevenueReportDto (1-7)
src/lib/hooks/useReport.ts (3)
  • useReportsActivity (53-80)
  • useReportTicket (82-108)
  • useRevenueTicket (110-137)
src/lib/hooks/useReport.ts (5)
src/types/activity.d.ts (1)
  • ActivityDto (1-6)
src/types/ticketReport.d.ts (1)
  • TicketReportDto (1-6)
src/types/revenue.d.ts (1)
  • RevenueReportDto (1-7)
src/constants/api-urls.ts (1)
  • API_URL (5-7)
src/lib/hooks/useFetch.tsx (1)
  • useFetch (24-44)
🔇 Additional comments (2)
package.json (1)

24-37: Review added dependencies
The new dependencies (chart.js, react-chartjs-2, swr, xlsx) align with the analytics reporting feature. Ensure that xlsx ships with its own TypeScript definitions and that these versions integrate smoothly with your code.

src/types/revenue.d.ts (1)

1-7: LGTM!

The interface definition is well-structured and follows TypeScript conventions. Using string types for monetary values is appropriate for avoiding floating-point precision issues and maintaining consistency with other DTOs in the codebase.

Comment thread tsconfig.json
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"types": ["node", "chart.js"],

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

Restrictive types configuration
By specifying "types": ["node", "chart.js"], the compiler will ignore all other @types packages (e.g., React, React DOM, Next.js). Either remove the types option to include all ambient definitions or explicitly add "react", "react-dom", "next", etc., to this array.

🤖 Prompt for AI Agents
In tsconfig.json at line 18, the "types" array currently restricts TypeScript to
only include "node" and "chart.js" type definitions, excluding others like React
and Next.js. To fix this, either remove the "types" option entirely to include
all available ambient type definitions or explicitly add "react", "react-dom",
"next", and any other needed packages to the array to ensure their types are
included during compilation.

Comment thread package.json
Comment on lines 42 to 44
"@tailwindcss/postcss": "^4",
"@types/chart.js": "^2.9.41",
"@types/node": "^20",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

Mismatched Chart.js type definitions
@types/chart.js@^2.9.41 targets Chart.js v2, but the project uses chart.js@^4.5.0, which already includes its own TS types. Remove this outdated devDependency to prevent type conflicts.

🤖 Prompt for AI Agents
In package.json around lines 42 to 44, remove the devDependency
"@types/chart.js": "^2.9.41" because it targets Chart.js v2, while the project
uses chart.js@^4.5.0 which includes its own TypeScript types. Deleting this
outdated type definition will prevent type conflicts.

Comment on lines +367 to +382
const [dayA, monthA, yearA] = a.split('/').map(Number);
const [dayB, monthB, yearB] = b.split('/').map(Number);
return (
new Date(yearA, monthA - 1, dayA).getTime() -
new Date(yearB, monthB - 1, dayB).getTime()
);
} else if (viewMode === 'month') {
const [monthA, yearA] = a.split('/').map(Number);
const [monthB, yearB] = b.split('/').map(Number);
return (
new Date(yearA, monthA - 1).getTime() -
new Date(yearB, monthB - 1).getTime()
);
}
return a.localeCompare(b);
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix date separator mismatch in sorting logic

The date keys are created using - as separator (e.g., 01-12-2024) but the sorting logic attempts to split by /. This will cause the sorting to fail for day view mode.

Apply this diff to fix the issue:

-const [dayA, monthA, yearA] = a.split('/').map(Number);
-const [dayB, monthB, yearB] = b.split('/').map(Number);
+const [dayA, monthA, yearA] = a.split('-').map(Number);
+const [dayB, monthB, yearB] = b.split('-').map(Number);

And similarly for month view:

-const [monthA, yearA] = a.split('/').map(Number);
-const [monthB, yearB] = b.split('/').map(Number);
+const [monthA, yearA] = a.split('-').map(Number);
+const [monthB, yearB] = b.split('-').map(Number);
🤖 Prompt for AI Agents
In src/app/(dashboard)/analytics-reports/page.tsx around lines 367 to 382, the
sorting logic splits date strings using '/' but the actual date keys use '-' as
the separator. Update the split calls to use '-' instead of '/' for both day and
month view modes to correctly parse the date components and fix the sorting.

Comment on lines +72 to +79
return useMemo(() => {
return {
...raw,
reports: raw.data?.data,
meta: raw.data?.meta,
links: raw.data?.links,
};
}, [raw]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Fix useMemo dependency to prevent unnecessary re-computations

The dependency array [raw] includes the entire object, which may change reference on every render even if the actual data hasn't changed. This could cause unnecessary re-computations.

return useMemo(() => {
  return {
    ...raw,
    reports: raw.data?.data,
    meta: raw.data?.meta,
    links: raw.data?.links,
  };
-}, [raw]);
+}, [raw.data, raw.error, raw.isLoading, raw.isValidating, raw.mutate]);
📝 Committable suggestion

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

Suggested change
return useMemo(() => {
return {
...raw,
reports: raw.data?.data,
meta: raw.data?.meta,
links: raw.data?.links,
};
}, [raw]);
return useMemo(() => {
return {
...raw,
reports: raw.data?.data,
meta: raw.data?.meta,
links: raw.data?.links,
};
}, [raw.data, raw.error, raw.isLoading, raw.isValidating, raw.mutate]);
🤖 Prompt for AI Agents
In src/lib/hooks/useReport.ts around lines 72 to 79, the useMemo hook's
dependency array currently includes the entire 'raw' object, which can cause
unnecessary recomputations due to reference changes. To fix this, update the
dependency array to include only the specific properties of 'raw' that are used
inside useMemo, such as 'raw.data?.data', 'raw.data?.meta', and
'raw.data?.links', ensuring useMemo only recomputes when these actual data
values change.

Comment on lines +8 to +51
interface ReportActivityResponse {
data: ActivityDto[];
meta: {
itemsPerPage: number;
sortBy: [string, string][];
};
links: {
previous?: string;
current: string;
next?: string;
};
}

interface ReportTicketResponse {
data: TicketReportDto[];
meta: {
itemsPerPage: number;
totalItems: number;
currentPages: number;
totalPages: number;
sortBy: [string, string][];
};
links: {
previous?: string;
current: string;
next?: string;
};
}

interface ReportRevenueResponse {
data: RevenueReportDto[];
meta: {
itemsPerPage: number;
totalItems: number;
currentPages: number;
totalPages: number;
sortBy: [string, string][];
};
links: {
previous?: string;
current: string;
next?: string;
};
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

❓ Verification inconclusive

Fix interface inconsistencies and naming issues

There are two issues with the response interfaces:

  1. ReportActivityResponse has a different meta structure compared to the other two interfaces - it's missing pagination fields.
  2. currentPages should be currentPage (singular) in both ReportTicketResponse and ReportRevenueResponse.

Please verify the actual API response structure to ensure these interfaces match:


🏁 Script executed:

#!/bin/bash
# Description: Search for API endpoint definitions or documentation to verify the response structure

# Search for API endpoint implementations
rg -A 10 "reports/(activity|ticket|revenue)" --type ts

# Search for any API documentation or tests that might show the response structure
fd -e md -e ts -e js | xargs rg -l "reports.*activity.*ticket.*revenue" | head -20

Length of output: 1906


Fix interface inconsistencies and naming issues

There are two issues with the response interfaces:

  1. ReportActivityResponse has a different meta structure compared to the other two interfaces - it's missing pagination fields.
  2. currentPages should be currentPage (singular) in both ReportTicketResponse and ReportRevenueResponse.

Please verify the actual API response structure to ensure these interfaces match:

#!/bin/bash
# Description: Search for API endpoint definitions or documentation to verify the response structure

# Search for API endpoint implementations
rg -A 10 "reports/(activity|ticket|revenue)" --type ts

# Search for any API documentation or tests that might show the response structure
fd -e md -e ts -e js | xargs rg -l "reports.*activity.*ticket.*revenue" | head -20
🤖 Prompt for AI Agents
In src/lib/hooks/useReport.ts between lines 8 and 51, fix the interface
inconsistencies by updating ReportActivityResponse's meta to include the missing
pagination fields (totalItems, currentPage, totalPages) to match the other
interfaces. Also, rename the property currentPages to currentPage (singular) in
both ReportTicketResponse and ReportRevenueResponse. Verify these changes
against the actual API response structure to ensure accuracy.

@ditto-11 ditto-11 merged commit e6c496f into main Jun 20, 2025
2 of 3 checks passed
@coderabbitai coderabbitai Bot mentioned this pull request Jun 20, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[web] export report

1 participant