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: [
{