diff --git a/src/components/pages/tabs/CaseStudiesTab.tsx b/src/components/pages/tabs/CaseStudiesTab.tsx index 16cf89a..e3c9557 100644 --- a/src/components/pages/tabs/CaseStudiesTab.tsx +++ b/src/components/pages/tabs/CaseStudiesTab.tsx @@ -4,10 +4,10 @@ import { Input } from "../../ui/input"; import { Search, Upload, Loader2 } from "lucide-react"; import { ContentTable } from "../shared/ContentTable"; import { UploadDrawer, UploadFormData } from "../shared/UploadDrawer"; -import { - useGetCaseStudiesQuery, +import { + useGetCaseStudiesQuery, useDeleteCaseStudyMutation, - useCreateCaseStudyMutation + useCreateCaseStudyMutation } from "../../../store/services/contentManager.service"; import { toast } from "sonner"; @@ -22,20 +22,26 @@ export function CaseStudiesTab({ onNavigate, user }: CaseStudiesTabProps) { const [searchTerm, setSearchTerm] = useState(""); const [selectedItems, setSelectedItems] = useState([]); const [isUploadDrawerOpen, setIsUploadDrawerOpen] = useState(false); + const [currentPage, setCurrentPage] = useState(1); + const [limit] = useState(10); // Use the case studies API - const { - data: caseStudiesResponse, - isLoading, - error, - refetch - } = useGetCaseStudiesQuery({}); - + const { + data: caseStudiesResponse, + isLoading, + error, + refetch + } = useGetCaseStudiesQuery({ + page: currentPage, + limit: limit + }); + const [deleteCaseStudy, { isLoading: isDeleting }] = useDeleteCaseStudyMutation(); const [createCaseStudy, { isLoading: isCreating }] = useCreateCaseStudyMutation(); // Transform API data to match table structure const caseStudies = caseStudiesResponse?.data || caseStudiesResponse || []; + const paginationMeta = caseStudiesResponse?.meta; const handleUploadComplete = async (data: UploadFormData) => { try { @@ -60,6 +66,15 @@ export function CaseStudiesTab({ onNavigate, user }: CaseStudiesTabProps) { onNavigate(`/content/case-studies/edit/${caseStudy.id}`); }; + const handlePageChange = (page: number) => { + setCurrentPage(page); + setSelectedItems([]); // Clear selection when page changes + }; + + useEffect(() => { + setCurrentPage(1); + }, [searchTerm]); + const filteredCaseStudies = caseStudies.filter((caseStudy: any) => caseStudy.title?.toLowerCase().includes(searchTerm.toLowerCase()) || caseStudy.description?.toLowerCase().includes(searchTerm.toLowerCase()) || @@ -84,6 +99,14 @@ export function CaseStudiesTab({ onNavigate, user }: CaseStudiesTabProps) { client: caseStudy.client || "Confidential" })); + const pagination = paginationMeta ? { + currentPage: paginationMeta.page, + totalPages: paginationMeta.totalPages, + hasNext: paginationMeta.hasNext, + hasPrev: paginationMeta.hasPrev, + onPageChange: handlePageChange + } : undefined; + if (error) { return (
@@ -111,6 +134,15 @@ export function CaseStudiesTab({ onNavigate, user }: CaseStudiesTabProps) {
+
+ + Showing {enhancedCaseStudies.length} of {paginationMeta?.total || 0} items + {paginationMeta && paginationMeta.totalPages > 1 && ( + (Page {currentPage} of {paginationMeta.totalPages}) + )} + +
+
-
- {filteredArchive.length} items +
+ + Showing {enhancedArchive.length} of {paginationMeta?.total || 0} items + {paginationMeta && paginationMeta.totalPages > 1 && ( + (Page {currentPage} of {paginationMeta.totalPages}) + )} +
+ {/*
+ {filteredArchive.length} items +
*/} +
+
+ + Showing {enhancedPodcasts.length} of {paginationMeta?.total || 0} items + {paginationMeta && paginationMeta.totalPages > 1 && ( + (Page {currentPage} of {paginationMeta.totalPages}) + )} + +
+
+
+ + Showing {enhancedReadingMaterials.length} of {paginationMeta?.total || 0} items + {paginationMeta && paginationMeta.totalPages > 1 && ( + (Page {currentPage} of {paginationMeta.totalPages}) + )} + +
+
- {enhancedMaterials.length} items - {allTrainingMaterials.length > 0 && ( - (Total: {allTrainingMaterials.length}) - )} + + Showing {enhancedMaterials.length} of {paginationMeta?.total || 0} items + {paginationMeta && paginationMeta.totalPages > 1 && ( + (Page {currentPage} of {paginationMeta.totalPages}) + )} +
@@ -238,6 +271,7 @@ export function TrainingMaterialsTab({ onNavigate={onNavigate} user={user} onItemDeleted={refetch} + pagination={pagination} /> )} diff --git a/src/components/pages/tabs/WebcastsTab.tsx b/src/components/pages/tabs/WebcastsTab.tsx index 816073b..20fa905 100644 --- a/src/components/pages/tabs/WebcastsTab.tsx +++ b/src/components/pages/tabs/WebcastsTab.tsx @@ -22,27 +22,33 @@ export function WebcastsTab({ onNavigate, user }: WebcastsTabProps) { const [searchTerm, setSearchTerm] = useState(""); const [selectedItems, setSelectedItems] = useState([]); const [isUploadDrawerOpen, setIsUploadDrawerOpen] = useState(false); + const [currentPage, setCurrentPage] = useState(1); + const [limit] = useState(10); // You can make this configurable - // Use the webcast API + // Use the webcast API with pagination const { - data: webcastsData, + data: webcastsResponse, isLoading, error, refetch - } = useGetWebcastsQuery({}); + } = useGetWebcastsQuery({ + page: currentPage, + limit: limit + }); const [deleteWebcast, { isLoading: isDeleting }] = useDeleteWebcastMutation(); const [createWebcast, { isLoading: isCreating }] = useCreateWebcastMutation(); - // Transform API data to match table structure - const webcasts = webcastsData?.data || webcastsData || []; + // Extract data and pagination info from response + const webcasts = webcastsResponse?.data || []; + const paginationMeta = webcastsResponse?.meta; const handleUploadComplete = async (data: UploadFormData) => { try { const webcastData = { title: data.title, description: data.description, - fileUrl: data.fileUrl, // This should come from your file upload process + fileUrl: data.fileUrl, tags: data.tags || [], }; @@ -71,19 +77,40 @@ export function WebcastsTab({ onNavigate, user }: WebcastsTabProps) { } }; + const handlePageChange = (page: number) => { + setCurrentPage(page); + setSelectedItems([]); // Clear selection when page changes + }; + + // Reset to page 1 when search term changes + useEffect(() => { + setCurrentPage(1); + }, [searchTerm]); + const filteredWebcasts = webcasts.filter((webcast: any) => webcast.title.toLowerCase().includes(searchTerm.toLowerCase()) || - webcast.tags.some((tag: string) => tag.toLowerCase().includes(searchTerm.toLowerCase())) + (webcast.tags && webcast.tags.some((tag: string) => + tag.toLowerCase().includes(searchTerm.toLowerCase()) + )) ); // Add status and other fields for table display const enhancedWebcasts = filteredWebcasts.map((webcast: any) => ({ ...webcast, - status: "Published", // You might want to add this field to your API + status: "Published", updated: new Date(webcast.updatedAt).toLocaleDateString(), type: "Webcast", })); + // Prepare pagination object for ContentTable + const pagination = paginationMeta ? { + currentPage: paginationMeta.page, + totalPages: paginationMeta.totalPages, + hasNext: paginationMeta.hasNext, + hasPrev: paginationMeta.hasPrev, + onPageChange: handlePageChange + } : undefined; + if (error) { return (
@@ -140,10 +167,10 @@ export function WebcastsTab({ onNavigate, user }: WebcastsTabProps) { selectedItems={selectedItems} onSelectionChange={setSelectedItems} onEdit={handleEditWebcast} - onDelete={handleDeleteWebcast} onNavigate={onNavigate} user={user} onItemDeleted={refetch} + pagination={pagination} /> )} diff --git a/src/store/services/contentManager.service.ts b/src/store/services/contentManager.service.ts index f749763..0f024f9 100644 --- a/src/store/services/contentManager.service.ts +++ b/src/store/services/contentManager.service.ts @@ -2,6 +2,26 @@ import { createApi } from "@reduxjs/toolkit/query/react"; import baseQuery from "../baseQuery"; +// Add these type definitions at the top +interface PaginationParams { + page?: number; + limit?: number; +} + +interface PaginationMeta { + page: number; + limit: number; + total: number; + totalPages: number; + hasNext: boolean; + hasPrev: boolean; +} + +interface ApiResponse { + data: T[]; + meta: PaginationMeta; +} + export const contentManagerApi = createApi({ reducerPath: "contentManagerApi", baseQuery, @@ -17,8 +37,8 @@ export const contentManagerApi = createApi({ ], endpoints: (builder) => ({ - // Existing Blog endpoints - getBlogs: builder.query({ + // Blog endpoints with pagination + getBlogs: builder.query, PaginationParams>({ query: ({ page = 1, limit = 10 }) => `/blogs?page=${page}&limit=${limit}`, providesTags: ["Blogs"], }), @@ -57,8 +77,8 @@ export const contentManagerApi = createApi({ invalidatesTags: ["Blogs"], }), - // Existing FAQ endpoints - getFAQs: builder.query({ + // FAQ endpoints with pagination + getFAQs: builder.query, PaginationParams>({ query: ({ page = 1, limit = 10 }) => `/faq?page=${page}&limit=${limit}`, providesTags: ["FAQs"], }), @@ -97,10 +117,12 @@ export const contentManagerApi = createApi({ invalidatesTags: ["FAQs"], }), - // Webcast endpoints - getWebcasts: builder.query({ - query: ({ page = 1, limit = 10 }) => - `/webcasts?page=${page}&limit=${limit}`, + // Webcast endpoints with pagination - FIXED + getWebcasts: builder.query, PaginationParams>({ + query: ({ page = 1, limit = 10 }) => ({ + url: '/webcasts', + params: { page, limit } + }), providesTags: ["Webcasts"], }), @@ -138,10 +160,12 @@ export const contentManagerApi = createApi({ invalidatesTags: ["Webcasts"], }), - // Training Materials endpoints - getTrainingMaterials: builder.query({ - query: ({ page = 1, limit = 10 }) => - `/training-materials?page=${page}&limit=${limit}`, + // Training Materials endpoints with pagination + getTrainingMaterials: builder.query, PaginationParams>({ + query: ({ page = 1, limit = 10 }) => ({ + url: '/training-materials', + params: { page, limit } + }), providesTags: ["TrainingMaterials"], }), @@ -181,10 +205,12 @@ export const contentManagerApi = createApi({ invalidatesTags: ["TrainingMaterials"], }), - // Podcast endpoints - getPodcasts: builder.query({ - query: ({ page = 1, limit = 10 }) => - `/podcasts?page=${page}&limit=${limit}`, + // Podcast endpoints with pagination + getPodcasts: builder.query, PaginationParams>({ + query: ({ page = 1, limit = 10 }) => ({ + url: '/podcasts', + params: { page, limit } + }), providesTags: ["Podcasts"], }), @@ -222,10 +248,12 @@ export const contentManagerApi = createApi({ invalidatesTags: ["Podcasts"], }), - // Reading Materials endpoints - getReadingMaterials: builder.query({ - query: ({ page = 1, limit = 10 }) => - `/reading-materials?page=${page}&limit=${limit}`, + // Reading Materials endpoints with pagination + getReadingMaterials: builder.query, PaginationParams>({ + query: ({ page = 1, limit = 10 }) => ({ + url: '/reading-materials', + params: { page, limit } + }), providesTags: ["ReadingMaterials"], }), @@ -263,10 +291,12 @@ export const contentManagerApi = createApi({ invalidatesTags: ["ReadingMaterials"], }), - // Case Studies endpoints - getCaseStudies: builder.query({ - query: ({ page = 1, limit = 10 }) => - `/case-studies?page=${page}&limit=${limit}`, + // Case Studies endpoints with pagination + getCaseStudies: builder.query, PaginationParams>({ + query: ({ page = 1, limit = 10 }) => ({ + url: '/case-studies', + params: { page, limit } + }), providesTags: ["CaseStudies"], }), @@ -319,10 +349,12 @@ export const contentManagerApi = createApi({ invalidatesTags: ["CaseStudies"], }), - // KLC Archive endpoints - getKlcArchives: builder.query({ - query: ({ page = 1, limit = 10 }) => - `/klc-archive?page=${page}&limit=${limit}`, + // KLC Archive endpoints with pagination + getKlcArchives: builder.query, PaginationParams>({ + query: ({ page = 1, limit = 10 }) => ({ + url: '/klc-archive', + params: { page, limit } + }), providesTags: ["KlcArchive"], }), @@ -426,4 +458,4 @@ export const { useCreateKlcArchiveMutation, useUpdateKlcArchiveMutation, useDeleteKlcArchiveMutation, -} = contentManagerApi; +} = contentManagerApi; \ No newline at end of file