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(time-picker): Added min and max props #590

Merged
merged 1 commit into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
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
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,27 @@ <h3>Disabled</h3>

<h3>Has Error</h3>
<gux-time-picker has-error></gux-time-picker>

<h3>Min of "03:15" and Max of "10:45" with 24 Hour Time Format</h3>
katie-bobbe-genesys marked this conversation as resolved.
Show resolved Hide resolved
<gux-time-picker
value="16:15"
interval="15"
min="03:15"
max="10:45"
clock-type="24h"
></gux-time-picker>

<h3>
Wrapped around boundaries: min of "20:30" and Max of "04:45" with 24 Hour
Time Format
</h3>
<gux-time-picker
value="16:15"
interval="15"
min="20:30"
max="04:45"
clock-type="24h"
></gux-time-picker>
</form>

<h2>Languages</h2>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ import {

export function getTimeDisplayValues(
minuteInterval: GuxMinuteInterval,
clockType: GuxClockType
clockType: GuxClockType,
min?: string,
max?: string
): GuxISOHourMinute[] {
const minuteOptions = [0, 15, 30, 45]
.filter(option => Number.isInteger(option / minuteInterval))
Expand All @@ -22,13 +24,59 @@ export function getTimeDisplayValues(
? ['12', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11']
: Array.from(Array(24).keys()).map(x => String(x).padStart(2, '0'));

return hourOptions.reduce((acc, hourOption) => {
const hourOptionsFormatted = hourOptions.reduce((acc, hourOption) => {
return acc.concat(
minuteOptions.map(
minuteOption => `${hourOption}:${minuteOption}`
) as GuxISOHourMinute[]
);
}, [] as GuxISOHourMinute[]);

return clockType === '24h'
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@katie-bobbe-genesys this is where I check if the clocktype is 24h before applying the min/max check.

? applyHourBoundaries(hourOptionsFormatted, min, max)
: hourOptionsFormatted;
}

function applyHourBoundaries(hours: string[], min?: string, max?: string) {
// Check if min and max are wrapped around (e.g. min of 22:00 and max of 04:00)
if (min && max && hourToMilliseconds(min) > hourToMilliseconds(max)) {
hours = hours.filter(hour => {
const hourConverted = hourToMilliseconds(hour);
const minConverted = hourToMilliseconds(min);
const maxConverted = hourToMilliseconds(max);
const dayCeiling = hourToMilliseconds('23:59');

return (
(hourConverted >= minConverted && hourConverted < dayCeiling) ||
hourConverted <= maxConverted
);
});
} else {
// min and max are not wrapped around (e.g. min of 03:30 and max of 20:00)
if (min) {
hours = hours.filter(
hour => hourToMilliseconds(hour) >= hourToMilliseconds(min)
);
}
if (max) {
hours = hours.filter(
hour => hourToMilliseconds(hour) <= hourToMilliseconds(max)
);
}
}

return hours as GuxISOHourMinute[];
}

function hourToMilliseconds(hour: string): number {
// Convert the hour to milliseconds from midnight
const date = new Date();
const [hours, minutes] = hour.split(':');
date.setHours(parseFloat(hours));
date.setMinutes(parseFloat(minutes));
date.setSeconds(0);
const seconds = date.getTime();
return seconds;
}

export function getLocaleClockType(root: HTMLElement): GuxClockType {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ export class GuxTimePicker {
@Prop({ mutable: true })
clockType: GuxClockType;

@Prop()
min?: string;

@Prop()
max?: string;

@State()
expanded: boolean = false;

Expand Down Expand Up @@ -102,6 +108,10 @@ export class GuxTimePicker {

this.i18n = await buildI18nForComponent(this.root, translationResources);
this.clockType = this.clockType || getLocaleClockType(this.root);

if (this.clockType == '12h' && (this.min || this.max)) {
console.error('clock type must be "24h" when using min/max props');
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@katie-bobbe-genesys I had this code here already to check if the clock type is 12h but I used a console error. Should I keep this code but change to a console warn? I'll also do an if check like you mentioned to ignore the min/max logic in a certain scenario.

}
}

private updateValue(
Expand Down Expand Up @@ -343,20 +353,23 @@ export class GuxTimePicker {
}

private renderTimeListItems(): JSX.Element[] {
return getTimeDisplayValues(this.interval, this.clockType).map(
displayValue => {
const value = getValue(displayValue, this.clockType, isAm(this.value));

return (
<gux-list-item
id={this.valueToId(value)}
onClick={() => this.handleClickDropdownValue(displayValue)}
>
{displayValue}
</gux-list-item>
) as JSX.Element;
}
);
return getTimeDisplayValues(
this.interval,
this.clockType,
this.min,
this.max
).map(displayValue => {
const value = getValue(displayValue, this.clockType, isAm(this.value));

return (
<gux-list-item
id={this.valueToId(value)}
onClick={() => this.handleClickDropdownValue(displayValue)}
>
{displayValue}
</gux-list-item>
) as JSX.Element;
});
}

private renderTarget(): JSX.Element {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
| `disabled` | `disabled` | | `boolean` | `false` |
| `hasError` | `has-error` | | `boolean` | `false` |
| `interval` | `interval` | | `15 \| 30 \| 60` | `60` |
| `max` | `max` | | `string` | `undefined` |
| `min` | `min` | | `string` | `undefined` |
| `required` | `required` | | `boolean` | `false` |
| `step` | `step` | | `1 \| 10 \| 15 \| 20 \| 30 \| 5 \| 60` | `1` |
| `value` | `value` | | ``${string}:${string}`` | `'00:00'` |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,68 @@ describe('gux-time-picker.service', () => {
);
});

describe('#getTimeDisplayValues with set boundaries', () => {
it(`should work as expected for 24h with 30 minute intervals and boundaries of 08:30-20:00`, async () => {
const minuteInterval = 30;
const clockType = '24h';
const min = '08:30';
const max = '20:00';
const expectedOutput = [
'08:30',
'09:00',
'09:30',
'10:00',
'10:30',
'11:00',
'11:30',
'12:00',
'12:30',
'13:00',
'13:30',
'14:00',
'14:30',
'15:00',
'15:30',
'16:00',
'16:30',
'17:00',
'17:30',
'18:00',
'18:30',
'19:00',
'19:30',
'20:00'
];

expect(
getTimeDisplayValues(minuteInterval, clockType, min, max)
).toStrictEqual(expectedOutput);
});

it(`should work as expected for 24h with 30 minute intervals and wrapped around boundaries of 22:00-02:30`, async () => {
const minuteInterval = 30;
const clockType = '24h';
const min = '22:00';
const max = '02:30';
const expectedOutput = [
'00:00',
'00:30',
'01:00',
'01:30',
'02:00',
'02:30',
'22:00',
'22:30',
'23:00',
'23:30'
];

expect(
getTimeDisplayValues(minuteInterval, clockType, min, max)
).toStrictEqual(expectedOutput);
});
});

describe('#getLocaleClockType', () => {
[
{ locale: 'ar' },
Expand Down