Skip to content

Commit b1de52c

Browse files
committed
feat(js): Dynamic snooze dropdown
1 parent 06930ed commit b1de52c

File tree

3 files changed

+72
-71
lines changed

3 files changed

+72
-71
lines changed

packages/js/src/ui/components/Notification/DefaultNotification.tsx

+60-50
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { MarkAsUnread } from '../../icons/MarkAsUnread';
1212
import { Snooze } from '../../icons/Snooze';
1313
import { Unsnooze } from '../../icons/Unsnooze';
1414
import {
15+
LocalizationKey,
1516
NotificationStatus,
1617
type BodyRenderer,
1718
type NotificationActionClickHandler,
@@ -25,6 +26,38 @@ import { Badge } from '../primitives/Badge';
2526
import { Tooltip } from '../primitives/Tooltip';
2627
import { SnoozeDateTimePicker } from './SnoozeDateTimePicker';
2728

29+
const SNOOZE_PRESETS = [
30+
{
31+
key: 'snooze.options.inOneHour',
32+
hours: 1,
33+
getDate: () => new Date(Date.now() + 1 * 60 * 60 * 1000),
34+
},
35+
{
36+
key: 'snooze.options.inTwoHours',
37+
hours: 2,
38+
getDate: () => new Date(Date.now() + 2 * 60 * 60 * 1000),
39+
},
40+
{
41+
key: 'snooze.options.inTwelveHours',
42+
hours: 12,
43+
getDate: () => new Date(Date.now() + 12 * 60 * 60 * 1000),
44+
},
45+
{
46+
key: 'snooze.options.inOneDay',
47+
hours: 24,
48+
getDate: () => new Date(Date.now() + 1 * 24 * 60 * 60 * 1000),
49+
},
50+
{
51+
key: 'snooze.options.inOneWeek',
52+
hours: 168,
53+
getDate: () => new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
54+
},
55+
] satisfies {
56+
key: LocalizationKey;
57+
hours: number;
58+
getDate: () => Date;
59+
}[];
60+
2861
type DefaultNotificationProps = {
2962
notification: Notification;
3063
renderSubject?: SubjectRenderer;
@@ -65,6 +98,12 @@ export const DefaultNotification = (props: DefaultNotificationProps) => {
6598
);
6699
});
67100

101+
const availableSnoozePresets = createMemo(() => {
102+
if (!maxSnoozeDurationHours()) return SNOOZE_PRESETS;
103+
104+
return SNOOZE_PRESETS.filter((preset) => preset.hours <= maxSnoozeDurationHours());
105+
});
106+
68107
createEffect(() => {
69108
const interval = setInterval(() => {
70109
setMinutesPassed((prev) => prev + 1);
@@ -242,55 +281,26 @@ export const DefaultNotification = (props: DefaultNotificationProps) => {
242281
)}
243282
/>
244283
<Dropdown.Content portal appearanceKey="notificationSnooze__dropdownContent">
245-
<Dropdown.Item
246-
appearanceKey="notificationSnooze__dropdownItem"
247-
onClick={async (e) => {
248-
e.stopPropagation();
249-
await props.notification.snooze(new Date(Date.now() + 2 * 60 * 1000).toISOString());
250-
}}
251-
>
252-
<Clock
253-
class={style(
254-
'notificationSnooze__dropdownItem__icon',
255-
'nt-size-3 nt-text-foreground-alpha-400'
256-
)}
257-
/>
258-
{t('snooze.options.anHourFromNow')}
259-
</Dropdown.Item>
260-
<Dropdown.Item
261-
appearanceKey="notificationSnooze__dropdownItem"
262-
onClick={async (e) => {
263-
e.stopPropagation();
264-
await props.notification.snooze(
265-
new Date(Date.now() + 1 * 24 * 60 * 60 * 1000).toISOString()
266-
);
267-
}}
268-
>
269-
<Clock
270-
class={style(
271-
'notificationSnooze__dropdownItem__icon',
272-
'nt-size-3 nt-text-foreground-alpha-400'
273-
)}
274-
/>
275-
{new Date(Date.now() + 1 * 24 * 60 * 60 * 1000).toLocaleString()}
276-
</Dropdown.Item>
277-
<Dropdown.Item
278-
appearanceKey="notificationSnooze__dropdownItem"
279-
onClick={async (e) => {
280-
e.stopPropagation();
281-
await props.notification.snooze(
282-
new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString()
283-
);
284-
}}
285-
>
286-
<Clock
287-
class={style(
288-
'notificationSnooze__dropdownItem__icon',
289-
'nt-size-3 nt-text-foreground-alpha-400'
290-
)}
291-
/>
292-
{new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toLocaleString()}
293-
</Dropdown.Item>
284+
<For each={availableSnoozePresets()}>
285+
{(preset) => (
286+
<Dropdown.Item
287+
appearanceKey="notificationSnooze__dropdownItem"
288+
onClick={async (e) => {
289+
e.stopPropagation();
290+
await props.notification.snooze(preset.getDate().toISOString());
291+
}}
292+
>
293+
<Clock
294+
class={style(
295+
'notificationSnooze__dropdownItem__icon',
296+
'nt-size-3 nt-text-foreground-alpha-400'
297+
)}
298+
/>
299+
{t(preset.key)}
300+
</Dropdown.Item>
301+
)}
302+
</For>
303+
294304
<Popover.Root open={isSnoozeDateTimePickerOpen()} onOpenChange={setIsSnoozeDateTimePickerOpen}>
295305
<Dropdown.Item
296306
asChild={(props) => (
@@ -304,7 +314,7 @@ export const DefaultNotification = (props: DefaultNotificationProps) => {
304314
'nt-size-3 nt-text-foreground-alpha-400'
305315
)}
306316
/>
307-
Custom time...
317+
{t('snooze.options.customTime')}
308318
</Popover.Trigger>
309319
)}
310320
/>

packages/js/src/ui/config/defaultLocalization.ts

+6
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ export const defaultLocalization = {
3636
'snooze.datePicker.cancel': 'Cancel',
3737
'snooze.options.anHourFromNow': 'An hour from now',
3838
'snooze.datePicker.applyTooltip': 'Date and time out of range',
39+
'snooze.options.customTime': 'Custom time...',
40+
'snooze.options.inOneHour': 'in 1 hour',
41+
'snooze.options.inTwoHours': 'in 2 hours',
42+
'snooze.options.inTwelveHours': 'in 12 hours',
43+
'snooze.options.inOneDay': 'in 1 day',
44+
'snooze.options.inOneWeek': 'in 1 week',
3945
} as const;
4046

4147
export const [dynamicLocalization, setDynamicLocalization] = createSignal<Record<string, string>>({});

packages/js/src/ui/icons/Unsnooze.tsx

+6-21
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,12 @@ import { JSX } from 'solid-js';
33
export const Unsnooze = (props?: JSX.HTMLAttributes<SVGSVGElement>) => {
44
return (
55
<svg viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
6-
<g clip-path="url(#clip0_3196_17609)">
7-
<path
8-
d="M4.99992 9.16634C7.30111 9.16634 9.16658 7.30086 9.16658 4.99967C9.16658 2.69849 7.30111 0.833008 4.99992 0.833008C2.69873 0.833008 0.833252 2.69849 0.833252 4.99967C0.833252 7.30086 2.69873 9.16634 4.99992 9.16634Z"
9-
stroke="currentColor"
10-
stroke-linecap="round"
11-
stroke-linejoin="round"
12-
/>
13-
<path d="M5 2.91699V5.00033" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" />
14-
<path
15-
d="M4.80005 5.39648L3.27405 6.46585"
16-
stroke="currentColor"
17-
stroke-linecap="round"
18-
stroke-linejoin="round"
19-
/>
20-
<path
21-
d="M1.66675 1.66699L8.33341 8.33366"
22-
stroke="currentColor"
23-
stroke-linecap="round"
24-
stroke-linejoin="round"
25-
/>
26-
</g>
6+
<path
7+
d="M4.99992 2.91634V4.99967M4.79992 5.39616L3.27392 6.46553M1.66659 1.66634L8.33325 8.33301M9.16658 4.99967C9.16658 7.30086 7.30111 9.16634 4.99992 9.16634C2.69873 9.16634 0.833252 7.30086 0.833252 4.99967C0.833252 2.69849 2.69873 0.833008 4.99992 0.833008C7.30111 0.833008 9.16658 2.69849 9.16658 4.99967Z"
8+
stroke="currentColor"
9+
stroke-linecap="round"
10+
stroke-linejoin="round"
11+
/>
2712
</svg>
2813
);
2914
};

0 commit comments

Comments
 (0)