Emails
1 month ago
EngagementChart
1 month ago
MediaHub
1 month ago
Onboarding
1 month ago
Popup
1 month ago
Skeletons
1 week ago
WhatsNew
1 month ago
charts
1 month ago
test
1 month ago
AdminMenuSync.js
1 month ago
ChartEmptyState.js
1 month ago
ChooseDate.js
1 month ago
ColorPicker.js
1 month ago
ExtendPlugins.js
1 month ago
Filters.js
1 month ago
Link.js
1 month ago
Navbar.js
1 week ago
NoFound.js
1 month ago
PageHeader.js
1 month ago
PluginRecommendations.js
1 month ago
PostScheduleField.js
1 month ago
PrestoPlayerIcon.js
1 month ago
ProGateOverlay.js
1 month ago
QuickAccess.js
1 month ago
RankedTable.js
1 month ago
StatCard.js
1 month ago
TopMedia.js
1 month ago
TopPerformingMedia.js
1 month ago
TopUsers.js
1 month ago
TruncatedTitle.js
1 month ago
UpgradeNotice.js
1 month ago
UpgradeToPro.js
1 month ago
VideoModal.js
1 month ago
WelcomeBanner.js
1 month ago
TopUsers.js
98 lines
| 1 | const { __ } = wp.i18n; |
| 2 | import { Badge, Text } from "@bsf/force-ui"; |
| 3 | import { useHistory } from "../router/router"; |
| 4 | import ChartEmptyState from "./ChartEmptyState"; |
| 5 | import TruncatedTitle from "./TruncatedTitle"; |
| 6 | import RankedTable from "./RankedTable"; |
| 7 | |
| 8 | /** |
| 9 | * Top Users table with server-side pagination. |
| 10 | * |
| 11 | * @param {Object} props |
| 12 | * @param {Array} props.users Current page of user items. |
| 13 | * @param {number} props.currentPage 1-indexed page. |
| 14 | * @param {number} props.totalItems Total items across pages. |
| 15 | * @param {number} props.totalPages Total page count. |
| 16 | * @param {number} props.perPage Items per page. |
| 17 | * @param {Function} props.onPageChange (page) => void. |
| 18 | */ |
| 19 | const TopUsers = ({ |
| 20 | users = [], |
| 21 | currentPage = 1, |
| 22 | totalItems = 0, |
| 23 | totalPages = 0, |
| 24 | perPage = 5, |
| 25 | onPageChange, |
| 26 | }) => { |
| 27 | const history = useHistory(); |
| 28 | |
| 29 | const goToDetail = (user) => |
| 30 | history.push({ |
| 31 | tab: "Analytics", |
| 32 | detail: "user", |
| 33 | id: String(user.id), |
| 34 | }); |
| 35 | |
| 36 | const columns = [ |
| 37 | { |
| 38 | key: "name", |
| 39 | header: __("Viewer", "presto-player"), |
| 40 | headerClassName: "w-1/3 text-text-secondary font-medium py-2", |
| 41 | cellClassName: "w-1/3 py-3", |
| 42 | render: (user) => <TruncatedTitle title={user.name} />, |
| 43 | }, |
| 44 | { |
| 45 | key: "totalViews", |
| 46 | header: __("Views", "presto-player"), |
| 47 | headerClassName: |
| 48 | "w-1/3 whitespace-nowrap text-text-secondary font-medium py-2", |
| 49 | cellClassName: "w-1/3 whitespace-nowrap py-2", |
| 50 | render: (user) => ( |
| 51 | <Text as="span" size="sm" className="text-text-secondary"> |
| 52 | {`${user.totalViews} ${__("views", "presto-player")}`} |
| 53 | </Text> |
| 54 | ), |
| 55 | }, |
| 56 | { |
| 57 | key: "avgViewTime", |
| 58 | header: __("Avg View Time", "presto-player"), |
| 59 | headerClassName: |
| 60 | "w-1/3 whitespace-nowrap text-text-secondary font-medium py-2", |
| 61 | cellClassName: "w-1/3 whitespace-nowrap py-2", |
| 62 | render: (user) => ( |
| 63 | <Badge |
| 64 | label={user.avgViewTime} |
| 65 | type="rounded" |
| 66 | size="sm" |
| 67 | variant="neutral" |
| 68 | className="border-0 bg-gray-100 w-fit" |
| 69 | /> |
| 70 | ), |
| 71 | }, |
| 72 | ]; |
| 73 | |
| 74 | return ( |
| 75 | <RankedTable |
| 76 | title={__("Most Engaged Viewers", "presto-player")} |
| 77 | className="w-full" |
| 78 | columns={columns} |
| 79 | rows={users} |
| 80 | rowKey={(user) => user.id} |
| 81 | onRowClick={goToDetail} |
| 82 | pagination={{ |
| 83 | currentPage, |
| 84 | totalItems: totalItems || users.length, |
| 85 | totalPages: |
| 86 | totalPages || Math.ceil((totalItems || users.length) / perPage), |
| 87 | perPage, |
| 88 | onPageChange, |
| 89 | }} |
| 90 | emptyState={ |
| 91 | <ChartEmptyState className="min-h-[180px] pb-6 px-1" proGated /> |
| 92 | } |
| 93 | /> |
| 94 | ); |
| 95 | }; |
| 96 | |
| 97 | export default TopUsers; |
| 98 |