diff --git a/src/components/ChecklistItemRow/ChecklistItemRow.test.ts b/src/components/ChecklistItemRow/ChecklistItemRow.test.ts
index 0e166f5..489c48f 100644
--- a/src/components/ChecklistItemRow/ChecklistItemRow.test.ts
+++ b/src/components/ChecklistItemRow/ChecklistItemRow.test.ts
@@ -57,6 +57,7 @@ vi.mock('@/api/images', () => ({
vi.mock('@/utils/rrule', () => ({
formatRrule: (rrule: string) => rrule,
+ formatNextRecurrence: () => null,
}))
import ChecklistItemRow from './ChecklistItemRow.vue'
diff --git a/src/components/ChecklistItemRow/ChecklistItemRow.vue b/src/components/ChecklistItemRow/ChecklistItemRow.vue
index 6bdfb6a..306dbbd 100644
--- a/src/components/ChecklistItemRow/ChecklistItemRow.vue
+++ b/src/components/ChecklistItemRow/ChecklistItemRow.vue
@@ -24,7 +24,7 @@
× {{ item.quantity }}
-
+
{{ formatRrule(item.rrule) }}
@@ -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'),
diff --git a/src/components/ChecklistItemViewDialog/ChecklistItemViewDialog.test.ts b/src/components/ChecklistItemViewDialog/ChecklistItemViewDialog.test.ts
index 5854c9f..54c7dc9 100644
--- a/src/components/ChecklistItemViewDialog/ChecklistItemViewDialog.test.ts
+++ b/src/components/ChecklistItemViewDialog/ChecklistItemViewDialog.test.ts
@@ -45,6 +45,7 @@ vi.mock('@/api/images', () => ({
vi.mock('@/utils/rrule', () => ({
formatRrule: (rrule: string) => rrule,
+ formatNextRecurrence: () => null,
}))
import ChecklistItemViewDialog from './ChecklistItemViewDialog.vue'
diff --git a/src/components/ChecklistItemViewDialog/ChecklistItemViewDialog.vue b/src/components/ChecklistItemViewDialog/ChecklistItemViewDialog.vue
index 6b64899..9b2be47 100644
--- a/src/components/ChecklistItemViewDialog/ChecklistItemViewDialog.vue
+++ b/src/components/ChecklistItemViewDialog/ChecklistItemViewDialog.vue
@@ -40,6 +40,10 @@
{{ formatRrule(item.rrule) }}
+
+ {{ strings.nextRecurrence }}:
+ {{ nextRecurrence }}
+
{{ strings.status }}:
{{ strings.done }}
@@ -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'),
diff --git a/src/utils/rrule.ts b/src/utils/rrule.ts
index f02b1f0..09819e0 100644
--- a/src/utils/rrule.ts
+++ b/src/utils/rrule.ts
@@ -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
+}