From 0a993757e955e795980bb5c5f9786f915f3420dd Mon Sep 17 00:00:00 2001 From: kihyeoon Date: Sun, 1 Sep 2024 14:32:25 +0900 Subject: [PATCH 1/8] =?UTF-8?q?=F0=9F=A5=85=20=EC=9C=A0=ED=8A=9C=EB=B8=8C?= =?UTF-8?q?=20=EC=8D=B8=EB=84=A4=EC=9D=BC=20=EC=97=90=EB=9F=AC=EC=8B=9C=20?= =?UTF-8?q?fallbackImg=20=EC=B6=9C=EB=A0=A5=ED=95=98=EB=8F=84=EB=A1=9D=20u?= =?UTF-8?q?seImgSrc=20=ED=9B=85=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../recipe/components/detail/RecipeView.tsx | 13 +++++++---- .../recipe/components/list/RecipeListItem.tsx | 12 ++++++---- src/features/recipe/hooks/useImgSrc.ts | 22 +++++++++++++++++++ 3 files changed, 39 insertions(+), 8 deletions(-) create mode 100644 src/features/recipe/hooks/useImgSrc.ts diff --git a/src/features/recipe/components/detail/RecipeView.tsx b/src/features/recipe/components/detail/RecipeView.tsx index 4f6cd4d..87b2230 100644 --- a/src/features/recipe/components/detail/RecipeView.tsx +++ b/src/features/recipe/components/detail/RecipeView.tsx @@ -2,6 +2,7 @@ import Image from "next/image"; +import useImgSrc from "@/features/recipe/hooks/useImgSrc"; import { getVideoId } from "@/features/recipe/libs/utils"; import { Recipe } from "@/features/recipe/models/recipe"; @@ -14,18 +15,22 @@ const sectionStyle = "flex flex-col gap-3 bg-background p-4"; export default function RecipeView({ recipe: { title, url, description, ingredients, steps, tips }, }: Props) { + const { imgSrc, handleImageError } = useImgSrc({ + url: + url && `https://img.youtube.com/vi/${getVideoId(url)}/maxresdefault.jpg`, + fallbackImg: "/images/placeholder.png", + }); + return (
{url && ( {title} { - e.currentTarget.src = "/images/placeholder.png"; - }} + onError={handleImageError} /> )} diff --git a/src/features/recipe/components/list/RecipeListItem.tsx b/src/features/recipe/components/list/RecipeListItem.tsx index 12b3682..99d0e2c 100644 --- a/src/features/recipe/components/list/RecipeListItem.tsx +++ b/src/features/recipe/components/list/RecipeListItem.tsx @@ -7,6 +7,7 @@ import { useState } from "react"; import DeleteButton from "@/components/DeleteButton"; +import useImgSrc from "@/features/recipe/hooks/useImgSrc"; import { getVideoId } from "@/features/recipe/libs/utils"; import { RecipePreview } from "@/features/recipe/models/recipe"; @@ -22,6 +23,11 @@ export const RecipeListItem = ({ deleteRecipe, }: Props) => { const [isHovered, setIsHovered] = useState(false); + const { imgSrc, handleImageError } = useImgSrc({ + url: url && `https://img.youtube.com/vi/${getVideoId(url)}/mqdefault.jpg`, + fallbackImg: "/images/placeholder.png", + }); + const router = useRouter(); return ( @@ -36,13 +42,11 @@ export const RecipeListItem = ({ {url ? ( {title} { - e.currentTarget.src = "/images/placeholder.png"; - }} + onError={handleImageError} /> ) : (
diff --git a/src/features/recipe/hooks/useImgSrc.ts b/src/features/recipe/hooks/useImgSrc.ts new file mode 100644 index 0000000..2bfa899 --- /dev/null +++ b/src/features/recipe/hooks/useImgSrc.ts @@ -0,0 +1,22 @@ +import { useState } from "react"; + +interface Props { + url: string | null; + fallbackImg: string; +} + +export default function useImgSrc({ url, fallbackImg }: Props) { + const [imgSrc, setImgSrc] = useState(url ?? fallbackImg); + + const handleImageError = ( + e: React.SyntheticEvent, + ) => { + console.error("error => ", e); + setImgSrc(fallbackImg); + }; + + return { + imgSrc, + handleImageError, + }; +} From 0c62bdf629a6f58a20d1d3358aaf717cf6078600 Mon Sep 17 00:00:00 2001 From: kihyeoon Date: Sun, 1 Sep 2024 16:08:53 +0900 Subject: [PATCH 2/8] =?UTF-8?q?=E2=9C=A8=20=EB=A0=88=EC=8B=9C=ED=94=BC=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=20=ED=8E=98=EC=9D=B4=EC=A7=80=20loading=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EC=83=9D=EC=84=B1=20#21?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/recipe/[id]/loading.tsx | 9 +++++++++ src/features/recipe/components/detail/RecipeSkeleton.tsx | 1 + .../recipe/components/list/RecipeListSkeleton.tsx | 2 +- 3 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 src/app/recipe/[id]/loading.tsx diff --git a/src/app/recipe/[id]/loading.tsx b/src/app/recipe/[id]/loading.tsx new file mode 100644 index 0000000..348950d --- /dev/null +++ b/src/app/recipe/[id]/loading.tsx @@ -0,0 +1,9 @@ +import RecipeSkeleton from "@/features/recipe/components/detail/RecipeSkeleton"; + +export default function Loading() { + return ( +
+ +
+ ); +} diff --git a/src/features/recipe/components/detail/RecipeSkeleton.tsx b/src/features/recipe/components/detail/RecipeSkeleton.tsx index 0661314..1f8bd84 100644 --- a/src/features/recipe/components/detail/RecipeSkeleton.tsx +++ b/src/features/recipe/components/detail/RecipeSkeleton.tsx @@ -3,6 +3,7 @@ import { Skeleton } from "@/components/ui/skeleton"; export default function RecipeSkeleton() { return (
+ diff --git a/src/features/recipe/components/list/RecipeListSkeleton.tsx b/src/features/recipe/components/list/RecipeListSkeleton.tsx index 42aa9cd..f04e574 100644 --- a/src/features/recipe/components/list/RecipeListSkeleton.tsx +++ b/src/features/recipe/components/list/RecipeListSkeleton.tsx @@ -1,6 +1,6 @@ import { Skeleton } from "@/components/ui/skeleton"; -export default function RecipeSkeleton() { +export default function RecipeListSkeleton() { return (
{Array.from({ length: 15 }).map((_, index) => ( From e61d2bc755cab9e0f2e3cea73b4b34f94432b08f Mon Sep 17 00:00:00 2001 From: kihyeoon Date: Sat, 7 Sep 2024 21:17:27 +0900 Subject: [PATCH 3/8] =?UTF-8?q?=F0=9F=92=84=20=EB=A0=88=EC=9D=B4=EC=95=84?= =?UTF-8?q?=EC=9B=83=20=ED=8F=AD=20=EC=83=81=ED=96=A5=20#22?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/layout.tsx | 2 +- src/components/NavBar.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 3abac63..87c62f0 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -34,7 +34,7 @@ export default function RootLayout({ > -
+
{children}
diff --git a/src/components/NavBar.tsx b/src/components/NavBar.tsx index 713061b..f397bb8 100644 --- a/src/components/NavBar.tsx +++ b/src/components/NavBar.tsx @@ -10,7 +10,7 @@ export default function NavBar() { const user = session?.user; return ( -
- {isHovered && ( + {!isTouchDevice && isHovered && ( { From 7e1300071316b3840be63172248abe471ec7184d Mon Sep 17 00:00:00 2001 From: kihyeoon Date: Sat, 7 Sep 2024 23:55:27 +0900 Subject: [PATCH 5/8] =?UTF-8?q?=E2=9C=A8=20=EC=B2=B4=ED=97=98=EC=9A=A9=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=84=B0=20=EA=B3=84=EC=A0=95=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?#22?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/auth/signIn/page.tsx | 2 +- src/features/auth/components/SignIn.tsx | 36 +++++++++++++++++++---- src/features/auth/services/auth.ts | 38 +++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 7 deletions(-) diff --git a/src/app/auth/signIn/page.tsx b/src/app/auth/signIn/page.tsx index c1a6f84..aa25b1e 100644 --- a/src/app/auth/signIn/page.tsx +++ b/src/app/auth/signIn/page.tsx @@ -29,7 +29,7 @@ export default async function SignInPage({ const providers = (await getProviders()) ?? {}; return ( -
+
); diff --git a/src/features/auth/components/SignIn.tsx b/src/features/auth/components/SignIn.tsx index 80f30d1..db9c8b0 100644 --- a/src/features/auth/components/SignIn.tsx +++ b/src/features/auth/components/SignIn.tsx @@ -1,6 +1,6 @@ "use client"; -import { ClientSafeProvider, signIn } from "next-auth/react"; +import { type ClientSafeProvider, signIn } from "next-auth/react"; import { Button } from "@/components/ui/button"; @@ -10,13 +10,37 @@ interface Props { } export default function SignIn({ providers, callbackUrl }: Props) { + const testAccount = { + email: "test@example.com", + password: "testpassword", + }; + return ( <> - {Object.values(providers).map(({ name, id }) => ( - - ))} + {Object.values(providers).map(({ name, id }) => { + if (id !== "credentials") { + return ( + + ); + } else { + return ( + + ); + } + })} ); } diff --git a/src/features/auth/services/auth.ts b/src/features/auth/services/auth.ts index abbd05f..c2bbc08 100644 --- a/src/features/auth/services/auth.ts +++ b/src/features/auth/services/auth.ts @@ -1,4 +1,5 @@ import NextAuth, { NextAuthOptions } from "next-auth"; +import CredentialsProvider from "next-auth/providers/credentials"; import GoogleProvider from "next-auth/providers/google"; import { addUser } from "@/features/auth/services/user"; @@ -9,6 +10,43 @@ export const authOptions: NextAuthOptions = { clientId: process.env.GOOGLE_CLIENT_ID || "", clientSecret: process.env.GOOGLE_CLIENT_SECRET || "", }), + CredentialsProvider({ + name: "Credentials", + credentials: { + email: { + label: "Email", + type: "email", + placeholder: "test@example.com", + }, + password: { label: "Password", type: "password" }, + }, + async authorize(credentials) { + const { email, password } = credentials || {}; + + const testAccounts = [ + { + email: "test@example.com", + password: "testpassword", + name: "Test User", + }, + ]; + + const user = testAccounts.find( + (account) => account.email === email && account.password === password, + ); + + if (user) { + return { + id: "test-id", + name: user.name, + email: user.email, + username: user.email.split("@")[0], + }; + } + + return null; + }, + }), ], callbacks: { async signIn({ user: { id, name, image, email } }) { From 79e3e2893e4a7f39213e23b9d03d90f2836ea5e2 Mon Sep 17 00:00:00 2001 From: kihyeoon Date: Sun, 8 Sep 2024 11:10:42 +0900 Subject: [PATCH 6/8] =?UTF-8?q?=F0=9F=92=84=20=EB=A0=88=EC=8B=9C=ED=94=BC?= =?UTF-8?q?=20=EC=8D=B8=EB=84=A4=EC=9D=BC=20=EC=8A=A4=EC=BC=88=EB=A0=88?= =?UTF-8?q?=ED=86=A4=20UI=20=EB=84=93=EC=9D=B4=20=EB=B3=80=EA=B2=BD=20#22?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/recipe/components/detail/RecipeSkeleton.stories.ts | 2 +- src/features/recipe/components/detail/RecipeSkeleton.tsx | 2 +- .../recipe/components/list/RecipeListSkeleton.stories.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/features/recipe/components/detail/RecipeSkeleton.stories.ts b/src/features/recipe/components/detail/RecipeSkeleton.stories.ts index 354e1d1..310aa62 100644 --- a/src/features/recipe/components/detail/RecipeSkeleton.stories.ts +++ b/src/features/recipe/components/detail/RecipeSkeleton.stories.ts @@ -3,7 +3,7 @@ import type { Meta, StoryObj } from "@storybook/react"; import RecipeSkeleton from "./RecipeSkeleton"; const meta = { - title: "recipe/skeleton", + title: "recipe/skeleton/detail", component: RecipeSkeleton, parameters: { layout: "centered", diff --git a/src/features/recipe/components/detail/RecipeSkeleton.tsx b/src/features/recipe/components/detail/RecipeSkeleton.tsx index 1f8bd84..f26c35c 100644 --- a/src/features/recipe/components/detail/RecipeSkeleton.tsx +++ b/src/features/recipe/components/detail/RecipeSkeleton.tsx @@ -3,7 +3,7 @@ import { Skeleton } from "@/components/ui/skeleton"; export default function RecipeSkeleton() { return (
- + diff --git a/src/features/recipe/components/list/RecipeListSkeleton.stories.tsx b/src/features/recipe/components/list/RecipeListSkeleton.stories.tsx index b71ae72..9cfa231 100644 --- a/src/features/recipe/components/list/RecipeListSkeleton.stories.tsx +++ b/src/features/recipe/components/list/RecipeListSkeleton.stories.tsx @@ -3,7 +3,7 @@ import type { Meta, StoryObj } from "@storybook/react"; import RecipeListSkeleton from "./RecipeListSkeleton"; const meta = { - title: "recipe/list skeleton", + title: "recipe/skeleton/list", component: RecipeListSkeleton, parameters: { layout: "centered", From 0de3ff0cd94b5cfca1945173b00113a5a51d1146 Mon Sep 17 00:00:00 2001 From: kihyeoon Date: Sun, 8 Sep 2024 12:26:10 +0900 Subject: [PATCH 7/8] =?UTF-8?q?=F0=9F=92=84=20=EA=B2=BD=EB=A1=9C=EB=AA=85?= =?UTF-8?q?=EC=9D=B4=20"/auth/signIn"=EC=9D=BC=20=EB=95=8C=20=EB=A0=8C?= =?UTF-8?q?=EB=8D=94=EB=A7=81=20NavBar=EB=A5=BC=20=EB=A0=8C=EB=8D=94?= =?UTF-8?q?=EB=A7=81=ED=95=98=EC=A7=80=20=EC=95=8A=EC=9D=8C=20#22?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/NavBar.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/components/NavBar.tsx b/src/components/NavBar.tsx index f397bb8..ca686e3 100644 --- a/src/components/NavBar.tsx +++ b/src/components/NavBar.tsx @@ -1,6 +1,7 @@ "use client"; import { signIn, signOut, useSession } from "next-auth/react"; +import { usePathname } from "next/navigation"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { Button } from "@/components/ui/button"; @@ -8,6 +9,11 @@ import { Button } from "@/components/ui/button"; export default function NavBar() { const { data: session } = useSession(); const user = session?.user; + const pathname = usePathname(); + + if (pathname === "/auth/signIn") { + return null; + } return (