Skip to content
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

[Feat]: Add Delete Task Timesheet function #3338

Merged
merged 6 commits into from
Nov 17, 2024
Merged

Conversation

Innocent-Akim
Copy link
Contributor

@Innocent-Akim Innocent-Akim commented Nov 14, 2024

Description

#3045
Please include a summary of the changes and the related issue.

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 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 previous status

Current screenshots

Please add here videos or images of previous status

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced bulk deletion functionality for task timesheets via a new API endpoint.
    • Added a new hook for managing timesheet log deletions, including loading states.
    • Implemented a new API function for deleting specific timesheet logs based on IDs.
    • Added state management for deleted timesheets within the application.
    • Introduced a confirmation dialog component for user actions.
    • Enhanced task management with improved filtering options and user interface updates.
  • Bug Fixes

    • Enhanced error handling for deletion requests to ensure proper user feedback.

Copy link
Contributor

coderabbitai bot commented Nov 14, 2024

Walkthrough

The changes introduce a new asynchronous DELETE endpoint for bulk deletion of task timesheets, alongside a new API function for deleting timesheet logs. The useTimesheet hook is updated to manage the deletion process, incorporating a loading state and a callback function. Additionally, a new type and function for handling deletion requests are added, and a state atom for tracking deleted timesheets is introduced. These modifications enhance the functionality related to managing timesheet logs and their deletion.

Changes

File Path Change Summary
apps/web/app/api/timer/timesheet/bulk-delete/route.ts Added asynchronous DELETE endpoint for bulk deletion of task timesheets; utilizes authenticatedGuard and deleteTaskTimesheetRequest.
apps/web/app/hooks/features/useTimesheet.ts Introduced deleteTaskTimesheetLogsApi function; updated useTimesheet hook to manage deletion state and callback.
apps/web/app/services/client/api/timer/timer-log.ts Added deleteTaskTimesheetLogsApi function for deleting timesheet logs; modified import statement to include deleteApi.
apps/web/app/services/server/requests/timesheet.ts Introduced IDeleteTimesheetProps type and deleteTaskTimesheetRequest function for handling deletion requests.
apps/web/app/stores/time-logs.ts Added new atom timesheetDeleteState for managing deleted timesheets state.
apps/web/app/[locale]/timesheet/[memberId]/components/TimesheetAction.tsx Added StatusAction type for button actions; updated button configurations to reflect new status actions.
apps/web/app/hooks/features/useTimelogFilterOptions.ts Updated to manage timesheetDeleteState and added selection handling for timesheet items.
apps/web/components/ui/alert-dialog.tsx Introduced a new alert dialog component using Radix UI for confirmation actions.
apps/web/lib/components/alert-dialog-confirmation.tsx Added AlertDialogConfirmation component for handling confirmation dialogs with customizable actions.
apps/web/lib/components/index.ts Exported AlertDialogConfirmation component for broader access.
apps/web/lib/features/integrations/calendar/table-time-sheet.tsx Updated to manage task deletions and integrate confirmation dialogs within the DataTableTimeSheet component.
apps/web/lib/features/user-profile-plans.tsx Enhanced filtering options and layout adjustments for managing user profile plans.
apps/web/package.json Added @radix-ui/react-alert-dialog dependency; reorganized existing dependencies.

Possibly related PRs

Suggested labels

feature, WEB, Ever Teams

Suggested reviewers

  • evereq
  • Cedric921

Poem

🐇 In the meadow, where timesheets lay,
A new path opens, bright as day.
With logs to delete, and states to track,
Our bunny team hops, never looking back!
So gather 'round, let’s cheer and play,
For the timesheet magic is here to stay! 🌼

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.

apps/web/app/hooks/features/useTimelogFilterOptions.ts

Oops! Something went wrong! :(

ESLint: 8.46.0

ESLint couldn't find the config "next/core-web-vitals" to extend from. Please check that the name of the config is correct.

The config "next/core-web-vitals" was referenced from the config file in "/apps/web/.eslintrc.json".

If you still have problems, please stop by https://eslint.org/chat/help to chat with the team.


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ 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 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 added the Don't Merge Do not merge this PR until label not removed label Nov 14, 2024
@Innocent-Akim Innocent-Akim self-assigned this Nov 14, 2024
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: 6

🧹 Outside diff range and nitpick comments (6)
apps/web/app/stores/time-logs.ts (1)

8-8: Implementation looks good but could use documentation.

The atom implementation follows the established patterns and uses appropriate typing.

Consider adding JSDoc documentation to explain the atom's purpose and lifecycle:

+/**
+ * Tracks the list of timesheets that have been marked for deletion.
+ * @note Remember to reset this state after successful bulk deletion
+ */
export const timesheetDeleteState = atom<ITimeSheet[]>([])
apps/web/app/api/timer/timesheet/bulk-delete/route.ts (3)

1-4: Consider standardizing import path styles

The imports mix different path styles (@/ and @app/). Consider standardizing to one approach for better maintainability.

-import { deleteTaskTimesheetRequest } from '@/app/services/server/requests';
-import { authenticatedGuard } from '@app/services/server/guards/authenticated-guard-app';
+import { deleteTaskTimesheetRequest } from '@app/services/server/requests';
+import { authenticatedGuard } from '@app/services/server/guards/authenticated-guard-app';

25-31: Enhance error handling and logging

The current error handling could be more informative for debugging and client feedback.

Consider implementing more structured error handling:

     } catch (error) {
-        console.error('Error delete timesheet:', error);
+        console.error('[Timesheet Bulk Delete]', {
+            error,
+            tenantId,
+            organizationId,
+            timestamp: new Date().toISOString()
+        });
+
+        if (error.response?.status === 404) {
+            return NextResponse.json(
+                { error: 'Specified timesheets not found' },
+                { status: 404 }
+            );
+        }
+
         return NextResponse.json(
-            { error: 'Failed to delete timesheet data' },
+            { error: 'Failed to delete timesheet data', message: error.message },
             { status: 500 }
         );
     }

1-33: Consider adding transaction safety and permission validation

For bulk operations affecting multiple records, consider:

  1. Implementing transaction handling to ensure atomic operations
  2. Adding permission checks to verify user's rights to delete specific timesheets
  3. Adding rate limiting to prevent abuse
  4. Implementing batch size limits
  5. Adding success/failure reporting for each timesheet in the bulk operation

Would you like assistance in implementing these architectural improvements?

apps/web/app/services/server/requests/timesheet.ts (1)

83-87: Add JSDoc documentation for the new type.

Consider adding documentation similar to ITimesheetProps to improve code maintainability and developer experience.

+/**
+ * Parameters for timesheet deletion requests
+ * @property organizationId - Organization identifier
+ * @property tenantId - Tenant identifier
+ * @property logIds - Optional array of timesheet log identifiers for bulk deletion
+ */
 type IDeleteTimesheetProps = {
   organizationId: string;
   tenantId: string;
   logIds?: string[]
 }
apps/web/app/hooks/features/useTimesheet.ts (1)

93-94: Add JSDoc documentation for new return properties

Add documentation to help consumers of this hook understand the new functionality.

 return {
     loadingTimesheet,
     timesheet: groupByDate(timesheet),
     getTaskTimesheet,
+    /** Indicates whether a timesheet deletion operation is in progress */
     loadingDeleteTimesheet,
+    /** Deletes the specified timesheet entries. Throws error if operation fails */
     deleteTaskTimesheet
 };
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 1a1d0c6 and 038ae57.

📒 Files selected for processing (5)
  • apps/web/app/api/timer/timesheet/bulk-delete/route.ts (1 hunks)
  • apps/web/app/hooks/features/useTimesheet.ts (4 hunks)
  • apps/web/app/services/client/api/timer/timer-log.ts (2 hunks)
  • apps/web/app/services/server/requests/timesheet.ts (1 hunks)
  • apps/web/app/stores/time-logs.ts (1 hunks)
🔇 Additional comments (5)
apps/web/app/stores/time-logs.ts (1)

8-8: Verify state cleanup handling.

Ensure that the timesheet deletion state is properly cleaned up after successful deletion operations to prevent stale state and memory leaks.

apps/web/app/services/client/api/timer/timer-log.ts (2)

2-2: LGTM: Import addition is appropriate

The addition of deleteApi import is correctly placed and necessary for the new delete functionality.


78-79: Verify the delete endpoint implementation and usage

The endpoint structure needs verification to ensure it matches the backend API specification and is used correctly in the frontend.

✅ Verification successful

Based on the gathered information, I can now provide the final response:

Delete endpoint implementation and usage are correct

The delete endpoint is properly implemented and used:

  • The endpoint correctly constructs URL parameters including organizationId, tenantId and logIds array
  • The hook implementation in useTimesheet.ts properly handles the deletion with correct parameters
  • The interface ITimeSheet is properly defined and used across the codebase
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any existing usage of the delete timesheet endpoint
echo "Checking frontend usage of delete timesheet endpoint..."
rg -l "deleteTaskTimesheetLogsApi" 

# Check if the endpoint is consistently defined in API documentation or types
echo "Checking API documentation and type definitions..."
fd -e ts -e tsx -e md -e yaml --exec rg -l "timesheet/time-log.*delete"

Length of output: 436


Script:

#!/bin/bash
# Let's check the implementation details in both files
echo "Checking implementation in useTimesheet.ts..."
rg -A 5 -B 5 "deleteTaskTimesheetLogsApi" "apps/web/app/hooks/features/useTimesheet.ts"

echo "\nChecking implementation in timer-log.ts..."
rg -A 5 -B 5 "deleteTaskTimesheetLogsApi" "apps/web/app/services/client/api/timer/timer-log.ts"

# Let's also check for any API type definitions
echo "\nChecking for API type definitions..."
fd -e ts -e tsx --exec rg -l "interface.*TimeSheet"

# If we find type definitions, let's examine them
echo "\nExamining TimeSheet interface..."
ast-grep --pattern 'interface $_ {
  $$$
}'

Length of output: 362396


Script:

#!/bin/bash
# Let's check the implementation of the delete endpoint and its usage
echo "Checking delete endpoint implementation..."
rg -A 5 -B 5 "deleteTaskTimesheetLogsApi" "apps/web/app/services/client/api/timer/timer-log.ts"

echo "\nChecking usage in useTimesheet hook..."
rg -A 5 -B 5 "deleteTaskTimesheetLogsApi" "apps/web/app/hooks/features/useTimesheet.ts"

# Let's also check for any related interfaces and types
echo "\nChecking for timesheet interfaces..."
rg -A 5 -B 5 "interface.*TimeSheet" "apps/web/app/interfaces/timer/ITimerLog.ts"

Length of output: 2024


Script:

#!/bin/bash
# Let's check the complete implementation of the delete endpoint
echo "Checking complete delete endpoint implementation..."
rg -A 10 -B 1 "export async function deleteTaskTimesheetLogsApi" "apps/web/app/services/client/api/timer/timer-log.ts"

# Let's also check for any delete API usage in the codebase
echo "\nChecking for delete API usage across codebase..."
rg -A 5 "queryDeleteTimesheet\(" "apps/web/app/**/*"

# Let's verify if there are any related test files
echo "\nChecking for related test files..."
fd -e test.ts -e spec.ts --exec rg -l "deleteTaskTimesheetLogsApi"

Length of output: 821


Script:

#!/bin/bash
# Let's check for delete API usage with correct path
echo "Checking for delete API usage across codebase..."
rg -A 5 "queryDeleteTimesheet\(" apps/web/app/

# Let's check the complete implementation of the delete endpoint with more context
echo "\nChecking complete delete endpoint implementation with more context..."
rg -A 15 -B 5 "deleteTaskTimesheetLogsApi" apps/web/app/services/client/api/timer/timer-log.ts

# Let's also check for any related delete API calls
echo "\nChecking for related delete API calls..."
rg -l "delete.*timesheet" apps/web/app/services/client/api/

Length of output: 1428

apps/web/app/services/server/requests/timesheet.ts (1)

89-98: Verify API endpoint compatibility and existing usages.

Before implementing the suggested changes, please verify:

  1. That the API endpoint supports path parameters for deletion
  2. Any existing code that might be using this endpoint
apps/web/app/hooks/features/useTimesheet.ts (1)

Line range hint 1-94: Verify integration with UI components

The hook implementation needs to be verified in the context of its usage.

✅ Verification successful

Based on the search results, I can now provide a final response regarding the integration verification:

Hook integration is properly implemented across the application

The useTimesheet hook is well integrated within the application:

  • Main usage in timesheet view: apps/web/app/[locale]/timesheet/[memberId]/page.tsx
  • Proper type exports being used by components: GroupedTimesheet interface used in TimesheetView.tsx
  • Consistent error handling pattern matching other hooks in the codebase
  • Clear integration with the global state management via timesheetRapportState

The implementation follows the application's patterns and is properly consumed by the UI components.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Find components using this hook to ensure proper integration
echo "Searching for components using useTimesheet hook..."
rg -l "useTimesheet" --type ts --type tsx

# Find any existing error handling patterns
echo "Checking error handling patterns in other hooks..."
rg "catch\s*\([^)]*\)\s*{" "apps/web/app/hooks"

Length of output: 447


Script:

#!/bin/bash
# Find components using useTimesheet hook with correct syntax
echo "Searching for components using useTimesheet hook..."
rg "useTimesheet" --type ts

# Check error handling patterns with correct regex
echo "Checking error handling patterns in other hooks..."
rg "catch.*{" "apps/web/app/hooks"

# Find UI components that might use this hook
echo "Looking for potential UI components..."
fd -e tsx -e ts . apps/web/app/components | xargs rg "useTimesheet"

# Check for timesheet related components
echo "Checking timesheet related components..."
fd -e tsx -e ts . apps/web | xargs rg "timesheet" -i

Length of output: 38481

apps/web/app/api/timer/timesheet/bulk-delete/route.ts Outdated Show resolved Hide resolved
apps/web/app/api/timer/timesheet/bulk-delete/route.ts Outdated Show resolved Hide resolved
apps/web/app/services/client/api/timer/timer-log.ts Outdated Show resolved Hide resolved
apps/web/app/services/server/requests/timesheet.ts Outdated Show resolved Hide resolved
apps/web/app/hooks/features/useTimesheet.ts Show resolved Hide resolved
apps/web/app/hooks/features/useTimesheet.ts Outdated Show resolved Hide resolved
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: 1

🧹 Outside diff range and nitpick comments (8)
apps/web/app/api/timer/timesheet/bulk-delete/route.ts (5)

1-3: Maintain consistency in import path aliases

The imports use different path aliases (@/ and @app/). Consider standardizing to one style for better maintainability.

-import { deleteTaskTimesheetRequest } from '@/app/services/server/requests';
-import { authenticatedGuard } from '@app/services/server/guards/authenticated-guard-app';
+import { deleteTaskTimesheetRequest } from '@app/services/server/requests';
+import { authenticatedGuard } from '@app/services/server/guards/authenticated-guard-app';

7-15: Enhance input validation for logIds

While the array validation is good, consider adding validation for individual logId values to ensure they are valid identifiers.

 const body = await req.json();
 const { logIds = [] } = body;

-if (!Array.isArray(logIds) || logIds.length === 0) {
+if (!Array.isArray(logIds) || logIds.length === 0 || !logIds.every(id => typeof id === 'string' && id.trim().length > 0)) {
     return NextResponse.json(
-        { error: 'logIds must be a non-empty array' },
+        { error: 'logIds must be a non-empty array of valid identifiers' },
         { status: 400 }
     );
 }

17-17: Remove trailing comma in destructuring

Minor style issue with trailing comma in object destructuring.

-const { $res, user, tenantId, organizationId, access_token, } = await authenticatedGuard(req, res);
+const { $res, user, tenantId, organizationId, access_token } = await authenticatedGuard(req, res);

34-40: Enhance error handling with more specific error messages

The catch block could provide more detailed error information to help with debugging while keeping the client response generic for security.

 } catch (error) {
-    console.error('Error delete timesheet:', error);
+    console.error('Failed to delete timesheet logs:', {
+        error,
+        tenantId,
+        organizationId,
+        logCount: logIds.length
+    });
     return NextResponse.json(
         { error: 'Failed to delete timesheet data' },
         { status: 500 }
     );
 }

5-41: Consider adding rate limiting and bulk operation constraints

For bulk operations, it's important to:

  1. Implement rate limiting to prevent abuse
  2. Set a maximum limit on the number of items that can be deleted in a single request
  3. Consider implementing batch processing for large deletions

Consider implementing these safeguards using middleware or within the route handler. Would you like me to provide an example implementation?

apps/web/app/services/client/api/timer/timer-log.ts (2)

92-96: Enhance error handling with more detailed error messages

While the error handling is implemented, it could be more informative by including the original error message.

Consider applying this improvement:

 	try {
 		return await deleteApi<{ success: boolean; message: string }>(endPoint, { tenantId });
 	} catch (error) {
-		throw new Error(`Failed to delete timesheet logs`);
+		throw new Error(`Failed to delete timesheet logs: ${error instanceof Error ? error.message : 'Unknown error'}`);
 	}

61-97: Consider adding request timeout and cancellation support

For bulk operations that might take longer to complete, it would be beneficial to:

  1. Add a timeout parameter to prevent long-running requests
  2. Support request cancellation using AbortController

Example implementation:

export async function deleteTaskTimesheetLogsApi({
	logIds,
	organizationId,
	tenantId,
	timeout = 30000,  // 30 seconds default
	signal?: AbortSignal
}: {
	organizationId: string,
	tenantId: string,
	logIds: string[],
	timeout?: number,
	signal?: AbortSignal
}) {
	// ... existing validation code ...

	const endPoint = `/timesheet/time-log?${params.toString()}`;
	try {
		return await deleteApi<{ success: boolean; message: string }>(
			endPoint,
			{ 
				tenantId,
				timeout,
				signal
			}
		);
	} catch (error) {
		if (error.name === 'AbortError') {
			throw new Error('Request was cancelled');
		}
		throw new Error(`Failed to delete timesheet logs: ${error instanceof Error ? error.message : 'Unknown error'}`);
	}
}
apps/web/app/hooks/features/useTimesheet.ts (1)

78-108: Optimize useCallback dependencies

The implementation looks solid with proper error handling and validation. However, the dependency array for useCallback should include handleDeleteTimesheet since it's used within the callback.

    const deleteTaskTimesheet = useCallback(
        async ({ logIds }: DeleteTimesheetParams): Promise<void> => {
            // ... existing implementation ...
        },
-        [user, queryDeleteTimesheet]
+        [user, handleDeleteTimesheet]
    );
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 038ae57 and 320ce1b.

📒 Files selected for processing (4)
  • apps/web/app/api/timer/timesheet/bulk-delete/route.ts (1 hunks)
  • apps/web/app/hooks/features/useTimesheet.ts (5 hunks)
  • apps/web/app/services/client/api/timer/timer-log.ts (2 hunks)
  • apps/web/app/services/server/requests/timesheet.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/web/app/services/server/requests/timesheet.ts
🔇 Additional comments (5)
apps/web/app/services/client/api/timer/timer-log.ts (2)

2-2: LGTM: Import statement is correctly updated

The deleteApi import is appropriately added to support the new deletion functionality.


71-89: LGTM: Validation and safety checks are well implemented

The implementation correctly addresses previous review comments regarding parameter validation and bulk operation limits. Good job on:

  • Validating required parameters
  • Implementing a reasonable bulk deletion limit
  • Adding individual logId validation
apps/web/app/hooks/features/useTimesheet.ts (3)

6-6: LGTM! Well-structured interface and imports

The DeleteTimesheetParams interface is well-defined with all necessary fields, and the import is appropriately placed with related API imports.

Also applies to: 19-23


54-54: LGTM! Query hook setup follows consistent pattern

The delete operation query hook follows the same pattern as the existing timesheet operations.


120-121: LGTM! Return object properly extended

The new fields are well-named and follow the existing pattern.

apps/web/app/hooks/features/useTimesheet.ts Outdated Show resolved Hide resolved
@Innocent-Akim Innocent-Akim marked this pull request as draft November 14, 2024 17:26
@Innocent-Akim Innocent-Akim marked this pull request as ready for review November 16, 2024 12:25
@Innocent-Akim Innocent-Akim marked this pull request as draft November 16, 2024 14:18
@Innocent-Akim Innocent-Akim force-pushed the feat/delete-task-timesheet branch from 721b9dd to 2936ab9 Compare November 16, 2024 14:43
@Innocent-Akim Innocent-Akim marked this pull request as ready for review November 16, 2024 14:44
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: 1

🧹 Outside diff range and nitpick comments (1)
apps/web/app/hooks/features/useTimesheet.ts (1)

96-117: Add explicit return type annotation to the callback

While the implementation is solid, consider adding an explicit return type annotation to the callback for better type safety.

 const deleteTaskTimesheet = useCallback(
-    async ({ logIds }: DeleteTimesheetParams): Promise<void> => {
+    async ({ logIds }: DeleteTimesheetParams): Promise<void | never> => {
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 721b9dd and 2936ab9.

📒 Files selected for processing (5)
  • apps/web/app/api/timer/timesheet/bulk-delete/route.ts (1 hunks)
  • apps/web/app/hooks/features/useTimesheet.ts (5 hunks)
  • apps/web/app/services/client/api/timer/timer-log.ts (2 hunks)
  • apps/web/app/services/server/requests/timesheet.ts (1 hunks)
  • apps/web/app/stores/time-logs.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • apps/web/app/api/timer/timesheet/bulk-delete/route.ts
  • apps/web/app/services/server/requests/timesheet.ts
  • apps/web/app/stores/time-logs.ts
🔇 Additional comments (5)
apps/web/app/services/client/api/timer/timer-log.ts (1)

2-2: LGTM: Import statement is properly organized

The deleteApi import is correctly added alongside related imports.

apps/web/app/hooks/features/useTimesheet.ts (4)

6-6: LGTM: Clean interface definition and import organization

The new DeleteTimesheetParams interface is well-structured with clear type definitions for the required parameters.

Also applies to: 20-24


55-55: LGTM: Proper query setup with loading state

The delete operation is correctly set up using the useQuery hook with appropriate loading state tracking.


87-94: LGTM: Well-implemented error handling wrapper

The handleDeleteTimesheet function properly implements error handling and logging as suggested in previous reviews.


129-130: LGTM: Clean hook interface extension

The return object is properly extended with the new deletion-related properties while maintaining a consistent structure.

Copy link

socket-security bot commented Nov 16, 2024

👍 Dependency issues cleared. Learn more about Socket for GitHub ↗︎

This PR previously contained dependency changes with security issues that have been resolved, removed, or ignored.

View full report↗︎

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: 8

🧹 Outside diff range and nitpick comments (21)
apps/web/lib/components/index.ts (1)

33-33: LGTM! Consider organizing exports into logical groups.

The new export follows the established pattern and its purpose aligns well with the PR's objective. However, as the number of exports grows, consider organizing them into logical groups with comments for better maintainability. For example:

 // UI Elements
 export * from './button';
 export * from './typography';
 export * from './badge';
 
 // Layout Components
 export * from './container';
 export * from './divider';
 export * from './separator';
 
 // Interactive Components
 export * from './dropdown';
 export * from './modal';
 export * from './alert-dialog-confirmation';
apps/web/app/hooks/features/useTimelogFilterOptions.ts (2)

16-18: Consider improving readability and type safety

While the logic is correct, the function could benefit from a more explicit implementation and additional type safety.

Consider this more readable version:

-    const handleSelectRowTimesheet = (items: ITimeSheet) => {
-        setSelectTimesheet((prev) => prev.includes(items) ? prev.filter((filter) => filter !== items) : [...prev, items])
-    }
+    const handleSelectRowTimesheet = (item: ITimeSheet): void => {
+        if (!item) return;
+        
+        setSelectTimesheet((prev) => {
+            const isSelected = prev.includes(item);
+            return isSelected 
+                ? prev.filter((timesheet) => timesheet !== item)
+                : [...prev, item];
+        });
+    }

Line range hint 20-31: Consider adding explicit return type

The return object would benefit from an explicit TypeScript interface definition.

Consider adding this interface:

interface TimelogFilterOptions {
    statusState: unknown; // replace with actual type
    employee: unknown; // replace with actual type
    project: unknown; // replace with actual type
    task: unknown; // replace with actual type
    setEmployeeState: (state: unknown) => void; // replace with actual type
    setProjectState: (state: unknown) => void; // replace with actual type
    setTaskState: (state: unknown) => void; // replace with actual type
    setStatusState: (state: unknown) => void; // replace with actual type
    handleSelectRowTimesheet: (item: ITimeSheet) => void;
    selectTimesheet: ITimeSheet[];
}

Then update the function signature:

- export function useTimelogFilterOptions() {
+ export function useTimelogFilterOptions(): TimelogFilterOptions {
apps/web/lib/components/alert-dialog-confirmation.tsx (3)

14-15: Remove unnecessary empty lines

Multiple consecutive empty lines can be reduced to one for better code organization.

 import React from "react";
-

-

 interface AlertDialogConfirmationProps {

16-26: Add JSDoc documentation for better code maintainability

Consider adding JSDoc documentation to describe the interface and its properties. This will improve code maintainability and provide better IDE support.

+/**
+ * Props for the AlertDialogConfirmation component
+ * @interface AlertDialogConfirmationProps
+ * @property {string} title - The title of the confirmation dialog
+ * @property {string} description - The description text of the confirmation dialog
+ * @property {string} [confirmText="Continue"] - Text for the confirm button
+ * @property {string} [cancelText="Cancel"] - Text for the cancel button
+ * @property {() => void} onConfirm - Callback function when confirm is clicked
+ * @property {() => void} onCancel - Callback function when cancel is clicked
+ * @property {boolean} isOpen - Controls the visibility of the dialog
+ * @property {(isOpen: boolean) => void} onOpenChange - Callback for dialog state changes
+ * @property {boolean} [loading] - Loading state for the confirm button
+ */
 interface AlertDialogConfirmationProps {

28-38: Consider making the component more flexible for different use cases

The component seems designed for destructive actions (given the red styling) but could be made more reusable for different types of confirmations.

Consider adding a variant prop to support different types of confirmations:

 interface AlertDialogConfirmationProps {
+    variant?: 'danger' | 'warning' | 'info';
     // ... other props
 }
apps/web/components/ui/button.tsx (3)

8-33: Excellent styling improvements with modern utilities!

The changes enhance the button's styling with better spacing, text handling, and SVG standardization. The use of modern utilities like size-4 is a good practice.

Consider adding a comment explaining the SVG-specific styles for better maintainability:

  "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50
+ /* Prevent SVG pointer events and standardize size */
  [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",

37-39: Well-structured interface with good composability!

The ButtonProps interface is well-typed and the asChild prop enables flexible composition with Radix UI's Slot component.

This pattern of using asChild with Radix UI's Slot is excellent for component polymorphism. Consider documenting this pattern in your team's component guidelines for consistency across other primitive components.


43-53: Consider improving type safety for prop spreading.

While the implementation is clean and functional, the current prop spreading could potentially allow invalid HTML attributes to pass through.

Consider adding a type guard or being more explicit about allowed props:

- ({ className, variant, size, asChild = false, ...props }, ref) => {
+ ({ className, variant, size, asChild = false, ...htmlProps }, ref) => {
+   // Extract only valid HTML button attributes
+   const { type = "button", ...props } = htmlProps;
    const Comp = asChild ? Slot : "button"
    return (
      <Comp
        className={cn(buttonVariants({ variant, size, className }))}
        ref={ref}
+       type={type}
        {...props}
      />
    )
  }
apps/web/app/[locale]/timesheet/[memberId]/components/TimesheetAction.tsx (2)

31-31: Consider adding validation for status-action combinations.

The function accepts any StatusAction for any StatusType, which could lead to invalid state transitions. Consider adding runtime validation to ensure only valid status-action combinations are possible.

-export const getTimesheetButtons = (status: StatusType, t: TranslationHooks, onClick: (action: StatusAction) => void) => {
+export const getTimesheetButtons = (status: StatusType, t: TranslationHooks, onClick: (action: StatusAction) => void) => {
+  const isValidTransition = (currentStatus: StatusType, action: StatusAction): boolean => {
+    const validTransitions: Record<StatusType, StatusAction[]> = {
+      Pending: ["Approved", "Rejected", "Deleted"],
+      Approved: ["Rejected", "Deleted"],
+      Rejected: ["Approved", "Deleted"]
+    };
+    return validTransitions[currentStatus].includes(action);
+  };

37-37: Consider adding confirmation dialog for delete action.

Delete is a destructive operation. Consider adding a confirmation dialog or implementing a soft-delete pattern to prevent accidental deletions.

Some suggestions:

  1. Add a confirmation dialog before deletion
  2. Consider implementing undo functionality
  3. Add visual distinction for the delete button (e.g., red color) to indicate destructive action
  4. Consider implementing soft-delete pattern if not already in place

Example implementation:

const handleDelete = async (action: StatusAction) => {
  if (action === 'Deleted') {
    const confirmed = await showConfirmationDialog({
      title: t('pages.timesheet.DELETE_CONFIRMATION_TITLE'),
      message: t('pages.timesheet.DELETE_CONFIRMATION_MESSAGE'),
      confirmButtonText: t('pages.timesheet.DELETE_CONFIRM'),
      cancelButtonText: t('pages.timesheet.DELETE_CANCEL'),
      type: 'danger'
    });
    if (!confirmed) return;
  }
  onClick(action);
};

Also applies to: 41-41, 45-45

apps/web/components/ui/alert-dialog.tsx (2)

28-44: Consider adding aria-label for better accessibility.

While Radix UI provides good accessibility defaults, consider adding an aria-label prop to the AlertDialogContent component to provide more context for screen readers, especially when the dialog serves different purposes (e.g., delete confirmation).

 <AlertDialogPrimitive.Content
   ref={ref}
+  aria-label={`${title || 'Alert'} Dialog`}
   className={cn(
     "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
     className
   )}
   {...props}
 />

99-125: LGTM! Well-suited for delete confirmation.

The Action and Cancel buttons are well-implemented for the delete timesheet feature:

  • Clear visual hierarchy with variant differences
  • Proper responsive spacing
  • Consistent button styling

For the delete timesheet feature, consider using:

  • AlertDialogAction with destructive styling for the delete action
  • AlertDialogCancel as a safe default option
apps/web/lib/features/user-profile-plans.tsx (5)

458-459: Fix template literal syntax for className

The className string template could be simplified using the clsxm utility that's already imported and used elsewhere in the file.

-className={`mb-6 flex ${planMode === 'Future Tasks' ? 'justify-start' : 'justify-around'} items-center gap-5`}
+className={clsxm(
+  'mb-6 flex items-center gap-5',
+  planMode === 'Future Tasks' ? 'justify-start' : 'justify-around'
+)}

Line range hint 137-152: Improve error handling for plan deletion

The current implementation only logs errors to console without providing user feedback. Consider implementing proper error handling and user notifications.

 try {
   if (requirePlan) {
     localStorage.removeItem(DAILY_PLAN_SUGGESTION_MODAL_DATE);
   }
   todayPlan[0].id && (await deleteDailyPlan(todayPlan[0].id));
+  // Show success notification
+  toast.success(t('common.plan.PLAN_DELETED_SUCCESSFULLY'));
 } catch (error) {
-  console.error(error);
+  // Show error notification
+  toast.error(t('common.ERROR_OCCURRED'));
+  // Log error for debugging
+  console.error('Failed to delete daily plan:', error);
 } finally {
   setPopupOpen(false);
 }

Line range hint 66-76: Implement safe localStorage operations

Direct localStorage access could throw errors in private browsing mode or when storage is unavailable. Consider implementing a safe storage utility.

+// Create a new utility file: utils/storage.ts
+const safeStorage = {
+  get: (key: string, defaultValue: any = null) => {
+    try {
+      const item = window?.localStorage.getItem(key);
+      return item ? JSON.parse(item) : defaultValue;
+    } catch {
+      return defaultValue;
+    }
+  },
+  set: (key: string, value: any) => {
+    try {
+      window?.localStorage.setItem(key, JSON.stringify(value));
+      return true;
+    } catch {
+      return false;
+    }
+  },
+  remove: (key: string) => {
+    try {
+      window?.localStorage.removeItem(key);
+      return true;
+    } catch {
+      return false;
+    }
+  }
+};

Then use it in the component:

-const dailyPlanSuggestionModalDate = window && window?.localStorage.getItem(DAILY_PLAN_SUGGESTION_MODAL_DATE);
+const dailyPlanSuggestionModalDate = safeStorage.get(DAILY_PLAN_SUGGESTION_MODAL_DATE);

Line range hint 471-489: Enhance time input validation and UX

The time input field lacks proper validation and could benefit from a more user-friendly interface.

 <input
   min={0}
+  max={24}
+  step={0.5}
   type="number"
+  placeholder={formatIntegerToHour(plan.workTimePlanned)}
+  onKeyPress={(e) => {
+    if (e.key === 'Enter') {
+      updateDailyPlan({ workTimePlanned: time }, plan.id ?? '');
+      setEditTime(false);
+    }
+  }}
+  onBlur={() => {
+    if (!time) {
+      setEditTime(false);
+    }
+  }}
   className={clsxm(
     'outline-none p-0 bg-transparent border-b text-center max-w-[54px] text-xs font-medium',
+    'hover:border-blue-500 focus:border-blue-500'
   )}
   onChange={(e) => setTime(parseFloat(e.target.value))}
 />

Line range hint 367-378: Optimize filtered plans implementation

The current implementation using useRef could be simplified and optimized using useMemo.

-const filteredPlans = useRef<IDailyPlan[]>([]);
+const filteredPlans = useMemo(() => {
+  if (currentTab === 'Today Tasks') {
+    return todayPlan;
+  }
+  return sortedPlans;
+}, [currentTab, todayPlan, sortedPlans]);

-if (currentTab === 'Today Tasks') {
-  filteredPlans.current = todayPlan;
-} else {
-  filteredPlans.current = sortedPlans;
-}
apps/web/lib/features/integrations/calendar/table-time-sheet.tsx (3)

Line range hint 222-234: Implement deletion logic in handleButtonClick

The TODO comment for deletion logic should be implemented as it's the main purpose of this PR.

 case 'Deleted':
-    // TODO: Implement pending logic
+    setIsDialogOpen(true);
     break;

240-250: Make dialog text more specific to timesheet deletion

The current dialog text is generic. Consider making it more specific to timesheet deletion for better user experience.

-    title="Are you sure you want to delete this?"
-    description="This action is irreversible. All related data will be lost."
+    title="Delete Selected Timesheets?"
+    description="This action will permanently delete the selected timesheet entries. This cannot be undone."

307-310: Enhance checkbox accessibility and visual feedback

Add proper accessibility attributes and visual feedback for better user experience.

 <Checkbox className="h-5 w-5"
+    id={`select-task-${task.id}`}
+    aria-label={`Select timesheet for ${task.description || 'task'}`}
+    className={clsxm(
+      "h-5 w-5",
+      selectTimesheet.includes(task) && "border-primary"
+    )}
     onClick={() => handleSelectRowTimesheet(task)}
     checked={selectTimesheet.includes(task)}
 />
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 2936ab9 and ec39ba9.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (11)
  • apps/web/app/[locale]/timesheet/[memberId]/components/TimesheetAction.tsx (1 hunks)
  • apps/web/app/hooks/features/useTimelogFilterOptions.ts (2 hunks)
  • apps/web/app/hooks/features/useTimesheet.ts (5 hunks)
  • apps/web/app/services/client/api/timer/timer-log.ts (2 hunks)
  • apps/web/components/ui/alert-dialog.tsx (1 hunks)
  • apps/web/components/ui/button.tsx (1 hunks)
  • apps/web/lib/components/alert-dialog-confirmation.tsx (1 hunks)
  • apps/web/lib/components/index.ts (1 hunks)
  • apps/web/lib/features/integrations/calendar/table-time-sheet.tsx (6 hunks)
  • apps/web/lib/features/user-profile-plans.tsx (1 hunks)
  • apps/web/package.json (3 hunks)
🔇 Additional comments (17)
apps/web/app/hooks/features/useTimelogFilterOptions.ts (2)

1-2: LGTM: Clean state management setup

The new imports and state declaration are well-organized and follow the existing patterns in the codebase.

Also applies to: 10-10


Line range hint 1-31: Verify integration with deletion flow

The selection mechanism is implemented, but let's verify its integration with the actual deletion functionality.

✅ Verification successful

Selection mechanism properly integrated with deletion flow

The verification confirms proper integration:

  • Selection state (timesheetDeleteState) is managed via useTimelogFilterOptions hook
  • Selection UI is implemented in table-time-sheet.tsx with checkbox controls
  • Selected items are passed to deleteTaskTimesheet function through a confirmation dialog
  • Complete deletion flow exists from UI through API endpoints to server requests
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for usage of handleSelectRowTimesheet and timesheetDeleteState
# to ensure proper integration with deletion flow

echo "Checking for handleSelectRowTimesheet usage:"
rg "handleSelectRowTimesheet" -A 5

echo "\nChecking for timesheetDeleteState consumption:"
rg "timesheetDeleteState" -A 5

echo "\nChecking for delete API implementation:"
rg "deleteTaskTimesheet" -A 5

Length of output: 9040

apps/web/lib/components/alert-dialog-confirmation.tsx (1)

1-59: Implementation aligns well with PR objectives

The AlertDialogConfirmation component provides a solid foundation for the timesheet deletion feature with proper user interaction patterns and loading states.

apps/web/components/ui/button.tsx (1)

1-5: LGTM! Clean and well-organized imports.

The imports are properly structured and each dependency serves a clear purpose.

apps/web/app/services/client/api/timer/timer-log.ts (1)

2-2: LGTM!

The import of deleteApi is correctly added and follows the existing import pattern.

apps/web/app/[locale]/timesheet/[memberId]/components/TimesheetAction.tsx (1)

27-27: Verify the impact of the new StatusAction type.

While the type definition is clear, we should ensure that all consumers of this type are properly updated, especially since it differs from StatusType by replacing "Pending" with "Deleted".

Consider adding JSDoc comments to document the relationship between StatusType and StatusAction.

✅ Verification successful

Let me try another search strategy to better understand the usage and impact.


The new StatusAction type is correctly implemented and used

The search results show that:

  1. StatusAction is only used in two files:
    • Its definition in TimesheetAction.tsx
    • Its usage in table-time-sheet.tsx where it's properly imported and used in the handleButtonClick function
  2. The type is used consistently with the button configuration in TimesheetAction.tsx where each status has appropriate actions mapped
  3. The "Deleted" action is a new action type that doesn't conflict with existing status types, as it represents an action rather than a state
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any direct usage of StatusAction type
rg "StatusAction" --type typescript

# Search for potential places where status types are used
ast-grep --pattern 'type $_ = "Pending" | "Approved" | "Rejected"'

Length of output: 278


Script:

#!/bin/bash
# Search for any usage of StatusAction using ripgrep without file type
rg "StatusAction"

# Search for status-related string literals to find potential consumers
rg '"(Deleted|Approved|Rejected)"' -A 2 -B 2

# Search for any type definitions or interfaces that might be using these status values
ast-grep --pattern 'type $_ = $_ | "Deleted" | $_'

Length of output: 17635

apps/web/app/hooks/features/useTimesheet.ts (3)

55-55: LGTM! Proper hook setup for delete operation

The deletion query hook is correctly set up with loading state tracking.


128-129: LGTM! Proper exposure of new functionality

The hook correctly exposes both the loading state and delete function.


53-53: Verify loading state usage in UI components

The hook exposes loadingDeleteTimesheet, but we should verify that UI components properly handle this loading state during deletion operations.

✅ Verification successful

Loading state is properly handled during deletion operations

The loading state is correctly implemented in the UI components:

  • The loadingDeleteTimesheet state is passed to the AlertDialogConfirmation component through its loading prop
  • The alert dialog is used for deletion confirmation and properly disables the confirmation button during the loading state
  • The implementation follows best practices for user feedback during async operations
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if UI components properly handle the loading state

# Search for components using loadingDeleteTimesheet
echo "Checking loading state usage in components..."
rg "loadingDeleteTimesheet" --type tsx -A 5

# Search for components using deleteTaskTimesheet
echo "\nChecking delete function usage in components..."
rg "deleteTaskTimesheet" --type tsx -A 5

Length of output: 350


Script:

#!/bin/bash
# Let's try searching without file type restriction since tsx might not be recognized
echo "Checking loading state usage in components..."
rg "loadingDeleteTimesheet"

echo -e "\nChecking delete function usage in components..."
rg "deleteTaskTimesheet"

# Let's also check for any files that might be importing the useTimesheet hook
echo -e "\nChecking files importing useTimesheet..."
rg "useTimesheet"

Length of output: 2813


Script:

#!/bin/bash
# Let's check the implementation of table-time-sheet.tsx to see how the loading state is handled
echo "Checking table-time-sheet.tsx implementation..."
cat "apps/web/lib/features/integrations/calendar/table-time-sheet.tsx"

Length of output: 23201

apps/web/components/ui/alert-dialog.tsx (5)

1-11: LGTM! Good choice using Radix UI for accessibility.

The component is well-structured using Radix UI primitives, which provides built-in accessibility features like ARIA attributes, keyboard navigation, and focus management.


46-72: LGTM! Well-structured layout components.

The Header and Footer components are well-implemented with:

  • Proper responsive design
  • Clean prop handling
  • Semantic structure

127-139: LGTM! Clean and organized exports.

All components are properly exported in a logical order.


13-27: Verify z-index consistency across the application.

The overlay uses z-index: 50. Ensure this value aligns with the application's z-index system to prevent potential stacking context issues with other modals or overlays.

✅ Verification successful

The previous script's output seems incorrect as it shows results for "text-muted-foreground" instead of z-index values. Let me search again specifically for z-index values.


Z-index value of 50 for the overlay is consistent with the application's z-index system

The codebase analysis shows that z-index: 50 is appropriately used for overlay and modal-like components. This value aligns with the z-index hierarchy where:

  • Regular UI elements use z-index: 10-40
  • Overlays, modals, and important UI elements use z-index: 50
  • Critical UI elements like toasts and popups use higher values (z-index: 9999, z-index: 5000)

The current implementation follows this pattern correctly, ensuring proper stacking context for the overlay component.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other z-index values in the codebase
rg -g '*.{css,scss,tsx,jsx}' 'z-\w*:\s*\d+' --no-filename | sort -u

Length of output: 4408


Script:

#!/bin/bash
# Search for z-index values in the codebase using a more specific pattern
rg -g '*.{css,scss,tsx,jsx}' 'z-\[?[0-9]+\]?|z-index:\s*[0-9]+' --no-filename | sort -u

Length of output: 18660


74-98: Verify color contrast for text elements.

Please ensure the text colors provide sufficient contrast ratios for accessibility:

  • Title uses default text color
  • Description uses text-muted-foreground
✅ Verification successful

Let me generate additional scripts to check the color theme configuration more comprehensively.


Let me fix the regex and try again.


Let me check for any Tailwind theme configuration files.


Let me check for the CSS variables that define these colors.


Based on the analysis of the color definitions in the codebase, I can now provide the final response:

Color contrast meets accessibility standards

The text colors used in the AlertDialog components have sufficient contrast:

  • Title uses default text color (foreground: HSL 222.2 84% 4.9% in light mode, HSL 210 40% 98% in dark mode)
  • Description uses muted-foreground (HSL 215.4 16.3% 46.9% in light mode, HSL 215 20.2% 65.1% in dark mode) against background colors (HSL 0 0% 100% in light mode, HSL 222.2 84% 4.9% in dark mode)

These color combinations meet WCAG contrast requirements for both light and dark themes.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for color definitions in the theme
rg -g '*.{css,scss,tsx,jsx}' '(text-muted-foreground|--muted-foreground)' --no-filename | sort -u

Length of output: 4408


Script:

#!/bin/bash
# Search for theme configuration files and color definitions
rg -g '*.{css,scss,tsx,jsx}' --multiline --multiline-dotall 'const.*theme.*=.*{.*}|:root.*{.*}' -A 20

Length of output: 237


Script:

#!/bin/bash
# Search for theme configuration files and color definitions
rg -g '*.{css,scss,tsx,jsx}' --multiline '^:root' -A 10

Length of output: 1807


Script:

#!/bin/bash
# Search for tailwind config files
fd -e js -e ts "tailwind.config" -x cat {}

Length of output: 11359


Script:

#!/bin/bash
# Search for CSS variable definitions related to colors
rg -g '*.{css,scss}' '(:root|\.dark).*\{' -A 20

Length of output: 13716

apps/web/package.json (3)

55-55: LGTM: Appropriate addition of alert dialog dependency.

The addition of @radix-ui/react-alert-dialog is well-suited for implementing deletion confirmation dialogs, which is essential for the new Delete Task Timesheet feature.


152-154: LGTM: Re-added styling dependencies.

The re-addition of PostCSS, Tailwind CSS, and Tailwind CSS Animate with their stable versions is appropriate for maintaining the project's styling capabilities.


102-102: Verify Next.js version compatibility.

The update to Next.js 14.2.17 is relatively recent. Please ensure compatibility with the project's dependencies and features.

✅ Verification successful

Let me try a different approach to gather information about Next.js version compatibility.


Let me check the Next.js configuration and app router implementation to verify compatibility.


Based on the gathered information, I can now provide the final response:

Next.js 14.2.17 update is compatible with the project setup

The codebase shows proper compatibility with Next.js 14.2.17:

  • Using the App Router pattern (apps/web/app directory)
  • Configured with appropriate Next.js features in next.config.js
  • All dependencies in package.json are aligned with Next.js 14.2.17, including:
    • next-auth v5 beta
    • next-intl v3
    • React 18.2.0
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for potential compatibility issues with Next.js 14.2.17

# Check for known breaking changes or issues
gh api graphql -f query='
{
  repository(owner: "vercel", name: "next.js") {
    release(tagName: "v14.2.17") {
      description
      url
    }
    issues(first: 5, states: OPEN, labels: ["type: bug"], searchQuery: "14.2.17") {
      nodes {
        title
        url
        labels(first: 5) {
          nodes {
            name
          }
        }
      }
    }
  }
}'

# Check peer dependencies
jq -r '.dependencies | to_entries | .[] | select(.key | startswith("@next") or startswith("next"))' package.json

Length of output: 825


Script:

#!/bin/bash
# Check package.json for dependencies that might have Next.js peer dependencies
cat package.json

# Look for Next.js specific configurations and features in use
fd -e js -e jsx -e ts -e tsx -e mjs . | xargs rg -l "next/"

# Check for any Next.js specific configuration files
fd -e js -e ts "next.config"

# Look for app router usage (Next.js 13+ feature)
fd -e js -e jsx -e ts -e tsx "app/" "pages/"

Length of output: 20809


Script:

#!/bin/bash
# Check Next.js configuration
cat apps/web/next.config.js

# Check package dependencies that might affect Next.js compatibility
cat apps/web/package.json

# Look for app directory structure and routing patterns
fd -t d "app" apps/web

Length of output: 11681

apps/web/lib/components/alert-dialog-confirmation.tsx Outdated Show resolved Hide resolved
apps/web/app/services/client/api/timer/timer-log.ts Outdated Show resolved Hide resolved
apps/web/app/services/client/api/timer/timer-log.ts Outdated Show resolved Hide resolved
apps/web/app/hooks/features/useTimesheet.ts Outdated Show resolved Hide resolved
apps/web/app/hooks/features/useTimesheet.ts Outdated Show resolved Hide resolved
apps/web/app/hooks/features/useTimesheet.ts Outdated Show resolved Hide resolved
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: 2

🧹 Outside diff range and nitpick comments (8)
apps/web/app/hooks/features/useTimelogFilterOptions.ts (2)

15-17: Consider improving type safety and readability

While the toggle logic is functional, it could benefit from better type safety and readability.

Consider this refactoring:

-const handleSelectRowTimesheet = (items: string) => {
-    setSelectTimesheet((prev) => prev.includes(items) ? prev.filter((filter) => filter !== items) : [...prev, items])
+const handleSelectRowTimesheet = (itemId: string): void => {
+    setSelectTimesheet((previousSelection) => {
+        const isSelected = previousSelection.includes(itemId);
+        return isSelected
+            ? previousSelection.filter((id) => id !== itemId)
+            : [...previousSelection, itemId];
+    });
}

27-30: Consider grouping related properties in the return object

While the additions are correct, consider organizing the return object properties by grouping related items together (states with their setters, handlers separately).

 return {
     statusState,
+    setStatusState,
     employee,
-    project,
-    task,
     setEmployeeState,
+    project,
     setProjectState,
+    task,
     setTaskState,
-    setStatusState,
+    // Selection related
+    selectTimesheet,
+    setSelectTimesheet,
     handleSelectRowTimesheet,
-    selectTimesheet,
-    setSelectTimesheet
 };
apps/web/lib/components/alert-dialog-confirmation.tsx (1)

16-26: Add JSDoc documentation and improve type safety.

Consider adding JSDoc documentation for the interface and its properties, and making the callback types more specific.

+/**
+ * Props for the AlertDialogConfirmation component
+ */
 interface AlertDialogConfirmationProps {
+  /** The title of the confirmation dialog */
   title: string;
+  /** The description/message of the confirmation dialog */
   description: string;
+  /** Text for the confirm button. Defaults to "Continue" */
   confirmText?: string;
+  /** Text for the cancel button. Defaults to "Cancel" */
   cancelText?: string;
-  onConfirm: () => void;
-  onCancel: () => void;
+  /** Callback function when user confirms the action */
+  onConfirm: () => Promise<void> | void;
+  /** Callback function when user cancels the action */
+  onCancel: () => Promise<void> | void;
+  /** Controls the visibility of the dialog */
   isOpen: boolean;
+  /** Callback for handling dialog open state changes */
   onOpenChange: (isOpen: boolean) => void;
+  /** Optional loading state for the confirm action */
   loading?: boolean
 }
apps/web/app/hooks/features/useTimesheet.ts (2)

20-24: Add JSDoc documentation for the DeleteTimesheetParams interface

Consider adding JSDoc documentation to improve code maintainability and developer experience.

+/**
+ * Parameters for deleting timesheet entries
+ * @property {string} organizationId - The ID of the organization
+ * @property {string} tenantId - The tenant identifier
+ * @property {string[]} logIds - Array of timesheet log IDs to delete
+ */
 interface DeleteTimesheetParams {
     organizationId: string;
     tenantId: string;
     logIds: string[];
 }

88-116: Enhance error messages for better debugging

While the error handling is good, consider enhancing the error messages to include more context.

 const deleteTaskTimesheet = useCallback(async () => {
     if (!user) {
-        throw new Error('User not authenticated');
+        throw new Error('[deleteTaskTimesheet] User not authenticated');
     }
     if (!logIds.length) {
-        throw new Error('No timesheet IDs provided for deletion');
+        throw new Error('[deleteTaskTimesheet] No timesheet IDs provided for deletion');
     }
     try {
         await handleDeleteTimesheet({
             organizationId: user.employee.organizationId,
             tenantId: user.tenantId ?? "",
             logIds
         });
     } catch (error) {
-        console.error('Failed to delete timesheets:', error);
+        console.error('[deleteTaskTimesheet] Failed to delete timesheets:', { error, logIds });
         throw error;
     }
 },
     [user, queryDeleteTimesheet, logIds, handleDeleteTimesheet]
 );
apps/web/lib/features/integrations/calendar/table-time-sheet.tsx (3)

181-183: Add type safety for timesheet selection state

Consider adding TypeScript types for the selection state to improve type safety and maintainability.

-const { handleSelectRowTimesheet, selectTimesheet, setSelectTimesheet } = useTimelogFilterOptions()
+type TimesheetId = string | number;
+const { 
+  handleSelectRowTimesheet, 
+  selectTimesheet, 
+  setSelectTimesheet 
+} = useTimelogFilterOptions<TimesheetId>()

Line range hint 232-245: Implement approval logic for handleButtonClick

The TODO comment indicates missing implementation for the approval logic.

Would you like me to help implement the approval logic or create a GitHub issue to track this task?


181-196: Consider implementing optimistic updates for deletion

The current implementation waits for the server response before updating the UI. Consider implementing optimistic updates to improve the user experience:

  1. Update the UI immediately on deletion
  2. Revert changes if the server request fails
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between ec39ba9 and bae0eab.

📒 Files selected for processing (6)
  • apps/web/app/hooks/features/useTimelogFilterOptions.ts (2 hunks)
  • apps/web/app/hooks/features/useTimesheet.ts (5 hunks)
  • apps/web/app/services/client/api/timer/timer-log.ts (2 hunks)
  • apps/web/app/stores/time-logs.ts (1 hunks)
  • apps/web/lib/components/alert-dialog-confirmation.tsx (1 hunks)
  • apps/web/lib/features/integrations/calendar/table-time-sheet.tsx (6 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/web/app/stores/time-logs.ts
🔇 Additional comments (11)
apps/web/app/hooks/features/useTimelogFilterOptions.ts (1)

1-1: LGTM: Import statement is well-organized

The new import for timesheetDeleteState follows the existing pattern and is grouped appropriately with related state atoms.

apps/web/lib/components/alert-dialog-confirmation.tsx (1)

1-12: LGTM! Imports are well-organized and complete.

The imports are properly structured and include all necessary UI components.

apps/web/app/services/client/api/timer/timer-log.ts (4)

2-2: LGTM!

The import of deleteApi is correctly added and follows the existing import pattern.


80-88: LGTM! Robust parameter validation and safety measures.

The implementation includes:

  • Required parameter validation
  • Bulk operation limit for safety (max 100 logs)

90-99: LGTM! Proper parameter construction with validation.

The implementation correctly:

  • Constructs URL parameters
  • Validates individual log IDs
  • Handles array parameters properly

102-106: ⚠️ Potential issue

Align with codebase conventions for delete operations

The implementation needs to use the DeleteResponse type and include more detailed error information.

This issue was previously identified. Apply the suggested changes:

 	try {
-		return await deleteApi<{ success: boolean; message: string }>(endPoint, { tenantId });
+		return await deleteApi<DeleteResponse>(endPoint, { tenantId });
 	} catch (error) {
-		throw new Error(`Failed to delete timesheet logs`);
+		throw new Error(`Failed to delete timesheet logs: ${error instanceof Error ? error.message : 'Unknown error'}`);
 	}
apps/web/app/hooks/features/useTimesheet.ts (2)

55-55: LGTM! Proper API integration setup

The delete operation is correctly integrated using the existing query pattern, with proper loading state tracking.


128-129: Verify UI implementation of loading state

The loading state and delete function are correctly exposed, but ensure they're properly utilized in UI components.

✅ Verification successful

Loading state and delete functionality are properly implemented

The verification shows that both loadingDeleteTimesheet and deleteTaskTimesheet are correctly used in the UI component:

  • table-time-sheet.tsx properly handles the loading state in its UI
  • Delete functionality is implemented with proper error handling and state management
  • The implementation includes a confirmation dialog and cleanup of selected items after successful deletion
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for components using these new values
echo "Checking usage of loadingDeleteTimesheet..."
rg "loadingDeleteTimesheet" --type tsx

echo "\nChecking implementation of delete functionality..."
rg "deleteTaskTimesheet.*" --type tsx -A 5

Length of output: 351


Script:

#!/bin/bash
# Search for components using these new values with correct file extension
echo "Checking usage of loadingDeleteTimesheet..."
rg "loadingDeleteTimesheet" --type ts --type jsx --type tsx

echo -e "\nChecking implementation of delete functionality..."
rg "deleteTaskTimesheet" --type ts --type jsx --type tsx -A 5

Length of output: 391


Script:

#!/bin/bash
# Search for components using these new values without file type restrictions
echo "Checking usage of loadingDeleteTimesheet..."
rg "loadingDeleteTimesheet"

echo -e "\nChecking implementation of delete functionality..."
rg "deleteTaskTimesheet" -A 5

Length of output: 5834

apps/web/lib/features/integrations/calendar/table-time-sheet.tsx (3)

184-197: Missing error handling and user feedback

This implementation still needs proper error handling and user feedback as mentioned in the previous review.


250-260: LGTM! Well-implemented confirmation dialog

The AlertDialogConfirmation implementation is complete with:

  • Clear title and description
  • Loading state handling
  • Proper cancel/confirm actions

317-320: LGTM! Well-implemented row selection

The checkbox implementation correctly:

  • Handles row selection
  • Maintains selection state
  • Updates parent components

Copy link

Report too large to display inline

View full report↗︎

@Innocent-Akim Innocent-Akim added bug Something isn't working feature WEB Web app Ever Teams and removed Don't Merge Do not merge this PR until label not removed labels Nov 16, 2024
@Innocent-Akim Innocent-Akim added this to the v0.3.0 milestone Nov 16, 2024
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: 0

🧹 Outside diff range and nitpick comments (2)
apps/web/app/hooks/features/useTimelogFilterOptions.ts (2)

16-18: Consider renaming the handler to better reflect its toggle behavior

The function handles both selection and deselection of timesheets. A more descriptive name like handleToggleTimesheetSelection would better communicate its purpose.

-const handleSelectRowTimesheet = (items: string) => {
+const handleToggleTimesheetSelection = (items: string) => {

31-34: Consider grouping related properties in the return object

For better organization, consider grouping related properties together:

 return {
     statusState,
     employee,
     project,
     task,
+    selectTimesheet,
     setEmployeeState,
     setProjectState,
     setTaskState,
     setStatusState,
+    setSelectTimesheet,
     handleSelectRowTimesheet,
-    selectTimesheet,
-    setSelectTimesheet
 };
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between bae0eab and e6ce502.

📒 Files selected for processing (2)
  • apps/web/app/hooks/features/useTimelogFilterOptions.ts (2 hunks)
  • apps/web/lib/components/alert-dialog-confirmation.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/web/lib/components/alert-dialog-confirmation.tsx
🔇 Additional comments (3)
apps/web/app/hooks/features/useTimelogFilterOptions.ts (3)

1-1: LGTM: Clean state management implementation

The addition of timesheet deletion state management follows React best practices using Jotai atoms.

Also applies to: 10-10


19-21: LGTM: Proper cleanup implementation

The cleanup effect correctly resets the selection state on component unmount, addressing the previous review feedback.


Line range hint 5-35: Verify hook usage in consuming components

Let's verify that components using this hook properly handle the selection state and cleanup.

✅ Verification successful

Based on the shell script results, I can now generate the final response:

Hook usage verification completed - implementation is correct

The hook is properly used in the consuming components with appropriate cleanup:

  • table-time-sheet.tsx correctly uses selectTimesheet state and handleSelectRowTimesheet handler for checkbox interactions
  • The selection state is used in a confirmation dialog showing selected count
  • The hook's cleanup effect properly resets selection state on unmount
  • useTimesheet.ts correctly consumes the selected IDs as logIds for deletion
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Find components using the hook
rg -l "useTimelogFilterOptions"

# Check if selection state and handler are properly used
rg "handleSelectRowTimesheet|selectTimesheet" -A 5

# Verify no memory leaks from selection state
ast-grep --pattern 'const {
  $$$
  selectTimesheet,
  $$$
} = useTimelogFilterOptions()'

Length of output: 5241

@Innocent-Akim Innocent-Akim requested a review from evereq November 16, 2024 17:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working Ever Teams feature WEB Web app
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants