+
+
Page {{ page }} of {{ totalPages }} ({{ totalItems }} items)
+
+
+
+
+
+
+
+
+ ...
+
+
+
+
+
+
+
+
+ Go to
+
+
+
+
@@ -132,23 +164,90 @@
}>();
const projectStore = useProjectStore();
- const { projects, isLoading: loading } = toRefs(projectStore);
- const { createProject, loadProjectData } = useProjectManager();
-
+ const { createProject } = useProjectManager();
const searchQuery = ref('');
- const filteredProjects = computed(() => {
- if (!searchQuery.value) return projects.value;
- const query = searchQuery.value.toLowerCase();
- return projects.value.filter(p => p.name.toLowerCase().includes(query));
+ const { projects, isLoading: loading, page, perPage, totalItems, totalPages, fetchProjects } = toRefs(projectStore);
+
+ let searchTimeout: any = null;
+
+ watch(searchQuery, newVal => {
+ if (searchTimeout) clearTimeout(searchTimeout);
+ searchTimeout = setTimeout(() => {
+ fetchProjects.value(1, perPage.value, newVal);
+ }, 300);
+ });
+
+ const nextPage = () => {
+ if (page.value < totalPages.value) {
+ fetchProjects.value(page.value + 1, perPage.value, searchQuery.value);
+ }
+ };
+
+ const prevPage = () => {
+ if (page.value > 1) {
+ fetchProjects.value(page.value - 1, perPage.value, searchQuery.value);
+ }
+ };
+
+ const goToPage = (p: number) => {
+ if (p !== page.value && p >= 1 && p <= totalPages.value) {
+ fetchProjects.value(p, perPage.value, searchQuery.value);
+ }
+ };
+
+ const jumpToPage = (event: any) => {
+ const val = parseInt(event.target.value);
+ if (!isNaN(val) && val >= 1 && val <= totalPages.value) {
+ goToPage(val);
+ // Clear input after jump if desired, or keep it. Keeping it is fine.
+ } else {
+ // Reset to current page if invalid
+ event.target.value = '';
+ }
+ };
+
+ const visiblePages = computed(() => {
+ const total = totalPages.value;
+ const current = page.value;
+ const delta = 2; // How many pages to show around current
+ const range: (number | string)[] = [];
+ const left = current - delta;
+ const right = current + delta + 1;
+
+ for (let i = 1; i <= total; i++) {
+ if (i === 1 || i === total || (i >= left && i < right)) {
+ range.push(i);
+ }
+ }
+
+ // Add dots
+ const finalRange: (number | string)[] = [];
+ let l: number | null = null;
+
+ for (const i of range) {
+ if (typeof i === 'number') {
+ if (l) {
+ if (i - l === 2) {
+ finalRange.push(l + 1);
+ } else if (i - l !== 1) {
+ finalRange.push('...');
+ }
+ }
+ finalRange.push(i);
+ l = i;
+ }
+ }
+ return finalRange;
});
watch(
() => props.isOpen,
isOpen => {
if (isOpen) {
- projectStore.fetchProjects();
searchQuery.value = ''; // Reset search on open
+ // Reset to page 1 is handled by fetchProjects default or we can explicitly call it
+ projectStore.fetchProjects(1, perPage.value, '');
}
}
);
diff --git a/src/stores/useProjectStore.ts b/src/stores/useProjectStore.ts
index bcfa13f..431051e 100644
--- a/src/stores/useProjectStore.ts
+++ b/src/stores/useProjectStore.ts
@@ -15,13 +15,19 @@ export const useProjectStore = defineStore('project', () => {
const projects = ref
([]);
const currentProject = ref(null);
const isLoading = ref(false);
+ const page = ref(1);
+ const perPage = ref(12);
+ const totalItems = ref(0);
+ const totalPages = ref(0);
- async function fetchProjects() {
+ async function fetchProjects(pageVal = 1, perPageVal = 12, searchVal = '') {
if (!authStore.user) return;
isLoading.value = true;
try {
- const records = await authStore.pb.collection('projects').getList(1, 50, {
+ const filter = searchVal ? `name ~ "${searchVal}"` : '';
+ const records = await authStore.pb.collection('projects').getList(pageVal, perPageVal, {
sort: '-updated',
+ filter,
});
projects.value = records.items.map((r: any) => ({
id: r.id,
@@ -30,6 +36,10 @@ export const useProjectStore = defineStore('project', () => {
created: r.created,
updated: r.updated,
}));
+ page.value = records.page;
+ perPage.value = records.perPage;
+ totalItems.value = records.totalItems;
+ totalPages.value = records.totalPages;
} catch (error) {
console.error('Failed to fetch projects:', error);
} finally {
@@ -53,7 +63,8 @@ export const useProjectStore = defineStore('project', () => {
created: record.created,
updated: record.updated,
};
- await fetchProjects();
+ // Refresh current page
+ await fetchProjects(page.value, perPage.value);
} catch (error) {
console.error('Failed to create project:', error);
throw error;
@@ -76,7 +87,9 @@ export const useProjectStore = defineStore('project', () => {
data: record.data,
updated: record.updated,
};
- await fetchProjects();
+ // No need to fetch all, just update locals or re-fetch current page if desired.
+ // For now, let's re-fetch to keep consistency.
+ await fetchProjects(page.value, perPage.value);
} catch (error) {
console.error('Failed to update project:', error);
throw error;
@@ -115,7 +128,9 @@ export const useProjectStore = defineStore('project', () => {
if (currentProject.value?.id === id) {
currentProject.value = null;
}
- await fetchProjects();
+ // If we delete the last item on a page, we might want to go back a page.
+ // For simplicity, just refetch current page.
+ await fetchProjects(page.value, perPage.value);
} catch (error) {
console.error('Failed to delete project:', error);
} finally {
@@ -127,6 +142,10 @@ export const useProjectStore = defineStore('project', () => {
projects,
currentProject,
isLoading,
+ page,
+ perPage,
+ totalItems,
+ totalPages,
fetchProjects,
createProject,
updateProject,