Skip to content

Commit

Permalink
feat(example-marketing): add pagination to view
Browse files Browse the repository at this point in the history
  • Loading branch information
shadcn committed Jun 16, 2021
1 parent 4236043 commit feb6543
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 54 deletions.
1 change: 1 addition & 0 deletions examples/example-marketing/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"dependencies": {
"next": "^10.1.3",
"next-drupal": "^0.11.0",
"nprogress": "^0.2.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-hook-form": "^7.8.6",
Expand Down
7 changes: 7 additions & 0 deletions examples/example-marketing/pages/_app.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import * as React from "react"
import { AppProps } from "next/app"
import Router from "next/router"
import { ThemeProvider } from "reflexjs"
import { QueryClient, QueryClientProvider } from "react-query"
import { Hydrate } from "react-query/hydration"
import NProgress from "nprogress"
import "nprogress/nprogress.css"

Router.events.on("routeChangeStart", () => NProgress.start())
Router.events.on("routeChangeComplete", () => NProgress.done())
Router.events.on("routeChangeError", () => NProgress.done())

import { Layout } from "@/components/layout"
import theme from "../src/theme"
Expand Down
27 changes: 18 additions & 9 deletions examples/example-marketing/src/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -378,8 +378,12 @@ const theme: Theme = {
cursor: "pointer",
transition: "all .15s ease-in",

":disabled": {
opacity: 0.5,
cursor: "not-allowed",
},

":hover, :focus": {
transform: "translateY(-2px)",
boxShadow: "lg",
},

Expand All @@ -403,9 +407,6 @@ const theme: Theme = {
"&:hover, &:focus": {
bg: "primaryHover",
color: "white",
borderColor: "primaryHover",
transform: "translateY(-2px)",
boxShadow: "lg",
},
},

Expand All @@ -418,8 +419,6 @@ const theme: Theme = {
bg: "secondaryHover",
color: "white",
borderColor: "secondaryHover",
transform: "translateY(-2px)",
boxShadow: "lg",
},
},

Expand All @@ -432,8 +431,6 @@ const theme: Theme = {
bg: "accentHover",
color: "white",
borderColor: "accentHover",
transform: "translateY(-2px)",
boxShadow: "lg",
},
},

Expand All @@ -445,12 +442,24 @@ const theme: Theme = {
"&:hover, &:focus": {
bg: "transparent",
borderColor: "transparent",
transform: "translateY(-2px)",
boxShadow: "none",
color: "primary",
},
},

outline: {
bg: "transparent",
color: "text",
borderColor: "text",

"&:hover, &:focus": {
bg: "text",
borderColor: "text",
boxShadow: "none",
color: "background",
},
},

icon: {
bg: "transparent",
p: 2,
Expand Down
131 changes: 86 additions & 45 deletions examples/example-marketing/src/views/view-properties-listing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,53 +7,55 @@ import { Icon } from "reflexjs"
import { FormItem } from "@/components/form-item"
import { NodePropertyGrid, NodePropertyList } from "@/nodes/node-property"

const filters = ["location", "status", "beds", "baths"]
const filters = { location: "All", status: "All", beds: "1", baths: "1" }

export function ViewPropertiesListing({ view: initialData, ...props }) {
async function fetchView(url, params) {
const _url = new URL(url)
_url.search = new URLSearchParams(params).toString()

const result = await fetch(_url.toString())

if (!result.ok) {
throw new Error(result.statusText)
}

const data = await result.json()

return {
results: deserialize(data),
meta: data.meta,
links: data.links,
}
}

export function ViewPropertiesListing({ view: initialView, ...props }) {
const [page, setPage] = React.useState(0)
const queryClient = useQueryClient()
const [display, setDisplay] = React.useState<"grid" | "list">("grid")
const { register, handleSubmit, getValues, formState, reset } = useForm({
defaultValues: {
location: "All",
status: "All",
beds: "1",
baths: "1",
},
defaultValues: filters,
})
const [locations, setLocations] = React.useState([])
const { data: view, isLoading } = useQuery(
[initialData.name],
const { data: view, isLoading, isPreviousData } = useQuery(
[initialView.name, page],
async () => {
// Build params from form values.
const values = getValues()
const params = {
page: page + "",
include: "field_location,field_images.field_media_image",
}
for (const filter of filters) {
for (const filter of Object.keys(filters)) {
if (values[filter]) {
params[`views-filter[${filter}]`] = values[filter]
}
}

const url = new URL(initialData.jsonApiUrl)
url.search = new URLSearchParams(params).toString()

const result = await fetch(url.toString())

if (!result.ok) {
throw new Error(result.statusText)
}

const data = await result.json()

return {
...initialData,
results: deserialize(data),
count: data.meta.count,
}
return fetchView(initialView.links.self.href.split("?")[0], params)
},
{
initialData,
initialData: initialView,
keepPreviousData: true,
}
)

Expand All @@ -73,6 +75,7 @@ export function ViewPropertiesListing({ view: initialData, ...props }) {
}, [])

async function submitForm() {
setPage(0)
await queryClient.invalidateQueries(view.name)
}

Expand Down Expand Up @@ -100,14 +103,6 @@ export function ViewPropertiesListing({ view: initialData, ...props }) {
<h4 variant="heading.h4" fontFamily="sans">
Find your place
</h4>
<button
type="button"
variant="button.link.sm"
onClick={() => resetForm()}
visibility={formState.isSubmitted ? "visible" : "hidden"}
>
Reset
</button>
</div>
<hr />
<form onSubmit={handleSubmit(submitForm)}>
Expand Down Expand Up @@ -171,9 +166,26 @@ export function ViewPropertiesListing({ view: initialData, ...props }) {
</div>
</div>
<hr />
<button variant="button.primary" width="full">
Search Properties
</button>
<div
display="grid"
col="2"
gap="4"
alignItems="center"
justifyContent="space-between"
>
<button variant="button.primary" width="full">
Search
</button>
<button
type="button"
variant="button.outline"
ml="auto"
onClick={() => resetForm()}
visibility={formState.isSubmitted ? "visible" : "hidden"}
>
Reset
</button>
</div>
</form>
</div>
<div>
Expand All @@ -186,7 +198,9 @@ export function ViewPropertiesListing({ view: initialData, ...props }) {
alignItems="center"
justifyContent="space-between"
>
<h3 fontWeight="normal">Found {view.count} properties.</h3>
<h3 fontWeight="normal">
Found {view.meta?.count} properties.
</h3>
<div display="grid" col="2" gap="2">
<button
type="button"
Expand All @@ -213,18 +227,45 @@ export function ViewPropertiesListing({ view: initialData, ...props }) {
opacity={isLoading ? 0.5 : 1}
>
{view.results.map((node) => (
<>
<div key={node.id}>
{display === "grid" ? (
<NodePropertyGrid key={node.id} node={node} />
<NodePropertyGrid node={node} />
) : (
<NodePropertyList key={node.id} node={node} />
<NodePropertyList node={node} />
)}
</>
</div>
))}
</div>
<hr />
<div
display="flex"
alignItems="center"
justifyContent="space-between"
>
<button
variant="button"
onClick={() => setPage((old) => Math.max(old - 1, 0))}
disabled={page === 0}
>
Previous
</button>
<button
variant="button"
onClick={() => {
if (!isPreviousData && view.links.next) {
setPage((old) => old + 1)
}
}}
disabled={isPreviousData || !view?.links.next}
>
Next
</button>
</div>
</>
) : (
<p>No properties found.</p>
<p textAlign="center" py="20">
No properties found.
</p>
)}
</div>
</div>
Expand Down
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -10573,6 +10573,11 @@ npmlog@^4.1.2:
gauge "~2.7.3"
set-blocking "~2.0.0"

nprogress@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/nprogress/-/nprogress-0.2.0.tgz#cb8f34c53213d895723fcbab907e9422adbcafb1"
integrity sha1-y480xTIT2JVyP8urkH6UIq28r7E=

nth-check@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c"
Expand Down

1 comment on commit feb6543

@vercel
Copy link

@vercel vercel bot commented on feb6543 Jun 16, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.