Skip to content

Commit

Permalink
Pagination #4
Browse files Browse the repository at this point in the history
  • Loading branch information
darsan-in committed Aug 1, 2024
1 parent 9556ca8 commit fd8f9b4
Show file tree
Hide file tree
Showing 3 changed files with 194 additions and 50 deletions.
95 changes: 52 additions & 43 deletions app/providerWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,63 +9,72 @@ import Navbar from "../components/navbar";
interface AppStateType {
imageData: any[][];
isLoading: boolean;
pagination: { currentPage: number; currentQuery: string };
getResult: (query: string, page?: number) => void;
}

const intialState: AppStateType = {
imageData: [],
isLoading: false,
pagination: { currentPage: 0, currentQuery: "" },
getResult: () => {},
};

export const NavContext = createContext<{ appState: AppStateType }>({
appState: { imageData: [], isLoading: false },
appState: intialState,
});

export default ({ children }: { children: React.ReactNode }) => {
const [appState, setAppState] = useState<AppStateType>({
imageData: [],
isLoading: false,
});
const [appState, setAppState] = useState<AppStateType>(intialState);

const router = useRouter();

return (
<NavContext.Provider value={{ appState }}>
<header>
<Banner />
/* callback */
const getResult = (query: string, page: number = 1): void => {
router.replace("/");

<Navbar
formCallback={(query) => {
const page = 1;
router.replace("/");
const formData: string = JSON.stringify({
query: query,
page: page,
});

const formData: string = JSON.stringify({
query: query,
page: page,
/* set load state */
setAppState({ ...appState, isLoading: true });
/* */

fetch(`https://asia-south1-bonse-430603.cloudfunctions.net/fastimage-api`, {
method: "POST",
body: formData,
})
.then((response) => {
response
.json()
.then((data) => {
setAppState({
imageData: data.results,
isLoading: false,
pagination: { currentPage: page, currentQuery: query },
getResult: getResult,
});
})
.catch((err) => {
console.error(err);
router.refresh();
});
})
.catch((err) => {
console.error(err);
router.refresh();
});
};
/* */

/* set load state */
setAppState({ imageData: appState.imageData, isLoading: true });
/* */
return (
<NavContext.Provider value={{ appState }}>
<header>
<Banner />

fetch(
`https://asia-south1-bonse-430603.cloudfunctions.net/fastimage-api`,
{
method: "POST",
body: formData,
}
)
.then((response) => {
response
.json()
.then((data) => {
setAppState({ imageData: data.results, isLoading: false });
})
.catch((err) => {
console.error(err);
router.refresh();
});
})
.catch((err) => {
console.error(err);
router.refresh();
});
}}
/>
<Navbar formCallback={getResult} />
</header>
{children}
<Footer />
Expand Down
26 changes: 19 additions & 7 deletions components/home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,35 @@ import { useContext } from "react";
import { NavContext } from "../app/providerWrapper";
import ImageRow from "./image-row";
import Loading from "./loading";
import PageController from "./page-controller";
import Waitroom from "./waitroom";

export default () => {
const { appState } = useContext(NavContext);

const { isLoading, imageData, pagination, getResult } = appState;

const { currentPage, currentQuery } = pagination;

return (
<>
{appState.isLoading ? (
{isLoading ? (
<Loading />
) : appState.imageData.length === 0 ? (
) : imageData.length === 0 ? (
<Waitroom />
) : (
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 p-10">
{appState.imageData.map((imageBatch, idx) => (
<ImageRow imageRecord={imageBatch} key={idx} />
))}
</div>
<>
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 p-10">
{imageData.map((imageBatch, idx) => (
<ImageRow imageRecord={imageBatch} key={idx} />
))}
</div>
<PageController
callback={getResult}
currentPage={currentPage}
currentQuery={currentQuery}
/>
</>
)}
</>
);
Expand Down
123 changes: 123 additions & 0 deletions components/page-controller.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
export default ({
callback,
currentQuery,
currentPage,
}: {
callback: (query: string, page?: number) => void;
currentQuery: string;
currentPage: number;
}) => {
const tenPagesFromCurrent = Array.from(
{ length: 10 },
(_, idx) => idx + currentPage
);

const pageTrain = [
...tenPagesFromCurrent.slice(0, 3),
"...",
...tenPagesFromCurrent.slice(-3),
];

return (
<div className="max-w-screen-xl mx-auto mt-12 px-4 text-gray-600 md:px-8">
<div
className="hidden items-center justify-between sm:flex"
aria-label="Pagination"
>
{currentPage > 1 ? (
<button
onClick={() => {
callback(currentQuery, currentPage - 1);
}}
className="hover:text-indigo-600 flex items-center gap-x-2"
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
className="w-5 h-5"
>
<path
fillRule="evenodd"
d="M18 10a.75.75 0 01-.75.75H4.66l2.1 1.95a.75.75 0 11-1.02 1.1l-3.5-3.25a.75.75 0 010-1.1l3.5-3.25a.75.75 0 111.02 1.1l-2.1 1.95h12.59A.75.75 0 0118 10z"
clipRule="evenodd"
/>
</svg>
Previous
</button>
) : (
""
)}
<ul className="flex items-center gap-1">
{pageTrain.map((item, idx) => (
<li key={item} className="text-sm">
{item == "..." ? (
<div>{item}</div>
) : (
<button
onClick={() => {
callback(currentQuery, parseInt(item + ""));
}}
aria-current={currentPage + "" == item ? "page" : false}
className={`px-3 py-2 rounded-lg duration-150 hover:text-indigo-600 hover:bg-indigo-50 ${
currentPage + "" == item
? "bg-indigo-50 text-indigo-600 font-medium"
: ""
}`}
>
{item}
</button>
)}
</li>
))}
</ul>
<button
onClick={() => {
callback(currentQuery, currentPage + 1);
}}
className="hover:text-indigo-600 flex items-center gap-x-2"
>
Next
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
className="w-5 h-5"
>
<path
fillRule="evenodd"
d="M2 10a.75.75 0 01.75-.75h12.59l-2.1-1.95a.75.75 0 111.02-1.1l3.5 3.25a.75.75 0 010 1.1l-3.5 3.25a.75.75 0 11-1.02-1.1l2.1-1.95H2.75A.75.75 0 012 10z"
clipRule="evenodd"
/>
</svg>
</button>
</div>
{/* On mobile version */}
<div className="flex items-center justify-between text-sm text-gray-600 font-medium sm:hidden">
{currentPage > 1 ? (
<button
onClick={() => {
callback(currentQuery, currentPage - 1);
}}
className="px-4 py-2 border rounded-lg duration-150 hover:bg-gray-50"
>
Previous
</button>
) : (
""
)}
<div className="font-medium">
Page {currentPage} of {pageTrain.length}
</div>
<button
onClick={() => {
callback(currentQuery, currentPage + 1);
}}
className="px-4 py-2 border rounded-lg duration-150 hover:bg-gray-50"
>
Next
</button>
</div>
</div>
);
};

0 comments on commit fd8f9b4

Please sign in to comment.