elder_scrolling/src/cards/Cards.tsx

110 lines
2.8 KiB
TypeScript

import * as React from "react";
import { Loading } from "./Loading";
import { Card } from "./Card";
import { GridLayout } from "@egjs/react-infinitegrid";
import ReactModal from "react-modal";
import { FullCard, fullcardStyles } from "./FullCard";
import {
CardProps,
CardRequestProps,
CardState,
CardStateHandler
} from "./types";
const { useState, useCallback, useEffect } = React;
export const Cards = ({ rootUrl }: { rootUrl: string }) => {
const emptyCards: CardState = {
cards: [],
first: rootUrl,
next: rootUrl,
maxCards: -1
};
const [cards, setCards]: CardStateHandler = useState(emptyCards);
const [loading, setLoading]: [boolean, Function] = useState(false);
const [currentCard, setCurrentCard]: [CardProps | null, Function] = useState(
null
);
// Good GRIEF, the things we have to do convince React to actually
// draw sometimes.
useEffect(() => {
if (cards.first !== rootUrl) {
setCards(emptyCards);
}
}, [cards.first, rootUrl, emptyCards]);
// Debounce that annoying loopback.
const loadItems = useCallback(() => {
if (cards.next === null || cards.cards.length === cards.maxCards) {
return;
}
const request = new Request(cards.next);
fetch(request)
.then(response => response.json())
.then((data: CardRequestProps) => {
setCards({
...cards,
cards: [...cards.cards, ...data.cards],
next: data._links && data._links.next ? data._links.next : null,
maxcards: data._totalCount
});
setLoading(false);
});
}, [cards]);
const loadMoreCards = (options: any) => {
if (options.startLoading !== null) {
options.startLoading();
}
loadItems();
};
const onLayoutComplete = (options: any) => {
!options.isLayout && options.endLoading();
};
const handleCloseCard = () => {
setCurrentCard(null);
};
const handleOpenCard = (id: string) => {
const card = cards.cards.find(card => card.id === id);
if (card) {
setCurrentCard(card);
}
};
return (
<div className="container">
<ReactModal
isOpen={currentCard !== null}
style={fullcardStyles}
contentLabel=""
onRequestClose={handleCloseCard}
>
<FullCard card={currentCard} />
</ReactModal>
<GridLayout
options={{
isConstantSize: true,
isEqualSize: true,
transitionDuration: 0.2
}}
layoutOptions={{
margin: 10
}}
onAppend={loadMoreCards}
onLayoutComplete={onLayoutComplete}
>
{cards.cards.map((card: CardProps, count: number) => (
<Card card={card} key={count} onClick={handleOpenCard} />
))}
</GridLayout>
{loading ? <Loading /> : ""}
</div>
);
};