Skip to content

[Feat]-Web: improve kanban and dashboard with pdf export and skeletons #3911

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

NdekoCode
Copy link
Collaborator

@NdekoCode NdekoCode commented Jun 23, 2025

Improve Kanban and Dashboard performances and fix PDF Export and Loading Skeletons

What was done?

Improved the user experience across multiple pages by adding smooth loading animations and fixing broken features.

Main improvements

Kanban Board

  • Added smooth loading animations when switching between tasks
  • Fixed slow loading when opening task cards
  • Made the board feel more responsive

Dashboards

  • Fixed PDF export that was showing "PDF Error"
  • Added loading animations for data tables
  • Fixed dates showing wrong month/year
  • Made export buttons work properly

Loading Experience

  • Added 16+ new loading animations (skeletons) across the app
  • No more blank screens while waiting for data
  • Loading animations match the final content layout

Settings & Profile Pages

  • Added loading animations for forms
  • Improved page loading speed
  • Better user feedback during actions

Files changed

  • 51 files updated
  • 2,167 lines added
  • 451 lines removed

What users will notice

Before

  • Blank screens while loading
  • "PDF Error" when trying to export
  • Wrong dates displayed
  • Slow, unresponsive feeling

After

  • Smooth loading animations everywhere
  • PDF export works correctly
  • Correct dates displayed
  • Fast, responsive experience

How to test

  1. Kanban: Go to kanban page, switch between tasks - should see smooth loading
  2. Dashboard: Try PDF export - should work without errors
  3. Any page: Refresh and watch for loading animations instead of blank screens

Type of changes

  • Bug fixes (PDF export, dates)
  • New features (loading animations)
  • Better user experience
  • Breaking changes

Ready for review

  • All changes tested
  • No errors introduced
  • Works on mobile and desktop
  • Works in light and dark mode
ever-teams-update.mp4

Summary by CodeRabbit

  • New Features

    • Introduced numerous skeleton loading placeholders for dashboard, kanban, productivity tables, settings, and team stats to enhance perceived performance during data loading.
    • Added lazy loading and React Suspense for heavy components across dashboard, kanban, and settings pages, improving initial load times and responsiveness.
    • Enhanced PDF export handling with improved data fallback and clearer messaging when no data is available.
  • Improvements

    • Refined timer status logic and error handling for more accurate status display.
    • Optimized loading state detection and unified modal loading experiences in kanban and dashboard features.
    • Improved date and month display formatting for activity reports.
  • Bug Fixes

    • Added type safety and checks to prevent errors when handling potentially malformed or empty data in reports and exports.
  • Style

    • Updated and standardized CSS utility class orders for consistency and improved layout across multiple components.
    • Adjusted spacing and overflow handling for better UI presentation.
  • Chores

    • Centralized and exported utility constants for timer status logic.
    • Added a new icon for online status.
  • Documentation

    • No user-facing documentation changes included.

NdekoCode added 11 commits June 22, 2025 13:17
…an page

- Refactored the Kanban page to utilize dynamic imports for various components, enhancing performance and user experience during loading states.
- Introduced skeleton components for Kanban cards, filters, and views to provide visual feedback while data is being fetched.
- Updated the Kanban card and filters to use lazy loading, ensuring smoother transitions and reduced initial load times.
- Enhanced the overall structure and readability of the Kanban component, improving maintainability.
…ban component

- Updated Kanban page and related components to utilize ModalSkeleton for better user experience during modal loading.
- Replaced fallback divs in Suspense components with ModalSkeleton, enhancing visual feedback while modals are being loaded.
- Ensured consistent loading states across various modals within the Kanban interface, improving overall responsiveness and user interaction.
…s in Kanban component

- Introduced a new KanbanColumnLoadingSkeleton component to provide visual feedback during loading states in the Kanban view.
- Updated InnerItemList to utilize the new skeleton component, enhancing user experience by clearly indicating loading conditions.
- Enhanced conditional rendering logic to handle loading states more effectively, ensuring a smoother user interaction while data is being fetched.
…components

- Implemented lazy loading for `TeamStatsChart`, `TeamStatsTable`, and various dashboard components to enhance performance during data fetching.
- Introduced new skeleton components: `ChartSkeleton` and `TeamStatsTableSkeleton` to provide visual feedback while data is loading.
- Updated `DashboardHeader` and `TeamStatsTable` to utilize dynamic imports, improving user experience by reducing initial load times and ensuring smoother transitions.
- Enhanced conditional rendering for modals and loading states, ensuring a consistent and responsive interface.
…components

- Implemented lazy loading for various components in the dashboard and settings pages, including `TeamStatsChart`, `TeamStatsTable`, and personal settings components, to improve performance during data fetching.
- Introduced new skeleton components such as `AccordionContentSkeleton`, `PersonalSettingFormSkeleton`, and `WorkingHoursSkeleton` to provide visual feedback while data is loading.
- Updated the `DashboardHeader` and `ExportMenu` to utilize dynamic imports and skeletons, ensuring a smoother user experience and reducing initial load times.
- Enhanced conditional rendering for loading states across multiple components, improving overall responsiveness and user interaction.
…ed UI consistency

- Adjusted margin and padding values across multiple components, including `UserProfileTask`, `DataTable`, and skeleton components, to enhance visual alignment and spacing.
- Updated class names to ensure consistent styling, particularly in loading states and skeletons, improving user experience during data fetching.
- Enhanced the structure of flexbox properties in components like `SettingsPersonalSkeleton` and `UserTeamCard` for better responsiveness and layout coherence.
…ts and dynamic imports

- Introduced multiple skeleton components for improved loading states, including `ProductivityApplicationTableSkeleton`, `ProductivityEmployeeTableSkeleton`, and `ProductivityProjectTableSkeleton`, enhancing user experience during data fetching.
- Implemented lazy loading for the `DashboardHeader` and `ProductivityChart` components, optimizing performance and reducing initial load times.
- Updated the `ExportButtons` component to handle empty data gracefully, ensuring a smoother user experience when generating reports.
- Refactored the `ProductivityPDF` and `ProductivityApplicationPDF` components to manage empty data scenarios, providing clear feedback to users when no data is available.
- Enhanced the `ProductivityHeader` component to accept a string for the year, improving flexibility in displaying date information.
…components

- Removed unused `DashboardHeaderSkeleton` import from the team dashboard page for better code clarity.
- Adjusted flexbox properties in `ProductivityTableSkeleton` to enhance layout consistency and responsiveness.
- Streamlined class names for improved readability and maintainability across skeleton components.
… states

- Registered Helvetica font for improved PDF styling in `ProductivityPDF` and `ProductivityApplicationPDF` components.
- Updated `ProductivityApplicationPDF` to use Helvetica font for consistent typography.
- Added a new loading state for the `ProductivityEmployeeTable` in the dashboard, enhancing user experience during data fetching.
…ration

- Added user authentication hook to retrieve current user information for PDF exports.
- Updated PDF-compatible data structure to include real user details such as full name, first name, last name, employee ID, and user ID.
- Enhanced debugging output for PDF export data to include user information, aiding in development and troubleshooting.
Copy link
Contributor

coderabbitai bot commented Jun 23, 2025

Walkthrough

This update introduces extensive use of lazy loading and React Suspense for dashboard, kanban, and settings components to optimize performance and loading states. Numerous skeleton components are added for visual feedback during loading. The dashboard export logic is enhanced with a PDF-compatible data transformation function and improved handling of empty or malformed data.

Changes

Files/Groups Change Summary
apps/web/app/[locale]/(main)/dashboard/app-url/[teamId]/page.tsx Adds lazy loading/Suspense for dashboard components, new PDF-compatible data function, and refactors table rendering.
apps/web/app/[locale]/(main)/dashboard/team-dashboard/[teamId]/page.tsx Refactors to use lazy loading and Suspense for heavy dashboard components.
apps/web/app/[locale]/(main)/kanban/page.tsx Refactors Kanban page to use dynamic imports and Suspense for board, filters, and modal components.
apps/web/app/[locale]/(main)/settings/personal/page.tsx Implements lazy loading and Suspense for personal settings components with skeleton fallbacks.
apps/web/core/components/common/skeleton/*.tsx Adds multiple new skeleton components for dashboard, productivity, kanban, and settings UIs.
apps/web/core/components/common/data-table.tsx, settings-personal-skeleton.tsx, etc. Reorders and tweaks CSS class names for consistent styling and spacing.
apps/web/core/components/pages/dashboard/app-url/productivity-application/productivity-application-pdf.tsx
productivity-pdf.tsx
Improves PDF export: adds empty data handling, font change, and robust data checks.
apps/web/core/components/pages/dashboard/dashboard-header.tsx
team-dashboard/lazy-components.tsx
Refactors to use lazy loading and Suspense for dashboard header and export-related components.
apps/web/core/components/pages/dashboard/export-dialog.tsx, export-menu.tsx Enhances export logic, adds default prop values, improves data validation, and uses Suspense for PDF export.
apps/web/core/components/pages/dashboard/team-dashboard/team-stats-grid.tsx Shows skeleton loader for stats grid during loading instead of per-card loaders.
apps/web/core/components/pages/dashboard/team-dashboard/team-stats-table.tsx Uses lazy loading and Suspense for modal and empty state components; minor class reorderings.
apps/web/core/components/pages/kanban/team-members-kanban-view.tsx Passes all columns data to Kanban draggable component.
apps/web/core/components/pages/profile/screenshots/screenshoots-per-hour-skeleton.tsx
user-profile-tasks.tsx
Minor margin and spacing adjustments.
apps/web/core/components/pages/teams/team/team-members-views/user-team-card/index.tsx Uses useMemo for booleans, refactors conditional logic, and tweaks layout.
apps/web/core/components/tasks/kanban-card.tsx
kanban.tsx
Switches to dynamic imports and Suspense for modal and heavy Kanban components; refines loading logic.
apps/web/core/components/tasks/task-block-card.tsx, task-times.tsx Adjusts layout, spacing, and text overflow handling.
apps/web/core/components/timer/timer-status.tsx Refactors status mapping logic, adds error handling, and centralizes constants.
apps/web/core/components/users/user-nav-menu.tsx, user-profile-plans.tsx Reorders CSS class names for consistency; no logic changes.
apps/web/core/constants/config/constants.tsx Adds new TIMER_STATUS_CONSTANTS export.
apps/web/core/hooks/activities/use-report-activity.ts Adds array type guard for activity report data.
apps/web/styles/globals.css Adds global shimmer keyframe animation.
apps/web/core/components/icons/icons.tsx Adds new OnlineIcon SVG component.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant DashboardPage
  participant LazyDashboardHeader
  participant ProductivityTable
  participant Skeletons

  User->>DashboardPage: Load dashboard
  DashboardPage->>LazyDashboardHeader: Render (Suspense)
  LazyDashboardHeader-->>Skeletons: Show DashboardHeaderSkeleton while loading
  LazyDashboardHeader-->>DashboardPage: Rendered header (with pdfCompatibleData)
  DashboardPage->>ProductivityTable: Render table (Suspense)
  ProductivityTable-->>Skeletons: Show ProductivityTableSkeleton while loading
  ProductivityTable-->>DashboardPage: Rendered productivity table
Loading

Possibly related issues

Possibly related PRs

Suggested labels

feature, UI/UX, WEB, Bug fix

Suggested reviewers

  • evereq
  • Innocent-Akim

Poem

In the warren of code, a rabbit did hop,
Adding lazy loads—no need to stop!
Skeletons shimmer as dashboards awake,
PDF exports now handle an empty mistake.
With Suspense and a wink,
The UI’s in sync—
Fast as a bunny, for performance’s sake! 🐇✨

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.

yarn install v1.22.22
[1/4] Resolving packages...
(node:2663) [DEP0169] DeprecationWarning: url.parse() behavior is not standardized and prone to errors that have security implications. Use the WHATWG URL API instead. CVEs are not issued for url.parse() vulnerabilities.
(Use node --trace-deprecation ... to show where the warning was created)
error Couldn't find package "@ever-teams/eslint-config@" required by "@ever-teams/types@" on the "npm" registry.
info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate Unit Tests
  • Create PR with Unit Tests
  • Post Copyable Unit Tests in Comment
  • Commit Unit Tests in branch feat/improve-kanban-and-dashboard-with-pdf-export-and-skeletons

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 auto-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.

Copy link

⚠️ Unused code detected in the following changed files:

  • apps/web/core/components/common/skeleton/kanban-card-skeleton.tsx
  • apps/web/core/components/common/skeleton/kanban-filters-skeleton.tsx
  • apps/web/core/components/icons/icons.tsx
  • apps/web/core/components/tasks/kanban-card.tsx
  • apps/web/core/components/tasks/kanban.tsx
  • apps/web/core/components/timer/timer-status.tsx
  • apps/web/core/constants/config/constants.tsx
  • apps/web/core/hooks/activities/use-report-activity.ts

Please review these files and clean up the unused code.

Copy link

⚠️ Unused code detected in the following changed files:

  • apps/web/core/components/common/skeleton/kanban-card-skeleton.tsx
  • apps/web/core/components/common/skeleton/kanban-filters-skeleton.tsx
  • apps/web/core/components/icons/icons.tsx
  • apps/web/core/components/tasks/kanban-card.tsx
  • apps/web/core/components/tasks/kanban.tsx
  • apps/web/core/components/timer/timer-status.tsx
  • apps/web/core/constants/config/constants.tsx
  • apps/web/core/hooks/activities/use-report-activity.ts

Please review these files and clean up the unused code.

@NdekoCode NdekoCode marked this pull request as ready for review June 23, 2025 13:00
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

PR Summary

Major enhancement to application-wide loading states and PDF export functionality, introducing 16+ new skeleton components and fixing critical rendering issues.

  • Added comprehensive skeleton loading system in apps/web/core/components/common/skeleton/ with unified shimmer animations and dark mode support
  • Fixed PDF export by switching to Helvetica font and adding proper data validation in apps/web/core/components/pages/dashboard/app-url/productivity-pdf.tsx
  • Optimized performance through lazy loading with Next.js dynamic imports in dashboard and kanban components
  • Improved date handling and validation across productivity reports and dashboard components
  • Enhanced timer status display with proper constants and type safety in apps/web/core/components/timer/timer-status.tsx

50 files reviewed, 38 comments
Edit PR Review Bot Settings | Greptile

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🔭 Outside diff range comments (2)
apps/web/core/constants/config/constants.tsx (1)

749-755: New constant appears unused, causing pipeline failure.

TIMER_STATUS_CONSTANTS is defined but not referenced anywhere in this module—Knip flagged it as unused. Please either import and use it in your updated timer-status logic or remove it if redundant.

apps/web/core/components/pages/dashboard/team-dashboard/team-stats-grid.tsx (1)

97-105: Remove redundant loading logic for consistency.

Since the component now renders StatsCardSkeleton when loadingTimesheetStatisticsCounts is true, the individual loader logic inside each card is redundant and will never be reached. This creates maintenance overhead and potential confusion.

Remove the individual loading logic since the skeleton handles the entire loading state:

-						<div className="mt-2 h-9">
-							{loadingTimesheetStatisticsCounts ? (
-								<Loader2 className="w-6 h-6 text-gray-500 animate-spin" />
-							) : (
-								<span
-									className={`text-2xl font-semibold ${stat.color || 'text-gray-900 dark:text-white'}`}
-								>
-									{stat.value}
-								</span>
-							)}
-						</div>
+						<div className="mt-2 h-9">
+							<span
+								className={`text-2xl font-semibold ${stat.color || 'text-gray-900 dark:text-white'}`}
+							>
+								{stat.value}
+							</span>
+						</div>
🧹 Nitpick comments (14)
apps/web/core/components/tasks/task-times.tsx (2)

117-121: Use correct spacing utility and remove invalid CSS class

The switch from space-x-4 to gap-x-4 is spot on for modern Tailwind layouts. However, text-nowrap isn’t a default Tailwind utility and has no effect. You can drop text-nowrapwhitespace-nowrap already enforces no wrapping (or use truncate for overflow).


135-141: Consistent spacing update and invalid class cleanup

Again, replacing space-x-4 with gap-x-4 is correct. The text-nowrap class here should also be removed since it’s not a standard Tailwind utility. Rely on whitespace-nowrap or add truncate if needed.

apps/web/core/components/common/skeleton/kanban-view-skeleton.tsx (1)

8-39: Well-implemented skeleton component with responsive considerations

The KanbanViewSkeleton component effectively provides loading state feedback with appropriate styling and animations. The fixed layout with 5 columns and responsive width classes aligns well with typical Kanban board implementations.

Consider making the number of columns configurable via props to increase reusability across different Kanban layouts.

-export function KanbanViewSkeleton({ className, fullWidth = true }: KanbanViewSkeletonProps) {
-	const columns = Array.from(Array(5));
+export function KanbanViewSkeleton({ className, fullWidth = true, columnCount = 5 }: KanbanViewSkeletonProps) {
+	const columns = Array.from(Array(columnCount));
interface KanbanViewSkeletonProps {
	className?: string;
	fullWidth?: boolean;
+	columnCount?: number;
}
apps/web/core/components/pages/dashboard/team-dashboard/team-stats-grid.tsx (1)

113-114: Consider removing loading-dependent width calculation.

The progress bar width is set to 0 when loading, but since the skeleton handles the loading state, this logic is now redundant.

Simplify the width calculation:

-									style={{
-										width: `${loadingTimesheetStatisticsCounts ? 0 : stat.progress}%`
-									}}
+									style={{
+										width: `${stat.progress}%`
+									}}
apps/web/core/components/common/skeleton/working-hours-skeleton.tsx (1)

14-34: Good implementation with minor suggestion

The working hours skeleton is well-implemented. The conditional rendering for time slots (index < 5) makes sense for business days, but consider making this more explicit.

-						{/* Time Slots (only for enabled days) */}
-						{index < 5 && (
+						{/* Time Slots (only for weekdays) */}
+						{index < 5 && (

Or even better, define a constant:

+const WEEKDAYS_COUNT = 5;
+
 export const WorkingHoursSkeleton = () => {
 	return (
 		<div className="space-y-6 mt-6">
 			{/* Timezone Section */}
 			<div className="space-y-4">
 				<div className="w-32 h-4 bg-[#F0F0F0] dark:bg-[#353741] animate-pulse rounded" />
 				<div className="w-64 h-10 bg-[#F0F0F0] dark:bg-[#353741] animate-pulse rounded" />
 			</div>

 			{/* Working Days */}
 			<div className="space-y-4">
 				{Array.from({ length: 7 }).map((_, index) => (
 					<div key={index} className="relative rounded-lg border border-gray-200 dark:border-gray-700 p-4">
 						{/* Day Toggle */}
 						<div className="flex items-center justify-between mb-4">
 							<div className="flex items-center gap-3">
 								<div className="w-12 h-6 bg-[#F0F0F0] dark:bg-[#353741] animate-pulse rounded-full" />
 								<div className="w-20 h-4 bg-[#F0F0F0] dark:bg-[#353741] animate-pulse rounded" />
 							</div>
 							<div className="w-6 h-6 bg-[#F0F0F0] dark:bg-[#353741] animate-pulse rounded" />
 						</div>

 						{/* Time Slots (only for weekdays) */}
-						{index < 5 && (
+						{index < WEEKDAYS_COUNT && (
 							<div className="flex items-center gap-4 pl-[180px]">
 								<div className="w-24 h-8 bg-[#F0F0F0] dark:bg-[#353741] animate-pulse rounded" />
 								<div className="w-4 h-1 bg-[#F0F0F0] dark:bg-[#353741] animate-pulse rounded" />
 								<div className="w-24 h-8 bg-[#F0F0F0] dark:bg-[#353741] animate-pulse rounded" />
 							</div>
 						)}
 					</div>
 				))}
 			</div>
apps/web/core/components/pages/dashboard/app-url/productivity-pdf.tsx (1)

9-13: Consider font loading reliability.

The font registration improves PDF rendering consistency. However, loading fonts from external URLs could cause issues if the CDN is unavailable.

Consider hosting the font locally or providing a fallback mechanism:

Font.register({
	family: 'Helvetica',
-	src: 'https://fonts.gstatic.com/s/helveticaneue/v70/1Ptsg8zYS_SKggPNyC0IT0kLW-43aMEzIO6XUTLjad8.ttf'
+	src: 'https://fonts.gstatic.com/s/helveticaneue/v70/1Ptsg8zYS_SKggPNyC0IT0kLW-43aMEzIO6XUTLjad8.ttf',
+	fontWeight: 'normal'
});
apps/web/core/components/pages/dashboard/team-dashboard/team-stats-table.tsx (1)

159-166: Verify the lazy component usage without Suspense wrapper.

The LazyAnimatedEmptyState is used here without a Suspense boundary, which could cause issues if the component fails to load. Since this component has its own loading state defined in the dynamic import, it should work, but consider wrapping it in Suspense for consistency.

Consider wrapping with Suspense for consistency:

<div className="grow w-full min-h-[600px] flex items-center justify-center flex-col">
+	<Suspense fallback={
+		<div className="grow w-full min-h-[600px] flex items-center justify-center flex-col">
+			<div className="w-32 h-32 bg-[#F0F0F0] dark:bg-[#353741] animate-pulse rounded-full mb-4" />
+			<div className="w-48 h-6 bg-[#F0F0F0] dark:bg-[#353741] animate-pulse rounded mb-2" />
+			<div className="w-64 h-4 bg-[#F0F0F0] dark:bg-[#353741] animate-pulse rounded" />
+		</div>
+	}>
		<LazyAnimatedEmptyState
			title={t('common.NO_ACTIVITY_DATA')}
			message={t('common.SELECT_DIFFERENT_DATE')}
			showBorder={true}
		/>
+	</Suspense>
</div>
apps/web/core/components/common/skeleton/accordion-content-skeleton.tsx (1)

13-14: Consider extracting color values to constants.

The color values #F0F0F0 and #353741 are repeated throughout the component. Consider extracting them to constants or CSS variables for better maintainability.

+const SKELETON_COLORS = {
+  light: '#F0F0F0',
+  dark: '#353741'
+} as const;

 export const AccordionContentSkeleton = ({ type = 'form', className = '' }: AccordionContentSkeletonProps) => {

Then use them like:

-<div className="w-20 h-4 bg-[#F0F0F0] dark:bg-[#353741] animate-pulse rounded" />
+<div className={`w-20 h-4 bg-[${SKELETON_COLORS.light}] dark:bg-[${SKELETON_COLORS.dark}] animate-pulse rounded`} />

Also applies to: 24-25, 34-36, 46-49, 52-52

apps/web/core/components/common/skeleton/productivity-employee-table-skeleton.tsx (1)

31-35: Simplify key prop usage in employee groups.

The Fragment and its first TableRow child both use similar key patterns, which could be confusing. Consider using a more distinct key pattern or removing the key from the Fragment since React 18+ doesn't require keys on Fragments when children have keys.

-<Fragment key={`employee-group-${employeeIndex}`}>
+<Fragment key={employeeIndex}>
   {/* Employee Header Row */}
   <TableRow
-    key={`employee-header-${employeeIndex}`}
+    key={`header-${employeeIndex}`}
apps/web/app/[locale]/(main)/kanban/page.tsx (1)

29-36: Consider simplifying the KanbanView import.

The dynamic import can be simplified by using a named export directly.

-const LazyKanbanView = dynamic(
-	() =>
-		import('@/core/components/pages/kanban/team-members-kanban-view').then((mod) => ({ default: mod.KanbanView })),
+const LazyKanbanView = dynamic(
+	() => import('@/core/components/pages/kanban/team-members-kanban-view').then((mod) => mod.KanbanView),

Note: This assumes KanbanView is a named export. If it's the default export, the current pattern is correct.

apps/web/core/components/pages/dashboard/export-dialog.tsx (1)

42-51: Good development-only debug logging!

The debug logging is properly gated behind NODE_ENV check. Consider using a more structured logging approach for better debugging experience.

-console.log('ExportButtons Debug:', {
+console.debug('[ExportButtons]', {
   reportData: reportData?.length,
   exportType,
   groupByType,
   startDate,
   endDate
 });
apps/web/app/[locale]/(main)/dashboard/app-url/[teamId]/page.tsx (1)

190-204: Consider removing or redacting sensitive user information from debug logs.

Even in development, logging user PII (fullName, employeeId) could be problematic if logs are persisted or shared.

Consider logging only non-sensitive debugging information:

 console.log('📄 PDF Export Data Debug:', {
   originalActivityReport: activityReport?.length,
   pdfCompatibleDataLength: pdfCompatibleData?.length,
-  pdfCompatibleDataStructure: pdfCompatibleData?.[0],
+  hasData: pdfCompatibleData?.length > 0,
   reportDataType: typeof pdfCompatibleData,
   reportDataIsArray: Array.isArray(pdfCompatibleData),
-  userInfo: {
-    fullName: user?.fullName,
-    firstName: user?.firstName,
-    lastName: user?.lastName,
-    employeeId: user?.employee?.id
-  }
+  hasUserInfo: !!user
 });
apps/web/core/components/tasks/kanban.tsx (2)

101-103: Consider adding a comment to explain the loading state logic.

The isActuallyLoading calculation handles important edge cases but could benefit from documentation.

 // Check if we're in a "false loading" state where isLoading=false but no data is actually available yet
 const isActuallyLoading = useMemo(() => {
+  // Show loading state if:
+  // 1. Explicitly loading
+  // 2. Items is not a valid array (data not yet received)
+  // 3. Items is empty but we know there should be data (allColumnsData exists)
   return isLoading || !Array.isArray(items) || (items.length === 0 && allColumnsData);
 }, [isLoading, items, allColumnsData]);

165-177: Consider extracting modal implementations to reduce code duplication.

The same modal patterns are repeated multiple times throughout the file. This violates the DRY principle.

Consider creating reusable modal wrapper components:

// Add these components at the top of the file
const CreateTaskModalWrapper = ({ isOpen, closeModal, title }: { 
  isOpen: boolean; 
  closeModal: () => void; 
  title: string;
}) => {
  if (!isOpen) return null;
  
  return (
    <Suspense fallback={<ModalSkeleton size="lg" />}>
      <Modal isOpen={isOpen} closeModal={closeModal}>
        <LazyCreateTaskModal
          onClose={closeModal}
          title={title}
          initEditMode={false}
          task={null}
          tasks={[]}
        />
      </Modal>
    </Suspense>
  );
};

const EditStatusModalWrapper = ({ isOpen, closeModal, status, setColumn }: {
  isOpen: boolean;
  closeModal: () => void;
  status: any;
  setColumn: any;
}) => {
  if (!isOpen) return null;
  
  return (
    <Suspense fallback={<ModalSkeleton size="md" />}>
      <Modal isOpen={isOpen} closeModal={closeModal}>
        <LazyEditStatusModal 
          status={status} 
          onClose={closeModal} 
          setColumn={setColumn} 
        />
      </Modal>
    </Suspense>
  );
};

Then replace all instances with these wrapper components.

Also applies to: 388-398, 426-445, 535-541, 640-652

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between de43c8a and b20cfed.

📒 Files selected for processing (51)
  • apps/web/app/[locale]/(main)/dashboard/app-url/[teamId]/page.tsx (7 hunks)
  • apps/web/app/[locale]/(main)/dashboard/team-dashboard/[teamId]/page.tsx (5 hunks)
  • apps/web/app/[locale]/(main)/kanban/page.tsx (8 hunks)
  • apps/web/app/[locale]/(main)/settings/personal/page.tsx (2 hunks)
  • apps/web/core/components/common/data-table.tsx (2 hunks)
  • apps/web/core/components/common/skeleton/accordion-content-skeleton.tsx (1 hunks)
  • apps/web/core/components/common/skeleton/auth-user-task-input-skeleton.tsx (0 hunks)
  • apps/web/core/components/common/skeleton/chart-skeleton.tsx (1 hunks)
  • apps/web/core/components/common/skeleton/dashboard-header-skeleton.tsx (1 hunks)
  • apps/web/core/components/common/skeleton/export-pdf-skeleton.tsx (1 hunks)
  • apps/web/core/components/common/skeleton/kanban-card-skeleton.tsx (1 hunks)
  • apps/web/core/components/common/skeleton/kanban-column-loading-skeleton.tsx (1 hunks)
  • apps/web/core/components/common/skeleton/kanban-filters-skeleton.tsx (1 hunks)
  • apps/web/core/components/common/skeleton/kanban-view-skeleton.tsx (1 hunks)
  • apps/web/core/components/common/skeleton/no-team-skeleton.tsx (1 hunks)
  • apps/web/core/components/common/skeleton/personal-setting-form-skeleton.tsx (1 hunks)
  • apps/web/core/components/common/skeleton/productivity-application-table-skeleton.tsx (1 hunks)
  • apps/web/core/components/common/skeleton/productivity-employee-table-skeleton.tsx (1 hunks)
  • apps/web/core/components/common/skeleton/productivity-project-table-skeleton.tsx (1 hunks)
  • apps/web/core/components/common/skeleton/productivity-skeletons.tsx (1 hunks)
  • apps/web/core/components/common/skeleton/productivity-table-skeleton.tsx (1 hunks)
  • apps/web/core/components/common/skeleton/settings-personal-skeleton.tsx (9 hunks)
  • apps/web/core/components/common/skeleton/stats-card-skeleton.tsx (1 hunks)
  • apps/web/core/components/common/skeleton/task-timer-section-skeleton.tsx (0 hunks)
  • apps/web/core/components/common/skeleton/team-stats-table-skeleton.tsx (1 hunks)
  • apps/web/core/components/common/skeleton/working-hours-skeleton.tsx (1 hunks)
  • apps/web/core/components/icons/icons.tsx (1 hunks)
  • apps/web/core/components/pages/dashboard/app-url/productivity-application/productivity-application-pdf.tsx (2 hunks)
  • apps/web/core/components/pages/dashboard/app-url/productivity-header.tsx (1 hunks)
  • apps/web/core/components/pages/dashboard/app-url/productivity-pdf.tsx (2 hunks)
  • apps/web/core/components/pages/dashboard/dashboard-header.tsx (2 hunks)
  • apps/web/core/components/pages/dashboard/export-dialog.tsx (2 hunks)
  • apps/web/core/components/pages/dashboard/export-menu.tsx (2 hunks)
  • apps/web/core/components/pages/dashboard/team-dashboard/lazy-components.tsx (1 hunks)
  • apps/web/core/components/pages/dashboard/team-dashboard/team-stats-grid.tsx (2 hunks)
  • apps/web/core/components/pages/dashboard/team-dashboard/team-stats-table.tsx (8 hunks)
  • apps/web/core/components/pages/kanban/team-members-kanban-view.tsx (1 hunks)
  • apps/web/core/components/pages/profile/screenshots/screenshoots-per-hour-skeleton.tsx (1 hunks)
  • apps/web/core/components/pages/profile/user-profile-tasks.tsx (1 hunks)
  • apps/web/core/components/pages/teams/team/team-members-views/user-team-card/index.tsx (7 hunks)
  • apps/web/core/components/tasks/daily-plan/past-tasks.tsx (2 hunks)
  • apps/web/core/components/tasks/kanban-card.tsx (5 hunks)
  • apps/web/core/components/tasks/kanban.tsx (14 hunks)
  • apps/web/core/components/tasks/task-block-card.tsx (5 hunks)
  • apps/web/core/components/tasks/task-times.tsx (2 hunks)
  • apps/web/core/components/timer/timer-status.tsx (3 hunks)
  • apps/web/core/components/users/user-nav-menu.tsx (10 hunks)
  • apps/web/core/components/users/user-profile-plans.tsx (12 hunks)
  • apps/web/core/constants/config/constants.tsx (1 hunks)
  • apps/web/core/hooks/activities/use-report-activity.ts (1 hunks)
  • apps/web/styles/globals.css (1 hunks)
💤 Files with no reviewable changes (2)
  • apps/web/core/components/common/skeleton/task-timer-section-skeleton.tsx
  • apps/web/core/components/common/skeleton/auth-user-task-input-skeleton.tsx
🧰 Additional context used
🪛 GitHub Actions: Knip Review - Cleanup Unused Code - WEB
apps/web/core/constants/config/constants.tsx

[error] 1-1: Unused code detected in this file.

apps/web/core/hooks/activities/use-report-activity.ts

[error] 1-1: Unused code detected in this file.

apps/web/core/components/icons/icons.tsx

[error] 1-1: Unused code detected in this file.

apps/web/core/components/common/skeleton/kanban-filters-skeleton.tsx

[error] 1-1: Unused code detected in this file.

apps/web/core/components/tasks/kanban-card.tsx

[error] 1-1: Unused code detected in this file.

apps/web/core/components/tasks/kanban.tsx

[error] 1-1: Unused code detected in this file.

apps/web/core/components/timer/timer-status.tsx

[error] 1-1: Unused code detected in this file.

apps/web/core/components/common/skeleton/kanban-card-skeleton.tsx

[error] 1-1: Unused code detected in this file.

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: deploy
🔇 Additional comments (74)
apps/web/core/components/pages/profile/screenshots/screenshoots-per-hour-skeleton.tsx (1)

31-31: Minor spacing adjustment approved.

The bottom margin on the <p> element has been fine-tuned from mb-6 to mb-5 to align with surrounding components.

apps/web/core/components/pages/profile/user-profile-tasks.tsx (1)

59-59: Margin-top refinement is consistent.

Updating the container’s mt-12 to mt-5 reduces vertical spacing to match other UI tweaks in this PR.

apps/web/core/components/common/skeleton/dashboard-header-skeleton.tsx (1)

1-17: Dashboard header skeleton implemented correctly.

The new DashboardHeaderSkeleton provides a clear loading fallback for the lazy-loaded header. Layout, classes, and structure align with existing skeleton patterns.

apps/web/core/components/common/skeleton/export-pdf-skeleton.tsx (1)

1-13: PDF export skeleton looks good.

ExportPDFSkeleton offers a simple, centered loading UI for PDF export actions, consistent with design guidelines.

apps/web/core/components/tasks/daily-plan/past-tasks.tsx (2)

71-72: LGTM: Class ordering consistency improvement

The reordering of CSS classes maintains consistent styling patterns across the codebase without affecting functionality.


103-105: Enhanced drag state visual feedback

Good improvement to the droppable container styling. The explicit border color definitions provide clearer visual feedback during drag operations.

apps/web/core/components/pages/teams/team/team-members-views/user-team-card/index.tsx (2)

150-157: Excellent performance optimization with proper memoization

Good use of useMemo to optimize expensive boolean calculations. The dependency arrays are correctly configured to ensure the memoized values update when the underlying data changes.


179-184: Consistent usage of memoized values and cn utility

The implementation correctly uses the memoized values throughout the component and the cn utility for conditional class application, maintaining the same functionality while improving performance.

Also applies to: 196-196, 203-203, 277-277, 301-301

apps/web/core/components/common/skeleton/chart-skeleton.tsx (1)

1-47: Comprehensive and well-designed chart skeleton component

Excellent implementation that covers all typical chart elements including controls, axis labels, data points, and legend. The skeleton provides realistic visual feedback during chart loading with proper dark mode support and animations.

apps/web/core/components/users/user-profile-plans.tsx (2)

187-187: CSS class ordering consistency improvements

The reordering of CSS classes throughout the component maintains consistent styling patterns across the codebase. These changes improve code maintainability without affecting functionality.

Also applies to: 234-234, 273-273, 276-276, 406-407, 435-435, 439-441, 565-565, 609-609, 618-618, 629-629, 633-633, 637-637, 649-649, 660-660


559-559: Minor spacing adjustment in PlanHeader

The margin change from mb-6 to mb-5 provides slightly tighter spacing that aligns with the overall design improvements.

apps/web/core/components/pages/kanban/team-members-kanban-view.tsx (1)

251-251: LGTM! Supporting enhanced loading states.

The addition of allColumnsData={items} prop to KanbanDraggable aligns well with the PR's objective to improve loading states and skeleton animations. This provides the component with access to all column data to make informed decisions about when to display loading skeletons versus empty states.

apps/web/styles/globals.css (1)

774-781: Excellent refactoring! Centralizing shimmer animation.

Moving the shimmer animation to global CSS is a great improvement for maintainability. This eliminates duplication across skeleton components and ensures consistent shimmer effects throughout the application.

apps/web/core/components/common/skeleton/no-team-skeleton.tsx (1)

18-18: LGTM! Improved spacing consistency.

The margin reduction from mb-6 to mb-5 on the icon and description skeleton elements provides better visual hierarchy and aligns with the overall spacing improvements across the application's skeleton components.

Also applies to: 25-25

apps/web/core/components/pages/dashboard/app-url/productivity-header.tsx (1)

5-5: Good type flexibility improvement.

Changing the year prop type to number | string provides better flexibility for handling different data formats, particularly useful for the enhanced PDF export functionality mentioned in the PR objectives. The component logic remains unchanged while becoming more permissive.

apps/web/core/components/icons/icons.tsx (1)

637-648: ```shell
#!/bin/bash

Broad search for any reference to OnlineIcon across the repository

echo "Searching for any usage or import of OnlineIcon..."
rg -i "OnlineIcon" -A2 -B2

Also specifically check TSX files

echo "Searching for OnlineIcon in TSX files..."
rg -i "OnlineIcon" -g "*.tsx" -A2 -B2 || true


</details>
<details>
<summary>apps/web/core/components/common/data-table.tsx (1)</summary>

`70-70`: **LGTM! Good styling refinements.**

The CSS class reordering, margin reduction from `mt-8` to `mt-5`, and removal of duplicate `divide-y` classes improve visual consistency and code cleanliness. These changes align well with the UI improvements mentioned in the PR objectives.



Also applies to: 103-103, 106-106

</details>
<details>
<summary>apps/web/core/components/pages/dashboard/team-dashboard/team-stats-grid.tsx (2)</summary>

`9-9`: **Good addition of skeleton loading component.**

The import of `StatsCardSkeleton` supports the improved loading experience mentioned in the PR objectives.

---

`88-90`: **Excellent improvement to loading UX.**

Rendering the `StatsCardSkeleton` for the entire grid provides a better loading experience than individual card loaders.

</details>
<details>
<summary>apps/web/core/hooks/activities/use-report-activity.ts (2)</summary>

`324-324`: **Excellent type safety improvement.**

Adding the `Array.isArray()` check ensures `activityReport` is always an array, preventing potential runtime errors when the API response is malformed or unexpected. This aligns well with the broader data handling improvements mentioned in the PR objectives for PDF export functionality.

---

`1-1`: ```shell
#!/bin/bash
# Check usage of imported symbols excluding import statements
file="apps/web/core/hooks/activities/use-report-activity.ts"
symbols=(useCallback useEffect useState useMemo useQuery useAtom useTimelogFilterOptions activityService statisticsService timeLogService useAuthenticateUser ETimeLogType queryKeys ITimeLogReportDailyChartProps)

for s in "${symbols[@]}"; do
  echo -n "$s: "
  # List usages excluding the import lines
  usages=$(grep -E -n "\b$s\b" "$file" | grep -v "^import")
  if [ -z "$usages" ]; then
    echo "none"
  else
    echo "$usages"
  fi
done
apps/web/core/components/pages/dashboard/team-dashboard/lazy-components.tsx (1)

1-13: Excellent lazy loading implementation.

This component perfectly aligns with the PR objectives of improving dashboard performance and loading states. The implementation follows Next.js best practices:

  • Proper dynamic import with destructured default export
  • SSR disabled for client-dependent dashboard components
  • Skeleton loading fallback for better UX during code splitting

The lazy loading will reduce initial bundle size and improve page load performance.

apps/web/core/components/common/skeleton/productivity-skeletons.tsx (1)

1-5: Good centralization of skeleton exports.

This barrel export file provides a clean way to import related productivity skeleton components from a single location. The structure aligns well with the PR's goal of adding 16+ loading animations across the application.

apps/web/app/[locale]/(main)/settings/personal/page.tsx (1)

32-68: LGTM! Consistent lazy loading implementation

The lazy loading pattern is implemented consistently across all components with appropriate skeleton fallbacks. The ProfileAvatar component correctly includes a custom loading placeholder since it's not wrapped in Suspense.

apps/web/core/components/common/skeleton/personal-setting-form-skeleton.tsx (1)

1-62: Excellent skeleton implementation

The PersonalSettingFormSkeleton component is well-structured with logical sections that mirror the actual form layout. The consistent use of styling classes, proper dark mode support, and appropriate spacing make this a high-quality loading placeholder.

apps/web/core/components/common/skeleton/stats-card-skeleton.tsx (2)

65-81: Well-designed skeleton grid layout

The StatsCardSkeleton component effectively composes multiple skeleton cards with varied configurations. The grid layout and different progress bar colors create a realistic loading preview.


9-64: Sophisticated skeleton implementation with shimmer effects

The StatCardSkeleton implementation is excellent with advanced shimmer animations and proper TypeScript interfaces. The shimmer effect adds professional visual polish to the loading state.

Ensure the shimmer animation is properly defined in the global CSS file:

#!/bin/bash
# Description: Verify shimmer animation is defined in global CSS

# Search for shimmer keyframe definition
rg -A 10 "@keyframes shimmer" apps/web/styles/
apps/web/core/components/tasks/kanban-card.tsx (2)

22-51: Excellent lazy loading implementation

The dynamic import pattern is consistently implemented across all components with appropriate loading placeholders. The ssr: false configuration is correct for these UI-heavy components, and the simple skeleton placeholders provide good visual feedback during loading.


221-303: LGTM! Proper usage of lazy components

The lazy components are correctly integrated into the JSX with the same props and behavior as the original static imports. The conversion maintains all existing functionality while improving performance through code splitting.

apps/web/core/components/tasks/task-block-card.tsx (3)

80-80: LGTM! Border addition improves visual definition.

The addition of the border enhances the card's visual separation and aligns with the overall UI improvements mentioned in the PR objectives.


120-136: Good text overflow handling improvements.

The changes to constrain width and improve text wrapping are well-implemented. The use of text-ellipsis with overflow-hidden and the structured span elements for task number and title provide better control over text display.


150-166: Approve flex container improvements.

The addition of gap-2 and items-center classes improves the layout consistency and spacing of the timer display elements.

apps/web/core/components/common/skeleton/settings-personal-skeleton.tsx (1)

29-170: LGTM! CSS class reordering improves consistency.

The systematic reordering of CSS classes in flex containers enhances code consistency and readability without affecting functionality.

apps/web/core/components/common/skeleton/kanban-filters-skeleton.tsx (1)

1-42: Well-implemented skeleton component with unused code concern.

The component is excellently structured with:

  • Proper TypeScript interface
  • Comprehensive filter placeholders
  • Good dark/light theme support
  • Consistent animation usage

However, the pipeline failure indicates unused code. Please ensure this component is properly imported and used in the kanban page.

#!/bin/bash
# Description: Check if KanbanFiltersSkeleton is being used in the codebase
# Expected: Find imports and usage of this component

echo "Searching for KanbanFiltersSkeleton usage..."
rg -A 3 -B 3 "KanbanFiltersSkeleton"

echo -e "\nSearching for imports of kanban-filters-skeleton..."
rg -A 2 -B 2 "kanban-filters-skeleton"
apps/web/core/components/common/skeleton/kanban-column-loading-skeleton.tsx (1)

1-33: Excellent skeleton component implementation.

The component demonstrates excellent practices:

  • Loading spinner with proper animation
  • Comprehensive placeholder content representing the actual UI structure
  • Consistent dark/light theme support
  • Well-structured TypeScript interface
  • Proper use of Tailwind classes for animations and responsive design

The component effectively mimics the actual kanban column structure during loading states.

apps/web/core/components/pages/dashboard/app-url/productivity-application/productivity-application-pdf.tsx (3)

19-19: Good font change for PDF compatibility.

Switching from Inter to Helvetica for PDF rendering is a good choice as Helvetica is more universally supported in PDF generation.


117-144: Excellent empty data handling implementation.

The comprehensive empty data handling prevents crashes and provides meaningful user feedback. The fallback UI with proper headers and "No Data Available" message maintains a professional appearance even when data is missing.


149-171: Outstanding defensive programming practices.

The defensive checks for nested properties (dayData?.employees, Array.isArray() checks, activity?.title) prevent runtime errors when data structure is unexpected or malformed. This robust approach significantly improves the reliability of PDF generation.

apps/web/core/components/common/skeleton/team-stats-table-skeleton.tsx (1)

1-84: LGTM! Well-structured skeleton component.

The skeleton component is well-implemented with proper TypeScript interface, consistent dark mode support, and semantic table structure. The layout effectively mimics a real team stats table with appropriate placeholders.

apps/web/core/components/common/skeleton/kanban-card-skeleton.tsx (1)

1-68: The previous search failed due to unsupported file-type filters. Let’s retry across all files:

#!/bin/bash
# Search for any references to KanbanCardSkeleton in the repo
rg "KanbanCardSkeleton" -n .
apps/web/core/components/pages/dashboard/app-url/productivity-pdf.tsx (1)

225-255: Excellent error handling for empty data.

The implementation properly handles empty or invalid data by providing a clear "No Data Available" message and maintaining the PDF structure. This prevents crashes and provides good user feedback.

apps/web/core/components/common/skeleton/productivity-project-table-skeleton.tsx (1)

1-111: LGTM! Comprehensive skeleton with proper internationalization.

The skeleton component effectively mimics the hierarchical structure of a productivity project table with proper nesting of project groups, date groups, and activity rows. The use of translations and consistent styling patterns are well-implemented.

apps/web/app/[locale]/(main)/dashboard/team-dashboard/[teamId]/page.tsx (2)

21-42: Excellent lazy loading implementation for performance optimization.

The dynamic imports with proper loading states and SSR configuration are well-implemented. Disabling SSR for the chart component is appropriate given that charts often have client-side dependencies.


155-159: Proper Suspense integration with skeleton fallback.

The Suspense wrapper with TeamStatsTableSkeleton provides a smooth loading experience while the table component loads asynchronously.

apps/web/core/components/pages/dashboard/team-dashboard/team-stats-table.tsx (3)

12-20: LGTM! Clean lazy loading implementation with proper pattern.

The dynamic import for ActivityModal follows best practices by using Next.js dynamic imports with SSR disabled. The comment referencing "Medium article pattern" is helpful for understanding the approach.


26-39: Well-implemented lazy loading with custom skeleton fallback.

The LazyAnimatedEmptyState implementation is excellent:

  • Uses appropriate skeleton dimensions that match the final content
  • Provides proper dark mode support
  • Maintains consistent loading experience

170-174: Proper Suspense boundary implementation.

The conditional rendering of the modal with Suspense wrapper is correctly implemented:

  • Only renders when employeeLog exists
  • Uses appropriate ModalSkeleton fallback
  • Maintains the existing modal functionality
apps/web/core/components/common/skeleton/productivity-application-table-skeleton.tsx (4)

7-9: Simple and effective interface design.

The props interface is clean and minimal, accepting only an optional className for styling customization. This follows good component design principles.


11-27: Excellent skeleton table structure with proper internationalization.

The component effectively uses:

  • useTranslations for localized table headers
  • Proper table structure with semantic HTML
  • Consistent styling with theme support

30-69: Well-structured skeleton data simulation.

The nested loops effectively simulate the grouped application data structure:

  • 3 application groups with header rows
  • 5 activity rows per group
  • Proper skeleton placeholders for avatars, text, and progress indicators
  • Consistent spacing and alignment

73-87: Comprehensive pagination skeleton.

The pagination skeleton includes all necessary elements:

  • Navigation controls
  • Page indicators
  • Consistent spacing and alignment
  • Proper dark mode support
apps/web/core/components/pages/dashboard/dashboard-header.tsx (4)

6-16: Proper lazy loading implementation for GroupBySelectTimeActivity.

The dynamic import follows best practices:

  • Uses Next.js dynamic imports
  • SSR disabled for performance
  • Appropriate loading skeleton with matching dimensions
  • Clear comment explaining the optimization

25-49: Excellent lazy loading pattern for multiple components.

All lazy-loaded components follow consistent patterns:

  • DateRangePicker, TeamDashboardFilter, and ExportDialog properly configured
  • Appropriate loading skeletons with matching dimensions
  • SSR disabled where appropriate
  • Good comment explaining conditional component pattern

105-117: Proper conditional Suspense boundary for ExportDialog.

The modal rendering is correctly implemented:

  • Only renders when isOpen is true
  • Uses appropriate ModalSkeleton fallback
  • Passes all required props to the lazy component

132-140: Effective Suspense usage for PDF generation.

The TeamStatsPDF component is properly wrapped in Suspense with an appropriate fallback skeleton, which is important for PDF generation that can be computationally expensive.

apps/web/core/components/pages/dashboard/export-menu.tsx (3)

9-16: Good addition of Suspense and proper imports.

The imports are well-organized and include the necessary components for the refactored dropdown implementation.


72-117: Excellent dropdown refactoring with improved UX.

The component has been successfully refactored with several improvements:

  • Custom DropdownMenu replaces @headlessui/react dependency
  • Suspense wrapper for PDF export provides better loading feedback
  • Proper conditional rendering based on showModal prop
  • Enhanced accessibility with proper ARIA attributes
  • Disabled state handling for CSV export

87-103: Proper Suspense implementation for PDF export.

The PDF export is correctly wrapped in Suspense:

  • Uses ExportPDFSkeleton as fallback
  • Provides loading state feedback
  • Maintains existing PDF generation functionality
apps/web/core/components/common/skeleton/productivity-table-skeleton.tsx (4)

6-8: Clean and minimal props interface.

The interface follows good component design principles with only the necessary className prop for customization.


10-49: Excellent table header skeleton structure.

The header implementation is well-designed:

  • Proper table structure with semantic HTML
  • Consistent skeleton placeholders for sortable headers
  • Good use of flexbox for alignment
  • Appropriate skeleton dimensions

52-95: Comprehensive table body skeleton simulation.

The table body effectively simulates the real data structure:

  • 3 date groups with proper header rows
  • 4 employee activity rows per group
  • Consistent skeleton placeholders for all data types
  • Proper spacing and alignment
  • Good use of Fragment for grouping

98-113: Complete pagination skeleton implementation.

The pagination skeleton includes all necessary elements:

  • Navigation controls
  • Page indicators
  • Consistent spacing and layout
  • Proper dark mode support
apps/web/core/components/common/skeleton/accordion-content-skeleton.tsx (1)

1-77: Well-implemented skeleton component!

The component is well-structured with clear separation of concerns for each skeleton type. The TypeScript interface is properly defined, and the implementation follows React best practices.

apps/web/core/components/common/skeleton/productivity-employee-table-skeleton.tsx (1)

85-102: Good implementation of pagination skeleton!

The pagination skeleton properly represents the expected layout with appropriate placeholder elements for page controls and information.

apps/web/core/components/users/user-nav-menu.tsx (1)

62-65: Good CSS class refactoring!

The refactoring improves code consistency by:

  • Using size-* utility classes instead of separate width/height classes
  • Logically grouping related classes (flex, positioning, styling)
  • Following Tailwind CSS best practices

These changes enhance readability without affecting functionality.

Also applies to: 81-81, 86-86, 90-90, 122-127, 168-176

apps/web/app/[locale]/(main)/kanban/page.tsx (1)

22-117: Excellent implementation of lazy loading and code-splitting!

The dynamic imports with loading skeletons significantly improve the initial page load performance. The Suspense boundary for the modal is properly implemented, and the loading states provide good user feedback.

Also applies to: 466-470

apps/web/core/components/pages/dashboard/export-dialog.tsx (2)

53-69: Excellent error handling and data validation!

The implementation properly handles edge cases:

  • Allows export of empty datasets (good UX)
  • Prevents errors with invalid data formats
  • Provides clear user feedback for all states
  • Uses safe fallbacks for PDF components

This effectively addresses the PDF export errors mentioned in the PR objectives.

Also applies to: 78-79, 85-86


139-139: Good defensive programming for closeModal!

The fallback to empty function prevents potential runtime errors if onClose is undefined.

apps/web/app/[locale]/(main)/dashboard/app-url/[teamId]/page.tsx (2)

38-47: Good implementation of lazy loading for the chart component.

The dynamic import with SSR disabled and skeleton fallback is well-implemented for improving initial page load performance.


233-259: Well-structured refactoring with proper loading states.

The groupByMap implementation with Suspense boundaries and appropriate skeleton fallbacks improves code maintainability and user experience.

apps/web/core/components/timer/timer-status.tsx (2)

21-41: Excellent refactoring using mapping objects.

The centralized status mappings improve maintainability and make the component more readable. The separation of concerns (styles, icons, tooltips) is well-structured.


1-1: I’ll broaden the search to include all .ts and .tsx files and drop the unrecognized type filter:

#!/bin/bash
# Search all .ts/.tsx files for TimerStatus (excluding its own file)
echo "🔍 TimerStatus usages (excluding timer-status.tsx):"
rg -n "TimerStatus" -g "*.ts*" | grep -v "timer-status.tsx" || echo "— none found —"

echo -e "\n🔍 getTimerStatusValue usages (excluding timer-status.tsx):"
rg -n "getTimerStatusValue" -g "*.ts*" | grep -v "timer-status.tsx" || echo "— none found —"

echo -e "\n🔍 getTimerStatusValueWithValidation usages (excluding timer-status.tsx):"
rg -n "getTimerStatusValueWithValidation" -g "*.ts*" | grep -v "timer-status.tsx" || echo "— none found —"
apps/web/core/components/tasks/kanban.tsx (2)

34-44: Good implementation of unified loading states.

The approach of removing individual loading props and relying on Suspense fallbacks prevents double loading states and provides a consistent UX.


1-1: ```shell
#!/bin/bash

Check for ThreeDotIcon usage in kanban.tsx

rg -n "ThreeDotIcon" apps/web/core/components/tasks/kanban.tsx || true


</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->

Copy link
Contributor

@Innocent-Akim Innocent-Akim left a comment

Choose a reason for hiding this comment

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

Please @NdekoCode, would it be possible to fix these spacing issues in the Kanban?

Screenshot 2025-06-24 at 09 22 20 Screenshot 2025-06-24 at 09 22 32

@NdekoCode NdekoCode merged commit b3b316d into develop Jun 24, 2025
14 of 16 checks passed
@NdekoCode NdekoCode deleted the feat/improve-kanban-and-dashboard-with-pdf-export-and-skeletons branch June 24, 2025 08:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

2 participants