Skip to content

Commit 48515fc

Browse files
committed
feat: added shortcuts for date picking in user modal
1 parent 7be3548 commit 48515fc

File tree

2 files changed

+106
-39
lines changed

2 files changed

+106
-39
lines changed

dashboard/src/components/common/date-picker.tsx

Lines changed: 45 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -199,14 +199,8 @@ export function DatePicker({
199199
selectedDate = new Date(now)
200200
}
201201

202-
// Set time based on whether it's today
203-
if (selectedDateOnly.getTime() === today.getTime()) {
204-
// Set to end of day if today
205-
selectedDate.setHours(23, 59, 59)
206-
} else {
207-
// Set current time for future dates
208-
selectedDate.setHours(now.getHours(), now.getMinutes())
209-
}
202+
// Always use current time (not end of day)
203+
selectedDate.setHours(now.getHours(), now.getMinutes(), now.getSeconds(), now.getMilliseconds())
210204

211205
setInternalDate(selectedDate)
212206
const value = useUtcTimestamp ? Math.floor(selectedDate.getTime() / 1000) : getLocalISOTime(selectedDate)
@@ -368,15 +362,49 @@ export function DatePicker({
368362
/>
369363
)}
370364
{showTime && (
371-
<div className="flex items-center gap-4 border-t p-3">
372-
<Input
373-
type="time"
374-
value={timeValue}
375-
onChange={handleTimeChange}
376-
className="w-full"
377-
dir="ltr"
378-
/>
379-
</div>
365+
<>
366+
<div className="hidden lg:flex items-center gap-1.5 flex-wrap border-t p-3">
367+
{[
368+
{ label: '7d', days: 7 },
369+
{ label: '30d', days: 30 },
370+
{ label: '60d', days: 60 },
371+
{ label: '90d', days: 90 },
372+
{ label: '1y', days: 365 },
373+
].map(({ label, days }) => {
374+
const handleShortcut = () => {
375+
const targetDate = new Date(now)
376+
targetDate.setDate(now.getDate() + days)
377+
// Use current time instead of end of day
378+
handleDateSelect(targetDate)
379+
}
380+
return (
381+
<Button
382+
key={label}
383+
type="button"
384+
variant="ghost"
385+
size="sm"
386+
className="h-7 px-2.5 text-xs text-muted-foreground hover:text-foreground"
387+
onClick={(e) => {
388+
e.preventDefault()
389+
e.stopPropagation()
390+
handleShortcut()
391+
}}
392+
>
393+
{label}
394+
</Button>
395+
)
396+
})}
397+
</div>
398+
<div className="flex items-center gap-4 border-t p-3">
399+
<Input
400+
type="time"
401+
value={timeValue}
402+
onChange={handleTimeChange}
403+
className="w-full"
404+
dir="ltr"
405+
/>
406+
</div>
407+
</>
380408
)}
381409
</PopoverContent>
382410
</Popover>

dashboard/src/components/dialogs/user-modal.tsx

Lines changed: 61 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -131,34 +131,73 @@ const ExpiryDateField = ({
131131
[field, handleFieldChange, startTransition, useUtcTimestamp, fieldName],
132132
)
133133

134+
const handleShortcut = React.useCallback(
135+
(days: number) => {
136+
const now = new Date()
137+
const targetDate = new Date(now)
138+
targetDate.setDate(now.getDate() + days)
139+
// Use current time instead of end of day
140+
handleDateChange(targetDate)
141+
},
142+
[handleDateChange],
143+
)
144+
134145
const now = new Date()
135146
const maxDate = new Date(now.getFullYear() + 15, 11, 31)
136147

148+
const shortcuts = [
149+
{ label: '7d', days: 7 },
150+
{ label: '1m', days: 30 },
151+
{ label: '2m', days: 60 },
152+
{ label: '3m', days: 90 },
153+
{ label: '1y', days: 365 },
154+
]
155+
137156
return (
138157
<FormItem className="flex flex-1 flex-col">
139158
<FormLabel className='mb-0.5'>{label}</FormLabel>
140-
<div className="relative">
141-
<DatePicker
142-
mode="single"
143-
date={displayDate}
144-
onDateChange={handleDateChange}
145-
showTime={true}
146-
useUtcTimestamp={useUtcTimestamp}
147-
placeholder={t('userDialog.expireDate', { defaultValue: 'Expire date' })}
148-
minDate={now}
149-
maxDate={maxDate}
150-
open={calendarOpen}
151-
onOpenChange={setCalendarOpen}
152-
fieldName={fieldName}
153-
onFieldChange={handleFieldChange}
154-
/>
155-
{expireInfo && (
156-
<p className={cn('absolute top-full text-end right-0 mt-1 whitespace-nowrap text-xs text-muted-foreground', !expireInfo.time && 'hidden', dir === 'rtl' ? 'right-0' : 'left-0')}>
157-
{expireInfo.time !== '0' && expireInfo.time !== '0s'
158-
? t('expires', { time: expireInfo.time, defaultValue: 'Expires in {{time}}' })
159-
: t('expired', { time: expireInfo.time, defaultValue: 'Expired in {{time}}' })}
160-
</p>
161-
)}
159+
<div className="space-y-2">
160+
<div className="flex lg:hidden items-center gap-1.5 flex-wrap">
161+
{shortcuts.map(({ label, days }) => (
162+
<Button
163+
key={label}
164+
type="button"
165+
variant="ghost"
166+
size="sm"
167+
className="h-7 px-2.5 text-xs text-muted-foreground hover:text-foreground"
168+
onClick={(e) => {
169+
e.preventDefault()
170+
e.stopPropagation()
171+
handleShortcut(days)
172+
}}
173+
>
174+
{label}
175+
</Button>
176+
))}
177+
</div>
178+
<div className="relative">
179+
<DatePicker
180+
mode="single"
181+
date={displayDate}
182+
onDateChange={handleDateChange}
183+
showTime={true}
184+
useUtcTimestamp={useUtcTimestamp}
185+
placeholder={t('userDialog.expireDate', { defaultValue: 'Expire date' })}
186+
minDate={now}
187+
maxDate={maxDate}
188+
open={calendarOpen}
189+
onOpenChange={setCalendarOpen}
190+
fieldName={fieldName}
191+
onFieldChange={handleFieldChange}
192+
/>
193+
{expireInfo && (
194+
<p className={cn('absolute top-full text-end right-0 mt-1 whitespace-nowrap text-xs text-muted-foreground', !expireInfo.time && 'hidden', dir === 'rtl' ? 'right-0' : 'left-0')}>
195+
{expireInfo.time !== '0' && expireInfo.time !== '0s'
196+
? t('expires', { time: expireInfo.time, defaultValue: 'Expires in {{time}}' })
197+
: t('expired', { time: expireInfo.time, defaultValue: 'Expired in {{time}}' })}
198+
</p>
199+
)}
200+
</div>
162201
</div>
163202
<FormMessage />
164203
</FormItem>

0 commit comments

Comments
 (0)