diff --git a/apps/frontend/src/routes/_app/recipe/$recipeId/.skelton-recipe.tsx b/apps/frontend/src/routes/_app/recipe/$recipeId/.skelton-recipe.tsx new file mode 100644 index 0000000..e88f9f4 --- /dev/null +++ b/apps/frontend/src/routes/_app/recipe/$recipeId/.skelton-recipe.tsx @@ -0,0 +1,70 @@ +import { IconChevronLeft } from '@tabler/icons-react' +import { Link } from '@tanstack/react-router' +import type { FC } from 'react' + +type SkeltonRecipeProps = { + searchResult?: string +} + +export const SkeltonRecipe: FC = ({ searchResult }) => ( + <> +
+ {searchResult !== undefined && ( + + + 検索結果に戻る + + )} +
+
+
+
+
+
+
+ {[...Array(2)].map((_, i) => ( +
+ ))} +
+
+
+
+
    + {[...Array(5)].map((_, i) => ( +
  • + + +
  • + ))} +
+
    + {[...Array(8)].map((_, i) => ( + // biome-ignore lint/suspicious/noArrayIndexKey: This is a skeleton component, so index key is not a problem +
  1. +
    + {i + 1} +
    +
    +
    +
    +
    +
  2. + ))} +
+
+

作る際のポイント

+
+
+
+
+
+ +) diff --git a/apps/frontend/src/routes/_app/recipe/$recipeId/index.tsx b/apps/frontend/src/routes/_app/recipe/$recipeId/index.tsx index 0737dfc..2cc9241 100644 --- a/apps/frontend/src/routes/_app/recipe/$recipeId/index.tsx +++ b/apps/frontend/src/routes/_app/recipe/$recipeId/index.tsx @@ -4,6 +4,7 @@ import { useLayoutEffect } from 'react' import { twJoin } from 'tailwind-merge' import { z } from 'zod' import { apiClient } from '../../../../lib/apiClient' +import { SkeltonRecipe } from './.skelton-recipe' const searchParamsSchema = z.object({ searchResult: z.string().url().optional(), @@ -20,6 +21,7 @@ export const Route = createFileRoute('/_app/recipe/$recipeId/')({ validateSearch: (search) => searchParamsSchema.parse(search), loader: ({ params }) => loader(params.recipeId), component: () => , + pendingComponent: () => , }) const RecipeInfo = () => { @@ -118,3 +120,18 @@ const RecipeInfo = () => {
) } + +const PendingRecipe = () => { + const { searchResult } = Route.useSearch() + + useLayoutEffect(() => { + const scrollToTop = () => window.scrollTo({ top: 0, behavior: 'smooth' }) + scrollToTop() + }, []) + + return ( +
+ +
+ ) +} diff --git a/apps/frontend/src/routes/_app/recipe/.skelton-card.tsx b/apps/frontend/src/routes/_app/recipe/.skelton-card.tsx new file mode 100644 index 0000000..35b5eb0 --- /dev/null +++ b/apps/frontend/src/routes/_app/recipe/.skelton-card.tsx @@ -0,0 +1,20 @@ +import type { FC } from 'react' + +export const SkeltonCard: FC = () => ( +
+
+
+
+
+
+
+
+ {[...Array(Math.floor(Math.random() * 3 + 4))].map((_, i) => ( + // biome-ignore lint/suspicious/noArrayIndexKey: This is a skeleton component, so index key is not a problem +
+ ))} +
+
+
+
+) diff --git a/apps/frontend/src/routes/_app/recipe/index.tsx b/apps/frontend/src/routes/_app/recipe/index.tsx index f0b1bad..0279a7c 100644 --- a/apps/frontend/src/routes/_app/recipe/index.tsx +++ b/apps/frontend/src/routes/_app/recipe/index.tsx @@ -5,6 +5,7 @@ import { z } from 'zod' import { LinkButton } from '../../../components/common/LinkButton' import { apiClient } from '../../../lib/apiClient' import { RecipeCard } from './.recipe-card' +import { SkeltonCard } from './.skelton-card' const recipeSearchSchema = z.object({ foods: z.array(z.string()).catch([]), @@ -21,24 +22,10 @@ export const Route = createFileRoute('/_app/recipe/')({ return data }, component: () => , - pendingComponent: () => , - errorComponent: () => , + pendingComponent: () => , + errorComponent: () => , }) -const ErrorComponents = () => ( - <> -

レシピが見つかりませんでした。

- 戻る - -) - -const Pending = () => ( -
- -

レシピを検索中

-
-) - const Recipe = () => { const { foods } = Route.useSearch() const { data, page } = Route.useLoaderData() @@ -92,3 +79,25 @@ const Recipe = () => { ) } + +const PendingRecipe = () => ( + <> +
+

レシピ一覧

+

Recipe

+
+
+ {[...Array(5)].map((_, i) => ( + // biome-ignore lint/suspicious/noArrayIndexKey: This is a skeleton component, so index key is not a problem + + ))} +
+ +) + +const ErrorComponent = () => ( + <> +

レシピが見つかりませんでした。

+ 戻る + +)