Skip to content
Merged
Changes from all commits
Commits
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
34 changes: 18 additions & 16 deletions web/src/pages/Cases/CaseDetails/Timeline.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ const Timeline: React.FC<{
currentPeriodIndex: number;
}> = ({ currentPeriodIndex, dispute }) => {
const currentItemIndex = currentPeriodToCurrentItem(currentPeriodIndex, dispute?.court.hiddenVotes);
const items = useTimeline(dispute, currentItemIndex, currentItemIndex);
const items = useTimeline(dispute, currentPeriodIndex);

return (
<TimeLineContainer>
Expand Down Expand Up @@ -103,41 +103,43 @@ const currentPeriodToCurrentItem = (currentPeriodIndex: number, hiddenVotes?: bo
else return currentPeriodIndex - 1;
};

const useTimeline = (dispute: DisputeDetailsQuery["dispute"], currentItemIndex: number, currentPeriodIndex: number) => {
const useTimeline = (dispute: DisputeDetailsQuery["dispute"], currentPeriodIndex: number) => {
const isDesktop = useIsDesktop();
const titles = useMemo(() => {
const titles = ["Evidence", "Voting", "Appeal", "Executed"];
if (dispute?.court.hiddenVotes) {
titles.splice(1, 0, "Commit");
}
return titles;
}, [dispute]);
const titles = ["Evidence", "Commit", "Voting", "Appeal", "Executed"];

const deadlineCurrentPeriod = getDeadline(
currentPeriodIndex,
dispute?.lastPeriodChange,
dispute?.court.timesPerPeriod
);

const countdown = useCountdown(deadlineCurrentPeriod);
const getSubitems = (index: number): string[] | React.ReactNode[] => {
if (typeof countdown !== "undefined" && dispute) {
if (index === titles.length - 1) {
return [];
} else if (index === currentItemIndex && countdown === 0) {
} else if (index === currentPeriodIndex && countdown === 0) {
return ["Time's up!"];
} else if (index < currentItemIndex) {
} else if (index < currentPeriodIndex) {
return [];
} else if (index === currentItemIndex) {
} else if (index === currentPeriodIndex) {
return [secondsToDayHourMinute(countdown)];
} else {
Comment on lines +121 to 127
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Clamp “Time’s up!” condition to countdown <= 0 to avoid negative durations

If useCountdown ever returns negative values after the deadline, the UI could show negative durations instead of “Time’s up!”. Using <= 0 is safer and avoids transient negative subitems.

Apply this diff:

-      } else if (index === currentPeriodIndex && countdown === 0) {
+      } else if (index === currentPeriodIndex && countdown <= 0) {
         return ["Time's up!"];
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
} else if (index === currentPeriodIndex && countdown === 0) {
return ["Time's up!"];
} else if (index < currentItemIndex) {
} else if (index < currentPeriodIndex) {
return [];
} else if (index === currentItemIndex) {
} else if (index === currentPeriodIndex) {
return [secondsToDayHourMinute(countdown)];
} else {
} else if (index === currentPeriodIndex && countdown <= 0) {
return ["Time's up!"];
} else if (index < currentPeriodIndex) {
return [];
} else if (index === currentPeriodIndex) {
return [secondsToDayHourMinute(countdown)];
} else {
🤖 Prompt for AI Agents
In web/src/pages/Cases/CaseDetails/Timeline.tsx around lines 121 to 127, the
condition that shows "Time's up!" checks countdown === 0 which can allow
negative durations to render; change the condition to use countdown <= 0 so any
non-positive countdown displays "Time's up!" instead of a negative time string,
keeping the rest of the branch order intact.

return [secondsToDayHourMinute(dispute?.court.timesPerPeriod[index])];
}
Comment on lines 117 to 129
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Fix type mismatch and potential NaN in future-period subitems

secondsToDayHourMinute expects a number, but dispute?.court.timesPerPeriod[index] is typed as string | undefined. This can produce type errors and NaN at runtime when values are undefined or non-numeric. Parse the value and provide a safe default.

Apply this diff:

-      } else {
-        return [secondsToDayHourMinute(dispute?.court.timesPerPeriod[index])];
-      }
+      } else {
+        const raw = dispute?.court.timesPerPeriod?.[index];
+        const periodSeconds = Number(raw ?? 0);
+        return [secondsToDayHourMinute(periodSeconds)];
+      }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const getSubitems = (index: number): string[] | React.ReactNode[] => {
if (typeof countdown !== "undefined" && dispute) {
if (index === titles.length - 1) {
return [];
} else if (index === currentItemIndex && countdown === 0) {
} else if (index === currentPeriodIndex && countdown === 0) {
return ["Time's up!"];
} else if (index < currentItemIndex) {
} else if (index < currentPeriodIndex) {
return [];
} else if (index === currentItemIndex) {
} else if (index === currentPeriodIndex) {
return [secondsToDayHourMinute(countdown)];
} else {
return [secondsToDayHourMinute(dispute?.court.timesPerPeriod[index])];
}
} else if (index === currentPeriodIndex) {
return [secondsToDayHourMinute(countdown)];
} else {
- return [secondsToDayHourMinute(dispute?.court.timesPerPeriod[index])];
+ const raw = dispute?.court.timesPerPeriod?.[index];
+ const periodSeconds = Number(raw ?? 0);
+ return [secondsToDayHourMinute(periodSeconds)];
}
🤖 Prompt for AI Agents
In web/src/pages/Cases/CaseDetails/Timeline.tsx around lines 117 to 129,
secondsToDayHourMinute is being passed dispute?.court.timesPerPeriod[index]
which is typed string | undefined causing type errors and possible NaN; convert
the value to a number safely and provide a fallback before calling
secondsToDayHourMinute (e.g. const secs =
Number(dispute?.court.timesPerPeriod[index]); if (!Number.isFinite(secs) ||
isNaN(secs)) use 0 or another sensible default) and pass secs to
secondsToDayHourMinute so the function always receives a valid number.

}
return [<StyledSkeleton key={index} width={60} />];
};
return titles.map((title, i) => ({
title: i + 1 < titles.length && isDesktop ? `${title} Period` : title,
subitems: getSubitems(i),
}));
return titles.flatMap((title, i) => {
// if not hidden votes, skip commit index
if (!dispute?.court.hiddenVotes && i === Periods.commit) return [];
return [
{
title: i + 1 < titles.length && isDesktop ? `${title} Period` : title,
subitems: getSubitems(i),
},
];
});
};

export const getDeadline = (
Expand Down
Loading