Fix followers pagination UI

This commit is contained in:
Gabe Kangas 2022-07-05 12:53:21 -07:00
parent e443188cbc
commit 14f405bf58
No known key found for this signature in database
GPG Key ID: 9A56337728BC81EA

View File

@ -3,132 +3,133 @@ import htm from '/js/web_modules/htm.js';
import { URL_FOLLOWERS } from '/js/utils/constants.js'; import { URL_FOLLOWERS } from '/js/utils/constants.js';
const html = htm.bind(h); const html = htm.bind(h);
export default class FollowerList extends Component { export default class FollowerList extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
followers: [], followers: [],
followersPage: 0, followersPage: 0,
currentPage: 0, currentPage: 0,
total: 0, total: 0,
}; };
} }
componentDidMount() { componentDidMount() {
try { try {
this.getFollowers(); this.getFollowers();
} catch (e) { } catch (e) {
console.error('followers error: ', e); console.error('followers error: ', e);
} }
} }
async getFollowers() { async getFollowers(requestedPage) {
const { currentPage } = this.state; const limit = 24;
const limit = 24; const offset = requestedPage * limit;
const offset = currentPage * limit; const u = `${URL_FOLLOWERS}?offset=${offset || 0}&limit=${limit}`;
const u = `${URL_FOLLOWERS}?offset=${offset}&limit=${limit}`; const response = await fetch(u);
const response = await fetch(u); const followers = await response.json();
const followers = await response.json(); const pages = Math.ceil(followers.total / limit);
this.setState({ this.setState({
followers: followers.results, followers: followers.results,
total: response.total, total: followers.total,
}); pages: pages,
} });
}
changeFollowersPage(page) { changeFollowersPage(requestedPage) {
this.setState({ currentPage: page }); this.setState({ currentPage: requestedPage });
this.getFollowers(); this.getFollowers(requestedPage);
} }
render() { render() {
const { followers, total, currentPage } = this.state; const { followers, total, pages, currentPage } = this.state;
if (!followers) { if (!followers) {
return null; return null;
} }
const noFollowersInfo = html`<div class="col-span-4"> const noFollowersInfo = html`<div class="col-span-4">
<p class="mb-5 text-2xl">Be the first to follow this live stream.</p> <p class="mb-5 text-2xl">Be the first to follow this live stream.</p>
<p class="text-md"> <p class="text-md">
By following this stream you'll get updates when it goes live, receive By following this stream you'll get updates when it goes live, receive
posts from the streamer, and be featured here as a follower. posts from the streamer, and be featured here as a follower.
</p> </p>
<p class="text-md mt-5"> <p class="text-md mt-5">
Learn more about ${' '} Learn more about ${' '}
<a class="underline" href="https://en.wikipedia.org/wiki/Fediverse" <a class="underline" href="https://en.wikipedia.org/wiki/Fediverse"
>The Fediverse</a >The Fediverse</a
>, where you can follow this server as well as so much more. >, where you can follow this server as well as so much more.
</p> </p>
</div>`; </div>`;
const paginationControls = const paginationControls =
total > 1 && pages > 1 &&
Array(total) Array(pages)
.fill() .fill()
.map((x, n) => { .map((x, n) => {
const activePageClass = const activePageClass =
n === currentPage && n === currentPage &&
'bg-indigo-600 rounded-full shadow-md focus:shadow-md text-white'; 'bg-indigo-600 rounded-full shadow-md focus:shadow-md text-white';
return html` <li class="page-item active w-10"> return html` <li class="page-item active w-10">
<a <a
class="page-link relative block cursor-pointer hover:no-underline py-1.5 px-3 border-0 rounded-full hover:text-gray-800 hover:bg-gray-200 outline-none transition-all duration-300 ${activePageClass}" class="page-link relative block cursor-pointer hover:no-underline py-1.5 px-3 border-0 rounded-full hover:text-gray-800 hover:bg-gray-200 outline-none transition-all duration-300 ${activePageClass}"
onClick=${() => this.changeFollowersPage(n)} onClick=${() => this.changeFollowersPage(n)}
> >
${n + 1} ${n + 1}
</a> </a>
</li>`; </li>`;
}); });
return html` return html`
<div> <div>
<div <div
class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4" class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4"
> >
${followers.length === 0 && noFollowersInfo} ${followers.length === 0 && noFollowersInfo}
${followers.map((follower) => { ${followers.map((follower) => {
return html` <${SingleFollower} user=${follower} /> `; return html` <${SingleFollower} user=${follower} /> `;
})} })}
</div> </div>
<div class="flex"> <div class="flex">
<nav aria-label="Tab pages"> <nav aria-label="Tab pages">
<ul class="flex list-style-none flex-wrap"> <ul class="flex list-style-none flex-wrap">
${paginationControls} ${paginationControls}
</ul> </ul>
</nav> </nav>
</div> </div>
</div> </div>
`; `;
} }
} }
function SingleFollower(props) { function SingleFollower(props) {
const { user } = props; const { user } = props;
const { name, username, link, image } = user; const { name, username, link, image } = user;
var displayName = name; var displayName = name;
var displayUsername = username; var displayUsername = username;
if (!displayName) { if (!displayName) {
displayName = displayUsername.split('@', 1)[0]; displayName = displayUsername.split('@', 1)[0];
} }
return html` return html`
<a <a
href=${link} href=${link}
class="following-list-follower block bg-white flex p-2 rounded-xl shadow border hover:no-underline mb-3 mr-3" class="following-list-follower block bg-white flex p-2 rounded-xl shadow border hover:no-underline mb-3 mr-3"
target="_blank" target="_blank"
> >
<img <img
src="${image || '/img/logo.svg'}" src="${image || '/img/logo.svg'}"
class="w-16 h-16 rounded-full" class="w-16 h-16 rounded-full"
onError=${({ currentTarget }) => { onError=${({ currentTarget }) => {
currentTarget.onerror = null; currentTarget.onerror = null;
currentTarget.src = '/img/logo.svg'; currentTarget.src = '/img/logo.svg';
}} }}
/> />
<div class="p-3 truncate flex-grow"> <div class="p-3 truncate flex-grow">
<p class="font-semibold text-gray-700 truncate">${displayName}</p> <p class="font-semibold text-gray-700 truncate">${displayName}</p>
<p class="text-sm text-gray-500 truncate">${displayUsername}</p> <p class="text-sm text-gray-500 truncate">${displayUsername}</p>
</div> </div>
</a> </a>
`; `;
} }