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

Refactor TaskDetails Component for Improved Maintainability and Performance #1243

Merged
merged 15 commits into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
b7ea2f5
refactor(TaskDetails): Modularize and optimize TaskDetails component …
Achintya-Chatterjee Aug 28, 2024
30de74c
fix(TaskDetails): Correct data type issues and ensure proper conditio…
Achintya-Chatterjee Aug 28, 2024
4a38c2b
fix(task-details): Correct the position of status and link fields
Achintya-Chatterjee Aug 29, 2024
978f2ee
chore: remove unnecessary comments from the code
Achintya-Chatterjee Aug 29, 2024
3029018
fix: restore original styling for TaskDates and TaskParticipants comp…
Achintya-Chatterjee Aug 29, 2024
8b00a96
chore: remove react memo from every component as it was unnecessary
Achintya-Chatterjee Aug 31, 2024
f3daf06
chore: remove react memo from every component as it was unnecessary
Achintya-Chatterjee Aug 31, 2024
890ea61
refactor: TaskDates component to conditionally render Details based o…
Achintya-Chatterjee Aug 31, 2024
748bb14
refactor: switch to named exports for all of the sub-components
Achintya-Chatterjee Aug 31, 2024
51bc91f
chore: remove any from TaskDetails component and replace them with ap…
Achintya-Chatterjee Aug 31, 2024
67d30d8
chore: removed default export from every sub-component as we are alr…
Achintya-Chatterjee Sep 1, 2024
6b86410
refactor(TaskDetails): remove unnecessary TaskProgress and TaskDepend…
Achintya-Chatterjee Sep 1, 2024
832e1dd
refactor: refactor code to simplyfy code reading used is else instead…
Achintya-Chatterjee Sep 2, 2024
851f47b
chore: remove extra Taskcontainer wrap that was impacting styling of …
Achintya-Chatterjee Sep 2, 2024
67c90ed
Merge branch 'develop' into feature/refactor-taskdetails-component
ashifkhn Sep 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions src/components/taskDetails/TaskDates.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import React from 'react';
import Details from './Details';
import styles from './task-details.module.scss';
import { TASK_EXTENSION_REQUEST_URL } from '@/constants/url';
import convertTimeStamp from '@/helperFunctions/convertTimeStamp';

interface TaskDatesProps {
isEditing: boolean;
tejaskh3 marked this conversation as resolved.
Show resolved Hide resolved
isUserAuthorized: boolean;
ashifkhn marked this conversation as resolved.
Show resolved Hide resolved
startedOn: string;
endsOn: number;
newEndOnDate: string;
setNewEndOnDate: (date: string) => void;
handleBlurOfEndsOn: () => void;
isExtensionRequestPending: boolean;
taskId: string;
}

export const TaskDates: React.FC<TaskDatesProps> = ({
isEditing,
isUserAuthorized,
startedOn,
endsOn,
newEndOnDate,
setNewEndOnDate,
handleBlurOfEndsOn,
isExtensionRequestPending,
taskId,
}) => {
const formattedEndsOn = endsOn ? convertTimeStamp(endsOn) : 'TBD';

return (
<>
<div className={styles.inputContainer}>
<Details detailType="Started On" value={startedOn} />
</div>
<div className={styles.inputContainer}>
{isExtensionRequestPending && (
tejaskh3 marked this conversation as resolved.
Show resolved Hide resolved
<Details
detailType="Ends On"
value={formattedEndsOn}
url={`${TASK_EXTENSION_REQUEST_URL}?&q=${encodeURIComponent(
`taskId:${taskId},status:PENDING`
)}`}
/>
)}
{!isExtensionRequestPending && (
<Details detailType="Ends On" value={formattedEndsOn} />
)}
{isEditing && isUserAuthorized && (
<input
id="endsOnTaskDetails"
type="date"
name="endsOn"
onChange={(e) => setNewEndOnDate(e.target.value)}
onBlur={handleBlurOfEndsOn}
value={newEndOnDate}
data-testid="endsOnTaskDetails"
className={styles.inputField}
/>
)}
</div>
</>
);
};
33 changes: 33 additions & 0 deletions src/components/taskDetails/TaskDescription.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React from 'react';
import { Textarea } from './index';
import styles from './task-details.module.scss';

interface TaskDescriptionProps {
isEditing: boolean;
purpose: string;
handleChange: (event: React.ChangeEvent<HTMLTextAreaElement>) => void;
}

export const TaskDescription: React.FC<TaskDescriptionProps> = ({
isEditing,
purpose,
handleChange,
}) => {
if (isEditing) {
return (
<Textarea
name="purpose"
value={purpose}
onChange={handleChange}
testId="purpose-textarea"
placeholder="Enter task description"
/>
);
}

return (
<p className={styles.taskDescription}>
{purpose || 'No description available'}
tejaskh3 marked this conversation as resolved.
Show resolved Hide resolved
</p>
);
};
49 changes: 49 additions & 0 deletions src/components/taskDetails/TaskDetailsSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import React from 'react';
import Details from './Details';
import TaskDropDown from '../tasks/TaskDropDown';
import ProgressContainer from '../tasks/card/progressContainer';
import task, { taskStatusUpdateHandleProp } from '@/interfaces/task.type';
import styles from './task-details.module.scss';

interface TaskDetailsSectionProps {
isEditing: boolean;
tejaskh3 marked this conversation as resolved.
Show resolved Hide resolved
type: string;
priority: string;
status: string;
link: string;
percentCompleted: number;
handleTaskStatusUpdate: (props: taskStatusUpdateHandleProp) => void;
taskDetailsData: task;
}

export const TaskDetailsSection: React.FC<TaskDetailsSectionProps> = ({
isEditing,
type,
priority,
status,
link,
percentCompleted,
handleTaskStatusUpdate,
taskDetailsData,
}) => {
return (
<div className={styles['sub_details_grid_container']}>
<Details detailType={'Type'} value={type} />
<Details detailType={'Priority'} value={priority} />
{isEditing ? (
<TaskDropDown
onChange={handleTaskStatusUpdate}
oldStatus={status}
oldProgress={percentCompleted}
/>
) : (
<Details detailType={'Status'} value={status} />
)}
<Details detailType={'Link'} value={link} />
<ProgressContainer
content={taskDetailsData}
key={percentCompleted}
/>
</div>
);
};
57 changes: 57 additions & 0 deletions src/components/taskDetails/TaskHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import React from 'react';
import { Button, Textarea } from './index';
import styles from './task-details.module.scss';

interface TaskHeaderProps {
isEditing: boolean;
tejaskh3 marked this conversation as resolved.
Show resolved Hide resolved
setIsEditing: (isEditing: boolean) => void;
onSave: () => void;
onCancel: () => void;
title: string;
handleChange: (event: React.ChangeEvent<HTMLTextAreaElement>) => void;
isUserAuthorized: boolean;
}

export const TaskHeader: React.FC<TaskHeaderProps> = ({
isEditing,
setIsEditing,
onSave,
onCancel,
title,
handleChange,
isUserAuthorized,
}) => {
if (isEditing) {
return (
<div className={styles.titleContainer}>
<Textarea
name="title"
value={title}
onChange={handleChange}
testId="title-textarea"
placeholder="Enter task title"
/>
<div className={styles.editMode}>
<Button buttonName="Cancel" clickHandler={onCancel} />
<Button buttonName="Save" clickHandler={onSave} />
</div>
</div>
);
}

return (
<div className={styles.titleContainer}>
<span data-testid="task-title" className={styles.taskTitle}>
{title}
</span>
{isUserAuthorized && (
<Button
buttonName="Edit"
clickHandler={setIsEditing}
value={true}
className={styles.editButton}
/>
)}
</div>
);
};
55 changes: 55 additions & 0 deletions src/components/taskDetails/TaskParticipants.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React, { useRef } from 'react';
import Suggestions from '../tasks/SuggestionBox/Suggestions';
import styles from './task-details.module.scss';

interface TaskParticipantsProps {
isEditing: boolean;
isUserAuthorized: boolean;
assigneeName: string;
showSuggestion: boolean;
handleAssignment: (e: React.ChangeEvent<HTMLInputElement>) => void;
handleAssigneSelect: (userName: string) => void;
setShowSuggestion: (show: boolean) => void;
}

export const TaskParticipants: React.FC<TaskParticipantsProps> = ({
isEditing,
isUserAuthorized,
assigneeName,
showSuggestion,
handleAssignment,
handleAssigneSelect,
setShowSuggestion,
}) => {
const inputRef = useRef<HTMLInputElement>(null);

return (
<>
<div className={styles.inputContainer}>
<label htmlFor="assigneeInput" className={styles.detailType}>
Assignee:
</label>
<div className={styles.inputContainer}>
{isEditing && isUserAuthorized ? (
<Suggestions
handleClick={handleAssigneSelect}
assigneeName={assigneeName}
showSuggestion={showSuggestion}
handleAssignment={handleAssignment}
setShowSuggestion={setShowSuggestion}
ref={inputRef}
/>
) : (
<span className={styles.detailValue}>
{assigneeName}
</span>
)}
</div>
</div>
<div className={styles.inputContainer}>
<label className={styles.detailType}>Reporter:</label>
<span className={styles.detailValue}>Ankush</span>
</div>
</>
);
};
Loading
Loading