Skip to content

Conversation

Innocent-Akim
Copy link
Contributor

@Innocent-Akim Innocent-Akim commented Mar 5, 2025

Description

Please include a summary of the changes and the related issues.

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my code
  • I have commented on my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings

Previous screenshots

Please add here videos or images of the previous status

Current screenshots

Please add here videos or images of the current (new) status

Summary by CodeRabbit

  • New Features

    • Introduced an enhanced Time and Activity dashboard accessible from the sidebar.
    • Added interactive UI elements including a versatile view selector, a date range picker with calendar and quick-select options, a grouping selector for activity metrics, and metric cards with progress indicators.
    • Expanded reporting functionality to support additional grouping criteria.
  • Refactor / Style

    • Updated navigation links and streamlined layout classes for improved consistency.

- Add new time and activity tracking page component
- Implement basic page structure and routing
- Set up component organization for time tracking feature
- Rename components for better clarity (TimeAndActivity, TimectivityComponents)
- Update sidebar navigation path for time and activity
- Add new group by options (daily, weekly, member)
- Create time activity header and group select components
- Implement card layout with header section
- Update breadcrumb navigation
- Create new date range picker component for time activity
- Setup component structure for time activity header
- Add index file for time activity components
- Create new ViewSelect component for controlling column visibility
- Add checkbox options for Member, Project, Task, Tracked Hours, Earnings, and Activity Level
- Update date range picker with All Times option
- Improve styling and layout of dropdown menu
@Innocent-Akim Innocent-Akim self-assigned this Mar 5, 2025
Copy link
Contributor

coderabbitai bot commented Mar 5, 2025

Warning

Rate limit exceeded

@Innocent-Akim has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 14 minutes and 23 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 891d1e8 and 4d39359.

📒 Files selected for processing (4)
  • apps/web/app/[locale]/time-and-activity/Components/card-time-and-activity.tsx (1 hunks)
  • apps/web/app/[locale]/time-and-activity/Components/date-range-picker-time-activity.tsx (1 hunks)
  • apps/web/app/[locale]/time-and-activity/Components/page-component.tsx (1 hunks)
  • apps/web/app/[locale]/time-and-activity/page.tsx (1 hunks)

Walkthrough

This pull request introduces several new UI components for the time and activity section of the web application. It adds interactive features such as view selection with checkboxes, a date range picker with a calendar and predefined ranges, grouping options for activity data, and statistical cards with progress indicators. Additionally, the routing for the “TIME AND ACTIVITY” sidebar item has been updated, and type definitions have been extended for more granular reporting. These changes are organized and exported via an index file to streamline modular usage.

Changes

File(s) Change Summary
apps/web/app/[locale]/time-and-activity/Components/ViewSelect.tsx
apps/web/app/[locale]/time-and-activity/Components/GroupBySelectTimeActivity.tsx
apps/web/app/[locale]/time-and-activity/Components/date-range-picker-time-activity.tsx
apps/web/app/[locale]/time-and-activity/Components/card-time-and-activity.tsx
apps/web/app/[locale]/time-and-activity/Components/progress-bar.tsx
Added new UI components: a view selection dropdown with checkboxes, a date range picker with calendar and predefined ranges, a grouping selector, a statistics card (with progress bar) for displaying activity data, and a progress bar component with loading state.
apps/web/app/[locale]/time-and-activity/Components/time-activity-header.tsx
apps/web/app/[locale]/time-and-activity/Components/page-component.tsx
apps/web/app/[locale]/time-and-activity/page.tsx
apps/web/app/[locale]/time-and-activity/Components/index.tsx
Introduced page-level components to compose the time and activity dashboard by integrating the new UI components, organizing layout (header, back navigation, main content) and consolidating exports for ease of import.
apps/web/app/hooks/features/useReportActivity.ts Expanded the GroupByType type definition by adding 'daily', 'weekly', and 'member' for more granular grouping in report functionality.
apps/web/components/app-sidebar.tsx Refactored CSS class ordering for the project icon and updated the sidebar URL for “TIME AND ACTIVITY” from a placeholder ('#') to a functional route ('/time-and-activity').

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant ViewSelect
    participant State
    User->>ViewSelect: Click "View" button
    ViewSelect->>ViewSelect: Open dropdown menu
    User->>ViewSelect: Toggle a checkbox option
    ViewSelect->>State: Update viewOptions state
    ViewSelect-->>User: Rerender with updated options
Loading
sequenceDiagram
    participant User
    participant DateRangePicker
    participant CalendarPopover
    participant State
    User->>DateRangePicker: Click date picker button
    DateRangePicker->>CalendarPopover: Display calendar with predefined ranges
    User->>CalendarPopover: Select desired date range
    DateRangePicker->>State: Update selected date range and displayed month
    DateRangePicker-->>User: Show formatted date range
Loading

Possibly related PRs

Suggested labels

feature, WEB, Improvement, Ever Teams

Suggested reviewers

  • evereq

Poem

I'm a hopping rabbit in code's delight,
With dropdown views shining ever so bright.
Date pickers bloom like flowers fair,
Grouping options dance in the air.
Carrots and code unite in a joyful array,
Hopping through commits—hip hip hooray! 🐰


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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate unit testing code.
    • @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.

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

@Innocent-Akim Innocent-Akim marked this pull request as draft March 5, 2025 16:49
@Innocent-Akim Innocent-Akim changed the title [Feat]: time activity tracking [Feat]: time and activity Mar 5, 2025
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 (1)
apps/web/app/hooks/features/useReportActivity.ts (1)

268-269: 💡 Verification agent

🧩 Analysis chain

Update the conditional check to include new GroupByType values

The handleGroupByChange function only handles the 'application' special case, but with the new types added ('daily', 'weekly', 'member'), you may need to update this logic to ensure proper handling of all types.


🏁 Script executed:

#!/bin/bash
# Check where handleGroupByChange is called to understand the impact of new types

# Search for usages of handleGroupByChange
rg -A 2 "handleGroupByChange" --type tsx --type ts

# Search for places using GroupByType to see if they handle all cases
rg -A 5 "GroupByType" --type tsx --type ts

Length of output: 149


I'll re-run the verification search using file pattern filters instead of file type flags to gather more meaningful output. Please execute the script below:

Once we have the updated results, we can assess whether the new GroupByType values ('daily', 'weekly', 'member') are being handled correctly, or if the conditional needs to be updated further.


🏁 Script executed:

#!/bin/bash
# Re-run search for references to 'handleGroupByChange' and 'GroupByType' using glob patterns for .ts and .tsx files

echo "Searching for references to handleGroupByChange:"
rg "handleGroupByChange" -g "*.ts" -g "*.tsx"

echo "---"

echo "Searching for references to GroupByType:"
rg "GroupByType" -g "*.ts" -g "*.tsx"

Length of output: 2583


Action Required: Update mapping logic for new GroupByType values

The current implementation only remaps 'application' to 'date' and passes through all other values unchanged. Since the enum now also includes 'daily', 'weekly', and 'member', you should update the conditional logic to handle these cases appropriately. For example, if 'daily' should also map to 'date', or if 'weekly' and 'member' require their own specific mappings (possibly to 'week' or 'employee'), refactor this section—potentially using a switch or mapping object—to cover all valid types.

  • Location: apps/web/app/hooks/features/useReportActivity.ts (lines 268–269)
  • Suggestion: Replace the existing ternary with logic that explicitly maps each GroupByType value to the intended group value before calling fetchActivityReport.
🧹 Nitpick comments (11)
apps/web/app/[locale]/time-and-activity/page.tsx (1)

1-8: Consider renaming the component for better clarity and to resolve spelling issues

The component name "TimectivityComponents" is flagged as an unknown word by the static analysis tools. This appears to be a portmanteau of "Time" and "Activity", but may cause confusion for other developers.

-import TimectivityComponents from './Components/page-component'
+import TimeActivityComponents from './Components/page-component'

function TimeAndActivity() {
-  return (<TimectivityComponents/> )
+  return (<TimeActivityComponents />)
}

export default TimeAndActivity

Additionally, you'll need to update the component name in the page-component.tsx file.

🧰 Tools
🪛 GitHub Check: Cspell

[warning] 2-2:
Unknown word (Timectivity)


[warning] 5-5:
Unknown word (Timectivity)

🪛 GitHub Actions: Check Spelling and Typos with cspell

[warning] 2-2: Unknown word (Timectivity)


[warning] 5-5: Unknown word (Timectivity)

apps/web/app/hooks/features/useReportActivity.ts (1)

70-70: Improve type definition formatting for better readability

The GroupByType type definition has been expanded with new options but lacks consistent spacing between options.

-export type GroupByType = 'date' | 'project' | 'employee' | 'application'|'daily'|'weekly'|'member';
+export type GroupByType = 'date' | 'project' | 'employee' | 'application' | 'daily' | 'weekly' | 'member';
apps/web/app/[locale]/time-and-activity/Components/GroupBySelect.tsx (2)

13-13: Consider using controlled component pattern for better state management

The component uses defaultValue which won't react to changes in the groupByType prop after initial render. For a more reactive component, consider using value instead of defaultValue.

-        <Select defaultValue={groupByType} onValueChange={onGroupByChange}>
+        <Select value={groupByType} onValueChange={onGroupByChange}>

This change ensures the component will always reflect the current value from props.


6-9: Enhance prop interface with default values

The component accepts groupByType but doesn't specify a default value when not provided. Consider adding a default value to avoid undefined behavior.

interface GroupBySelectProps {
    onGroupByChange?: (value: GroupByType) => void;
-    groupByType?: GroupByType;
+    groupByType?: GroupByType;
}

-export function GroupBySelectTimeActivity({ onGroupByChange, groupByType }: GroupBySelectProps) {
+export function GroupBySelectTimeActivity({ 
+    onGroupByChange, 
+    groupByType = 'daily' 
+}: GroupBySelectProps) {
apps/web/app/[locale]/time-and-activity/Components/page-component.tsx (2)

27-27: Use translation for consistency with other breadcrumb items

The first breadcrumb title uses translations, but the "Time and Activity" title is hardcoded. For internationalization consistency, consider using the translation function for all UI text.

-			{ title: 'Time and Activity', href: `/${currentLocale}/time-and-activity` }
+			{ title: JSON.parse(t('pages.timeActivity.BREADCRUMB')), href: `/${currentLocale}/time-and-activity` }

Make sure to add the corresponding translation key to your localization files.


54-56: Missing implementation of time activity UI controls

The header area inside the Card (with h-[105px] height) is empty. This appears to be where the time period selector and grouping controls should be placed.

It appears that there's a missing implementation of the UI controls for time activity tracking. Would you like me to provide a suggestion for implementing this section using the GroupBySelectTimeActivity component and other necessary controls?

apps/web/app/[locale]/time-and-activity/Components/ViewSelect.tsx (3)

1-79: Component implementation looks good but could benefit from internationalization improvements.

The ViewSelect component is well-structured with proper state management, but the hardcoded English labels should use translations for consistency.

You're already importing the translation hook but not using it for the labels. Consider updating the labels to use translations:

-    { id: 'member', label: 'Member', checked: true },
-    { id: 'project', label: 'Project', checked: true },
-    { id: 'task', label: 'Task', checked: true },
-    { id: 'trackedHours', label: 'Tracked Hours', checked: true },
-    { id: 'earnings', label: 'Earnings', checked: true },
-    { id: 'activityLevel', label: 'Activity Level', checked: true },
+    { id: 'member', label: t('timeActivity.MEMBER'), checked: true },
+    { id: 'project', label: t('timeActivity.PROJECT'), checked: true },
+    { id: 'task', label: t('timeActivity.TASK'), checked: true },
+    { id: 'trackedHours', label: t('timeActivity.TRACKED_HOURS'), checked: true },
+    { id: 'earnings', label: t('timeActivity.EARNINGS'), checked: true },
+    { id: 'activityLevel', label: t('timeActivity.ACTIVITY_LEVEL'), checked: true },

Also on line 57, replace:

-          View
+          {t('timeActivity.VIEW')}

36-78: Consider adding props to make the component more reusable.

The component doesn't expose any way to control or read the selected view options from outside, limiting its reusability.

Consider adding props to make the component more flexible:

+ interface ViewSelectProps {
+   defaultOptions?: ViewOption[];
+   onChange?: (options: ViewOption[]) => void;
+ }
+ 
- export default function ViewSelect() {
+ export default function ViewSelect({ defaultOptions, onChange }: ViewSelectProps = {}) {
  const t = useTranslations();
-  const [viewOptions, setViewOptions] = React.useState<ViewOption[]>([
+  const defaultViewOptions = [
    { id: 'member', label: 'Member', checked: true },
    { id: 'project', label: 'Project', checked: true },
    { id: 'task', label: 'Task', checked: true },
    { id: 'trackedHours', label: 'Tracked Hours', checked: true },
    { id: 'earnings', label: 'Earnings', checked: true },
    { id: 'activityLevel', label: 'Activity Level', checked: true },
-  ]);
+  ];
+  const [viewOptions, setViewOptions] = React.useState<ViewOption[]>(defaultOptions || defaultViewOptions);

  const handleCheckChange = (id: string) => {
-    setViewOptions(prev =>
-      prev.map(option =>
+    setViewOptions(prev => {
+      const newOptions = prev.map(option =>
        option.id === id ? { ...option, checked: !option.checked } : option
-      )
-    );
+      );
+      onChange?.(newOptions);
+      return newOptions;
+    });
  };

41-57: Extract SVG icon to a separate component.

Consider extracting the SVG icon into a separate component for better maintainability and reusability.

+// In a separate file or at the top of this file
+const ViewIcon = ({ className }: { className?: string }) => (
+  <svg
+    width="24"
+    height="24"
+    viewBox="0 0 24 24"
+    fill="none"
+    xmlns="http://www.w3.org/2000/svg"
+    className={className}
+  >
+    <path
+      d="M4 5C4 4.44772 4.44772 4 5 4H19C19.5523 4 20 4.44772 20 5V7C20 7.55228 19.5523 8 19 8H5C4.44772 8 4 7.55228 4 7V5Z"
+      className="fill-current"
+    />
+    <path
+      d="M4 13C4 12.4477 4.44772 12 5 12H19C19.5523 12 20 12.4477 20 13V15C20 15.5523 19.5523 16 19 16H5C4.44772 16 4 15.5523 4 15V13Z"
+      className="fill-current"
+    />
+  </svg>
+);

// Then in your Button:
<Button variant="outline" className="gap-2">
-  <svg
-    width="24"
-    height="24"
-    viewBox="0 0 24 24"
-    fill="none"
-    xmlns="http://www.w3.org/2000/svg"
-    className="w-4 h-4"
-  >
-    <path
-      d="M4 5C4 4.44772 4.44772 4 5 4H19C19.5523 4 20 4.44772 20 5V7C20 7.55228 19.5523 8 19 8H5C4.44772 8 4 7.55228 4 7V5Z"
-      className="fill-current"
-    />
-    <path
-      d="M4 13C4 12.4477 4.44772 12 5 12H19C19.5523 12 20 12.4477 20 13V15C20 15.5523 19.5523 16 19 16H5C4.44772 16 4 15.5523 4 15V13Z"
-      className="fill-current"
-    />
-  </svg>
+  <ViewIcon className="w-4 h-4" />
  View
</Button>
apps/web/app/[locale]/time-and-activity/Components/date-range-picker-time-activity.tsx (2)

3-31: Inconsistent indentation style.

The file uses a mix of tabs and spaces for indentation, which can lead to formatting inconsistencies.

Consider standardizing on a single indentation style throughout the file (either tabs or spaces, but not both).
For example, lines 8-25 use tabs, while other parts of the file might be using spaces.


109-111: Multiple stopPropagation calls may indicate underlying event handling issues.

The component uses three separate event stopPropagation calls which might indicate an underlying issue with event bubbling.

A single event handler could likely handle all three cases:

-				onClick={(e) => e.stopPropagation()}
-				onMouseDown={(e) => e.stopPropagation()}
-				onChange={(e) => e.stopPropagation()}
+				onClick={(e) => e.stopPropagation()}
+				onMouseDown={(e) => e.stopPropagation()}

The onChange event on a div is unusual and likely unnecessary since divs don't typically have change events.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 9c03763 and 60b24df.

📒 Files selected for processing (8)
  • apps/web/app/[locale]/time-and-activity/Components/GroupBySelect.tsx (1 hunks)
  • apps/web/app/[locale]/time-and-activity/Components/ViewSelect.tsx (1 hunks)
  • apps/web/app/[locale]/time-and-activity/Components/date-range-picker-time-activity.tsx (1 hunks)
  • apps/web/app/[locale]/time-and-activity/Components/page-component.tsx (1 hunks)
  • apps/web/app/[locale]/time-and-activity/Components/time-activity-header.tsx (1 hunks)
  • apps/web/app/[locale]/time-and-activity/page.tsx (1 hunks)
  • apps/web/app/hooks/features/useReportActivity.ts (1 hunks)
  • apps/web/components/app-sidebar.tsx (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • apps/web/app/[locale]/time-and-activity/Components/time-activity-header.tsx
🧰 Additional context used
🧠 Learnings (1)
apps/web/app/[locale]/time-and-activity/Components/GroupBySelect.tsx (1)
Learnt from: CREDO23
PR: ever-co/ever-teams#3392
File: apps/web/app/[locale]/reports/weekly-limit/components/group-by-select.tsx:42-51
Timestamp: 2024-12-05T09:04:08.049Z
Learning: In the `GroupBySelect` component (`apps/web/app/[locale]/reports/weekly-limit/components/group-by-select.tsx`), only one option can be selected at a time; two options cannot be selected simultaneously.
🪛 GitHub Check: Cspell
apps/web/app/[locale]/time-and-activity/Components/page-component.tsx

[warning] 16-16:
Unknown word (Timectivity)


[warning] 70-70:
Unknown word (Timectivity)

apps/web/app/[locale]/time-and-activity/page.tsx

[warning] 2-2:
Unknown word (Timectivity)


[warning] 5-5:
Unknown word (Timectivity)

🪛 GitHub Actions: Check Spelling and Typos with cspell
apps/web/app/[locale]/time-and-activity/Components/page-component.tsx

[warning] 16-16: Unknown word (Timectivity)


[warning] 70-70: Unknown word (Timectivity)

apps/web/app/[locale]/time-and-activity/page.tsx

[warning] 2-2: Unknown word (Timectivity)


[warning] 5-5: Unknown word (Timectivity)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: deploy
🔇 Additional comments (5)
apps/web/app/[locale]/time-and-activity/Components/GroupBySelect.tsx (1)

21-24:

❓ Verification inconclusive

Ensure consistency with GroupByType values

While you've added "daily", "weekly", and "member" to the GroupByType in useReportActivity.ts, the select includes "project" but not other original values like "date", "employee", and "application". Ensure the options here align with the intended available values.


🏁 Script executed:

#!/bin/bash
# Check other GroupBySelect components for consistency in approach

# Search for other GroupBySelect components
fd -e tsx -e ts "GroupBySelect" --exec grep -l "SelectItem" {} \;

# Check how GroupByType values are used elsewhere
rg "'date' | 'project' | 'employee' | 'application'" --type tsx --type ts -A 2 -B 2

Length of output: 346


Ensure consistency between GroupBySelect options and GroupByType values
The GroupBySelect component in apps/web/app/[locale]/time-and-activity/Components/GroupBySelect.tsx still includes the "project" option—even though the updated GroupByType in useReportActivity.ts now only includes "daily", "weekly", and "member". Additionally, previous options such as "date", "employee", and "application" have been removed. Please verify that the options presented in the select element exactly match the intended values defined in GroupByType and update one or the other accordingly.

  • Check the definition of GroupByType in useReportActivity.ts to confirm which values should be supported.
  • Adjust the dropdown options in GroupBySelect.tsx to mirror those values or update the type if "project" is intended to be included.
apps/web/app/[locale]/time-and-activity/Components/page-component.tsx (1)

52-60:

❓ Verification inconclusive

Implement content within the card component

The Card component contains empty div containers. The implementation appears incomplete as there's no actual content displayed for time activity tracking.

I notice the Card has nested div containers but no actual content is rendered. This component structure seems incomplete:


🏁 Script executed:

#!/bin/bash
# Check if there are other components that should be imported here
# Look for possible components related to time and activity

# Search for components in the same directory
fd -e tsx -p "time-and-activity/Components" --exec grep -l "export" {} \;

# Look for GroupBySelectTimeActivity usage
rg "GroupBySelectTimeActivity" --type tsx

Length of output: 522


Attention: Incomplete Card Content Implementation

  • The Card component in apps/web/app/[locale]/time-and-activity/Components/page-component.tsx (lines 52-60) still contains empty container elements.
  • It is unclear whether these divs are simply placeholders or if they should host interactive components—for instance, one of the components available in this directory (such as GroupBySelect.tsx, ViewSelect.tsx, date-range-picker-time-activity.tsx, or time-activity-header.tsx) to provide time activity tracking functionality.
  • Please verify whether the missing content should involve integrating one or more of these components. If so, update the implementation accordingly; otherwise, remove the unnecessary markup.
apps/web/components/app-sidebar.tsx (2)

225-225: Reordering CSS classes maintains identical styling.

The CSS classes have been reordered but maintain the same styling and functionality. This change is harmless but doesn't provide any functional improvement.


312-312: Updated URL for time and activity navigation.

Good update replacing the placeholder '#' with the actual route '/time-and-activity', enabling proper navigation to the new time and activity feature.

apps/web/app/[locale]/time-and-activity/Components/date-range-picker-time-activity.tsx (1)

129-129:

✅ Verification successful

Calendar disable logic restricts future dates.

The calendar component disables future dates, which is appropriate for time tracking and reporting but should be documented.


🌐 Web query:

Is it a common practice to disable future dates in time tracking applications?

💡 Result:

Disabling future dates in time tracking applications is a practice implemented in some systems, though its prevalence depends on the specific tool and use case. Here’s a breakdown of how this feature is approached across platforms:

Common Use Cases for Disabling Future Dates

  • Preventing Inaccurate Entries: Some platforms, like monday.com, restrict future date selections in time tracking columns to avoid premature or speculative logging, ensuring entries reflect actual work hours[4].
  • Compliance and Accuracy: Apps like Clockify allow administrators to lock past timesheets but explicitly cannot lock future dates, highlighting a focus on historical accuracy rather than restricting future planning[5].
  • Form Validation: In form-building tools like Caspio, disabling future dates in calendars ensures users select valid dates (e.g., preventing return dates earlier than departure dates)[1].

Platform-Specific Implementations

  1. monday.com: Users have requested future date enablement for tracking planned leave, indicating that the platform currently disables future dates by default in time tracking columns[4].
  2. Clockify: While past dates can be locked to prevent edits, future dates remain editable, reflecting a balance between accountability and flexibility[5].
  3. Pega Systems: Developers can disable future dates in DateTime controls via configuration settings, catering to specific business rules[9].

Workarounds and Limitations

  • Manual Enforcement: Some tools lack built-in future date restrictions, requiring organizations to enforce policies manually (e.g., rejecting future entries during approvals)[5].
  • Technical Customization: Platforms like Caspio and Pega allow custom JavaScript or settings adjustments to disable future dates, but this often requires technical expertise[1][9].

User Needs and Trends

  • Employee Autonomy vs. Control: While disabling future dates can reduce errors, overly restrictive systems may hinder flexibility for remote or gig workers[8].
  • Emerging Features: Predictive analytics and blockchain-backed timestamping are evolving to enhance accuracy without rigid date restrictions[8].

Key Takeaway

Disabling future dates is common in applications prioritizing data integrity (e.g., project management or compliance tools) but less so in flexible workforce platforms. Organizations often balance this feature with user needs, leveraging technical configurations or policy enforcement where native options are limited[4][5][9].

Citations:


Calendar disable logic for future dates is correctly implemented.

The current logic on line 129 in apps/web/app/[locale]/time-and-activity/Components/date-range-picker-time-activity.tsx uses a standard approach to disable future dates (i.e., dates equal to or after the start of today). As confirmed by our research, restricting future date selection is a common pattern in time tracking applications to prevent premature or inaccurate time entries. While the implementation is correct, it is recommended to add an inline comment explaining this design choice for improved clarity and maintainability.

- Update ViewSelect component with custom checkbox style and hover effects
- Integrate TimeActivityHeader with export options
- Add GroupBySelectTimeActivity component
- Update page layout and component organization
- Remove unused GroupBySelect component
- Create reusable CardTimeandActivity component with TypeScript support
- Add three statistics cards for Total Hours, Average Activity, and Total Earnings
- Implement progress bar functionality for activity metrics
- Fix code formatting and improve component organization
- Create new reusable ProgressBar component
- Update CardTimeandActivity to use the new ProgressBar
- Add TypeScript interfaces for better type safety
- Improve component modularity and reusability
- Set exact height and colors for progress bar
- Update background color to #E4E4E7
- Set progress color to #0088CC
- Refine progress bar container styles
@Innocent-Akim Innocent-Akim marked this pull request as ready for review March 5, 2025 23:18
- Move weekOptions object into useMemo hook to maintain stable reference
- Prevent unnecessary re-renders in predefinedRanges useMemo
- Fix React performance warning about object literals in dependencies
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: 5

🧹 Nitpick comments (11)
apps/web/app/[locale]/time-and-activity/Components/time-activity-header.tsx (2)

6-31: Remove commented code and implement missing functionality.

The component looks well-structured, but there's a commented-out line referring to TeamDashboardFilter with an undefined isManage prop. Also, the Export dropdown doesn't have any functionality implemented - there's no handler for selection changes.

-        {/* <TeamDashboardFilter isManage={isManage} /> */}

For the export functionality, consider adding an event handler:

-            <Select defaultValue="export">
+            <Select defaultValue="export" onValueChange={(value) => handleExport(value)}>

And add the handler function above the return statement:

const handleExport = (format: string) => {
  // Implement export functionality based on format
  console.log(`Exporting in ${format} format`);
};

6-6: Add TypeScript type annotation for the component.

The component should have a TypeScript interface or type definition to improve type safety and documentation.

-function TimeActivityHeader() {
+interface TimeActivityHeaderProps {
+  // Add any props the component might need in the future
+}
+
+function TimeActivityHeader({}: TimeActivityHeaderProps) {
apps/web/app/[locale]/time-and-activity/Components/progress-bar.tsx (2)

9-26: Implement progress value validation.

While the component works correctly, there's no validation to ensure the progress value stays within the expected 0-100% range. This could lead to visual bugs if an invalid value is passed.

const ProgressBar: React.FC<ProgressBarProps> = ({
  progress,
  color = 'bg-[#0088CC]',
  isLoading = false,
}) => {
+  // Ensure progress is between 0 and 100
+  const validProgress = isLoading ? 0 : Math.min(Math.max(progress, 0), 100);
+
  return (
    <div className="mt-4">
      <div className="w-full h-1 bg-[#E4E4E7] dark:bg-gray-700 rounded-full overflow-hidden">
        <div
          className={`h-full transition-all duration-300 ${color}`}
          style={{
-            width: `${isLoading ? 0 : progress}%`,
+            width: `${validProgress}%`,
          }}
        />
      </div>
    </div>
  );
};

16-23: Consider adding an accessible ARIA attribute for screen readers.

For better accessibility, adding an ARIA role and label to the progress bar would be beneficial.

<div className="w-full h-1 bg-[#E4E4E7] dark:bg-gray-700 rounded-full overflow-hidden">
  <div
+    role="progressbar"
+    aria-valuenow={isLoading ? 0 : progress}
+    aria-valuemin={0}
+    aria-valuemax={100}
    className={`h-full transition-all duration-300 ${color}`}
    style={{
      width: `${isLoading ? 0 : progress}%`,
    }}
  />
</div>
apps/web/app/[locale]/time-and-activity/Components/card-time-and-activity.tsx (1)

27-33: Consider adding value formatting.

The component accepts both string and number values but doesn't apply any formatting. This could lead to inconsistent display, especially for numerical values.

<span className="text-[32px] leading-[38px] font-semibold text-gray-900 dark:text-white">
-  {value}
+  {typeof value === 'number' ? value.toLocaleString() : value}
</span>

This would ensure numbers are formatted with appropriate thousands separators according to the user's locale.

apps/web/app/[locale]/time-and-activity/Components/GroupBySelectTimeActivity.tsx (2)

13-13: Set a default value to prevent undefined selection.

The component doesn't specify a default value if groupByType is not provided. This could lead to an undefined selection initially.

-<Select defaultValue={groupByType} onValueChange={onGroupByChange}>
+<Select defaultValue={groupByType || "daily"} onValueChange={onGroupByChange}>

17-17: Review placeholder text and default value consistency.

The SelectValue component has a placeholder "Date" which doesn't align with any of the actual values in the dropdown (daily, weekly, etc.). This might confuse users if they see "Date" without making a selection.

-<SelectValue placeholder="Date" className="text-blue-600 dark:text-blue-500" />
+<SelectValue placeholder="Select grouping" className="text-blue-600 dark:text-blue-500" />
apps/web/app/[locale]/time-and-activity/Components/page-component.tsx (2)

28-28: Use translation for consistency.

The breadcrumb title "Time and Activity" should use the translation system for consistency with other translated content.

-{ title: 'Time and Activity', href: `/${currentLocale}/time-and-activity` }
+{ title: JSON.parse(t('pages.timeAndActivity.BREADCRUMB')), href: `/${currentLocale}/time-and-activity` }

37-39: Remove unnecessary ! operator in className.

Using the !important flag (via the ! prefix in Tailwind) should generally be avoided as it can lead to CSS specificity issues.

-className="items-start pb-1 !overflow-hidden w-full"
+className="items-start pb-1 overflow-hidden w-full"
apps/web/app/[locale]/time-and-activity/Components/ViewSelect.tsx (2)

34-56: Improve accessibility and add visual indication of selection state.

The current implementation lacks proper accessibility attributes and doesn't show how many options are selected.

  return (
    <DropdownMenu>
      <DropdownMenuTrigger asChild>
-        <Button variant="outline" className="gap-2">
+        <Button variant="outline" className="gap-2" aria-label="Select view options">
          <svg
            width="24"
            height="24"
            viewBox="0 0 24 24"
            fill="none"
            xmlns="http://www.w3.org/2000/svg"
            className="w-4 h-4"
+            aria-hidden="true"
          >
            <path
              d="M4 5C4 4.44772 4.44772 4 5 4H19C19.5523 4 20 4.44772 20 5V7C20 7.55228 19.5523 8 19 8H5C4.44772 8 4 7.55228 4 7V5Z"
              className="fill-current"
            />
            <path
              d="M4 13C4 12.4477 4.44772 12 5 12H19C19.5523 12 20 12.4477 20 13V15C20 15.5523 19.5523 16 19 16H5C4.44772 16 4 15.5523 4 15V13Z"
              className="fill-current"
            />
          </svg>
-          View
+          View ({viewOptions.filter(opt => opt.checked).length}/{viewOptions.length})
        </Button>
      </DropdownMenuTrigger>

58-71: Add "Select All" and "Clear All" functionality.

Providing options to select or clear all checkboxes at once improves user experience.

    <DropdownMenuContent className="p-2 w-56">
+      <div className="flex justify-between mb-2 pb-2 border-b">
+        <button
+          className="text-xs text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300"
+          onClick={() => {
+            const allSelected = viewOptions.map(opt => ({ ...opt, checked: true }));
+            setViewOptions(allSelected);
+            if (onViewOptionsChange) onViewOptionsChange(allSelected);
+          }}
+        >
+          Select All
+        </button>
+        <button
+          className="text-xs text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300"
+          onClick={() => {
+            const noneSelected = viewOptions.map(opt => ({ ...opt, checked: false }));
+            setViewOptions(noneSelected);
+            if (onViewOptionsChange) onViewOptionsChange(noneSelected);
+          }}
+        >
+          Clear All
+        </button>
+      </div>
      {viewOptions.map((option) => (
        // ... existing code
      ))}
    </DropdownMenuContent>
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 60b24df and 891d1e8.

📒 Files selected for processing (7)
  • apps/web/app/[locale]/time-and-activity/Components/GroupBySelectTimeActivity.tsx (1 hunks)
  • apps/web/app/[locale]/time-and-activity/Components/ViewSelect.tsx (1 hunks)
  • apps/web/app/[locale]/time-and-activity/Components/card-time-and-activity.tsx (1 hunks)
  • apps/web/app/[locale]/time-and-activity/Components/index.tsx (1 hunks)
  • apps/web/app/[locale]/time-and-activity/Components/page-component.tsx (1 hunks)
  • apps/web/app/[locale]/time-and-activity/Components/progress-bar.tsx (1 hunks)
  • apps/web/app/[locale]/time-and-activity/Components/time-activity-header.tsx (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • apps/web/app/[locale]/time-and-activity/Components/index.tsx
🧰 Additional context used
🪛 GitHub Check: Cspell
apps/web/app/[locale]/time-and-activity/Components/card-time-and-activity.tsx

[warning] 14-14:
Unknown word (Timeand)


[warning] 47-47:
Unknown word (Timeand)

apps/web/app/[locale]/time-and-activity/Components/page-component.tsx

[warning] 15-15:
Unknown word (Timeand)


[warning] 17-17:
Unknown word (Timectivity)


[warning] 55-55:
Unknown word (Timeand)


[warning] 60-60:
Unknown word (Timeand)


[warning] 68-68:
Unknown word (Timeand)


[warning] 82-82:
Unknown word (Timectivity)

🪛 GitHub Actions: Check Spelling and Typos with cspell
apps/web/app/[locale]/time-and-activity/Components/card-time-and-activity.tsx

[warning] 14-14: Unknown word (Timeand)


[warning] 47-47: Unknown word (Timeand)

apps/web/app/[locale]/time-and-activity/Components/page-component.tsx

[warning] 15-15: Unknown word (Timeand)


[warning] 17-17: Unknown word (Timectivity)


[warning] 55-55: Unknown word (Timeand)


[warning] 60-60: Unknown word (Timeand)


[warning] 68-68: Unknown word (Timeand)


[warning] 82-82: Unknown word (Timectivity)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: deploy
🔇 Additional comments (9)
apps/web/app/[locale]/time-and-activity/Components/time-activity-header.tsx (1)

1-5: Imports are correctly organized and relevant.

The component imports all necessary UI components and related custom components for the time activity header.

apps/web/app/[locale]/time-and-activity/Components/progress-bar.tsx (1)

3-7: Props interface correctly defines component parameters.

The interface clearly defines the expected props with appropriate types.

apps/web/app/[locale]/time-and-activity/Components/card-time-and-activity.tsx (1)

5-12: The props interface is well-defined and includes all necessary properties.

The StatisticCardProps interface properly defines all the required and optional properties with appropriate types.

apps/web/app/[locale]/time-and-activity/Components/GroupBySelectTimeActivity.tsx (3)

6-9: Props interface is well-defined with optional callbacks.

The interface correctly defines optional props with appropriate types.


1-2: The 'use client' directive is correctly placed.

The 'use client' directive is necessary for client-side interactivity and is correctly placed at the top of the file.


21-24:

✅ Verification successful

Verify the data attribute for styling selected items.

The className for SelectItems uses data-[state=checked]:text-blue-600, but for SelectItem components, the state is typically "selected", not "checked". Verify that this styling works as intended.


🏁 Script executed:

#!/bin/bash
# Look for references to SelectItem with data-[state=...] to verify correct attribute
rg -A 2 -B 2 "data-\[state=" --glob "*.tsx" | grep -i "select"

Length of output: 3782


Attribute Check: Confirmed Usage of data-[state=checked] is Intentional

After reviewing similar implementations in the codebase, we found that the SelectItem components consistently use data-[state=checked]:text-blue-600 (e.g., in both apps/web/app/[locale]/dashboard/app-url/components/GroupBySelect.tsx and apps/web/app/[locale]/time-and-activity/Components/GroupBySelectTimeActivity.tsx). This indicates that the use of the "checked" state is intentional in our implementation rather than an oversight.

No changes are needed here, but please ensure that any UI tests validate that the styling applies correctly under the expected interactive states.

apps/web/app/[locale]/time-and-activity/Components/page-component.tsx (3)

17-17: Rename component for consistency and to fix spelling issue.

The component name "TimectivityComponents" appears to be a spelling error. It's flagged by cspell checks and doesn't follow conventional naming patterns.

-const TimectivityComponents = () => {
+const TimeActivityComponents = () => {
🧰 Tools
🪛 GitHub Check: Cspell

[warning] 17-17:
Unknown word (Timectivity)

🪛 GitHub Actions: Check Spelling and Typos with cspell

[warning] 17-17: Unknown word (Timectivity)


78-78: Missing children in MainLayout component.

The MainLayout component is closed immediately without any children elements. If this is intentional, consider adding a comment explaining why, otherwise add the expected children.

-</MainLayout>
+</MainLayout>
+{/* TODO: Add main content here */}

82-82: Update component name in withAuthentication wrapper.

Update the component name in the withAuthentication wrapper to match your component name.

-export default withAuthentication(TimectivityComponents, { displayName: 'Time and Activity' });
+export default withAuthentication(TimeActivityComponents, { displayName: 'Time and Activity' });
🧰 Tools
🪛 GitHub Check: Cspell

[warning] 82-82:
Unknown word (Timectivity)

🪛 GitHub Actions: Check Spelling and Typos with cspell

[warning] 82-82: Unknown word (Timectivity)

- Rename CardTimeandActivity to CardTimeAndActivity
- Rename TimectivityComponents to TimeActivityComponents
- Fix camelCase naming in imports and usage
- Rename TimectivityComponents import to TimeActivityComponents
- Update component usage to match new name
@Innocent-Akim Innocent-Akim requested a review from evereq March 5, 2025 23:41
@evereq evereq merged commit 07e02cf into develop Mar 6, 2025
13 checks passed
@evereq evereq deleted the feat/time-activity-tracking branch March 6, 2025 07:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants