Skip to content

Commit aaa5071

Browse files
rowansmithauclaude
andauthored
fix: fix for template dormancy hour/day toggle (#19884)
resolves #15451 > Solution: Selecting days is always be enabled and rounds (up) the hours to the nearest day. I.e. 25 hours -> 2 days. tested with 26hrs saved, then toggled to days. result = value changed to 2 days If you have used AI to produce some or all of this PR, please ensure you have read our [AI Contribution guidelines](https://coder.com/docs/about/contributing/AI_CONTRIBUTING) before submitting. blink helped --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 54ce03a commit aaa5071

File tree

2 files changed

+34
-21
lines changed

2 files changed

+34
-21
lines changed

site/src/components/DurationField/DurationField.stories.tsx

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,16 +64,27 @@ export const ChangeUnit: Story = {
6464
},
6565
};
6666

67-
export const CantConvertToDays: Story = {
67+
export const ConvertSmallHoursToDays: Story = {
6868
args: {
69-
valueMs: hoursToMs(2),
69+
valueMs: hoursToMs(2), // 2 hours should convert to 1 day when switching units (rounded up)
7070
},
7171
play: async ({ canvasElement }) => {
7272
const canvas = within(canvasElement);
73+
74+
// Initially should show 2 hours
75+
const input = canvas.getByLabelText("Duration");
76+
await expect(input).toHaveValue("2");
77+
78+
// Switch to days by clicking the dropdown
7379
const unitDropdown = canvas.getByLabelText("Time unit");
7480
await userEvent.click(unitDropdown);
81+
82+
// Find and click the Days option - this should now work (no longer disabled)
7583
const daysOption = within(document.body).getByText("Days");
76-
await expect(daysOption).toHaveAttribute("aria-disabled", "true");
84+
await userEvent.click(daysOption);
85+
86+
// After switching to days, should show 1 day (2 hours rounded up to nearest day)
87+
await expect(input).toHaveValue("1");
7788
},
7889
};
7990

site/src/components/DurationField/DurationField.tsx

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -45,19 +45,12 @@ const reducer = (state: State, action: Action): State => {
4545
state.unit,
4646
);
4747

48-
if (
49-
action.unit === "days" &&
50-
!canConvertDurationToDays(currentDurationMs)
51-
) {
52-
return state;
53-
}
54-
5548
return {
5649
unit: action.unit,
5750
durationFieldValue:
5851
action.unit === "hours"
5952
? durationInHours(currentDurationMs).toString()
60-
: durationInDays(currentDurationMs).toString(),
53+
: Math.ceil(durationInDays(currentDurationMs)).toString(),
6154
};
6255
}
6356
default: {
@@ -124,17 +117,30 @@ export const DurationField: FC<DurationFieldProps> = (props) => {
124117
type: "CHANGE_TIME_UNIT",
125118
unit,
126119
});
120+
121+
// Calculate the new duration in ms after changing the unit
122+
// Important: When changing from hours to days, we need to round up to nearest day
123+
// but keep the millisecond value consistent for the parent component
124+
let newDurationMs: number;
125+
if (unit === "hours") {
126+
// When switching to hours, use the current milliseconds to get exact hours
127+
newDurationMs = currentDurationMs;
128+
} else {
129+
// When switching to days, round up to the nearest day
130+
const daysValue = Math.ceil(durationInDays(currentDurationMs));
131+
newDurationMs = daysToDuration(daysValue);
132+
}
133+
134+
// Notify parent component if the value has changed
135+
if (newDurationMs !== parentValueMs) {
136+
onChange(newDurationMs);
137+
}
127138
}}
128139
inputProps={{ "aria-label": "Time unit" }}
129140
IconComponent={ChevronDownIcon}
130141
>
131142
<MenuItem value="hours">Hours</MenuItem>
132-
<MenuItem
133-
value="days"
134-
disabled={!canConvertDurationToDays(currentDurationMs)}
135-
>
136-
Days
137-
</MenuItem>
143+
<MenuItem value="days">Days</MenuItem>
138144
</Select>
139145
</div>
140146

@@ -181,7 +187,3 @@ function hoursToDuration(hours: number): number {
181187
function daysToDuration(days: number): number {
182188
return days * 24 * hoursToDuration(1);
183189
}
184-
185-
function canConvertDurationToDays(duration: number): boolean {
186-
return Number.isInteger(durationInDays(duration));
187-
}

0 commit comments

Comments
 (0)