-
Notifications
You must be signed in to change notification settings - Fork 51
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
Conversation
WalkthroughThe changes introduce a new asynchronous DELETE endpoint for bulk deletion of task timesheets, alongside a new API function for deleting timesheet logs. The Changes
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
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
apps/web/app/hooks/features/useTimelogFilterOptions.tsOops! 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? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this 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 stylesThe 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 loggingThe 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 validationFor bulk operations affecting multiple records, consider:
- Implementing transaction handling to ensure atomic operations
- Adding permission checks to verify user's rights to delete specific timesheets
- Adding rate limiting to prevent abuse
- Implementing batch size limits
- 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 propertiesAdd 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
📒 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:
- That the API endpoint supports path parameters for deletion
- 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 inTimesheetView.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
There was a problem hiding this 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 aliasesThe 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 logIdsWhile 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 destructuringMinor 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 messagesThe 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 constraintsFor bulk operations, it's important to:
- Implement rate limiting to prevent abuse
- Set a maximum limit on the number of items that can be deleted in a single request
- 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 messagesWhile 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 supportFor bulk operations that might take longer to complete, it would be beneficial to:
- Add a timeout parameter to prevent long-running requests
- 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 dependenciesThe 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
📒 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.
721b9dd
to
2936ab9
Compare
There was a problem hiding this 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 callbackWhile 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
📒 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.
👍 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. |
There was a problem hiding this 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 safetyWhile 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 typeThe 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 linesMultiple 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 maintainabilityConsider 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 casesThe 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 theasChild
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 anyStatusType
, 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:
- Add a confirmation dialog before deletion
- Consider implementing undo functionality
- Add visual distinction for the delete button (e.g., red color) to indicate destructive action
- 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 theAlertDialogContent
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 actionAlertDialogCancel
as a safe default optionapps/web/lib/features/user-profile-plans.tsx (5)
458-459
: Fix template literal syntax for classNameThe 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 deletionThe 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 operationsDirect 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 UXThe 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 implementationThe 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 handleButtonClickThe 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 deletionThe 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 feedbackAdd 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
⛔ 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 viauseTimelogFilterOptions
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:
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 thehandleButtonClick
function
- Its definition in
- The type is used consistently with the button configuration in
TimesheetAction.tsx
where each status has appropriate actions mapped - 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 theAlertDialogConfirmation
component through itsloading
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/features/integrations/calendar/table-time-sheet.tsx
Outdated
Show resolved
Hide resolved
There was a problem hiding this 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 readabilityWhile 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 objectWhile 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 interfaceConsider 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 debuggingWhile 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 stateConsider 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 handleButtonClickThe 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 deletionThe current implementation waits for the server response before updating the UI. Consider implementing optimistic updates to improve the user experience:
- Update the UI immediately on deletion
- Revert changes if the server request fails
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 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
:
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
Report too large to display inline |
There was a problem hiding this 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 behaviorThe 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 objectFor 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
📒 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 usesselectTimesheet
state andhandleSelectRowTimesheet
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 aslogIds
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
Description
#3045
Please include a summary of the changes and the related issue.
Type of Change
Checklist
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
Bug Fixes