Skip to content

Commit

Permalink
술-상세페이지내-리뷰-불러오기-기능-추가 (#94)
Browse files Browse the repository at this point in the history
* Minor : 컴포넌트 디렉토리 변경

* Minor : 컴포넌트 디렉토리 변경

* Minor : 스타일 변경

* Minor : 인터페이스 명 변경

* New : Next Image remote patterns 추가

* New : 이미지 추가

* New : 술상세페이지내 포스트리스트 추가

* Refactor : SearchParam으로 제공된 AlcoholNo로 검색이 가능하도록 리팩토링
  • Loading branch information
jobkaeHenry authored Jan 5, 2024
1 parent 11f70db commit 8f4f8bf
Show file tree
Hide file tree
Showing 17 changed files with 306 additions and 46 deletions.
28 changes: 19 additions & 9 deletions client/next.config.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'standalone',
output: "standalone",
images: {
remotePatterns: [
{
protocol: "https",
hostname: "res.cloudinary.com",
},
],
},
webpack(config, { isServer }) {
// @ts-ignore - rules is a private property that is not typed
const fileLoaderRule = config.module.rules.find((rule) => rule.test?.test?.('.svg'));

const fileLoaderRule = config.module.rules.find((rule) =>
rule.test?.test?.(".svg")
);

config.module.rules.push(
// Reapply the existing rule, but only for svg imports ending in ?url
{
Expand All @@ -17,22 +27,22 @@ const nextConfig = {
test: /\.svg$/i,
issuer: fileLoaderRule.issuer,
resourceQuery: { not: [...fileLoaderRule.resourceQuery.not, /url/] }, // exclude if *.svg?url
use: ['@svgr/webpack'],
use: ["@svgr/webpack"],
}
);

// Modify the file loader rule to ignore *.svg, since we have it handled now.
fileLoaderRule.exclude = /\.svg$/i;

return config;
},
}
};

//For PWA
const withPWA = require("next-pwa")({
dest: "public",
disable: process.env.NODE_ENV === "development",
runtimeCaching: [],
sw:'/sw.js',
sw: "/sw.js",
});
module.exports = withPWA(nextConfig)
module.exports = withPWA(nextConfig);
6 changes: 5 additions & 1 deletion client/src/app/search/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@ const SearchPage = async ({
}: {
searchParams?: { [key: string]: string | undefined };
}) => {
const accessToken = await getTokenFromCookies()
const accessToken = await getTokenFromCookies();
const initialData = await getPostListQueryFn({
searchKeyword: searchParams?.keyword,
searchAlcoholNos: searchParams?.searchAlcoholNos
? Number(searchParams?.searchAlcoholNos)
: undefined,
headers: { Authorization: accessToken },
});

Expand All @@ -19,6 +22,7 @@ const SearchPage = async ({
<SearchArea
initialData={initialData}
searchKeyword={searchParams?.keyword}
searchAlcoholNos={Number(searchParams?.searchAlcoholNos)}
/>
</>
);
Expand Down
16 changes: 12 additions & 4 deletions client/src/app/wiki/[alcoholNo]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { HTML_TITLE, nameOfApp } from "@/const/brand";
import { getAlcoholDetailById } from "@/queries/alcohol/useGetAlcoholDetailQuery";
import { Metadata } from "next";
import AlcoholDetailPage from "./(components)/AlcoholDetailPage";
import AlcoholDetailPage from "../../../components/wiki/detail/AlcoholDetailPage";
import CustomAppbar from "@/components/layout/CustomAppbar";
import CustomContainer from "@/components/layout/CustomContainer";
import AlcoholDetailPostCardList from "@/components/wiki/detail/AlcoholDetailPostCardList";
import { getPostListQueryFn } from "@/queries/post/useGetPostListInfiniteQuery";

type Props = {
params: { alcoholNo: string };
Expand Down Expand Up @@ -41,18 +43,24 @@ export async function generateMetadata({ params }: Props): Promise<Metadata> {

const page = async ({ params }: Props) => {
const initialData = await getAlcoholDetailById(params.alcoholNo);
const initialPostData = await getPostListQueryFn({
searchAlcoholNos: Number(params?.alcoholNo),
size: 3,
});
const searchKeyword = initialData.alcoholName;

return (
<>
<CustomAppbar title={initialData.alcoholName} />
<CustomAppbar title={searchKeyword} />
<CustomContainer>
<AlcoholDetailPage
alcoholNo={params.alcoholNo}
initialData={initialData}
>
{/* 포스트리스트자리 */}
{/* FIXME */}
<AlcoholDetailPostCardList
initialData={initialPostData}
alcoholNo={Number(params.alcoholNo)}
/>
</AlcoholDetailPage>
</CustomContainer>
</>
Expand Down
14 changes: 7 additions & 7 deletions client/src/assets/icons/LogoLarge.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added client/src/assets/images/hasNoAlcoholImage.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion client/src/components/post/PostCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ const PostCard = ({
<Link href={USER_PAGE(createdBy)}>
<UserAvatar
src={profileImgUrls[0]?.attachUrl}
fallback={String(id)[0].toUpperCase()}
fallback={id?.[0]?.toUpperCase()}
/>
</Link>
<Box sx={{ width: "100%" }}>
Expand Down Expand Up @@ -143,6 +143,7 @@ const PostCard = ({
dangerouslySetInnerHTML={{
__html: sanitize(postContent),
}}
onClick={() => openPostDetailPage(id, String(postNo))}
></div>
{/* Hash tags */}
<PostHashTagList tags={tagList} />
Expand Down
18 changes: 14 additions & 4 deletions client/src/components/post/PostCardList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@ import getTokenFromLocalStorage from "@/utils/getTokenFromLocalStorage";
import { postcardContext } from "@/store/post/PostCardContext";
import PostCardSkeleton from "./PostCardSkeleton";

function PostCardList(props: UseGetPostListQueryInterface) {
function PostCardList({
searchAlcoholNos,
searchKeyword,
searchUserNos,
sort,
...props
}: UseGetPostListQueryInterface) {
const {
data,
fetchNextPage,
Expand All @@ -23,12 +29,16 @@ function PostCardList(props: UseGetPostListQueryInterface) {
isSuccess,
isLoading,
} = useGetPostListInfiniteQuery({
// 검색중이 아니면서 AlcoholNos 가 있는 경우에만 AlcoholNo로 검색
searchAlcoholNos:
searchKeyword === "" && searchAlcoholNos ? searchAlcoholNos : undefined,
sort,
searchUserNos,
searchKeyword: searchKeyword !== "" ? searchKeyword : undefined,
...props,
headers: { Authorization: getTokenFromLocalStorage() },
});

const { searchKeyword, searchUserNos, sort } = props;

const { ref, inView } = useInView();
useEffect(() => {
if (hasNextPage && inView) fetchNextPage();
Expand Down Expand Up @@ -59,7 +69,7 @@ function PostCardList(props: UseGetPostListQueryInterface) {
<PostCardSkeleton />
) : (
// 인터섹션옵저버
hasNextPage&&<div style={{ height: 60 }} ref={ref}></div>
hasNextPage && <div style={{ height: 60 }} ref={ref}></div>
)}
</div>
</postcardContext.Provider>
Expand Down
15 changes: 8 additions & 7 deletions client/src/components/post/PostHashtagList.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import { SEARCH_BY_KEYWORD } from "@/const/clientPath";
import { PostInterface } from "@/types/post/PostInterface";
import { Stack, StackProps, Typography } from "@mui/material";
import { Stack, StackProps, TypographyProps, Typography } from "@mui/material";
import Link from "next/link";

interface TagListInterface extends StackProps {
tags: PostInterface["tagList"];
color?: TypographyProps["color"];
}
const PostHashTagList = ({ tags, ...others }: TagListInterface) => {
const PostHashTagList = ({
tags,
color = "text.secondary",
...others
}: TagListInterface) => {
const uniqueSet = Array.from(new Set(tags));
return (
<>
Expand All @@ -21,11 +26,7 @@ const PostHashTagList = ({ tags, ...others }: TagListInterface) => {
>
{uniqueSet.map((tag, i) => (
<Link href={SEARCH_BY_KEYWORD(tag)} key={i}>
<Typography
component={"span"}
variant={"label"}
color="text.secondary"
>
<Typography component={"span"} variant={"label"} color={color}>
{`#${tag}`}
</Typography>
</Link>
Expand Down
12 changes: 9 additions & 3 deletions client/src/components/search/SearchArea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,25 @@ import useDebounce from "@/hooks/useDebounce";
import InputSearchIcon from "~/assets/icons/InputSearchIcon.svg";
import { motion } from "framer-motion";

type Props = {
type SearchAreaProps = {
initialData: AugmentedGetPostListResponse;
searchKeyword?: string;
searchAlcoholNos?: number;
};

const SearchArea = ({ initialData, searchKeyword }: Props) => {
const SearchArea = ({
initialData,
searchKeyword,
searchAlcoholNos,
}: SearchAreaProps) => {
const [keyword, setKeyword] = useState(searchKeyword ?? "");
const debouncedValue = useDebounce(keyword, 300);
const MemoidInitailData = useMemo(() => initialData, []);

return (
<>
<Box
height= {72}
height={72}
sx={{
position: "fixed",
top: 0,
Expand Down Expand Up @@ -55,6 +60,7 @@ const SearchArea = ({ initialData, searchKeyword }: Props) => {
<PostCardList
initialData={!keyword ? MemoidInitailData : undefined}
searchKeyword={debouncedValue}
searchAlcoholNos={searchAlcoholNos}
/>
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const AlcoholDetailPage = ({ alcoholNo, initialData, children }: Props) => {
/>
{children}

<Stack gap={2}>
<Stack gap={2} pt={2}>
<Typography
variant={"subtitle1"}
color="primary.main"
Expand Down
76 changes: 76 additions & 0 deletions client/src/components/wiki/detail/AlcoholDetailPostCardList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
"use client";

import AlcoholeDetailPostCard from "./AlcoholeDetailPostCard";
import ArrowDownwardIcon from "@mui/icons-material/ArrowDownward";
import { Stack, Box, Button, CircularProgress, Typography } from "@mui/material";

import AlcoholDetailPostCardListHeader from "./AlcoholDetailPostCardListHeader";
import useGetPostListInfiniteQuery, {
AugmentedGetPostListResponse,
} from "@/queries/post/useGetPostListInfiniteQuery";
import { SEARCH_BY_ALCOHOLNO } from "@/const/clientPath";

type Props = {
initialData?: AugmentedGetPostListResponse;
alcoholNo: number;
};

const AlcoholDetailPostCardList = ({ initialData, alcoholNo }: Props) => {
const { data, hasNextPage, isFetching, fetchNextPage } =
useGetPostListInfiniteQuery({
initialData,
searchAlcoholNos: alcoholNo,
size: 3,
});
const hasPost = (data?.pages?.[0]?.content?.length ?? 0) > 0;

return (
<div>
<AlcoholDetailPostCardListHeader
totalContents={data?.pages?.[0]?.totalElements ?? 0}
href={SEARCH_BY_ALCOHOLNO(alcoholNo)}
/>
<Stack gap={2} py={2} mt={6}>
{hasPost ? (
<>
{data?.pages.map(({ content }) =>
content.map((data) => (
<AlcoholeDetailPostCard {...data} key={data.postNo} />
))
)}
{hasNextPage && (
<Button
sx={ButtonStyle}
onClick={() => fetchNextPage()}
disabled={isFetching}
>
캐스크 더보기
<ArrowDownwardIcon sx={{ color: "primary.main" }} />
</Button>
)}
{isFetching && <CircularProgress sx={{ mx: "auto" }} />}
</>
) : (
<Typography textAlign='center'>작성된 캐스크가 없습니다</Typography>
)}
</Stack>
<Box
bgcolor={"gray.primary"}
position={"absolute"}
height={16}
left={0}
right={0}
/>
</div>
);
};

const ButtonStyle = {
backgroundColor: "#F6EAFB",
color: "primary.main",
":hover": {
backgroundColor: "#F6EAFB",
},
};

export default AlcoholDetailPostCardList;
Loading

0 comments on commit 8f4f8bf

Please sign in to comment.