Create ItemsView utility
This commit is contained in:
parent
bfd117ff20
commit
722ded6065
3 changed files with 115 additions and 193 deletions
109
src/components/pages/ItemsView.vue
Normal file
109
src/components/pages/ItemsView.vue
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
<template>
|
||||||
|
<div class="flex h-full">
|
||||||
|
<div class="grow basis-6/12 p-4 overflow-x-hidden relative">
|
||||||
|
<div class="text-3xl mb-4">{{ title }}</div>
|
||||||
|
<div v-if="categories.length === 0" class="absolute center text-9xl">∅</div>
|
||||||
|
<div v-for="category in categories">
|
||||||
|
<CategoryHeader v-bind="category" />
|
||||||
|
<ItemGroup
|
||||||
|
:items="showSnoozed ? category.snoozedItems : category.activeItems"
|
||||||
|
:selected-thread="showThread ? selectedItem : undefined"
|
||||||
|
:show-snoozed="showSnoozed"
|
||||||
|
@select-item="selectItem"
|
||||||
|
@snooze-item="snoozeItem"
|
||||||
|
@deselect="close" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="hidden xl:flex bg-slate-200 ml-0 h-screen flex-col overflow-hidden" :class="showThread ? 'p-4 basis-6/12' : 'basis-0'">
|
||||||
|
<PanelTitle :title="threadTitle" />
|
||||||
|
<Thread :source="selectedItem?.source ?? 0" :sourceItem="selectedItem?.sourceItem ?? 0" :thread="selectedItem?.thread ?? 0" :base-url="baseUrl" />
|
||||||
|
</div>
|
||||||
|
<Modal :model-value="showThread" class="block xl:hidden" @update:model-value="close">
|
||||||
|
<template v-slot:header><div class="text-3xl">{{ threadTitle }}</div></template>
|
||||||
|
<template v-slot:body><Thread :source="selectedItem?.source ?? 0" :sourceItem="selectedItem?.sourceItem ?? 0" :thread="selectedItem?.thread ?? 0" :base-url="baseUrl" /></template>
|
||||||
|
</Modal>
|
||||||
|
<SnoozeModal :snoozing="snoozing" :threadRef="snoozingItem" @close="stopSnoozing" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, ref, watch } from 'vue';
|
||||||
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
|
import { ThreadRef, sources, Category } from '../../state';
|
||||||
|
import CategoryHeader from "../CategoryHeader.vue";
|
||||||
|
import ItemGroup from "../ItemGroup.vue";
|
||||||
|
import Modal from '../Modal.vue';
|
||||||
|
import PanelTitle from '../PanelTitle.vue';
|
||||||
|
import SnoozeModal from '../SnoozeModal.vue';
|
||||||
|
import Thread from '../Thread.vue';
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
title: string;
|
||||||
|
categories: Category[];
|
||||||
|
baseUrl: string;
|
||||||
|
showSnoozed?: boolean;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const showThread = ref(false);
|
||||||
|
const selectedItem = ref<ThreadRef | undefined>();
|
||||||
|
const snoozingItem = ref<ThreadRef | undefined>();
|
||||||
|
const snoozing = ref(false);
|
||||||
|
watch([() => route.params.source, () => route.params.sourceItem, () => route.params.thread], ([source, sourceItem, thread]) => {
|
||||||
|
const sourceInt = parseInt(Array.isArray(source) ? source[0] : source);
|
||||||
|
const sourceItemInt = parseInt(Array.isArray(sourceItem) ? sourceItem[0] : sourceItem);
|
||||||
|
const threadInt = parseInt(Array.isArray(thread) ? thread[0] : thread);
|
||||||
|
if (!isNaN(sourceInt) && !isNaN(sourceItemInt) && !isNaN(threadInt)) {
|
||||||
|
selectedItem.value = { source: sourceInt, sourceItem: sourceItemInt, thread: threadInt };
|
||||||
|
showThread.value = true;
|
||||||
|
} else {
|
||||||
|
// Intentionally leave selectedItem so animations look right
|
||||||
|
showThread.value = false;
|
||||||
|
}
|
||||||
|
}, { immediate: true });
|
||||||
|
|
||||||
|
const threadTitle = computed(() => {
|
||||||
|
const selected = selectedItem.value;
|
||||||
|
if (selected == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return sources.value[selected.source].items[selected.sourceItem].threads[selected.thread].title;
|
||||||
|
});
|
||||||
|
|
||||||
|
function selectItem(source: number, sourceItem: number, thread: number) {
|
||||||
|
const p = route.params;
|
||||||
|
const sourceInt = parseInt(Array.isArray(p.source) ? p.source[0] : p.source);
|
||||||
|
const sourceItemInt = parseInt(Array.isArray(p.sourceItem) ? p.sourceItem[0] : p.sourceItem);
|
||||||
|
const threadInt = parseInt(Array.isArray(p.thread) ? p.thread[0] : p.thread);
|
||||||
|
if (source === sourceInt && sourceItem === sourceItemInt && thread === threadInt) {
|
||||||
|
close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
router.push(`${props.baseUrl}/${source}/${sourceItem}/${thread}`);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function snoozeItem(source: number, sourceItem: number, thread: number) {
|
||||||
|
snoozingItem.value = { source, sourceItem, thread };
|
||||||
|
snoozing.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function close() {
|
||||||
|
console.log("closing thread")
|
||||||
|
router.push(props.baseUrl);
|
||||||
|
snoozing.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function stopSnoozing() {
|
||||||
|
if (snoozingItem.value?.source === selectedItem.value?.source &&
|
||||||
|
snoozingItem.value?.sourceItem === selectedItem.value?.sourceItem &&
|
||||||
|
(snoozingItem.value?.thread === -1 || snoozingItem.value?.thread === selectedItem.value?.thread)
|
||||||
|
) {
|
||||||
|
close();
|
||||||
|
} else {
|
||||||
|
snoozing.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -1,102 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="flex h-full">
|
<ItemsView base-url="/snoozed" :categories="snoozedCategories" title="Snoozed" :show-snoozed="true" />
|
||||||
<div class="grow basis-6/12 p-4 overflow-x-hidden relative">
|
|
||||||
<div class="text-3xl mb-4">Snoozed</div>
|
|
||||||
<div v-if="snoozedCategories.length === 0" class="absolute center text-9xl">∅</div>
|
|
||||||
<div v-for="category in snoozedCategories">
|
|
||||||
<CategoryHeader v-bind="category" />
|
|
||||||
<ItemGroup
|
|
||||||
:items="category.snoozedItems"
|
|
||||||
:selected-thread="showThread ? selectedItem : undefined"
|
|
||||||
:show-snoozed="true"
|
|
||||||
@select-item="selectItem"
|
|
||||||
@snooze-item="snoozeItem"
|
|
||||||
@deselect="close" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="hidden xl:flex bg-slate-200 ml-0 h-screen flex-col overflow-hidden" :class="showThread ? 'p-4 basis-6/12' : 'basis-0'">
|
|
||||||
<PanelTitle :title="threadTitle" />
|
|
||||||
<Thread :source="selectedItem?.source ?? 0" :sourceItem="selectedItem?.sourceItem ?? 0" :thread="selectedItem?.thread ?? 0" base-url="/snoozed" />
|
|
||||||
</div>
|
|
||||||
<Modal :model-value="showThread" class="block xl:hidden" @update:model-value="close">
|
|
||||||
<template v-slot:header><div class="text-3xl">{{ threadTitle }}</div></template>
|
|
||||||
<template v-slot:body><Thread :source="selectedItem?.source ?? 0" :sourceItem="selectedItem?.sourceItem ?? 0" :thread="selectedItem?.thread ?? 0" base-url="/snoozed" /></template>
|
|
||||||
</Modal>
|
|
||||||
<SnoozeModal :snoozing="snoozing" :threadRef="snoozingItem" @close="stopSnoozing" />
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref, watch } from 'vue';
|
import { snoozedCategories } from '../../state';
|
||||||
import { useRoute, useRouter } from 'vue-router';
|
import ItemsView from './ItemsView.vue';
|
||||||
import { ThreadRef, sources, snoozedCategories } from '../../state';
|
|
||||||
import CategoryHeader from "../CategoryHeader.vue";
|
|
||||||
import ItemGroup from "../ItemGroup.vue";
|
|
||||||
import Modal from '../Modal.vue';
|
|
||||||
import PanelTitle from '../PanelTitle.vue';
|
|
||||||
import SnoozeModal from '../SnoozeModal.vue';
|
|
||||||
import Thread from '../Thread.vue';
|
|
||||||
|
|
||||||
const route = useRoute();
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
const showThread = ref(false);
|
|
||||||
const selectedItem = ref<ThreadRef | undefined>();
|
|
||||||
const snoozingItem = ref<ThreadRef | undefined>();
|
|
||||||
const snoozing = ref(false);
|
|
||||||
watch([() => route.params.source, () => route.params.sourceItem, () => route.params.thread], ([source, sourceItem, thread]) => {
|
|
||||||
const sourceInt = parseInt(Array.isArray(source) ? source[0] : source);
|
|
||||||
const sourceItemInt = parseInt(Array.isArray(sourceItem) ? sourceItem[0] : sourceItem);
|
|
||||||
const threadInt = parseInt(Array.isArray(thread) ? thread[0] : thread);
|
|
||||||
if (!isNaN(sourceInt) && !isNaN(sourceItemInt) && !isNaN(threadInt)) {
|
|
||||||
selectedItem.value = { source: sourceInt, sourceItem: sourceItemInt, thread: threadInt };
|
|
||||||
showThread.value = true;
|
|
||||||
} else {
|
|
||||||
// Intentionally leave selectedItem so animations look right
|
|
||||||
showThread.value = false;
|
|
||||||
}
|
|
||||||
}, { immediate: true });
|
|
||||||
|
|
||||||
const threadTitle = computed(() => {
|
|
||||||
const selected = selectedItem.value;
|
|
||||||
if (selected == null) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
return sources.value[selected.source].items[selected.sourceItem].threads[selected.thread].title;
|
|
||||||
});
|
|
||||||
|
|
||||||
function selectItem(source: number, sourceItem: number, thread: number) {
|
|
||||||
const p = route.params;
|
|
||||||
const sourceInt = parseInt(Array.isArray(p.source) ? p.source[0] : p.source);
|
|
||||||
const sourceItemInt = parseInt(Array.isArray(p.sourceItem) ? p.sourceItem[0] : p.sourceItem);
|
|
||||||
const threadInt = parseInt(Array.isArray(p.thread) ? p.thread[0] : p.thread);
|
|
||||||
if (source === sourceInt && sourceItem === sourceItemInt && thread === threadInt) {
|
|
||||||
close();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
router.push(`/snoozed/${source}/${sourceItem}/${thread}`);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function snoozeItem(source: number, sourceItem: number, thread: number) {
|
|
||||||
snoozingItem.value = { source, sourceItem, thread };
|
|
||||||
snoozing.value = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function close() {
|
|
||||||
console.log("closing thread")
|
|
||||||
router.push("/snoozed");
|
|
||||||
snoozing.value = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function stopSnoozing() {
|
|
||||||
if (snoozingItem.value?.source === selectedItem.value?.source &&
|
|
||||||
snoozingItem.value?.sourceItem === selectedItem.value?.sourceItem &&
|
|
||||||
(snoozingItem.value?.thread === -1 || snoozingItem.value?.thread === selectedItem.value?.thread)
|
|
||||||
) {
|
|
||||||
close();
|
|
||||||
} else {
|
|
||||||
snoozing.value = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,101 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="flex h-full">
|
<ItemsView base-url="/todo" :categories="todoCategories" title="Todo" />
|
||||||
<div class="grow basis-6/12 p-4 overflow-x-hidden relative">
|
|
||||||
<div class="text-3xl mb-4">Todo</div>
|
|
||||||
<div v-if="todoCategories.length === 0" class="absolute center text-9xl">∅</div>
|
|
||||||
<div v-for="category in todoCategories">
|
|
||||||
<CategoryHeader v-bind="category" />
|
|
||||||
<ItemGroup
|
|
||||||
:items="category.activeItems"
|
|
||||||
:selected-thread="showThread ? selectedItem : undefined"
|
|
||||||
@select-item="selectItem"
|
|
||||||
@snooze-item="snoozeItem"
|
|
||||||
@deselect="close" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="hidden xl:flex bg-slate-200 ml-0 h-screen flex-col overflow-hidden" :class="showThread ? 'p-4 basis-6/12' : 'basis-0'">
|
|
||||||
<PanelTitle :title="threadTitle" />
|
|
||||||
<Thread :source="selectedItem?.source ?? 0" :sourceItem="selectedItem?.sourceItem ?? 0" :thread="selectedItem?.thread ?? 0" base-url="/todo" />
|
|
||||||
</div>
|
|
||||||
<Modal :model-value="showThread" class="block xl:hidden" @update:model-value="close">
|
|
||||||
<template v-slot:header><div class="text-3xl">{{ threadTitle }}</div></template>
|
|
||||||
<template v-slot:body><Thread :source="selectedItem?.source ?? 0" :sourceItem="selectedItem?.sourceItem ?? 0" :thread="selectedItem?.thread ?? 0" base-url="/todo" /></template>
|
|
||||||
</Modal>
|
|
||||||
<SnoozeModal :snoozing="snoozing" :threadRef="snoozingItem" @close="stopSnoozing" />
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref, watch } from 'vue';
|
import { todoCategories } from '../../state';
|
||||||
import { useRoute, useRouter } from 'vue-router';
|
import ItemsView from './ItemsView.vue';
|
||||||
import { ThreadRef, sources, todoCategories } from '../../state';
|
|
||||||
import CategoryHeader from "../CategoryHeader.vue";
|
|
||||||
import ItemGroup from "../ItemGroup.vue";
|
|
||||||
import Modal from '../Modal.vue';
|
|
||||||
import PanelTitle from '../PanelTitle.vue';
|
|
||||||
import SnoozeModal from '../SnoozeModal.vue';
|
|
||||||
import Thread from '../Thread.vue';
|
|
||||||
|
|
||||||
const route = useRoute();
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
const showThread = ref(false);
|
|
||||||
const selectedItem = ref<ThreadRef | undefined>();
|
|
||||||
const snoozingItem = ref<ThreadRef | undefined>();
|
|
||||||
const snoozing = ref(false);
|
|
||||||
watch([() => route.params.source, () => route.params.sourceItem, () => route.params.thread], ([source, sourceItem, thread]) => {
|
|
||||||
const sourceInt = parseInt(Array.isArray(source) ? source[0] : source);
|
|
||||||
const sourceItemInt = parseInt(Array.isArray(sourceItem) ? sourceItem[0] : sourceItem);
|
|
||||||
const threadInt = parseInt(Array.isArray(thread) ? thread[0] : thread);
|
|
||||||
if (!isNaN(sourceInt) && !isNaN(sourceItemInt) && !isNaN(threadInt)) {
|
|
||||||
selectedItem.value = { source: sourceInt, sourceItem: sourceItemInt, thread: threadInt };
|
|
||||||
showThread.value = true;
|
|
||||||
} else {
|
|
||||||
// Intentionally leave selectedItem so animations look right
|
|
||||||
showThread.value = false;
|
|
||||||
}
|
|
||||||
}, { immediate: true });
|
|
||||||
|
|
||||||
const threadTitle = computed(() => {
|
|
||||||
const selected = selectedItem.value;
|
|
||||||
if (selected == null) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
return sources.value[selected.source].items[selected.sourceItem].threads[selected.thread].title;
|
|
||||||
});
|
|
||||||
|
|
||||||
function selectItem(source: number, sourceItem: number, thread: number) {
|
|
||||||
const p = route.params;
|
|
||||||
const sourceInt = parseInt(Array.isArray(p.source) ? p.source[0] : p.source);
|
|
||||||
const sourceItemInt = parseInt(Array.isArray(p.sourceItem) ? p.sourceItem[0] : p.sourceItem);
|
|
||||||
const threadInt = parseInt(Array.isArray(p.thread) ? p.thread[0] : p.thread);
|
|
||||||
if (source === sourceInt && sourceItem === sourceItemInt && thread === threadInt) {
|
|
||||||
close();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
router.push(`/todo/${source}/${sourceItem}/${thread}`);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function snoozeItem(source: number, sourceItem: number, thread: number) {
|
|
||||||
snoozingItem.value = { source, sourceItem, thread };
|
|
||||||
snoozing.value = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function close() {
|
|
||||||
console.log("closing thread")
|
|
||||||
router.push("/todo");
|
|
||||||
snoozing.value = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function stopSnoozing() {
|
|
||||||
if (snoozingItem.value?.source === selectedItem.value?.source &&
|
|
||||||
snoozingItem.value?.sourceItem === selectedItem.value?.sourceItem &&
|
|
||||||
(snoozingItem.value?.thread === -1 || snoozingItem.value?.thread === selectedItem.value?.thread)
|
|
||||||
) {
|
|
||||||
close();
|
|
||||||
} else {
|
|
||||||
snoozing.value = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
Loading…
Reference in a new issue