81 lines
2.8 KiB
Vue
81 lines
2.8 KiB
Vue
<template>
|
|
<div class="workspace-list" :class="{ 'workspace-list--list': viewMode === 'list' }">
|
|
<div v-if="items.length === 0" class="empty-workspace-state" role="status" aria-live="polite">
|
|
<i class="mdi mdi-view-grid-outline empty-workspace-icon" aria-hidden="true"></i>
|
|
<h3 class="empty-workspace-title">Nothing Here Yet</h3>
|
|
<p class="empty-workspace-message">This view has no notes or task lists yet.</p>
|
|
</div>
|
|
|
|
<div v-for="item in items" :key="`${item.kind}-${item.id}`" class="content-card" :class="contentCardClass(item)" @click="openItem(item)">
|
|
<h5 class="content-title">
|
|
<template v-if="item.kind === 'note'">
|
|
<i v-if="item.is_pinned" class="mdi mdi-pin pin-icon" aria-hidden="true"></i>
|
|
<i v-else-if="item.is_favorite || item.is_featured" class="mdi mdi-star featured-icon" aria-hidden="true"></i>
|
|
{{ item.title }}
|
|
</template>
|
|
<template v-else>
|
|
<i class="mdi mdi-format-list-checkbox list-icon" aria-hidden="true"></i>
|
|
{{ item.name }}
|
|
</template>
|
|
</h5>
|
|
<p class="content-preview">{{ getDescription(item) }}</p>
|
|
<small class="text-muted">Updated: {{ formatDate(item.updated_at) }}</small>
|
|
</div>
|
|
|
|
<div v-if="canLoadMore" class="list-footer">
|
|
<button class="btn btn-outline-secondary" :disabled="isLoadingMore" @click.stop="emit('loadMore')">
|
|
{{ isLoadingMore ? "Loading..." : "Load more" }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
const props = defineProps({
|
|
items: {
|
|
type: Array,
|
|
default: () => [],
|
|
},
|
|
canLoadMore: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
isLoadingMore: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
viewMode: {
|
|
type: String,
|
|
default: "grid",
|
|
},
|
|
});
|
|
|
|
const emit = defineEmits(["selectNote", "selectTaskList", "loadMore"]);
|
|
|
|
const openItem = (item) => {
|
|
if (item.kind === "task-list") {
|
|
emit("selectTaskList", item);
|
|
return;
|
|
}
|
|
emit("selectNote", item);
|
|
};
|
|
|
|
const formatDate = (dateString) => new Date(dateString).toLocaleDateString();
|
|
|
|
const getDescription = (item) => {
|
|
const description = (item?.description || "").trim();
|
|
if (description) {
|
|
return description;
|
|
}
|
|
return item.kind === "task-list" ? "Open this task list to manage tasks." : "No description";
|
|
};
|
|
|
|
const contentCardClass = (item) => ({
|
|
"is-pinned": item.kind === "note" && item.is_pinned,
|
|
"is-featured": item.kind === "note" && (item.is_favorite || item.is_featured),
|
|
"is-task-list": item.kind === "task-list",
|
|
});
|
|
</script>
|
|
|
|
<style scoped src="../assets/styles/scoped/components/WorkspaceList.css"></style>
|