diff --git a/src/components/content/lists/PurchasedListItem.js b/src/components/content/lists/PurchasedListItem.js index bea8714..03d673f 100644 --- a/src/components/content/lists/PurchasedListItem.js +++ b/src/components/content/lists/PurchasedListItem.js @@ -1,6 +1,6 @@ import React, { useEffect, useState } from 'react'; import { useNDKContext } from '@/context/NDKContext'; -import { parseEvent } from '@/utils/nostr'; +import { parseEvent, parseCourseEvent } from '@/utils/nostr'; import { ProgressSpinner } from 'primereact/progressspinner'; import { nip19 } from 'nostr-tools'; import appConfig from '@/config/appConfig'; @@ -8,50 +8,73 @@ import appConfig from '@/config/appConfig'; const PurchasedListItem = ({ eventId, category }) => { const { ndk } = useNDKContext(); const [event, setEvent] = useState(null); - const [naddr, setNaddr] = useState(null); useEffect(() => { const fetchEvent = async () => { - if (!eventId) return; + if (!eventId || !ndk) return; try { - await ndk.connect(); - const event = await ndk.fetchEvent(eventId); - if (event) { - setEvent(parseEvent(event)); + const filter = category === 'courses' + ? { + kinds: [30004], + authors: appConfig.authorPubkeys, + '#d': [eventId], + } + : { + kinds: [30023, 30402], + authors: appConfig.authorPubkeys, + '#d': [eventId], + }; + + const fetchedEvent = await ndk.fetchEvent(filter); + if (fetchedEvent) { + setEvent(category === 'courses' ? parseCourseEvent(fetchedEvent) : parseEvent(fetchedEvent)); } } catch (error) { - console.error('Error fetching event:', error); + console.error('Error fetching event in PurchasedListItem:', error); + setEvent(null); } }; fetchEvent(); - }, [eventId, ndk]); + }, [eventId, ndk, category]); - useEffect(() => { - if (event) { - encodeNaddr(); - } - }, [event]); - - const encodeNaddr = () => { - setNaddr( - nip19.naddrEncode({ + const encodeNaddrForLink = () => { + if (!event || !event.pubkey || !event.d) return null; + try { + return nip19.naddrEncode({ pubkey: event.pubkey, identifier: event.d, - kind: event.kind, + kind: category === 'courses' ? 30004 : event.kind, relays: appConfig.defaultRelayUrls, - }) - ); + }); + } catch (error) { + console.error("Error encoding naddr:", error); + return null; + } }; - return !event || !ndk ? ( - - ) : ( + if (!ndk) { + return ; + } + if (!eventId) { + return Missing item ID + } + if (!event) { + return ; + } + + const naddrValue = encodeNaddrForLink(); + + if (!naddrValue) { + return Error generating link. (Invalid Event ID?); + } + + return ( - {event.title} + {event.name || event.title || 'Unnamed Item'} ); }; diff --git a/src/components/profile/DataTables/UserProgressTable.js b/src/components/profile/DataTables/UserProgressTable.js index 986ccec..13ca984 100644 --- a/src/components/profile/DataTables/UserProgressTable.js +++ b/src/components/profile/DataTables/UserProgressTable.js @@ -1,6 +1,5 @@ import React from 'react'; -import { DataTable } from 'primereact/datatable'; -import { Column } from 'primereact/column'; +import GenericDataTable from '@/components/ui/DataTables/DataTable'; import ProgressListItem from '@/components/content/lists/ProgressListItem'; import { formatDateTime } from '@/utils/time'; import { ProgressSpinner } from 'primereact/progressspinner'; @@ -92,7 +91,7 @@ const UserProgressTable = ({ session, ndk }) => { return progressData.sort((a, b) => new Date(b.date) - new Date(a.date)); }; - const header = ( + const tableHeader = (
Progress
@@ -161,6 +160,13 @@ const UserProgressTable = ({ session, ndk }) => { ); }; + const columns = [ + { field: 'type', header: 'Type', body: typeTemplate }, + { field: 'eventType', header: 'Event', body: eventTemplate }, + { field: 'name', header: 'Name', body: nameTemplate }, + { field: 'date', header: 'Date', body: dateTemplate }, + ]; + if (!session || !session?.user || !ndk) { return (
@@ -170,10 +176,11 @@ const UserProgressTable = ({ session, ndk }) => { } return ( - { }, }} stripedRows + dataKey="id" > - - - - - + {/* Original Column definitions removed */} + ); }; diff --git a/src/components/profile/DataTables/UserPurchaseTable.js b/src/components/profile/DataTables/UserPurchaseTable.js index dc402e0..a836230 100644 --- a/src/components/profile/DataTables/UserPurchaseTable.js +++ b/src/components/profile/DataTables/UserPurchaseTable.js @@ -1,6 +1,5 @@ import React from 'react'; -import { DataTable } from 'primereact/datatable'; -import { Column } from 'primereact/column'; +import GenericDataTable from '@/components/ui/DataTables/DataTable'; import PurchasedListItem from '@/components/content/lists/PurchasedListItem'; import { formatDateTime } from '@/utils/time'; @@ -47,13 +46,22 @@ const UserPurchaseTable = ({ session, windowWidth }) => { ); }; + // Define columns for GenericDataTable + const columns = [ + { field: 'amountPaid', header: 'Cost', body: costTemplate }, + { field: 'name', header: 'Name', body: nameTemplate }, + { field: 'category', header: 'Category', body: categoryTemplate }, + { field: 'createdAt', header: 'Date', body: dateTemplate }, + ]; + return ( session && session?.user && ( - { }} stripedRows > - - - - - + {/* Original Column definitions removed */} + ) ); }; diff --git a/src/components/profile/DataTables/UserRelaysTable.js b/src/components/profile/DataTables/UserRelaysTable.js index ea2070a..28782f4 100644 --- a/src/components/profile/DataTables/UserRelaysTable.js +++ b/src/components/profile/DataTables/UserRelaysTable.js @@ -1,6 +1,5 @@ import React, { useState, useEffect, useCallback } from 'react'; -import { DataTable } from 'primereact/datatable'; -import { Column } from 'primereact/column'; +import GenericDataTable from '@/components/ui/DataTables/DataTable'; import { InputText } from 'primereact/inputtext'; import GenericButton from '@/components/buttons/GenericButton'; import { useToast } from '@/hooks/useToast'; @@ -54,7 +53,7 @@ const UserRelaysTable = ({ ndk, userRelays, setUserRelays, reInitializeNDK }) => } }; - const header = ( + const tableHeader = (
@@ -62,9 +61,10 @@ const UserRelaysTable = ({ ndk, userRelays, setUserRelays, reInitializeNDK }) =>
setCollapsed(!collapsed)} />
@@ -77,12 +77,14 @@ const UserRelaysTable = ({ ndk, userRelays, setUserRelays, reInitializeNDK }) => onChange={e => setNewRelayUrl(e.target.value)} className="flex-1" /> - +
)}
); + const relayUrlBody = rowData => rowData; + const relayStatusBody = url => { const isConnected = relayStatuses[url]; return ( @@ -118,13 +120,23 @@ const UserRelaysTable = ({ ndk, userRelays, setUserRelays, reInitializeNDK }) => ); }; + // Define columns for GenericDataTable + const columns = [ + { field: 'url', header: 'Relay URL', body: relayUrlBody }, + { header: 'Status', body: relayStatusBody }, + { header: 'Actions', body: relayActionsBody }, + ]; + return (
- - url} header="Relay URL"> - - - + rowData} + > +
); }; diff --git a/src/components/ui/DataTables/DataTable.js b/src/components/ui/DataTables/DataTable.js new file mode 100644 index 0000000..df67d6a --- /dev/null +++ b/src/components/ui/DataTables/DataTable.js @@ -0,0 +1,114 @@ +import React from 'react'; +import { DataTable } from 'primereact/datatable'; +import { Column } from 'primereact/column'; + +const GenericDataTable = ({ + value, + columns, + header, + emptyMessage = "No records found.", + className, + style, + pt, + stripedRows = false, + dataKey, + // Pagination props + paginator = false, + rows, + rowsPerPageOptions, + paginatorTemplate = "FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink CurrentPageReport RowsPerPageDropdown", + currentPageReportTemplate = "Showing {first} to {last} of {totalRecords} entries", + // Sorting props + sortMode, + sortField, + sortOrder, + onSort, + // Filtering props + filters, + onFilter, + globalFilter, + globalFilterFields, + filterDisplay = "menu", + // Selection props + selection, + onSelectionChange, + selectionMode, + // Row expansion + rowExpansionTemplate, + expandedRows, + onRowToggle, + // Context Menu + onContextMenu, + contextMenuSelection, + onContextMenuSelectionChange, + // Other common props + loading = false, + ...rest // Allows passing any other DataTable props +}) => { + return ( + + {columns && columns.map((col, i) => ( + + ))} + + ); +}; + +export default GenericDataTable; diff --git a/src/config/appConfig.js b/src/config/appConfig.js index a8325ba..4363377 100644 --- a/src/config/appConfig.js +++ b/src/config/appConfig.js @@ -11,7 +11,8 @@ const appConfig = { ], authorPubkeys: [ 'f33c8a9617cb15f705fc70cd461cfd6eaf22f9e24c33eabad981648e5ec6f741', - 'c67cd3e1a83daa56cff16f635db2fdb9ed9619300298d4701a58e68e84098345' + 'c67cd3e1a83daa56cff16f635db2fdb9ed9619300298d4701a58e68e84098345', + '6260f29fa75c91aaa292f082e5e87b438d2ab4fdf96af398567b01802ee2fcd4' ], customLightningAddresses: [ {