Skip to content

Commit 8ae50c9

Browse files
committed
feat: add checklist item view modal
1 parent 219997d commit 8ae50c9

1 file changed

Lines changed: 144 additions & 0 deletions

File tree

src/views/ChecklistDetail.vue

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,11 @@
127127
</span>
128128
</div>
129129
<div class="pantry-item__actions">
130+
<NcButton variant="tertiary" :aria-label="strings.viewItem" @click="openView(item)">
131+
<template #icon>
132+
<EyeIcon :size="18" />
133+
</template>
134+
</NcButton>
130135
<NcActions :aria-label="strings.itemActions">
131136
<NcActionButton @click="startEdit(item)">
132137
<template #icon>
@@ -257,6 +262,74 @@
257262
v-model:from-completion="editRepeatFromCompletion"
258263
/>
259264

265+
<NcDialog
266+
v-if="viewing"
267+
:name="viewing.name"
268+
:open="!!viewing"
269+
close-on-click-outside
270+
size="normal"
271+
@update:open="(v) => !v && (viewing = null)"
272+
>
273+
<div class="pantry-view">
274+
<button
275+
v-if="viewing.imageFileId"
276+
type="button"
277+
class="pantry-view__image-btn"
278+
:aria-label="strings.viewImage"
279+
@click="previewing = viewing"
280+
>
281+
<img class="pantry-view__image" :src="largeUrl(viewing)" :alt="viewing.name" />
282+
</button>
283+
284+
<div v-if="viewing.description" class="pantry-view__description">
285+
<NcRichText
286+
:text="viewing.description"
287+
:use-markdown="true"
288+
:use-extended-markdown="true"
289+
/>
290+
</div>
291+
292+
<div class="pantry-view__details">
293+
<div v-if="viewing.quantity" class="pantry-view__row">
294+
<span class="pantry-view__label">{{ strings.quantityLabel }}:</span>
295+
<span>&times; {{ viewing.quantity }}</span>
296+
</div>
297+
<div v-if="categoryFor(viewing.categoryId)" class="pantry-view__row">
298+
<span class="pantry-view__label">{{ strings.categoryLabel }}:</span>
299+
<span
300+
class="pantry-item__category"
301+
:style="{ color: categoryFor(viewing.categoryId)!.color }"
302+
>
303+
<component
304+
:is="categoryIconComponent(categoryFor(viewing.categoryId)!.icon)"
305+
:size="14"
306+
/>
307+
{{ categoryFor(viewing.categoryId)!.name }}
308+
</span>
309+
</div>
310+
<div v-if="viewing.rrule" class="pantry-view__row">
311+
<span class="pantry-view__label">{{ strings.recurrenceLabel }}:</span>
312+
<span class="pantry-item__recurrence">
313+
<RepeatIcon :size="14" />
314+
{{ formatRrule(viewing.rrule) }}
315+
</span>
316+
</div>
317+
<div v-if="viewing.done" class="pantry-view__row">
318+
<span class="pantry-view__label">{{ strings.status }}:</span>
319+
<span>{{ strings.done }}</span>
320+
</div>
321+
</div>
322+
</div>
323+
<template #actions>
324+
<NcButton variant="tertiary" @click="viewToEdit">
325+
<template #icon>
326+
<PencilIcon :size="20" />
327+
</template>
328+
{{ strings.editItem }}
329+
</NcButton>
330+
</template>
331+
</NcDialog>
332+
260333
<NcDialog
261334
v-if="previewing"
262335
:name="previewing.name"
@@ -289,6 +362,7 @@ import PlusIcon from '@icons/Plus.vue'
289362
import ArrowLeftIcon from '@icons/ArrowLeft.vue'
290363
import DeleteIcon from '@icons/Delete.vue'
291364
import PencilIcon from '@icons/Pencil.vue'
365+
import EyeIcon from '@icons/Eye.vue'
292366
import RepeatIcon from '@icons/Repeat.vue'
293367
import ChevronDownIcon from '@icons/ChevronDown.vue'
294368
import { AutoResizeTextarea } from '@/components/AutoResizeTextarea'
@@ -297,6 +371,7 @@ import UploadIcon from '@icons/Upload.vue'
297371
import RecurrenceEditor from '@/components/RecurrenceEditor'
298372
import CategoryPicker from '@/components/CategoryPicker'
299373
import { categoryIconComponent } from '@/components/CategoryPicker'
374+
import NcRichText from '@nextcloud/vue/components/NcRichText'
300375
import { useChecklistItems } from '@/composables/useChecklist'
301376
import { useCategories } from '@/composables/useCategories'
302377
import { getList } from '@/api/lists'
@@ -424,7 +499,20 @@ async function submitEdit() {
424499
}
425500
}
426501
502+
const viewing = ref<ChecklistItem | null>(null)
427503
const previewing = ref<ChecklistItem | null>(null)
504+
505+
function openView(item: ChecklistItem) {
506+
viewing.value = item
507+
}
508+
509+
function viewToEdit() {
510+
if (!viewing.value) return
511+
const item = viewing.value
512+
viewing.value = null
513+
startEdit(item)
514+
}
515+
428516
function openPreview(item: ChecklistItem) {
429517
previewing.value = item
430518
}
@@ -498,8 +586,12 @@ const strings = {
498586
descriptionPlaceholder: t('pantry', 'Add a description …'),
499587
descriptionToggle: t('pantry', 'Toggle description'),
500588
itemActions: t('pantry', 'Item actions'),
589+
viewItem: t('pantry', 'View item'),
501590
editItem: t('pantry', 'Edit item'),
502591
editDialogTitle: t('pantry', 'Edit item'),
592+
recurrenceLabel: t('pantry', 'Recurrence'),
593+
status: t('pantry', 'Status'),
594+
done: t('pantry', 'Done'),
503595
imageLabel: t('pantry', 'Image'),
504596
uploadImage: t('pantry', 'Upload image'),
505597
replaceImage: t('pantry', 'Replace image'),
@@ -599,6 +691,58 @@ const strings = {
599691
}
600692
}
601693
694+
.pantry-view {
695+
display: flex;
696+
flex-direction: column;
697+
gap: 1rem;
698+
699+
&__image-btn {
700+
display: block;
701+
width: 100%;
702+
padding: 0;
703+
border: 0;
704+
background: none;
705+
cursor: zoom-in;
706+
border-radius: var(--border-radius, 8px);
707+
overflow: hidden;
708+
}
709+
710+
&__image {
711+
width: 100%;
712+
max-height: 300px;
713+
object-fit: cover;
714+
display: block;
715+
border-radius: var(--border-radius, 8px);
716+
}
717+
718+
&__description {
719+
line-height: 1.6;
720+
font-size: 0.95rem;
721+
722+
:deep(*) {
723+
color: inherit;
724+
}
725+
}
726+
727+
&__details {
728+
display: flex;
729+
flex-direction: column;
730+
gap: 0.5rem;
731+
}
732+
733+
&__row {
734+
display: flex;
735+
align-items: center;
736+
gap: 0.5rem;
737+
font-size: 0.9rem;
738+
}
739+
740+
&__label {
741+
color: var(--color-text-maxcontrast);
742+
font-weight: 500;
743+
}
744+
}
745+
602746
.pantry-preview {
603747
display: flex;
604748
justify-content: center;

0 commit comments

Comments
 (0)