Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .graphqlrc.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"$schema": "https://raw.githubusercontent.com/kamilkisiela/graphql-config/master/config-schema.json",
"schema": ["./api/graph/schema/*.graphql"]
"schema": ["./api/graph/schema/*.graphql"],
"documents": ["./web/app/gql/operations/*.graphql"]
}
1 change: 1 addition & 0 deletions api/cmd/seed/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ func main() {
revisions := make([]RevisionWithIngredients, 0)
if forkdFrom.revision.ID.Valid {
initialRevision, err := qtx.SeedRevision(ctx, db.SeedRevisionParams{
Title: forkdFrom.revision.Title,
RecipeID: forkdFrom.revision.RecipeID,
RecipeDescription: forkdFrom.revision.RecipeDescription,
ChangeComment: forkdFrom.revision.ChangeComment,
Expand Down
5 changes: 5 additions & 0 deletions api/services/recipe/recipe.go
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,8 @@ func (r recipeService) ListRecipeRevisions(ctx context.Context, input *model.Lis
var NextCursor *string = nil

if len(revisions) == int(params.Limit) {
// We have to do this to keep the cursor size from ballooning, since we don't care about this field anyway
input.NextCursor = nil
cursor := ListRevisionsCursor{
ListRevisionsInput: *input,
}
Expand Down Expand Up @@ -708,6 +710,9 @@ func (r recipeService) ListRecipes(ctx context.Context, input *model.ListRecipeI
listInput = *input
}

// We have to do this to keep the cursor size from ballooning, since we don't care about this field anyway
listInput.NextCursor = nil

cursor := ListRecipesCursor{
ListRecipeInput: listInput,
}
Expand Down
22 changes: 22 additions & 0 deletions web/app/.server/loaders/recipes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { ClientError } from "graphql-request"
import { environment } from "~/.server/env"
import { getSessionOrThrow } from "~/.server/session"
import { getSDK } from "~/gql/client"
import { LoaderFunctionArgs } from "react-router"

export async function recipesLoader<T extends LoaderFunctionArgs>(args: T) {
const session = await getSessionOrThrow(args, false)
const auth = session.get("sessionToken")
const sdk = getSDK(`${environment.BACKEND_URL}`, auth)
try {
const data = await sdk.ListRecipes({
input: { nextCursor: args.params.cursor },
})
return data?.recipe?.list ?? null
} catch (err) {
if (err instanceof ClientError && err.message === "missing auth") {
return null
}
throw err
}
}
44 changes: 38 additions & 6 deletions web/app/components/recipeList/RecipeList.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,61 @@
import { SimpleGrid } from "@mantine/core"
import { ReactNode } from "react"
import { Center, Loader, Paper, SimpleGrid } from "@mantine/core"
import { ReactNode, useEffect, useState } from "react"
import { ListRecipesQuery } from "~/gql/forkd.g"
import { RecipeCard } from "../recipeCard/recipeCard"
import { useFetch, useIntersection } from "@mantine/hooks"

type Props = {
recipes: Exclude<ListRecipesQuery["recipe"], null | undefined>["list"]
}

export default function RecipeList({ recipes }: Props): ReactNode {
const [recipeList, setRecipeList] = useState(recipes.items)
const [cursor, setCursor] = useState(recipes.pagination.nextCursor)
const { refetch, data, loading, abort } = useFetch<Props["recipes"]>(
`/api/recipes/paginate/${cursor ?? ""}`,
{ autoInvoke: false }
)
useEffect(() => {
return () => {
abort()
}
}, [abort])
useEffect(() => {
if (data) {
setRecipeList((r) => r.concat(data.items))
setCursor(data.pagination.nextCursor)
}
}, [data])
const { ref, entry } = useIntersection({
rootMargin: "1200px",
})
useEffect(() => {
if (entry?.isIntersecting && !loading && cursor) {
refetch()
}
}, [entry?.isIntersecting, loading, refetch, cursor])
return (
<>
{/* recipe component */}
<Paper>
<SimpleGrid
cols={{ base: 1, sm: 2, md: 2, lg: 4 }}
pb={40}
pt={40}
style={styles.grid}
>
{recipes?.items.map((recipe) => (
{recipeList.map((recipe) => (
<div key={recipe.id} style={styles.col}>
<RecipeCard recipe={recipe || {}} />
</div>
))}
</SimpleGrid>
</>
{loading ? (
<Center>
<Loader size="xl" />{" "}
</Center>
) : (
<div ref={ref}></div>
)}
</Paper>
)
}

Expand Down
13 changes: 9 additions & 4 deletions web/app/gql/forkd.g.ts
Original file line number Diff line number Diff line change
Expand Up @@ -335,10 +335,12 @@ export type CheckUserSignupQueryVariables = Exact<{

export type CheckUserSignupQuery = { __typename?: 'Query', user?: { __typename?: 'UserQuery', byEmail?: { __typename?: 'User', email: string } | null, byDisplayName?: { __typename?: 'User', displayName: string } | null } | null };

export type ListRecipesQueryVariables = Exact<{ [key: string]: never; }>;
export type ListRecipesQueryVariables = Exact<{
input?: InputMaybe<ListRecipeInput>;
}>;


export type ListRecipesQuery = { __typename?: 'Query', recipe?: { __typename?: 'RecipeQuery', list: { __typename?: 'PaginatedRecipes', items: Array<{ __typename?: 'Recipe', slug: string, id: any, author: { __typename?: 'User', displayName: string }, featuredRevision?: { __typename?: 'RecipeRevision', recipeDescription?: string | null, publishDate: any, rating?: number | null, title: string } | null }> } } | null };
export type ListRecipesQuery = { __typename?: 'Query', recipe?: { __typename?: 'RecipeQuery', list: { __typename?: 'PaginatedRecipes', items: Array<{ __typename?: 'Recipe', slug: string, id: any, author: { __typename?: 'User', displayName: string }, featuredRevision?: { __typename?: 'RecipeRevision', recipeDescription?: string | null, publishDate: any, rating?: number | null, title: string } | null }>, pagination: { __typename?: 'PaginationInfo', nextCursor?: string | null } } } | null };

export type LoginMutationVariables = Exact<{
token: Scalars['String']['input'];
Expand Down Expand Up @@ -395,9 +397,9 @@ export const CheckUserSignupDocument = gql`
}
`;
export const ListRecipesDocument = gql`
query ListRecipes {
query ListRecipes($input: ListRecipeInput) {
recipe {
list {
list(input: $input) {
items {
slug
id
Expand All @@ -411,6 +413,9 @@ export const ListRecipesDocument = gql`
title
}
}
pagination {
nextCursor
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
query ListRecipes {
query ListRecipes($input: ListRecipeInput) {
recipe {
list {
list(input: $input) {
items {
slug
id
Expand All @@ -14,6 +14,9 @@ query ListRecipes {
title
}
}
pagination {
nextCursor
}
}
}
}
File renamed without changes.
23 changes: 4 additions & 19 deletions web/app/routes/_app._index/route.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { MetaFunction, useLoaderData, LoaderFunctionArgs } from "react-router"
import { ClientError } from "graphql-request"
import { getSessionOrThrow } from "~/.server/session"
import { getSDK } from "~/gql/client"
import { environment } from "~/.server/env"
import { MetaFunction, useLoaderData } from "react-router"
import { recipesLoader } from "~/.server/loaders/recipes"
import RecipeList from "../../components/recipeList/RecipeList"
import type { Route } from "./+types/route"

export const meta: MetaFunction = () => {
return [
Expand All @@ -15,20 +13,7 @@ export const meta: MetaFunction = () => {
]
}

export async function loader(args: LoaderFunctionArgs) {
const session = await getSessionOrThrow(args, false)
const auth = session.get("sessionToken")
const sdk = getSDK(`${environment.BACKEND_URL}`, auth)
try {
const data = await sdk.ListRecipes()
return data?.recipe?.list ?? null
} catch (err) {
if (err instanceof ClientError && err.message === "missing auth") {
return null
}
throw err
}
}
export const loader = recipesLoader<Route.LoaderArgs>

export default function Index() {
const recipes = useLoaderData<typeof loader>()
Expand Down
3 changes: 3 additions & 0 deletions web/app/routes/api.recipes.paginate.$cursor/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { recipesLoader } from "~/.server/loaders/recipes"
import type { Route } from "./+types/route"
export const loader = recipesLoader<Route.LoaderArgs>
2 changes: 1 addition & 1 deletion web/codegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { CodegenConfig } from "@graphql-codegen/cli"
const config: CodegenConfig = {
overwrite: true,
schema: "http://localhost:8000/query",
documents: "app/gql/**/*.gql",
documents: "app/gql/**/*.graphql",
generates: {
"app/gql/forkd.g.ts": {
plugins: [
Expand Down
Loading