mirror of
https://github.com/chenasraf/nextcloud-pantry.git
synced 2026-05-17 17:28:01 +00:00
feat: show next due date for items
This commit is contained in:
@@ -57,6 +57,7 @@ vi.mock('@/api/images', () => ({
|
||||
|
||||
vi.mock('@/utils/rrule', () => ({
|
||||
formatRrule: (rrule: string) => rrule,
|
||||
formatNextRecurrence: () => null,
|
||||
}))
|
||||
|
||||
import ChecklistItemRow from './ChecklistItemRow.vue'
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
</NcCheckboxRadioSwitch>
|
||||
<div class="checklist-row__meta">
|
||||
<span v-if="item.quantity" class="checklist-row__quantity">× {{ item.quantity }}</span>
|
||||
<span v-if="item.rrule" class="checklist-row__recurrence" :title="item.rrule">
|
||||
<span v-if="item.rrule" class="checklist-row__recurrence" :title="recurrenceTooltip">
|
||||
<RepeatIcon :size="14" />
|
||||
{{ formatRrule(item.rrule) }}
|
||||
</span>
|
||||
@@ -77,7 +77,7 @@ import DeleteIcon from '@icons/Delete.vue'
|
||||
import ArrowRightIcon from '@icons/ArrowRight.vue'
|
||||
import { categoryIconComponent } from '@/components/CategoryPicker'
|
||||
import { itemImagePreviewUrl } from '@/api/images'
|
||||
import { formatRrule } from '@/utils/rrule'
|
||||
import { formatRrule, formatNextRecurrence } from '@/utils/rrule'
|
||||
import type { ChecklistItem, Category } from '@/api/types'
|
||||
|
||||
const props = withDefaults(
|
||||
@@ -127,6 +127,15 @@ const thumbUrl = computed(() =>
|
||||
: '',
|
||||
)
|
||||
|
||||
const recurrenceTooltip = computed(() => {
|
||||
const next = formatNextRecurrence(
|
||||
props.item.nextDueAt,
|
||||
props.item.repeatFromCompletion,
|
||||
props.item.done,
|
||||
)
|
||||
return next ? t('pantry', 'Next: {next}', { next }) : formatRrule(props.item.rrule!)
|
||||
})
|
||||
|
||||
const strings = {
|
||||
viewImage: t('pantry', 'View image'),
|
||||
viewItem: t('pantry', 'View item'),
|
||||
|
||||
@@ -45,6 +45,7 @@ vi.mock('@/api/images', () => ({
|
||||
|
||||
vi.mock('@/utils/rrule', () => ({
|
||||
formatRrule: (rrule: string) => rrule,
|
||||
formatNextRecurrence: () => null,
|
||||
}))
|
||||
|
||||
import ChecklistItemViewDialog from './ChecklistItemViewDialog.vue'
|
||||
|
||||
@@ -40,6 +40,10 @@
|
||||
{{ formatRrule(item.rrule) }}
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="nextRecurrence" class="item-view__row">
|
||||
<span class="item-view__label">{{ strings.nextRecurrence }}:</span>
|
||||
<span>{{ nextRecurrence }}</span>
|
||||
</div>
|
||||
<div v-if="item.done" class="item-view__row">
|
||||
<span class="item-view__label">{{ strings.status }}:</span>
|
||||
<span>{{ strings.done }}</span>
|
||||
@@ -67,7 +71,7 @@ import RepeatIcon from '@icons/Repeat.vue'
|
||||
import PencilIcon from '@icons/Pencil.vue'
|
||||
import { categoryIconComponent } from '@/components/CategoryPicker'
|
||||
import { itemImagePreviewUrl } from '@/api/images'
|
||||
import { formatRrule } from '@/utils/rrule'
|
||||
import { formatRrule, formatNextRecurrence } from '@/utils/rrule'
|
||||
import type { ChecklistItem, Category } from '@/api/types'
|
||||
|
||||
const props = defineProps<{
|
||||
@@ -89,11 +93,18 @@ const largeUrl = computed(() =>
|
||||
: '',
|
||||
)
|
||||
|
||||
const nextRecurrence = computed(() =>
|
||||
props.item.rrule
|
||||
? formatNextRecurrence(props.item.nextDueAt, props.item.repeatFromCompletion, props.item.done)
|
||||
: null,
|
||||
)
|
||||
|
||||
const strings = {
|
||||
viewImage: t('pantry', 'View image'),
|
||||
quantity: t('pantry', 'Quantity'),
|
||||
category: t('pantry', 'Category'),
|
||||
recurrence: t('pantry', 'Recurrence'),
|
||||
nextRecurrence: t('pantry', 'Next recurrence'),
|
||||
status: t('pantry', 'Status'),
|
||||
done: t('pantry', 'Done'),
|
||||
editItem: t('pantry', 'Edit item'),
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { t } from '@nextcloud/l10n'
|
||||
import { RRule } from 'rrule'
|
||||
|
||||
export function formatRrule(rrule: string): string {
|
||||
@@ -8,3 +9,27 @@ export function formatRrule(rrule: string): string {
|
||||
return rrule
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a human-readable "next recurrence" string for a checklist item.
|
||||
*/
|
||||
export function formatNextRecurrence(
|
||||
nextDueAt: number | null,
|
||||
repeatFromCompletion: boolean,
|
||||
done: boolean,
|
||||
): string | null {
|
||||
if (nextDueAt) {
|
||||
const date = new Date(nextDueAt * 1000)
|
||||
return date.toLocaleDateString(undefined, {
|
||||
year: 'numeric',
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
})
|
||||
}
|
||||
if (repeatFromCompletion && !done) {
|
||||
return t('pantry', 'Starts after completion')
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user