From 8ca97468d925da6d3944487184b1f0f988a77c10 Mon Sep 17 00:00:00 2001 From: YI Na-yeon <2n.ayeon.yi@gmail.com> Date: Mon, 22 Jul 2024 20:08:20 +0900 Subject: [PATCH 01/33] =?UTF-8?q?[Style]=20=EB=B0=98=EC=9D=91=ED=98=95=20?= =?UTF-8?q?=EC=8A=A4=ED=83=80=EC=9D=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/_components/BannerImage.tsx | 2 +- .../CategoryTab/TabButtonsOfGoalSection.tsx | 2 +- src/app/_components/TopBannerSection.tsx | 57 ++++---- src/app/layout.tsx | 1 + src/common/Layout/Footer.tsx | 14 +- src/common/Layout/Header.tsx | 134 ++---------------- 6 files changed, 54 insertions(+), 156 deletions(-) diff --git a/src/app/_components/BannerImage.tsx b/src/app/_components/BannerImage.tsx index ed2c1bd..e837783 100644 --- a/src/app/_components/BannerImage.tsx +++ b/src/app/_components/BannerImage.tsx @@ -9,7 +9,7 @@ export default function BannerImage({ className }: { className?: string }) { viewBox="0 0 1440 1492" fill="none" xmlns="http://www.w3.org/2000/svg" - className="ml-auto translate-x-1/3 md:translate-x-1/2 xl:translate-x-2/3 -translate-y-1/4" + className="ml-auto translate-x-1/4 md:translate-x-1/2 xl:translate-x-2/3 -translate-y-1/4" > -
+
{GOALS_TAB.map(({ label, value, iconName }) => { const active = selected === value; return ( diff --git a/src/app/_components/TopBannerSection.tsx b/src/app/_components/TopBannerSection.tsx index 513e3e6..2451cf5 100644 --- a/src/app/_components/TopBannerSection.tsx +++ b/src/app/_components/TopBannerSection.tsx @@ -8,18 +8,19 @@ import { Container } from "@/common/Layout"; export default function TopBanner() { return (
-
+
-

- 케밋에서 케미 터지는 스터디 장과 멤버들을 만나,
+

+ 케밋에서 케미 터지는 스터디 장과 멤버들을 만나,{" "} +
놀라운 성장을 경험하세요!

-
+
-
+
-
- - +
+
+ + +
diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 429ed00..57c6a77 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -20,6 +20,7 @@ export const metadata: Metadata = { icons: { icon: "/favicon.ico", }, + viewport: "width=device-width, initial-scale=1.0", }; export default function RootLayout({ diff --git a/src/common/Layout/Footer.tsx b/src/common/Layout/Footer.tsx index 71507cc..bf88155 100644 --- a/src/common/Layout/Footer.tsx +++ b/src/common/Layout/Footer.tsx @@ -12,10 +12,10 @@ import { FLogo } from "../../../public/images"; export default function Footer() { return ( -
+
{/* sns md:추가 */} -
+
-
+
{/* sns md:제거 */}
  • @@ -119,10 +119,10 @@ export default function Footer() {
-
+
- 고객센터 : 0000-0000 - 월~금(공휴일제외) 09:00~18:00 +

고객센터 : 0000-0000

+

월~금(공휴일제외) 09:00~18:00

(주)웅진씽크빅 대표이사 : 이봉주 @@ -131,7 +131,7 @@ export default function Footer() {

{/* 모바일 open : start */} -
    +
    • 고객센터
    • diff --git a/src/common/Layout/Header.tsx b/src/common/Layout/Header.tsx index e1409c2..ef9f767 100644 --- a/src/common/Layout/Header.tsx +++ b/src/common/Layout/Header.tsx @@ -14,7 +14,7 @@ import { DummyProfileImg } from "@public/images"; import Container from "./Container"; import LoginModal from "@/app/(auth)/_components/LoginModal"; import { getSession } from "@/auth"; -import UnstyledLogoutButton from "./UnstyledLogoutButton"; +import ResponsiveMenu from "./ProfileMenu/ResponsiveMenu"; export default async function Header() { const session = await getSession(); @@ -23,14 +23,17 @@ export default async function Header() {
      -
      +

      logo

      {session ? ( -
      - <> - - create study - 스터디 만들기 - -
      -
      +
      + profile img -
        -
      • - - 내 프로필 - - 내 프로필 - - -
      • -
      • - - 내 스터디 - - 내 스터디 - - -
      • -
      • - - 찜 스터디 - - 찜 스터디 - - -
      • -
      • - - 내가 쓴 글 - - 내가 쓴 글 - - -
      • -
      • - - 로그아웃 - - 로그아웃 - - - {/* */} -
      • -
      + {session.user.name}
      -
      - alarm -
      -
      - - - {/* - 로그인 - */} + } + />
      ) : ( From 85bcb09d16cfea62e78cfaa782061166eb5a4c5b Mon Sep 17 00:00:00 2001 From: YI Na-yeon <2n.ayeon.yi@gmail.com> Date: Mon, 22 Jul 2024 20:08:51 +0900 Subject: [PATCH 02/33] =?UTF-8?q?[Feat]=20tailwind=20mediaquery=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=EC=9D=84=20=EC=9C=84=ED=95=9C=20=ED=9B=85=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/useMediaQuery.tsx | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/hooks/useMediaQuery.tsx diff --git a/src/hooks/useMediaQuery.tsx b/src/hooks/useMediaQuery.tsx new file mode 100644 index 0000000..1bfdbdb --- /dev/null +++ b/src/hooks/useMediaQuery.tsx @@ -0,0 +1,23 @@ +import resolveConfig from "tailwindcss/resolveConfig"; +import tailwindConfig from "tailwind.config"; +import { useEffect, useState } from "react"; + +const fullConfig = resolveConfig(tailwindConfig); +const { + theme: { screens }, +} = fullConfig; + +// tailwind breakpoints setting by config theme.screens token +// Tailwind 미디어쿼리 사용 방법과 동일하게 동작, 동일하게 사용 +export default function useMediaQuery(query: keyof typeof screens): boolean { + const mediaQuery = `(min-width: ${screens[query]})`; + const matchQueryList = window.matchMedia(mediaQuery); + const [isMatch, setMatch] = useState(false); + const onChange = (e: MediaQueryListEvent) => setMatch(e.matches); + useEffect(() => { + setMatch(matchQueryList.matches); + matchQueryList.addEventListener("change", onChange); + return () => matchQueryList.removeEventListener("change", onChange); + }, [query]); + return isMatch; +} From 465dc50fa58695abcb68a60dd75be0eb3e08fe1c Mon Sep 17 00:00:00 2001 From: YI Na-yeon <2n.ayeon.yi@gmail.com> Date: Mon, 22 Jul 2024 20:10:06 +0900 Subject: [PATCH 03/33] =?UTF-8?q?[Feat]=20=ED=8C=9D=EC=98=A4=EB=B2=84(?= =?UTF-8?q?=EB=AA=A8=EB=8B=AC=20=EB=93=B1=EC=9D=98=20=EA=B8=B0=EB=B3=B8=20?= =?UTF-8?q?=EA=B5=AC=EC=A1=B0)=20=EC=82=AC=EC=9A=A9=20=ED=9B=85=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/usePopover.tsx | 54 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 src/hooks/usePopover.tsx diff --git a/src/hooks/usePopover.tsx b/src/hooks/usePopover.tsx new file mode 100644 index 0000000..6add779 --- /dev/null +++ b/src/hooks/usePopover.tsx @@ -0,0 +1,54 @@ +import { useId, useRef, useState } from "react"; +import { createPortal } from "react-dom"; + +import { TProps } from "@/types/component/props"; +import useDialogEscape from "./useDialogEscape"; +import SidePopup from "@/common/Layout/Sidebar/SidePopup"; + +export type TPopoverHookParams = TProps & { + onClose?: () => void; + defaultValue?: boolean; + key?: string; +}; +export default function usePopover(props: TPopoverHookParams) { + const { onClose, children, defaultValue = false, key = undefined } = props; + const modalRef = useRef(null); + const uid = useId(); + const modalKey = key || uid; + const [show, setShow] = useState(defaultValue); + + useDialogEscape({ + show, + ref: modalRef, + close: () => setShow(false), + }); + + function open() { + if (show === false) { + setShow(true); + } + } + function close() { + if (show === true) { + setShow(false); + onClose && onClose(); + return; + } + } + + const element = show + ? createPortal( + + {children} + , + document.body, + modalKey + ) + : null; + + return { + Popup: element, + open, + close, + }; +} From f26895be8e76bc7b047d0d0324c770e816ee9d5a Mon Sep 17 00:00:00 2001 From: YI Na-yeon <2n.ayeon.yi@gmail.com> Date: Mon, 22 Jul 2024 20:14:07 +0900 Subject: [PATCH 04/33] =?UTF-8?q?[Feat]=20=ED=8C=9D=EC=98=A4=EB=B2=84=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=20=ED=9B=85=EA=B3=BC=20props=20=ED=83=80?= =?UTF-8?q?=EC=9E=85=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/useModal.tsx | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/hooks/useModal.tsx b/src/hooks/useModal.tsx index 0c83fca..e868d5c 100644 --- a/src/hooks/useModal.tsx +++ b/src/hooks/useModal.tsx @@ -1,16 +1,11 @@ -import { useEffect, useId, useReducer, useRef, useState } from "react"; +import { useId, useRef, useState } from "react"; import { createPortal } from "react-dom"; -import { TProps } from "@/types/component/props"; import ModalPortal from "@/common/Molecules/ModalPortal/ModalPortal"; import useDialogEscape from "./useDialogEscape"; +import { TPopoverHookParams } from "./usePopover"; -type TModalHookParams = TProps & { - onClose?: () => void; - defaultValue?: boolean; - key?: string; -}; -export default function useModal(props: TModalHookParams) { +export default function useModal(props: TPopoverHookParams) { const { onClose, children, defaultValue = false, key = undefined } = props; const modalRef = useRef(null); const uid = useId(); From 104098d83458440505742b4f3a957e3cc15a1af4 Mon Sep 17 00:00:00 2001 From: YI Na-yeon <2n.ayeon.yi@gmail.com> Date: Mon, 22 Jul 2024 20:15:11 +0900 Subject: [PATCH 05/33] =?UTF-8?q?[Style]=20z-modal=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/Molecules/ModalPortal/ModalPortal.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/Molecules/ModalPortal/ModalPortal.tsx b/src/common/Molecules/ModalPortal/ModalPortal.tsx index 2498197..9edd4ef 100644 --- a/src/common/Molecules/ModalPortal/ModalPortal.tsx +++ b/src/common/Molecules/ModalPortal/ModalPortal.tsx @@ -16,7 +16,7 @@ const ModalPortal = forwardRef( return ( From 72771cc7260cb2705e51486f852a35a2268ce0eb Mon Sep 17 00:00:00 2001 From: YI Na-yeon <2n.ayeon.yi@gmail.com> Date: Mon, 22 Jul 2024 20:16:17 +0900 Subject: [PATCH 06/33] =?UTF-8?q?[Style,=20Feat]=20CloseIcon=20stroke=3F:?= =?UTF-8?q?=20string=20=EC=86=8D=EC=84=B1=20=EC=B6=94=EA=B0=80,=20MenuIcon?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/Atoms/Image/Icon.tsx | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/common/Atoms/Image/Icon.tsx b/src/common/Atoms/Image/Icon.tsx index a1680bf..992eabc 100644 --- a/src/common/Atoms/Image/Icon.tsx +++ b/src/common/Atoms/Image/Icon.tsx @@ -223,7 +223,7 @@ export function OfflineIcon(props: TIconStylingProps) { ); } -export function CloseIcon() { +export function CloseIcon({ stroke = "#171719" }: { stroke?: string }) { return ( ); } + +export function MenuIcon() { + return ( + + + + ); +} From e1e3c2e872bc7651ff0c0994596f563cc61fcfbb Mon Sep 17 00:00:00 2001 From: YI Na-yeon <2n.ayeon.yi@gmail.com> Date: Mon, 22 Jul 2024 20:17:03 +0900 Subject: [PATCH 07/33] =?UTF-8?q?[Style,=20Feat]=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=ED=95=84=20=EB=A9=94=EB=89=B4=20=EB=B0=98=EC=9D=91=ED=98=95=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80,=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProfileMenu/DefaultProfileMenuItems.tsx | 65 +++++++++++++++++++ src/common/Layout/ProfileMenu/DesktopMenu.tsx | 30 +++++++++ src/common/Layout/ProfileMenu/MobileMenu.tsx | 58 +++++++++++++++++ .../Layout/ProfileMenu/ResponsiveMenu.tsx | 13 ++++ 4 files changed, 166 insertions(+) create mode 100644 src/common/Layout/ProfileMenu/DefaultProfileMenuItems.tsx create mode 100644 src/common/Layout/ProfileMenu/DesktopMenu.tsx create mode 100644 src/common/Layout/ProfileMenu/MobileMenu.tsx create mode 100644 src/common/Layout/ProfileMenu/ResponsiveMenu.tsx diff --git a/src/common/Layout/ProfileMenu/DefaultProfileMenuItems.tsx b/src/common/Layout/ProfileMenu/DefaultProfileMenuItems.tsx new file mode 100644 index 0000000..94d5009 --- /dev/null +++ b/src/common/Layout/ProfileMenu/DefaultProfileMenuItems.tsx @@ -0,0 +1,65 @@ +import { + LogoutIcon, + PostIcon, + SaveHeartIcon, + SettingProfileIcon, + StudyIcon, +} from "@public/icons"; +import Image from "next/image"; +import Link from "next/link"; +import UnstyledLogoutButton from "../UnstyledLogoutButton"; +import { ReactNode } from "react"; + +export default function DefaultProfileMenuItems() { + return ( + <> + + } + label="내 프로필" + /> + } + label="내 스터디" + /> + } + label="찜 스터디" + /> + } + label="내가 쓴 글" + /> +
      + + } + label="로그아웃" + /> + + + ); +} + +function ProfileMenuItemLink({ + icon, + label, +}: { + icon: ReactNode; + label: string; +}) { + return ( +
    • + +
      {icon}
      + {label} + +
    • + ); +} diff --git a/src/common/Layout/ProfileMenu/DesktopMenu.tsx b/src/common/Layout/ProfileMenu/DesktopMenu.tsx new file mode 100644 index 0000000..47d5dde --- /dev/null +++ b/src/common/Layout/ProfileMenu/DesktopMenu.tsx @@ -0,0 +1,30 @@ +import { AlarmIcon, CreateStudyIcon } from "@public/icons"; +import Image from "next/image"; +import Link from "next/link"; +import DefaultProfileMenuItems from "./DefaultProfileMenuItems"; +import { TProfileImage } from "./ResponsiveMenu"; + +export default function DesktopMenu({ profileImage }: TProfileImage) { + return ( +
      + + create study + 스터디 만들기 + +
      +
      + {profileImage} +
        + +
      +
      +
      + alarm +
      +
      +
      + ); +} diff --git a/src/common/Layout/ProfileMenu/MobileMenu.tsx b/src/common/Layout/ProfileMenu/MobileMenu.tsx new file mode 100644 index 0000000..05a6b47 --- /dev/null +++ b/src/common/Layout/ProfileMenu/MobileMenu.tsx @@ -0,0 +1,58 @@ +"use client"; +import usePopover from "@/hooks/usePopover"; +import { MenuIcon } from "../../Atoms/Image/Icon"; +import { TProfileImage } from "./ResponsiveMenu"; +import Link from "next/link"; +import Image from "next/image"; +import { AlarmIcon, CreateStudyIcon } from "@public/icons"; +import DefaultProfileMenuItems from "./DefaultProfileMenuItems"; +import { useEffect } from "react"; +import useMediaQuery from "@/hooks/useMediaQuery"; + +export default function MobileMenu({ profileImage }: TProfileImage) { + const notMobile = useMediaQuery("lg"); + const { Popup, open, close } = usePopover({ + key: "mobile-menu", + children: ( +
      +
      +
      + {profileImage} +
      + alarm +
      +
      + + create study + 스터디 만들기 + +
        + +
      +
      +
      + ), + }); + + useEffect(() => { + return () => { + close(); + }; + }, []); + + // useEffect(() => { + // console.log(notMobile); + // }, [notMobile]); + + return notMobile ? null : ( + <> + + {Popup} + + ); +} diff --git a/src/common/Layout/ProfileMenu/ResponsiveMenu.tsx b/src/common/Layout/ProfileMenu/ResponsiveMenu.tsx new file mode 100644 index 0000000..8942bb8 --- /dev/null +++ b/src/common/Layout/ProfileMenu/ResponsiveMenu.tsx @@ -0,0 +1,13 @@ +import { ReactNode } from "react"; +import MobileMenu from "./MobileMenu"; +import DesktopMenu from "./DesktopMenu"; + +export type TProfileImage = { profileImage: ReactNode }; +export default function ResponsiveMenu(props: TProfileImage) { + return ( + <> + + + + ); +} From b7e93e40f8eb56b247b196193567a09e8ad3909c Mon Sep 17 00:00:00 2001 From: YI Na-yeon <2n.ayeon.yi@gmail.com> Date: Mon, 22 Jul 2024 20:18:11 +0900 Subject: [PATCH 08/33] =?UTF-8?q?[Feat]=20ModalBackdrop=EC=9D=84=20?= =?UTF-8?q?=ED=99=9C=EC=9A=A9=ED=95=98=EC=97=AC=20=EC=82=AC=EC=9D=B4?= =?UTF-8?q?=EB=93=9C=20=EB=B0=94=20=ED=8C=9D=EC=97=85=20=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EC=95=84=EC=9B=83=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/Layout/Sidebar/SidePopup.tsx | 39 +++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 src/common/Layout/Sidebar/SidePopup.tsx diff --git a/src/common/Layout/Sidebar/SidePopup.tsx b/src/common/Layout/Sidebar/SidePopup.tsx new file mode 100644 index 0000000..2c994c3 --- /dev/null +++ b/src/common/Layout/Sidebar/SidePopup.tsx @@ -0,0 +1,39 @@ +import { ForwardedRef, forwardRef, MouseEventHandler } from "react"; +import { TModalPortalProps } from "@/types/component/props"; +import Button from "@/common/Atoms/Form/Button"; +import { CloseIcon } from "@/common/Atoms/Image/Icon"; +import ModalBackdrop from "@/common/Molecules/ModalPortal/ModalBackdrop"; + +const SidePopup = forwardRef( + ( + props: TModalPortalProps, + ref: ForwardedRef + ) => { + const { children, onClose } = props; + const stopPropagation: MouseEventHandler = (e) => { + e.stopPropagation(); + }; + return ( + + +
      + +
      {children}
      +
      +
      + ); + } +); + +SidePopup.displayName = "SidePopup"; + +export default SidePopup; From cb1aad9a8e1c185cbace7d99c9e474d4abad7db4 Mon Sep 17 00:00:00 2001 From: YI Na-yeon <2n.ayeon.yi@gmail.com> Date: Mon, 22 Jul 2024 22:51:34 +0900 Subject: [PATCH 09/33] =?UTF-8?q?[Fix]=20postId=EA=B0=92=EC=97=90=20?= =?UTF-8?q?=EB=AC=B8=EC=9E=90=EC=97=B4=EC=9D=84=20=EB=84=A3=EC=96=B4=20uni?= =?UTF-8?q?que=20key=20prop=20=EA=B2=BD=EA=B3=A0=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/dummies/posts.ts | 78 ++++++++++++++++++++++++++++---------------- 1 file changed, 49 insertions(+), 29 deletions(-) diff --git a/src/dummies/posts.ts b/src/dummies/posts.ts index b9e95b9..9ddfa24 100644 --- a/src/dummies/posts.ts +++ b/src/dummies/posts.ts @@ -1,8 +1,24 @@ import { TPost } from "@/types/model/PostItem"; +const alphabet = + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-"; +const base = alphabet.length; +function encodeNumToStr(num: number): string { + if (isNaN(num) || +num <= 0) { + throw new Error("It's not a number."); + } + let encoded = ""; + while (num) { + const remainder = num % base; + num = Math.floor(num / base); + encoded = alphabet[remainder].toString() + encoded; + } + return encoded; +} + const example: TPost[] = [ { - postId: "10", + postId: encodeNumToStr(101355), category: { value: "free", label: "자유게시판", @@ -25,7 +41,7 @@ const example: TPost[] = [ like: 15, }, { - postId: "9", + postId: encodeNumToStr(101354), category: { value: "study", label: "스터디 홍보", @@ -34,7 +50,7 @@ const example: TPost[] = [ contents: { title: "모든 프로덕트에 대한 스터디", body: "", - linkedStudyId: null, + linkedStudyId: "1", }, writer: { userId: "hanyoojun", @@ -48,7 +64,7 @@ const example: TPost[] = [ like: 15, }, { - postId: "8", + postId: encodeNumToStr(101353), category: { value: "study", label: "스터디 홍보", @@ -72,7 +88,7 @@ const example: TPost[] = [ like: 15, }, { - postId: "7", + postId: encodeNumToStr(101352), category: { value: "study", label: "스터디 홍보", @@ -95,7 +111,7 @@ const example: TPost[] = [ like: 15, }, { - postId: "10", + postId: encodeNumToStr(101351), category: { value: "free", label: "자유게시판", @@ -118,7 +134,7 @@ const example: TPost[] = [ like: 15, }, { - postId: "9", + postId: encodeNumToStr(101350), category: { value: "study", label: "스터디 홍보", @@ -141,7 +157,7 @@ const example: TPost[] = [ like: 15, }, { - postId: "8", + postId: encodeNumToStr(101349), category: { value: "study", label: "스터디 홍보", @@ -165,7 +181,7 @@ const example: TPost[] = [ like: 15, }, { - postId: "7", + postId: encodeNumToStr(101348), category: { value: "study", label: "스터디 홍보", @@ -188,7 +204,7 @@ const example: TPost[] = [ like: 15, }, { - postId: "10", + postId: encodeNumToStr(101347), category: { value: "free", label: "자유게시판", @@ -211,7 +227,7 @@ const example: TPost[] = [ like: 15, }, { - postId: "9", + postId: encodeNumToStr(101346), category: { value: "study", label: "스터디 홍보", @@ -234,7 +250,7 @@ const example: TPost[] = [ like: 15, }, { - postId: "8", + postId: encodeNumToStr(101345), category: { value: "study", label: "스터디 홍보", @@ -258,7 +274,7 @@ const example: TPost[] = [ like: 15, }, { - postId: "7", + postId: encodeNumToStr(101344), category: { value: "study", label: "스터디 홍보", @@ -281,7 +297,7 @@ const example: TPost[] = [ like: 15, }, { - postId: "10", + postId: encodeNumToStr(101343), category: { value: "free", label: "자유게시판", @@ -304,7 +320,7 @@ const example: TPost[] = [ like: 15, }, { - postId: "9", + postId: encodeNumToStr(101342), category: { value: "study", label: "스터디 홍보", @@ -327,7 +343,7 @@ const example: TPost[] = [ like: 15, }, { - postId: "8", + postId: encodeNumToStr(101341), category: { value: "study", label: "스터디 홍보", @@ -351,7 +367,7 @@ const example: TPost[] = [ like: 15, }, { - postId: "7", + postId: encodeNumToStr(101340), category: { value: "study", label: "스터디 홍보", @@ -374,7 +390,7 @@ const example: TPost[] = [ like: 15, }, { - postId: "10", + postId: encodeNumToStr(101339), category: { value: "free", label: "자유게시판", @@ -397,7 +413,7 @@ const example: TPost[] = [ like: 15, }, { - postId: "9", + postId: encodeNumToStr(101338), category: { value: "study", label: "스터디 홍보", @@ -420,7 +436,7 @@ const example: TPost[] = [ like: 15, }, { - postId: "8", + postId: encodeNumToStr(101337), category: { value: "study", label: "스터디 홍보", @@ -444,7 +460,7 @@ const example: TPost[] = [ like: 15, }, { - postId: "7", + postId: encodeNumToStr(101336), category: { value: "study", label: "스터디 홍보", @@ -467,7 +483,7 @@ const example: TPost[] = [ like: 15, }, { - postId: "10", + postId: encodeNumToStr(101335), category: { value: "free", label: "자유게시판", @@ -490,7 +506,7 @@ const example: TPost[] = [ like: 15, }, { - postId: "9", + postId: encodeNumToStr(101334), category: { value: "study", label: "스터디 홍보", @@ -513,7 +529,7 @@ const example: TPost[] = [ like: 15, }, { - postId: "8", + postId: encodeNumToStr(101333), category: { value: "study", label: "스터디 홍보", @@ -537,7 +553,7 @@ const example: TPost[] = [ like: 15, }, { - postId: "7", + postId: encodeNumToStr(101332), category: { value: "study", label: "스터디 홍보", @@ -560,7 +576,7 @@ const example: TPost[] = [ like: 15, }, { - postId: "10", + postId: encodeNumToStr(101331), category: { value: "free", label: "자유게시판", @@ -583,7 +599,7 @@ const example: TPost[] = [ like: 15, }, { - postId: "9", + postId: encodeNumToStr(101330), category: { value: "study", label: "스터디 홍보", @@ -606,7 +622,7 @@ const example: TPost[] = [ like: 15, }, { - postId: "8", + postId: encodeNumToStr(101329), category: { value: "study", label: "스터디 홍보", @@ -630,7 +646,7 @@ const example: TPost[] = [ like: 15, }, { - postId: "7", + postId: encodeNumToStr(101328), category: { value: "study", label: "스터디 홍보", @@ -659,5 +675,9 @@ export function getPosts(): TPost[] { } export function getPost(id: string): TPost { + const filtered = example.find((post) => post.postId === id); + if (filtered) { + return filtered; + } return { ...example[0] }; } From d4178ebf83983f0e33d5d4645e956cc87155e112 Mon Sep 17 00:00:00 2001 From: YI Na-yeon <2n.ayeon.yi@gmail.com> Date: Mon, 22 Jul 2024 22:52:28 +0900 Subject: [PATCH 10/33] =?UTF-8?q?[Feat]=20usePopover=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=EC=8B=9C=20document.body=20overflow=20hidden?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{Layout/Sidebar => Molecules}/SidePopup.tsx | 0 src/hooks/usePopover.tsx | 5 ++++- src/hooks/usePopoverScrollPrevent.tsx | 14 ++++++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) rename src/common/{Layout/Sidebar => Molecules}/SidePopup.tsx (100%) create mode 100644 src/hooks/usePopoverScrollPrevent.tsx diff --git a/src/common/Layout/Sidebar/SidePopup.tsx b/src/common/Molecules/SidePopup.tsx similarity index 100% rename from src/common/Layout/Sidebar/SidePopup.tsx rename to src/common/Molecules/SidePopup.tsx diff --git a/src/hooks/usePopover.tsx b/src/hooks/usePopover.tsx index 6add779..147f4e0 100644 --- a/src/hooks/usePopover.tsx +++ b/src/hooks/usePopover.tsx @@ -3,7 +3,8 @@ import { createPortal } from "react-dom"; import { TProps } from "@/types/component/props"; import useDialogEscape from "./useDialogEscape"; -import SidePopup from "@/common/Layout/Sidebar/SidePopup"; +import SidePopup from "@/common/Molecules/SidePopup"; +import usePopoverScrollPrevent from "./usePopoverScrollPrevent"; export type TPopoverHookParams = TProps & { onClose?: () => void; @@ -23,6 +24,8 @@ export default function usePopover(props: TPopoverHookParams) { close: () => setShow(false), }); + usePopoverScrollPrevent(show); + function open() { if (show === false) { setShow(true); diff --git a/src/hooks/usePopoverScrollPrevent.tsx b/src/hooks/usePopoverScrollPrevent.tsx new file mode 100644 index 0000000..b4608d8 --- /dev/null +++ b/src/hooks/usePopoverScrollPrevent.tsx @@ -0,0 +1,14 @@ +import { useEffect } from "react"; + +export default function usePopoverScrollPrevent(isOpen: boolean) { + useEffect(() => { + if (isOpen) { + document.body.style.overflow = "hidden"; + } else { + document.body.style.overflow = "auto"; + } + return () => { + document.body.style.overflow = "auto"; + }; + }, [isOpen]); +} From 3b52cacc3330aafa275c5e833dd3a4d24ac8a2a2 Mon Sep 17 00:00:00 2001 From: YI Na-yeon <2n.ayeon.yi@gmail.com> Date: Mon, 22 Jul 2024 22:53:45 +0900 Subject: [PATCH 11/33] =?UTF-8?q?[Style]=20=EB=B0=98=EC=9D=91=ED=98=95=20?= =?UTF-8?q?=EC=8A=A4=ED=83=80=EC=9D=BC=20=EC=B6=94=EA=B0=80=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/(route)/my/layout.tsx | 8 ------ src/app/(route)/my/profile/page.tsx | 2 +- .../_components/UserCurrentStudySection.tsx | 2 +- src/app/globals.css | 4 +++ src/common/Atoms/Form/Field.tsx | 2 +- .../Sidebar/SidebarAsideContentArea.tsx | 2 +- src/common/Layout/Sidebar/SidebarNavArea.tsx | 27 ++++++++++++++++++- 7 files changed, 34 insertions(+), 13 deletions(-) diff --git a/src/app/(route)/my/layout.tsx b/src/app/(route)/my/layout.tsx index d123257..88c2c5d 100644 --- a/src/app/(route)/my/layout.tsx +++ b/src/app/(route)/my/layout.tsx @@ -16,14 +16,6 @@ export default async function layout({ children }: TProps) { - {/* {MYPAGE_MENUS.map(({ key, ...item }) => ( - - ))} -
    • - - 로그아웃 - -
    • */}
      {children}
      diff --git a/src/app/(route)/my/profile/page.tsx b/src/app/(route)/my/profile/page.tsx index b3cd1f7..75a53da 100644 --- a/src/app/(route)/my/profile/page.tsx +++ b/src/app/(route)/my/profile/page.tsx @@ -52,7 +52,7 @@ export default function MyProfilePage() {
      -
      +
      diff --git a/src/app/_components/UserCurrentStudySection.tsx b/src/app/_components/UserCurrentStudySection.tsx index 46c119b..bf93f55 100644 --- a/src/app/_components/UserCurrentStudySection.tsx +++ b/src/app/_components/UserCurrentStudySection.tsx @@ -5,7 +5,7 @@ import Link from "next/link"; export default function UserCurrentStudySection() { return ( <> -
      +
      diff --git a/src/app/globals.css b/src/app/globals.css index 9c7ddd6..160e591 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -53,6 +53,10 @@ a { transition: backgroud-color ease-in-out 200ms, filter ease-in-out 200ms; } +details > summary { + list-style: none; +} + .scrollbar-hidden::-webkit-scrollbar { display: none; } diff --git a/src/common/Atoms/Form/Field.tsx b/src/common/Atoms/Form/Field.tsx index ad33fe6..4414b3a 100644 --- a/src/common/Atoms/Form/Field.tsx +++ b/src/common/Atoms/Form/Field.tsx @@ -2,7 +2,7 @@ import { TProps } from "@/types/component/props"; export default function GridField({ children }: TProps) { return ( -
      +
      {children}
      ); diff --git a/src/common/Layout/Sidebar/SidebarAsideContentArea.tsx b/src/common/Layout/Sidebar/SidebarAsideContentArea.tsx index b231653..1c8d93a 100644 --- a/src/common/Layout/Sidebar/SidebarAsideContentArea.tsx +++ b/src/common/Layout/Sidebar/SidebarAsideContentArea.tsx @@ -3,7 +3,7 @@ import { TProps } from "@/types/component/props"; export default function SidebarAsideContentArea({ children }: TProps) { return ( -
      +
      {children}
      ); diff --git a/src/common/Layout/Sidebar/SidebarNavArea.tsx b/src/common/Layout/Sidebar/SidebarNavArea.tsx index 5bb5d84..1e5cce9 100644 --- a/src/common/Layout/Sidebar/SidebarNavArea.tsx +++ b/src/common/Layout/Sidebar/SidebarNavArea.tsx @@ -1,6 +1,31 @@ +"use client"; import React from "react"; import { TProps } from "@/types/component/props"; +import useMediaQuery from "@/hooks/useMediaQuery"; +import { ChevronRightIcon } from "@/common/Atoms/Image/Icon"; export default function SidebarNavArea({ children }: TProps) { - return
        {children}
      ; + const notMobile = useMediaQuery("lg"); + return notMobile ? ( +
        + {children} +
      + ) : ( +
      + +
      + 메뉴 + + + +
      +
      +
        + {children} +
      +
      + ); } From 612ec885fe4aab2a51c453b7c43c51caf423213b Mon Sep 17 00:00:00 2001 From: YI Na-yeon <2n.ayeon.yi@gmail.com> Date: Mon, 22 Jul 2024 22:54:27 +0900 Subject: [PATCH 12/33] =?UTF-8?q?[Feat]=20postId=EC=97=90=20=EB=94=B0?= =?UTF-8?q?=EB=9D=BC=20LinkedStudyCard=20=ED=91=9C=EC=8B=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/(route)/post/[postId]/page.tsx | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/src/app/(route)/post/[postId]/page.tsx b/src/app/(route)/post/[postId]/page.tsx index 2993312..35be853 100644 --- a/src/app/(route)/post/[postId]/page.tsx +++ b/src/app/(route)/post/[postId]/page.tsx @@ -13,7 +13,7 @@ export default function PostDetail({ }: { params: { postId: string }; }) { - const post = getPost("10"); + const post = getPost(postId); const comments: TComment[] = []; return (
      @@ -64,20 +64,6 @@ export default function PostDetail({

      - {/* */}
      From 5e79f47fa1ca6b7945e36be1535b57f1c4632e26 Mon Sep 17 00:00:00 2001 From: YI Na-yeon <2n.ayeon.yi@gmail.com> Date: Tue, 23 Jul 2024 02:49:47 +0900 Subject: [PATCH 13/33] =?UTF-8?q?[Style]=20mediaquery=20=ED=9B=85=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98=EB=A1=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProfileMenu/DefaultProfileMenuItems.tsx | 15 ++++++++++-- src/common/Layout/ProfileMenu/MobileMenu.tsx | 15 ++++-------- src/hooks/useMediaQuery.tsx | 23 ------------------- 3 files changed, 18 insertions(+), 35 deletions(-) delete mode 100644 src/hooks/useMediaQuery.tsx diff --git a/src/common/Layout/ProfileMenu/DefaultProfileMenuItems.tsx b/src/common/Layout/ProfileMenu/DefaultProfileMenuItems.tsx index 94d5009..c1f1bb3 100644 --- a/src/common/Layout/ProfileMenu/DefaultProfileMenuItems.tsx +++ b/src/common/Layout/ProfileMenu/DefaultProfileMenuItems.tsx @@ -23,18 +23,22 @@ export default function DefaultProfileMenuItems() { /> } label="내 프로필" + href="/my/profile" /> } label="내 스터디" + href="/my/study" /> } label="찜 스터디" + href="/my/like-study" /> } label="내가 쓴 글" + href="/my/post" />
      @@ -50,16 +54,23 @@ export default function DefaultProfileMenuItems() { function ProfileMenuItemLink({ icon, label, + href, }: { icon: ReactNode; label: string; + href?: string; }) { - return ( + return href ? (
    • - +
      {icon}
      {label}
    • + ) : ( +
    • +
      {icon}
      + {label} +
    • ); } diff --git a/src/common/Layout/ProfileMenu/MobileMenu.tsx b/src/common/Layout/ProfileMenu/MobileMenu.tsx index 05a6b47..2373cb7 100644 --- a/src/common/Layout/ProfileMenu/MobileMenu.tsx +++ b/src/common/Layout/ProfileMenu/MobileMenu.tsx @@ -1,4 +1,5 @@ "use client"; + import usePopover from "@/hooks/usePopover"; import { MenuIcon } from "../../Atoms/Image/Icon"; import { TProfileImage } from "./ResponsiveMenu"; @@ -7,10 +8,8 @@ import Image from "next/image"; import { AlarmIcon, CreateStudyIcon } from "@public/icons"; import DefaultProfileMenuItems from "./DefaultProfileMenuItems"; import { useEffect } from "react"; -import useMediaQuery from "@/hooks/useMediaQuery"; export default function MobileMenu({ profileImage }: TProfileImage) { - const notMobile = useMediaQuery("lg"); const { Popup, open, close } = usePopover({ key: "mobile-menu", children: ( @@ -43,16 +42,12 @@ export default function MobileMenu({ profileImage }: TProfileImage) { }; }, []); - // useEffect(() => { - // console.log(notMobile); - // }, [notMobile]); - - return notMobile ? null : ( - <> - {Popup} - +
      ); } diff --git a/src/hooks/useMediaQuery.tsx b/src/hooks/useMediaQuery.tsx deleted file mode 100644 index 1bfdbdb..0000000 --- a/src/hooks/useMediaQuery.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import resolveConfig from "tailwindcss/resolveConfig"; -import tailwindConfig from "tailwind.config"; -import { useEffect, useState } from "react"; - -const fullConfig = resolveConfig(tailwindConfig); -const { - theme: { screens }, -} = fullConfig; - -// tailwind breakpoints setting by config theme.screens token -// Tailwind 미디어쿼리 사용 방법과 동일하게 동작, 동일하게 사용 -export default function useMediaQuery(query: keyof typeof screens): boolean { - const mediaQuery = `(min-width: ${screens[query]})`; - const matchQueryList = window.matchMedia(mediaQuery); - const [isMatch, setMatch] = useState(false); - const onChange = (e: MediaQueryListEvent) => setMatch(e.matches); - useEffect(() => { - setMatch(matchQueryList.matches); - matchQueryList.addEventListener("change", onChange); - return () => matchQueryList.removeEventListener("change", onChange); - }, [query]); - return isMatch; -} From fbd7c9d5c8bed3f29b82dbfba886700cef296b84 Mon Sep 17 00:00:00 2001 From: YI Na-yeon <2n.ayeon.yi@gmail.com> Date: Tue, 23 Jul 2024 02:50:13 +0900 Subject: [PATCH 14/33] =?UTF-8?q?[Fix]=20=ED=94=84=EB=A1=9C=ED=95=84=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20POST=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../profile/_components/FormEditProfile.tsx | 76 +++++++++++++------ .../my/profile/_components/ProfileForms.tsx | 72 ++++++++++++++++++ .../profile/_components/ProfileImageInput.tsx | 18 +++-- .../_components/ProfileImagePreviewModal.tsx | 2 +- src/app/(route)/my/profile/page.tsx | 60 ++------------- src/app/layout.tsx | 15 +++- src/common/Layout/Sidebar/SidebarNavArea.tsx | 40 +++++----- src/common/Molecules/Notification.tsx | 2 +- src/lib/schema.ts | 4 +- src/pages/api/auth/profile.ts | 10 ++- 10 files changed, 182 insertions(+), 117 deletions(-) create mode 100644 src/app/(route)/my/profile/_components/ProfileForms.tsx diff --git a/src/app/(route)/my/profile/_components/FormEditProfile.tsx b/src/app/(route)/my/profile/_components/FormEditProfile.tsx index 8be008f..1b19459 100644 --- a/src/app/(route)/my/profile/_components/FormEditProfile.tsx +++ b/src/app/(route)/my/profile/_components/FormEditProfile.tsx @@ -1,22 +1,24 @@ import { ActionMeta } from "react-select"; -import { ChangeEvent, Dispatch, SetStateAction } from "react"; +import { ChangeEvent, Dispatch, FormEvent, SetStateAction } from "react"; import Input from "@/common/Molecules/Form/Input"; import ProfileImageInput from "./ProfileImageInput"; import ProfileInputArea from "./ProfileInputArea"; import Button from "@/common/Atoms/Form/Button"; import { CATEGORIES } from "@/constants/categories/job_category"; -import { TProfileData } from "../page"; +import { Session } from "next-auth"; +import axios from "axios"; +import handleAlert from "@/app/(auth)/_components/ErrorAlert"; +import { TProfileData } from "./ProfileForms"; export default function FormEditProfile({ data, setData, + session, }: { data: TProfileData; setData: Dispatch>; + session: Session | null; }) { - function changeProfileImage(profileUrl: string) { - setData((p) => ({ ...p, profileUrl })); - } const changeData = ( e: ChangeEvent | ChangeEvent ) => { @@ -29,15 +31,32 @@ export default function FormEditProfile({ newValue: unknown, actionMeta: ActionMeta ) => void = (newValue) => { - console.log({ newValue }); + // console.log({ newValue }); if (Array.isArray(newValue)) setData((p) => ({ ...p, interest: newValue })); }; + async function save(e: FormEvent) { + e.preventDefault(); + + const userId = session?.user.id; + const my_category = data.interest.map((v) => v.value); + try { + const response = await axios.post("/api/auth/profile", { + // userId, + position_tag: data.positionTag, + introduce: data.introduce, + my_category, + }); + handleAlert("success", response.data.message); + } catch (error) { + if (axios.isAxiosError(error)) { + handleAlert("error", error.response?.data.message); + } + } + } + return ( -
      - - - +
      - - -
      - - - *변경 후 재인증이 필요합니다. - -
      -
      + {session?.account.provider === "credentials" && ( + + +
      + + + *변경 후 재인증이 필요합니다. + +
      +
      + )} 프로필 저장 -
      + ); } diff --git a/src/app/(route)/my/profile/_components/ProfileForms.tsx b/src/app/(route)/my/profile/_components/ProfileForms.tsx new file mode 100644 index 0000000..88be931 --- /dev/null +++ b/src/app/(route)/my/profile/_components/ProfileForms.tsx @@ -0,0 +1,72 @@ +"use client"; +import ProfileInputArea from "./ProfileInputArea"; +import ProfileImageInput from "./ProfileImageInput"; +import FormEditProfile from "./FormEditProfile"; +import { getUser } from "@/dummies/user"; +import { useState } from "react"; +import SectionTitle from "@/common/Atoms/Text/SectionTitle"; +import FormUpdatePassword from "./FormUpdatePassword"; +import FormUpdatePhoneNumber from "./FormUpdatePhoneNumber"; +import DeleteAccountConfirm from "./DeleteAccountConfirm"; +import ProfilePreview from "./ProfilePreview"; +import { Session } from "next-auth"; +import { CategoryOption } from "@/types/model/Category"; + +export type TProfileData = { + profileUrl: string; + positionTag: string; + introduce: string; + email: string; + interest: Array; +}; + +export default function ProfileForms({ session }: { session: Session | null }) { + const user = getUser(); + const defaultData = { + profileUrl: session?.user.image || "", + positionTag: user.position, + introduce: "", + email: session?.user.email || "", + interest: user.interest, + }; + const [data, setData] = useState(defaultData); + + const setProfileImage = (image: string) => { + setData((prev) => ({ ...prev, profileUrl: image })); + }; + + return ( + <> +
      +
      +

      {session?.user.name}

      + + + +
      + + {session?.account.provider === "credentials" && ( + <> +
      + + 비밀번호 수정 + + + + )} +
      + + 연락처 수정 + + +
      + +
      + +
      + +
      +
      + + ); +} diff --git a/src/app/(route)/my/profile/_components/ProfileImageInput.tsx b/src/app/(route)/my/profile/_components/ProfileImageInput.tsx index cb9c1e7..ee84979 100644 --- a/src/app/(route)/my/profile/_components/ProfileImageInput.tsx +++ b/src/app/(route)/my/profile/_components/ProfileImageInput.tsx @@ -6,9 +6,9 @@ import Button from "@/common/Atoms/Form/Button"; import ImageInputWithButton from "@/common/Molecules/Form/ImageInputWithButton"; export default function ProfileImageInput({ - setProfileImg, + setProfileImage, }: { - setProfileImg: Function; + setProfileImage: (image: string) => void; }) { const [imageUrl, setImageUrl] = useState(""); const { Modal, open, close } = useModal({ @@ -43,18 +43,20 @@ export default function ProfileImageInput({ } } - console.log(imageUrl); + // console.log(imageUrl); function onSave() { - // ...프로필 이미지 저장 - setProfileImg(imageUrl); + // TODO: DB에 저장 + setProfileImage(imageUrl); close(); } + return ( <>
      이미지 변경하기 - + */}

      *권장 이미지 - 확장자: png, jpg, jpeg / 용량: 1MB 이하 diff --git a/src/app/(route)/my/profile/_components/ProfileImagePreviewModal.tsx b/src/app/(route)/my/profile/_components/ProfileImagePreviewModal.tsx index 1a53af7..150b70b 100644 --- a/src/app/(route)/my/profile/_components/ProfileImagePreviewModal.tsx +++ b/src/app/(route)/my/profile/_components/ProfileImagePreviewModal.tsx @@ -33,7 +33,7 @@ export default function ProfileImagePreviewModal(props: PropsToPreviewModal) { 다시 선택

      diff --git a/src/app/(route)/my/profile/page.tsx b/src/app/(route)/my/profile/page.tsx index 84cd0c7..59f0dc3 100644 --- a/src/app/(route)/my/profile/page.tsx +++ b/src/app/(route)/my/profile/page.tsx @@ -1,66 +1,16 @@ -"use client"; -import { useState } from "react"; -import { getUser } from "@/dummies/user"; -import { CategoryOption } from "@/types/model/Category"; import SectionTitle from "@/common/Atoms/Text/SectionTitle"; -import DeleteAccountConfirm from "./_components/DeleteAccountConfirm"; -import ProfilePreview from "./_components/ProfilePreview"; -import FormEditProfile from "./_components/FormEditProfile"; -import FormUpdatePassword from "./_components/FormUpdatePassword"; -import FormUpdatePhoneNumber from "./_components/FormUpdatePhoneNumber"; -import { useSession } from "next-auth/react"; +import ProfileForms from "./_components/ProfileForms"; +import { getSession } from "@/auth"; -export type TProfileData = { - profileUrl: string; - positionTag: string; - introduce: string; - email: string; - interest: Array; -}; - -export default function MyProfilePage() { - const session = useSession(); - const user = getUser(); - const defaultData = { - profileUrl: user.profileUrl, - positionTag: user.position, - introduce: "", - email: user.email, - interest: user.interest, - }; - const [data, setData] = useState(defaultData); +export default async function MyProfilePage() { + const session = await getSession(); return ( <> 프로필 수정 -
      -
      -

      {session.data?.user.name}

      - - {session.data?.account.provider === "credentials" && ( - <> -
      - - 비밀번호 수정 - - - - )} -
      - - 연락처 수정 - - -
      - -
      - -
      - -
      -
      + ); } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 57c6a77..8475094 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,4 +1,4 @@ -import type { Metadata } from "next"; +import type { Metadata, Viewport } from "next"; import { Noto_Sans_KR } from "next/font/google"; import "./globals.css"; import { Toaster } from "react-hot-toast"; @@ -20,7 +20,18 @@ export const metadata: Metadata = { icons: { icon: "/favicon.ico", }, - viewport: "width=device-width, initial-scale=1.0", +}; + +export const generateViewport = (): Viewport => { + return { + width: "device-width", + initialScale: 1, + maximumScale: 1, + userScalable: false, + // Also supported by less commonly used + interactiveWidget: "resizes-visual", + themeColor: "#2A7FFE", + }; }; export default function RootLayout({ diff --git a/src/common/Layout/Sidebar/SidebarNavArea.tsx b/src/common/Layout/Sidebar/SidebarNavArea.tsx index 1e5cce9..6772c36 100644 --- a/src/common/Layout/Sidebar/SidebarNavArea.tsx +++ b/src/common/Layout/Sidebar/SidebarNavArea.tsx @@ -1,31 +1,33 @@ "use client"; import React from "react"; import { TProps } from "@/types/component/props"; -import useMediaQuery from "@/hooks/useMediaQuery"; import { ChevronRightIcon } from "@/common/Atoms/Image/Icon"; export default function SidebarNavArea({ children }: TProps) { - const notMobile = useMediaQuery("lg"); - return notMobile ? ( -
        - {children} -
      - ) : ( -
      - -
      - 메뉴 - - - -
      -
      + return ( + <>
        {children}
      -
      +
      + +
      + 메뉴 + + + +
      +
      +
        + {children} +
      +
      + ); } diff --git a/src/common/Molecules/Notification.tsx b/src/common/Molecules/Notification.tsx index 431c4e0..761738b 100644 --- a/src/common/Molecules/Notification.tsx +++ b/src/common/Molecules/Notification.tsx @@ -49,7 +49,7 @@ const STATUS_ICON = { stroke="white" strokeWidth="2" strokeLinecap="round" - stroke-linejoin="round" + strokeLinejoin="round" /> ), diff --git a/src/lib/schema.ts b/src/lib/schema.ts index 8fa8d7d..03f5489 100644 --- a/src/lib/schema.ts +++ b/src/lib/schema.ts @@ -17,10 +17,10 @@ const user = new mongoose.Schema( export const User = mongoose.models?.User || mongoose.model("User", user); const profile = new mongoose.Schema({ - userId: { type: mongoose.Schema.Types.ObjectId, ref: "User", required: true }, + // userId: { type: mongoose.Schema.Types.ObjectId, ref: "User", required: true }, position_tag: { type: String, default: null }, introduce: { type: String, default: null }, - my_category: { type: String, default: null }, + my_category: { type: [String], default: [] }, }); export const Profile = diff --git a/src/pages/api/auth/profile.ts b/src/pages/api/auth/profile.ts index 2b6d333..9d88881 100644 --- a/src/pages/api/auth/profile.ts +++ b/src/pages/api/auth/profile.ts @@ -1,6 +1,7 @@ import { NextApiRequest, NextApiResponse } from "next"; import { Profile } from "@/lib/schema"; import connectDB from "@/lib/db"; +import mongoose from "mongoose"; export default async function handler( req: NextApiRequest, @@ -8,15 +9,16 @@ export default async function handler( ) { if (req.method === "POST") { const { userId, position_tag, introduce, my_category } = req.body; + // console.log("userId", mongoose.Types.ObjectId.isValid(userId)); await connectDB(); - if (!userId) { - return res.status(400).json({ message: "사용자의 id가 필요합니다." }); - } + // if (!userId) { + // return res.status(400).json({ message: "사용자의 id가 필요합니다." }); + // } const profile = new Profile({ - userId, + // userId, position_tag, introduce, my_category, From 286c204b61826e7ecc409a77b2f6e3dd1e161702 Mon Sep 17 00:00:00 2001 From: YI Na-yeon <2n.ayeon.yi@gmail.com> Date: Tue, 23 Jul 2024 10:10:41 +0900 Subject: [PATCH 15/33] =?UTF-8?q?[Fix]=20=EA=B2=BD=EB=A1=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/(route)/my/profile/_components/ProfilePreview.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/(route)/my/profile/_components/ProfilePreview.tsx b/src/app/(route)/my/profile/_components/ProfilePreview.tsx index b61f216..a9f0a39 100644 --- a/src/app/(route)/my/profile/_components/ProfilePreview.tsx +++ b/src/app/(route)/my/profile/_components/ProfilePreview.tsx @@ -1,7 +1,7 @@ import ProfileImg from "@/common/Atoms/Image/ProfileImg"; import Keyword from "@/common/Atoms/Text/Keyword"; import { DummyProfileImg } from "@public/images"; -import { TProfileData } from "../page"; +import { TProfileData } from "./ProfileForms"; type TProfilePreviewProps = { name: string | null | undefined; From 42d854448bed71e100a2623be6d53d96e9f52ec6 Mon Sep 17 00:00:00 2001 From: YI Na-yeon <2n.ayeon.yi@gmail.com> Date: Tue, 23 Jul 2024 10:55:21 +0900 Subject: [PATCH 16/33] =?UTF-8?q?[Fix]=20params=20=EC=98=B5=EC=85=94?= =?UTF-8?q?=EB=84=90=20=EC=B2=B4=EC=9D=B4=EB=8B=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../(route)/study/_components/StudyCategoryTabButtonList.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/(route)/study/_components/StudyCategoryTabButtonList.tsx b/src/app/(route)/study/_components/StudyCategoryTabButtonList.tsx index d2929da..dc3ac11 100644 --- a/src/app/(route)/study/_components/StudyCategoryTabButtonList.tsx +++ b/src/app/(route)/study/_components/StudyCategoryTabButtonList.tsx @@ -21,7 +21,7 @@ export default function StudyCategoryTabButtonList({ categoryIcons: string[]; }) { const params = useSearchParams(); - const [select, setSelected] = useState(params.get(queryKey) || ""); + const [select, setSelected] = useState(params?.get(queryKey) || ""); const studyCategoryIcons = categoryName.map((category, index) => ({ ...category, From 3a47e5f5a50cb4bb3c0f31ae74e9ff982a4622f9 Mon Sep 17 00:00:00 2001 From: YI Na-yeon <2n.ayeon.yi@gmail.com> Date: Tue, 23 Jul 2024 10:57:25 +0900 Subject: [PATCH 17/33] =?UTF-8?q?[Fix]=20=EB=B3=80=EC=88=98=EB=AA=85=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/(route)/study/page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/(route)/study/page.tsx b/src/app/(route)/study/page.tsx index d80ef44..33bd306 100644 --- a/src/app/(route)/study/page.tsx +++ b/src/app/(route)/study/page.tsx @@ -29,7 +29,7 @@ export default async function StudyComponent({ searchParams: TQuery; }) { const session = await getSession(); - const studyCard = getStudiesData(); + const studyCards = getStudiesData(); return (
      From 83ec6f0f9ee8405ec2d9a22f141fcd879bfbd1c4 Mon Sep 17 00:00:00 2001 From: YI Na-yeon <2n.ayeon.yi@gmail.com> Date: Tue, 23 Jul 2024 11:00:13 +0900 Subject: [PATCH 18/33] =?UTF-8?q?[Fix]=20=EC=98=B5=EC=85=94=EB=84=90=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/useQueryString.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/hooks/useQueryString.tsx b/src/hooks/useQueryString.tsx index 9dbf1d7..6c38ab9 100644 --- a/src/hooks/useQueryString.tsx +++ b/src/hooks/useQueryString.tsx @@ -8,11 +8,13 @@ const useQueryString = ({ queryInclude: string; }) => { const params = useSearchParams(); - const newSearchParams = new URLSearchParams(params); + const newSearchParams = new URLSearchParams(params || undefined); const router = useRouter(); const pathname = usePathname(); - const url = pathname.includes(queryInclude) ? pathname : `${pathname}/search`; + const url = pathname?.includes(queryInclude) + ? pathname + : `${pathname}/search`; const onEventQueryString = (value: string) => { newSearchParams.set(paramsKey, value); From 2b13609d81c39e493978faa9b6f60ff5e517d618 Mon Sep 17 00:00:00 2001 From: YI Na-yeon <2n.ayeon.yi@gmail.com> Date: Thu, 25 Jul 2024 03:15:40 +0900 Subject: [PATCH 19/33] =?UTF-8?q?[Feat]=20profile=20=EC=A0=95=EB=B3=B4=20?= =?UTF-8?q?=EC=A0=80=EC=9E=A5=20=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../profile/_components/FormEditProfile.tsx | 78 ++++++++++--------- .../my/profile/_components/ProfileForms.tsx | 64 ++++++++++----- .../profile/_components/ProfileImageInput.tsx | 18 ++--- src/app/(route)/my/profile/page.tsx | 40 +++++----- src/constants/categories/job_category.ts | 9 ++- src/lib/action.ts | 31 +++++--- 6 files changed, 143 insertions(+), 97 deletions(-) diff --git a/src/app/(route)/my/profile/_components/FormEditProfile.tsx b/src/app/(route)/my/profile/_components/FormEditProfile.tsx index 135131d..5716960 100644 --- a/src/app/(route)/my/profile/_components/FormEditProfile.tsx +++ b/src/app/(route)/my/profile/_components/FormEditProfile.tsx @@ -18,34 +18,34 @@ import { profileAction } from "@/lib/action"; import handleAlert from "@/app/(auth)/_components/ErrorAlert"; export default function FormEditProfile({ - data, - setData, - session, + userId, + profile, + sessionProvider, }: { - data: TProfileData; - setData: Dispatch>; - session: Session | null; + userId: string; + profile: TProfileData; + sessionProvider: string; }) { - const changeData = ( - e: ChangeEvent | ChangeEvent - ) => { - console.log(e.target.name); - const name = e.target.name; - const value = e.target.value; - setData((p) => ({ ...p, [name]: value })); - }; - const changeMultiSelect: ( - newValue: unknown, - actionMeta: ActionMeta - ) => void = (newValue) => { - // console.log({ newValue }); - if (Array.isArray(newValue)) setData((p) => ({ ...p, interest: newValue })); - }; + // const changeData = ( + // e: ChangeEvent | ChangeEvent + // ) => { + // console.log(e.target.name); + // const name = e.target.name; + // const value = e.target.value; + // setData((p) => ({ ...p, [name]: value })); + // }; + // const changeMultiSelect: ( + // newValue: unknown, + // actionMeta: ActionMeta + // ) => void = (newValue) => { + // // console.log({ newValue }); + // if (Array.isArray(newValue)) setData((p) => ({ ...p, interest: newValue })); + // }; async function save(e: FormEvent) { e.preventDefault(); - const userId = session?.user.id as string; + // const userId = profile?.userId._id as string; const formData = new FormData(e.currentTarget); try { @@ -62,25 +62,26 @@ export default function FormEditProfile({ - {session?.account.provider === "credentials" && ( - - + + + {false && (
      -
      - )} + )} +
      - diff --git a/src/app/(route)/my/profile/_components/ProfileForms.tsx b/src/app/(route)/my/profile/_components/ProfileForms.tsx index 08ecadd..bcfa0c4 100644 --- a/src/app/(route)/my/profile/_components/ProfileForms.tsx +++ b/src/app/(route)/my/profile/_components/ProfileForms.tsx @@ -11,6 +11,8 @@ import DeleteAccountConfirm from "./DeleteAccountConfirm"; import ProfilePreview from "./ProfilePreview"; import { Session } from "next-auth"; import { CategoryOption } from "@/types/model/Category"; +import { ProfileSchema } from "@/types/model/Profile"; +import { CATEGORIES_ALL_OPTIONS } from "@/constants/categories/job_category"; export type TProfileData = { profileUrl: string; @@ -20,32 +22,54 @@ export type TProfileData = { interest: Array; }; -export default function ProfileForms({ session }: { session: Session | null }) { - const user = getUser(); - const defaultData = { - profileUrl: session?.user.image || "", - positionTag: user.position, - introduce: "", - email: session?.user.email || "", - interest: user.interest, +export default function ProfileForms({ + userId, + profile, + sessionProvider, +}: { + userId: string; + profile: ProfileSchema | null; + sessionProvider: string; +}) { + // const user = getUser(); + const interestCategory: CategoryOption[] = + profile?.my_category && profile.my_category.length > 0 + ? profile?.my_category.map( + (value) => + CATEGORIES_ALL_OPTIONS.find( + (opt) => opt.value === value + ) as CategoryOption + ) + : []; + const profileData = { + profileUrl: profile?.userId.profile_img || "", + positionTag: profile?.position_tag || "", + introduce: profile?.introduce || "", + email: profile?.userId.email || "", + interest: interestCategory || [], }; - const [data, setData] = useState(defaultData); + console.log({ profile, profileData }); - const setProfileImage = (image: string) => { - setData((prev) => ({ ...prev, profileUrl: image })); - }; + // const [data, setData] = useState(defaultData); + // const setProfileImage = (image: string) => { + // setData((prev) => ({ ...prev, profileUrl: image })); + // }; return ( <>
      -

      {session?.user.name}

      +

      {profile?.userId.name}

      - +
      - - {session?.account.provider === "credentials" && ( + + {sessionProvider === "credentials" && ( <>
      @@ -58,14 +82,14 @@ export default function ProfileForms({ session }: { session: Session | null }) { 연락처 수정 - +
      -
      - -
      + {/*
      + +
      */}
      ); diff --git a/src/app/(route)/my/profile/_components/ProfileImageInput.tsx b/src/app/(route)/my/profile/_components/ProfileImageInput.tsx index ee84979..a0cfbaa 100644 --- a/src/app/(route)/my/profile/_components/ProfileImageInput.tsx +++ b/src/app/(route)/my/profile/_components/ProfileImageInput.tsx @@ -1,3 +1,4 @@ +"use client"; import { ChangeEvent, useEffect, useState } from "react"; import useModal from "@/hooks/useModal"; @@ -5,11 +6,7 @@ import ProfileImagePreviewModal from "./ProfileImagePreviewModal"; import Button from "@/common/Atoms/Form/Button"; import ImageInputWithButton from "@/common/Molecules/Form/ImageInputWithButton"; -export default function ProfileImageInput({ - setProfileImage, -}: { - setProfileImage: (image: string) => void; -}) { +export default function ProfileImageInput() { const [imageUrl, setImageUrl] = useState(""); const { Modal, open, close } = useModal({ children: ( @@ -47,10 +44,13 @@ export default function ProfileImageInput({ function onSave() { // TODO: DB에 저장 - setProfileImage(imageUrl); close(); } + function onDelete() { + setImageUrl(""); + } + return ( <>
      @@ -68,13 +68,13 @@ export default function ProfileImageInput({ > 이미지 변경하기 - {/* */} +

      *권장 이미지 - 확장자: png, jpg, jpeg / 용량: 1MB 이하 diff --git a/src/app/(route)/my/profile/page.tsx b/src/app/(route)/my/profile/page.tsx index 8dd2008..0752d9d 100644 --- a/src/app/(route)/my/profile/page.tsx +++ b/src/app/(route)/my/profile/page.tsx @@ -3,37 +3,41 @@ import ProfileForms from "./_components/ProfileForms"; import { getSession } from "@/auth"; import { Profile } from "@/lib/schema"; import connectDB from "@/lib/db"; -import mongoose, { isValidObjectId, Types } from "mongoose"; +import { ProfileSchema } from "@/types/model/Profile"; +import NotFound from "@/app/not-found"; + +async function getProfile(userId: string) { + await connectDB(); + + const profile = await Profile.findOne({ userId }).populate("userId"); + return profile; +} export default async function MyProfilePage() { const session = await getSession(); - const { ObjectId } = mongoose.Types; // 소셜로그인 id 값 이슈로 다시 확인 - console.log(session?.user.id); + // console.log(session?.user.id); - await connectDB(); - - if (isValidObjectId(session?.user.id)) { - const profile = await Profile.findOne({ - userId: new Types.ObjectId(session?.user.id), - }); - - if (profile) { - console.log(profile); - } else { - console.log("프로필 미작성으로 작성 해주세요."); - } - } else { - console.log("유효 하지 않음"); + if (session === null) { + return ; } + const profile: ProfileSchema | null = await getProfile( + session?.user.id as string + ); + console.log("profile", profile); + return ( <> 프로필 수정 - + ); } diff --git a/src/constants/categories/job_category.ts b/src/constants/categories/job_category.ts index 37c8475..8e64c86 100644 --- a/src/constants/categories/job_category.ts +++ b/src/constants/categories/job_category.ts @@ -1,4 +1,4 @@ -import { CategoryGroup } from "@/types/model/Category"; +import { CategoryGroup, CategoryOption } from "@/types/model/Category"; export const CATEGORIES: CategoryGroup[] = [ { @@ -208,3 +208,10 @@ export const CATEGORIES: CategoryGroup[] = [ ], }, ]; + +export const CATEGORIES_ALL_OPTIONS: CategoryOption[] = CATEGORIES.reduce( + (prev: CategoryOption[], curr: CategoryGroup) => { + return [...prev, ...curr.options]; + }, + [] +); diff --git a/src/lib/action.ts b/src/lib/action.ts index 0b1d300..1db13a3 100644 --- a/src/lib/action.ts +++ b/src/lib/action.ts @@ -89,19 +89,28 @@ export async function profileAction(id: string, formData: FormData) { await connectDB(); - const profile = new Profile({ - userId, - position_tag, - introduce, - my_category, - }); + const isExistProfile = await Profile.findOne({ userId }); - await profile.save(); - const populatedProfile = await Profile.findById(profile._id).populate( - "userId" - ); + if (isExistProfile) { + console.log("update profile"); + return; + } - console.log(populatedProfile); + console.log("insert new profile"); + + // const profile = new Profile({ + // userId, + // position_tag, + // introduce, + // my_category, + // }); + // + // await profile.save(); + // const populatedProfile = await Profile.findById(profile._id).populate( + // "userId" + // ); + // + // console.log(populatedProfile); } // 커뮤니티 등록 From 0d395247462189959e0ee8fe0f4d7acc0f51e895 Mon Sep 17 00:00:00 2001 From: YI Na-yeon <2n.ayeon.yi@gmail.com> Date: Thu, 25 Jul 2024 03:15:53 +0900 Subject: [PATCH 20/33] =?UTF-8?q?[Chore[=20=EC=8A=A4=ED=82=A4=EB=A7=88=20?= =?UTF-8?q?=ED=83=80=EC=9E=85=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/types/model/Comment.ts | 16 ++++++++++++++++ src/types/model/PostItem.ts | 2 ++ src/types/model/Profile.ts | 4 ++-- src/types/model/User.ts | 14 ++++++++++++++ 4 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 src/types/model/Comment.ts diff --git a/src/types/model/Comment.ts b/src/types/model/Comment.ts new file mode 100644 index 0000000..f8976ca --- /dev/null +++ b/src/types/model/Comment.ts @@ -0,0 +1,16 @@ +import { WriterSchema } from "./User"; + +type CommentBase = { + commentId: string; + content: string; + writer: WriterSchema; + createdAt: string; +}; + +export type ReplySchema = CommentBase & { + originId: string; +}; + +export type CommentSchema = CommentBase & { + reply: ReplySchema[]; +}; diff --git a/src/types/model/PostItem.ts b/src/types/model/PostItem.ts index 929545c..ea5e2be 100644 --- a/src/types/model/PostItem.ts +++ b/src/types/model/PostItem.ts @@ -1,3 +1,4 @@ +import { CommentSchema } from "./Comment"; import { TUserBase } from "./User"; export type TPost = { @@ -16,4 +17,5 @@ export type TPost = { createdAt: string; view: number; like: number; + comments: CommentSchema[]; }; diff --git a/src/types/model/Profile.ts b/src/types/model/Profile.ts index bb77dfd..40516c2 100644 --- a/src/types/model/Profile.ts +++ b/src/types/model/Profile.ts @@ -1,8 +1,8 @@ -// import { UserSchema } from "./User"; +import { UserSchema } from "./User"; export type ProfileSchema = { _id: object; - userId: any; + userId: UserSchema; position_tag: string; introduce: string; my_category: string[]; diff --git a/src/types/model/User.ts b/src/types/model/User.ts index a255390..578bd6e 100644 --- a/src/types/model/User.ts +++ b/src/types/model/User.ts @@ -15,3 +15,17 @@ type UserInfo = UserIntroduce & { phone: string; interest: { categoryId: string; label: string }[]; }; + +export type UserSchema = { + _id: string; + email: string; + password: string; + name: string; + profile_img: string; + phone: string; + role: string; + createdAt: object; + updatedAt: object; +}; + +export type WriterSchema = TUserBase; From 6b9f4a3c6e64f642706d9d89320036f20b174abd Mon Sep 17 00:00:00 2001 From: YI Na-yeon <2n.ayeon.yi@gmail.com> Date: Thu, 25 Jul 2024 03:16:22 +0900 Subject: [PATCH 21/33] =?UTF-8?q?[Chore]=20=EB=9E=9C=EB=8D=A4=20=EC=9D=B4?= =?UTF-8?q?=EB=AF=B8=EC=A7=80=20=EC=A7=80=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/dummies/getImages.ts | 12 +++++++++--- src/dummies/studies.ts | 36 ++++++++++++++++++------------------ 2 files changed, 27 insertions(+), 21 deletions(-) diff --git a/src/dummies/getImages.ts b/src/dummies/getImages.ts index d119b74..34e08b5 100644 --- a/src/dummies/getImages.ts +++ b/src/dummies/getImages.ts @@ -16,14 +16,20 @@ type IdTypes = | "animal" | "all"; -export function getImageUrl(type?: IdTypes, width = 200, height = 200): string { +export function getImageUrl( + index: number, + type?: IdTypes, + width = 200, + height = 200 +): string { const key = type || "all"; const idsByKey = key === "all" ? Object.values(ids).reduce((prev, curr) => [...prev, ...curr], []) : ids[key]; - const randomIndex = Math.floor(Math.random() * idsByKey.length); - return `https://picsum.photos/id/${idsByKey[randomIndex]}/${width}/${height}`; + // const randomIndex = Math.floor(Math.random() * idsByKey.length); + // console.log({ randomIndex }); + return `https://picsum.photos/id/${idsByKey.at(index)}/${width}/${height}`; } export function getImageUrls( diff --git a/src/dummies/studies.ts b/src/dummies/studies.ts index bc69043..bbf0f5f 100644 --- a/src/dummies/studies.ts +++ b/src/dummies/studies.ts @@ -57,7 +57,7 @@ const studyCards: TStudyCard[] = [ user: { userType: "user", nickname: "디자이너 이수빈", - image: getImageUrl("animal", 48, 48), + image: getImageUrl(0, "animal", 48, 48), }, study: { title: "내가 디자인한 앱을 출시하기까지", @@ -65,7 +65,7 @@ const studyCards: TStudyCard[] = [ people: "모집 8명", deadline: "8/13 마감", RecruitmentStatus: "모집중", - image: getImageUrl("tech", 268, 180), + image: getImageUrl(4, "tech", 268, 180), }, }, { @@ -73,7 +73,7 @@ const studyCards: TStudyCard[] = [ user: { userType: "pro", nickname: "과학자 김민수", - image: getImageUrl("animal", 48, 48), + image: getImageUrl(11, "animal", 48, 48), }, study: { title: "재밌는 생명과학 실험 스터디", @@ -81,7 +81,7 @@ const studyCards: TStudyCard[] = [ people: "모집 12명", deadline: "8/23 마감", RecruitmentStatus: "모집중", - image: getImageUrl("nature", 268, 180), + image: getImageUrl(7, "nature", 268, 180), }, }, { @@ -89,7 +89,7 @@ const studyCards: TStudyCard[] = [ user: { userType: "pro", nickname: "과학자 김민수", - image: getImageUrl("animal", 48, 48), + image: getImageUrl(12, "animal", 48, 48), }, study: { title: "재밌는 생명과학 실험 스터디", @@ -97,7 +97,7 @@ const studyCards: TStudyCard[] = [ people: "모집 12명", deadline: "8/23 마감", RecruitmentStatus: "모집중", - image: getImageUrl("nature", 268, 180), + image: getImageUrl(4, "nature", 268, 180), }, }, { @@ -105,7 +105,7 @@ const studyCards: TStudyCard[] = [ user: { userType: "user", nickname: "디자이너 이수빈", - image: getImageUrl("animal", 48, 48), + image: getImageUrl(8, "animal", 48, 48), }, study: { title: "내가 디자인한 앱을 출시하기까지", @@ -113,7 +113,7 @@ const studyCards: TStudyCard[] = [ people: "모집 8명", deadline: "8/13 마감", RecruitmentStatus: "모집중", - image: getImageUrl("desk", 268, 180), + image: getImageUrl(7, "desk", 268, 180), }, }, { @@ -121,7 +121,7 @@ const studyCards: TStudyCard[] = [ user: { userType: "pro", nickname: "과학자 김민수", - image: getImageUrl("animal", 48, 48), + image: getImageUrl(9, "animal", 48, 48), }, study: { title: "재밌는 생명과학 실험 스터디", @@ -129,7 +129,7 @@ const studyCards: TStudyCard[] = [ people: "모집 12명", deadline: "8/23 마감", RecruitmentStatus: "모집중", - image: getImageUrl("nature", 268, 180), + image: getImageUrl(10, "nature", 268, 180), }, }, { @@ -137,7 +137,7 @@ const studyCards: TStudyCard[] = [ user: { userType: "pro", nickname: "과학자 김민수", - image: getImageUrl("animal", 48, 48), + image: getImageUrl(11, "animal", 48, 48), }, study: { title: "재밌는 생명과학 실험 스터디", @@ -145,7 +145,7 @@ const studyCards: TStudyCard[] = [ people: "모집 12명", deadline: "8/23 마감", RecruitmentStatus: "모집중", - image: getImageUrl("nature", 268, 180), + image: getImageUrl(5, "nature", 268, 180), }, }, { @@ -153,7 +153,7 @@ const studyCards: TStudyCard[] = [ user: { userType: "user", nickname: "디자이너 이수빈", - image: getImageUrl("animal", 48, 48), + image: getImageUrl(6, "animal", 48, 48), }, study: { title: "내가 디자인한 앱을 출시하기까지", @@ -161,7 +161,7 @@ const studyCards: TStudyCard[] = [ people: "모집 8명", deadline: "8/13 마감", RecruitmentStatus: "모집중", - image: getImageUrl("desk", 268, 180), + image: getImageUrl(1, "desk", 268, 180), }, }, { @@ -169,7 +169,7 @@ const studyCards: TStudyCard[] = [ user: { userType: "pro", nickname: "과학자 김민수", - image: getImageUrl("animal", 48, 48), + image: getImageUrl(11, "animal", 48, 48), }, study: { title: "재밌는 생명과학 실험 스터디", @@ -177,7 +177,7 @@ const studyCards: TStudyCard[] = [ people: "모집 12명", deadline: "8/23 마감", RecruitmentStatus: "모집중", - image: getImageUrl("nature", 268, 180), + image: getImageUrl(4, "nature", 268, 180), }, }, { @@ -185,7 +185,7 @@ const studyCards: TStudyCard[] = [ user: { userType: "pro", nickname: "과학자 김민수", - image: getImageUrl("animal", 48, 48), + image: getImageUrl(11, "animal", 48, 48), }, study: { title: "재밌는 생명과학 실험 스터디", @@ -193,7 +193,7 @@ const studyCards: TStudyCard[] = [ people: "모집 12명", deadline: "8/23 마감", RecruitmentStatus: "모집중", - image: getImageUrl("nature", 268, 180), + image: getImageUrl(4, "nature", 268, 180), }, }, ]; From 70ed75e3976fa1f97522b3207816643fe3afb324 Mon Sep 17 00:00:00 2001 From: YI Na-yeon <2n.ayeon.yi@gmail.com> Date: Thu, 25 Jul 2024 03:19:48 +0900 Subject: [PATCH 22/33] =?UTF-8?q?[Chore]=20=EC=8A=A4=ED=83=80=EC=9D=BC/?= =?UTF-8?q?=ED=83=9C=EA=B7=B8/=EB=A7=81=ED=81=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/(route)/my/study/page.tsx | 13 +- src/app/(route)/post/write/page.tsx | 4 +- .../_components/UserCurrentStudySection.tsx | 2 +- src/common/Atoms/Form/Field.tsx | 2 +- src/common/Atoms/Form/QuillNoSSR.tsx | 30 ++++ src/common/Atoms/Form/TextEditor.tsx | 2 +- src/common/Atoms/Form/customQuill.css | 39 +++++- src/common/Layout/Sidebar/SidebarNavArea.tsx | 2 +- src/common/Organisms/PostListItem.tsx | 3 +- src/common/Organisms/customContent.module.css | 128 ++++++++++++++++++ 10 files changed, 210 insertions(+), 15 deletions(-) diff --git a/src/app/(route)/my/study/page.tsx b/src/app/(route)/my/study/page.tsx index e0f6596..78ab019 100644 --- a/src/app/(route)/my/study/page.tsx +++ b/src/app/(route)/my/study/page.tsx @@ -50,32 +50,31 @@ export default async function MyStudyPage() { 참여 중인 스터디 -

      +
        {studyCard.slice(0, 1).map((card) => ( ))} -
      +
- {/* TODO: 종료된 스터디 표시 추가 필요 */}
종료된 스터디 -
+
    {studyCard.slice(1, 3).map((card) => ( ))} -
+
내가 만든 스터디 -
+
    {studyCard.slice(3, 5).map((card) => ( ))} -
+
); diff --git a/src/app/(route)/post/write/page.tsx b/src/app/(route)/post/write/page.tsx index 4c5e9fb..8b0294e 100644 --- a/src/app/(route)/post/write/page.tsx +++ b/src/app/(route)/post/write/page.tsx @@ -20,7 +20,7 @@ export default async function PostWrite() { <>
@@ -34,7 +34,7 @@ export default async function PostWrite() { 글 내용 diff --git a/src/app/_components/UserCurrentStudySection.tsx b/src/app/_components/UserCurrentStudySection.tsx index bf93f55..1dc9ad1 100644 --- a/src/app/_components/UserCurrentStudySection.tsx +++ b/src/app/_components/UserCurrentStudySection.tsx @@ -46,7 +46,7 @@ export default function UserCurrentStudySection() {
- +
diff --git a/src/common/Atoms/Form/Field.tsx b/src/common/Atoms/Form/Field.tsx index 0fb540e..c0ad857 100644 --- a/src/common/Atoms/Form/Field.tsx +++ b/src/common/Atoms/Form/Field.tsx @@ -2,7 +2,7 @@ import { TProps } from "@/types/component/props"; export default function GridField({ children }: TProps) { return ( -
+
{children}
); diff --git a/src/common/Atoms/Form/QuillNoSSR.tsx b/src/common/Atoms/Form/QuillNoSSR.tsx index 376858c..c5f8679 100644 --- a/src/common/Atoms/Form/QuillNoSSR.tsx +++ b/src/common/Atoms/Form/QuillNoSSR.tsx @@ -73,6 +73,32 @@ const QuillNoSSR = dynamic( ] = ` +`; + icons["list"][ + "ordered" + ] = ` + + +`; + icons["list"][ + "bullet" + ] = ` + + +`; + icons["indent"][ + "-1" + ] = ` + + + +`; + icons["indent"][ + "+1" + ] = ` + + + `; const Quill = ({ forwardedRef, @@ -106,6 +132,8 @@ const modules = { { align: "center" }, { align: "right" }, ], + [{ list: "ordered" }, { list: "bullet" }], + [{ indent: "-1" }, { indent: "+1" }], ], clipboard: { // toggle to add extra line breaks when pasting HTML: @@ -123,6 +151,8 @@ const formats = [ "link", "image", "align", + "list", + "indent", ]; QuillNoSSR.defaultProps = { diff --git a/src/common/Atoms/Form/TextEditor.tsx b/src/common/Atoms/Form/TextEditor.tsx index f916ec5..186dce9 100644 --- a/src/common/Atoms/Form/TextEditor.tsx +++ b/src/common/Atoms/Form/TextEditor.tsx @@ -5,7 +5,7 @@ import QuillNoSSR from "./QuillNoSSR"; type TEditorProps = ReactQuillProps; export default function TextEditor(props: TEditorProps) { return ( -
+
); diff --git a/src/common/Atoms/Form/customQuill.css b/src/common/Atoms/Form/customQuill.css index 178a8a4..86d0638 100644 --- a/src/common/Atoms/Form/customQuill.css +++ b/src/common/Atoms/Form/customQuill.css @@ -21,6 +21,7 @@ border-color: #b2b2b4; } .editor .ql-container.ql-snow { + font-size: 1rem; border-bottom-left-radius: 10px; border-bottom-right-radius: 10px; } @@ -45,7 +46,7 @@ } .editor .ql-editor.ql-blank::before { font-style: 400; - font-size: 16px; + font-size: 1rem; font-style: normal; color: var(--color-label-assist); } @@ -99,6 +100,42 @@ .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before { font-weight: 600; } +.ql-editor ol li:not(.ql-direction-rtl), +.ql-editor ul li:not(.ql-direction-rtl) { + padding-left: 0; +} +.editor .ql-editor ol li.ql-indent-1:not(.ql-direction-rtl), +.editor .ql-editor ul li.ql-indent-1:not(.ql-direction-rtl) { + padding-left: 1rem; +} +.editor .ql-editor ol li.ql-indent-2:not(.ql-direction-rtl), +.editor .ql-editor ul li.ql-indent-2:not(.ql-direction-rtl) { + padding-left: 2rem; +} +.editor .ql-editor ol li.ql-indent-3:not(.ql-direction-rtl), +.editor .ql-editor ul li.ql-indent-3:not(.ql-direction-rtl) { + padding-left: 3rem; +} +.editor .ql-editor ol li.ql-indent-4:not(.ql-direction-rtl), +.editor .ql-editor ul li.ql-indent-4:not(.ql-direction-rtl) { + padding-left: 4rem; +} +.editor .ql-editor ol li.ql-indent-5:not(.ql-direction-rtl), +.editor .ql-editor ul li.ql-indent-5:not(.ql-direction-rtl) { + padding-left: 5rem; +} +.editor .ql-editor ol li.ql-indent-6:not(.ql-direction-rtl), +.editor .ql-editor ul li.ql-indent-6:not(.ql-direction-rtl) { + padding-left: 6rem; +} +.editor .ql-editor ol li.ql-indent-7:not(.ql-direction-rtl), +.editor .ql-editor ul li.ql-indent-7:not(.ql-direction-rtl) { + padding-left: 7rem; +} +.editor .ql-editor ol li.ql-indent-8:not(.ql-direction-rtl), +.editor .ql-editor ul li.ql-indent-8:not(.ql-direction-rtl) { + padding-left: 8rem; +} .editor .ql-toolbar.ql-snow .ql-formats button:hover path, .editor .ql-toolbar.ql-snow .ql-formats .ql-picker-label:hover .ql-stroke { /* var(--color-main-800) */ diff --git a/src/common/Layout/Sidebar/SidebarNavArea.tsx b/src/common/Layout/Sidebar/SidebarNavArea.tsx index 6772c36..4aae950 100644 --- a/src/common/Layout/Sidebar/SidebarNavArea.tsx +++ b/src/common/Layout/Sidebar/SidebarNavArea.tsx @@ -8,7 +8,7 @@ export default function SidebarNavArea({ children }: TProps) { <>
    {children}
diff --git a/src/common/Organisms/PostListItem.tsx b/src/common/Organisms/PostListItem.tsx index a0e8c49..a3fd33e 100644 --- a/src/common/Organisms/PostListItem.tsx +++ b/src/common/Organisms/PostListItem.tsx @@ -60,7 +60,8 @@ export default function PostListItem({ item }: { item: TPost }) {
- {createdBefore} · 조회수 {item.view}회 · 좋아요 {item.like}개 + {createdBefore} · 조회수 {item.view}회 · 좋아요 {item.like}개 · + 댓글 {item.comments.length}개
{(item.category.value === "study" || diff --git a/src/common/Organisms/customContent.module.css b/src/common/Organisms/customContent.module.css index 7c10c12..5e98b4c 100644 --- a/src/common/Organisms/customContent.module.css +++ b/src/common/Organisms/customContent.module.css @@ -2,6 +2,21 @@ padding-block-start: 2.5rem; padding-block-end: 3.74rem; } +.postBody p, +.postBody ol, +.postBody ul, +.postBody pre, +.postBody blockquote, +.postBody h1, +.postBody h2, +.postBody h3, +.postBody h4, +.postBody h5, +.postBody h6 { + margin: 0; + padding: 0; + counter-reset: list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9; +} .postBody > * { display: block; color: black; @@ -50,3 +65,116 @@ .postBody .ql-align-right { text-align: right; } +.postBody ul, +.postBody ol { + padding-left: 0.5rem; +} +.postBody ul li { + list-style: disc; +} +.postBody ul li, +.postBody ol li { + padding-left: 0; + list-style-position: inside; +} +.postBody ul li[class="ql-indent-1"], +.postBody ol li[class="ql-indent-1"] { + padding-left: 1rem; +} +.postBody ul li[class="ql-indent-2"], +.postBody ol li[class="ql-indent-2"] { + padding-left: 2rem; +} +.postBody ul li[class="ql-indent-3"], +.postBody ol li[class="ql-indent-3"] { + padding-left: 3rem; +} +.postBody ul li[class="ql-indent-4"], +.postBody ol li[class="ql-indent-4"] { + padding-left: 4rem; +} +.postBody ul li[class="ql-indent-5"], +.postBody ol li[class="ql-indent-5"] { + padding-left: 5rem; +} +.postBody ul li[class="ql-indent-6"], +.postBody ol li[class="ql-indent-6"] { + padding-left: 6rem; +} +.postBody ul li[class="ql-indent-7"], +.postBody ol li[class="ql-indent-7"] { + padding-left: 7rem; +} +.postBody ul li[class="ql-indent-8"], +.postBody ol li[class="ql-indent-8"] { + padding-left: 8rem; +} +.postBody ol li { + counter-increment: list-0; + counter-reset: list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9; +} +.postBody ol li:before { + content: counter(list-0, decimal) ". "; +} +.postBody ol li[class="ql-indent-1"] { + counter-increment: list-1; + counter-reset: list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9; +} +.postBody ol li[class="ql-indent-1"]::before { + content: counter(list-1, lower-alpha) ". "; +} +.postBody ol li[class="ql-indent-2"] { + counter-increment: list-2; + counter-reset: list-3 list-4 list-5 list-6 list-7 list-8 list-9; +} +.postBody ol li[class="ql-indent-2"]::before { + content: counter(list-2, lower-roman) ". "; +} +.postBody ol li[class="ql-indent-3"] { + counter-increment: list-3; + counter-reset: list-4 list-5 list-6 list-7 list-8 list-9; +} +.postBody ol li[class="ql-indent-3"]:before { + content: counter(list-3, decimal) ". "; +} +.postBody ol li[class="ql-indent-4"] { + counter-increment: list-4; + counter-reset: list-5 list-6 list-7 list-8 list-9; +} +.postBody ol li[class="ql-indent-4"]::before { + content: counter(list-4, lower-alpha) ". "; +} +.postBody ol li[class="ql-indent-5"] { + counter-increment: list-5; + counter-reset: list-6 list-7 list-8 list-9; +} +.postBody ol li[class="ql-indent-5"]::before { + content: counter(list-5, lower-roman) ". "; +} +.postBody ol li[class="ql-indent-6"] { + counter-increment: list-6; + counter-reset: list-7 list-8 list-9; +} +.postBody ol li[class="ql-indent-6"]:before { + content: counter(list-6, decimal) ". "; +} +.postBody ol li[class="ql-indent-7"] { + counter-increment: list-7; + counter-reset: list-8 list-9; +} +.postBody ol li[class="ql-indent-7"]::before { + content: counter(list-7, lower-alpha) ". "; +} +.postBody ol li[class="ql-indent-8"] { + counter-increment: list-8; + counter-reset: list-9; +} +.postBody ol li[class="ql-indent-8"]::before { + content: counter(list-8, lower-roman) ". "; +} +.postBody ol li[class="ql-indent-9"] { + counter-increment: list-9; +} +.postBody ol li[class="ql-indent-9"]:before { + content: counter(list-9, decimal) ". "; +} From 3c25e53bc0c172a971f803de88e86bf052b5211b Mon Sep 17 00:00:00 2001 From: YI Na-yeon <2n.ayeon.yi@gmail.com> Date: Thu, 25 Jul 2024 03:24:59 +0900 Subject: [PATCH 23/33] =?UTF-8?q?[Feat]=20=20=EC=BB=A4=EB=AE=A4=EB=8B=88?= =?UTF-8?q?=ED=8B=B0=20=EA=B8=80=20=EC=A0=95=EB=A0=AC,=20=EC=B9=B4?= =?UTF-8?q?=ED=85=8C=EA=B3=A0=EB=A6=AC,=20=EA=B2=80=EC=83=89=EC=96=B4=20?= =?UTF-8?q?=ED=82=A4=EC=9B=8C=EB=93=9C=EC=97=90=20=EB=94=B0=EB=9D=BC=20?= =?UTF-8?q?=ED=95=84=ED=84=B0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/(route)/_components/SearchInput.tsx | 4 +- src/app/(route)/post/page.tsx | 60 +- src/dummies/posts.ts | 652 +++----------------- src/hooks/useQueryString.tsx | 4 +- 4 files changed, 125 insertions(+), 595 deletions(-) diff --git a/src/app/(route)/_components/SearchInput.tsx b/src/app/(route)/_components/SearchInput.tsx index ed44ac9..92bc61f 100644 --- a/src/app/(route)/_components/SearchInput.tsx +++ b/src/app/(route)/_components/SearchInput.tsx @@ -3,10 +3,10 @@ import useQueryString from "@/hooks/useQueryString"; import { FormEvent } from "react"; -export default function SearchInput() { +export default function SearchInput({ origin = "study" }: { origin?: string }) { const onChangeQuery = useQueryString({ paramsKey: "q", - queryInclude: "search", + queryInclude: origin === "study" ? "search" : origin, }); const onSubmit = (e: FormEvent) => { diff --git a/src/app/(route)/post/page.tsx b/src/app/(route)/post/page.tsx index 73c45ce..4363864 100644 --- a/src/app/(route)/post/page.tsx +++ b/src/app/(route)/post/page.tsx @@ -7,21 +7,22 @@ import SidebarNavArea from "@/common/Layout/Sidebar/SidebarNavArea"; import SideNavItem from "@/common/Layout/Sidebar/SideNavItem"; import Dropdown from "@/common/Molecules/Dropdown"; import { POST_CATEGORY, POST_SORT_BY } from "@/constants/menu/community_posts"; -import { getPosts } from "@/dummies/posts"; -import ContentSearchBar from "../_components/ContentSearchBar"; import { WriteIcon } from "@/common/Atoms/Image/Icon"; import PostListWithPagination from "@/common/Templates/PostListWithPagination"; +import SearchInput from "../_components/SearchInput"; +import NonePostItem from "./_components/NonePostItem"; + import { Post } from "@/lib/schema"; import connectDB from "@/lib/db"; +import { getPosts } from "@/dummies/posts"; type TQuery = { category?: string; sort?: string }; -export default async function CommunityPostList({ +export default function CommunityPostList({ searchParams, }: { searchParams: TQuery; }) { - const posts = getPosts(); const category = searchParams?.category || "all"; const sort = searchParams?.sort || "latest"; const filteredMenu = POST_CATEGORY.find((item) => item.key === category); @@ -33,16 +34,29 @@ export default async function CommunityPostList({ /** * TODO * - 글 리스트 데이터 가져오기 : TPost[] - * - 글 리스트 category에 따라 리스트 화면에 표시 - * - 정렬 방법에 따라 sorted - * - 검색 키워드에 따라 리스트 필터링 */ - await connectDB(); + // await connectDB(); + // + // const posts = await Post.find(); - const post = await Post.find(); + const posts = getPosts(category); - console.log(post); + const sortedPosts = posts.sort((a, b) => { + switch (sortedBy.key) { + case "latest": + return Date.parse(b.createdAt) - Date.parse(a.createdAt); + case "comments": + return b.comments.length - a.comments.length; + case "likes": + return b.like - a.like; + case "views": + return b.view - a.view; + default: + throw new Error("잘못된 정렬 기준입니다."); + } + }); + console.log("posts", posts); return ( @@ -51,12 +65,13 @@ export default async function CommunityPostList({ ))} -
-
+
+

{filteredMenu.label} 글

- + {/* */} +
-
+
( @@ -66,7 +81,12 @@ export default async function CommunityPostList({ sort === item.key ? "text-main-600" : "" }`} > - + {item.label} @@ -77,9 +97,13 @@ export default async function CommunityPostList({ 글 작성하기
-
- -
+ {sortedPosts.length > 0 ? ( +
+ +
+ ) : ( + + )}
); diff --git a/src/dummies/posts.ts b/src/dummies/posts.ts index 9ddfa24..73f7826 100644 --- a/src/dummies/posts.ts +++ b/src/dummies/posts.ts @@ -25,8 +25,8 @@ const example: TPost[] = [ isRecruiting: null, }, contents: { - title: "가나다라", - body: "

조금 더 공부하면서 성장하는게 목적인 온라인 디스코드 스터디원을 모집합니다.

스터디 목표는 단순히 저녁에 공부하는 습관을 만드는 것입니다.

하나의 공통된 주제는 없고

원하시는 공부를 하시면 됩니다.

장기간 성장을 바라보는 분들을 환영합니다.

진행 시간

월, 화, 목 오후 20시~오후 21시입니다.

최소 주 2회 참여 해주세요.

진행 방식

공부할 것을 공유하며 간단히 이야기하고

한시간동안 공부합니다.

관심이 있으시면 댓글로 간단하게 남겨주세요.

", + title: "고민있어요", + body: `

안녕하세요 신입 프론트 개발자입니다.

 

오늘 극 초기 스타트업에 합격했습니다.

제가 관심있는 도메인입니다.

초봉이 3300이고요

 

그리고 면접 예정인 회사가 2개있습니다.

그 중 하나는 스타트업, 솔루션 회사인데 초봉이 4500입니다.

1차 면접이 금요일에 예정입니다. (2차 면접까지 있어요.)

 

회사에 출근하는게 좋다생각하시나요

입사포기하고 4500 면접 보는게 좋다 생각하시나요?

 

초봉이 3300인게 이후 연봉에 크게 영향이 갈까요?

`, linkedStudyId: null, }, writer: { @@ -36,9 +36,10 @@ const example: TPost[] = [ position: "개발자", profileUrl: "", }, - createdAt: "2024-06-29 22:10:00", - view: 188, - like: 15, + createdAt: "2024-07-24 22:10:00", + view: 22, + like: 8, + comments: [], }, { postId: encodeNumToStr(101354), @@ -49,7 +50,7 @@ const example: TPost[] = [ }, contents: { title: "모든 프로덕트에 대한 스터디", - body: "", + body: `

조금 더 공부하면서 성장하는게 목적인 온라인 디스코드 스터디원을 모집합니다.

스터디 목표는 단순히 저녁에 공부하는 습관을 만드는 것입니다.

하나의 공통된 주제는 없고

원하시는 공부를 하시면 됩니다.

장기간 성장을 바라보는 분들을 환영합니다.

진행 시간

월, 화, 목 오후 20시~오후 21시입니다.

최소 주 2회 참여 해주세요.

진행 방식

공부할 것을 공유하며 간단히 이야기하고

한시간동안 공부합니다.

관심이 있으시면 댓글로 간단하게 남겨주세요.

`, linkedStudyId: "1", }, writer: { @@ -60,8 +61,23 @@ const example: TPost[] = [ profileUrl: "", }, createdAt: "2024-06-29 20:00:00", - view: 188, - like: 15, + view: 20, + like: 5, + comments: [ + { + commentId: "comment-12345", + content: "초보도 참여 가능할까요?", + writer: { + userId: "kimjihyeon", + name: "김지현", + role: "user", + position: "", + profileUrl: "", + }, + createdAt: "2024-07-01 11:02", + reply: [], + }, + ], }, { postId: encodeNumToStr(101353), @@ -73,7 +89,7 @@ const example: TPost[] = [ contents: { title: "[면접 스터디] 강남 오프라인 프론트엔드 면접 준비 ( 기술면접, CS 등 ) - 추가 모집중입니다!!", - body: "", + body: `

스터디 진행 방식

스터디 당일에 랜덤으로 질문 주제를 정합니다.

인성 질문 2개, 기술 질문 4개씩

인성 질문 e.g. “개발자가 되고 싶은 이유가 무엇인가요?”

기술 질문 e.g. “이 기술 스택을 선택한 이유가 무엇인가요?”

당황하는 연습도 중요하다고 생각해 랜덤으로 질문으로 선택하게 됐습니다.

밤 20시, 해당 질문에 대한 답변을 보지 않은 채 이야기합니다.

20시를 1순위로 하되, 합의 하에 시간을 유동적으로 정해도 됩니다.

7일 중 3일 진행합니다. (해당 주의 마지막 스터디 날에, 다음 주 일정을 픽스합니다)

캠 켜고 온라인으로 진행합니다.

총 4명으로 진행을 하며, 2:2로 나누어 진행을 합니다.

대상

면접 준비가 반드시 필요하신 분

프론트엔드 개발자로 취업을 준비하고 계신 분

이력서, 포트폴리오가 어느정도는 준비되신 분

주 3회 저녁 20시에 시간 투자가 가능하신 분

벌금제

공용 통장에 30,000원씩 입금합니다.

전 주에 픽스했던 스터디 날에 결석해야 하는 경우 5,000원씩 벌금이 늘어납니다.

정말 피치 못할 사정(경조사, 면접, 코테)의 경우만 제외합니다.

스터디 4주가 끝나면 자신이 쌓은 벌금은 상대방이 가져가게 됩니다.

중도 탈퇴 시, 반환금은 남은 스터디원과 나눠 갖습니다.

기간

1월 29일 ~ 2월 25일 (4주)

현재 2명 있으며, 2명 더 모집합니다.

면접에 대한 고민이 많고, 면접에서 벽을 느낀 한 프론트엔드 개발자 준비생입니다.

https://www.superookie.com/contents/5ddd14198b129f585f1fa15f

이 글과, 여러 멘토 분들이 추천해준 방식인 “경험을 직접 이야기하며 내 꺼로 만드는 것”이 중요하다는 것을 느껴 스터디를 기획하게 되었습니다. 높은 열정과, 저와 뜻이 같은 분과 함께 하고 싶습니다.

보증금이 적은 금액이 아니고, 규칙 또한 빡셉니다. 정말로 열심히 할 의지가 있으신 분들만 신청해주세요 !

`, linkedStudyId: null, }, writer: { @@ -84,8 +100,9 @@ const example: TPost[] = [ profileUrl: "", }, createdAt: "2024-06-29 00:00:00", - view: 188, - like: 15, + view: 12, + like: 9, + comments: [], }, { postId: encodeNumToStr(101352), @@ -96,7 +113,7 @@ const example: TPost[] = [ }, contents: { title: "안드로이드 면접 스터디", - body: "", + body: `

[개발 스터디 모집 내용]

  1. 스터디 주제 :백엔드 면접 준비
  2. 스터디 목표 : 백엔드 면접 준비
  3. 예상 모집인원 : 4 ~5
  4. 스터디 소개와 개설 이유 : 면접 준비
  5. 이력서 및 포트포폴리오 피드백 / 프로젝트 관련 질문 / CS 관련 질문
  6. 일주일에 한번씩 면접
  7. 한사람 당 약 20분

 

스터디 관련 주의사항 :

스터디에 지원할 수 있는 방법을 남겨주세요. (이메일, 카카오 오픈채팅방, 구글폼 등.) 😀

`, linkedStudyId: null, }, writer: { @@ -107,571 +124,58 @@ const example: TPost[] = [ profileUrl: "", }, createdAt: "2024-06-25 00:00:00", - view: 188, - like: 15, - }, - { - postId: encodeNumToStr(101351), - category: { - value: "free", - label: "자유게시판", - isRecruiting: null, - }, - contents: { - title: "가나다라", - body: "

조금 더 공부하면서 성장하는게 목적인 온라인 디스코드 스터디원을 모집합니다.

스터디 목표는 단순히 저녁에 공부하는 습관을 만드는 것입니다.

하나의 공통된 주제는 없고

원하시는 공부를 하시면 됩니다.

장기간 성장을 바라보는 분들을 환영합니다.

진행 시간

월, 화, 목 오후 20시~오후 21시입니다.

최소 주 2회 참여 해주세요.

진행 방식

공부할 것을 공유하며 간단히 이야기하고

한시간동안 공부합니다.

관심이 있으시면 댓글로 간단하게 남겨주세요.

", - linkedStudyId: null, - }, - writer: { - userId: "hanyoojun", - name: "한유준", - role: "user", - position: "개발자", - profileUrl: "", - }, - createdAt: "2024-06-29 22:10:00", - view: 188, - like: 15, - }, - { - postId: encodeNumToStr(101350), - category: { - value: "study", - label: "스터디 홍보", - isRecruiting: true, - }, - contents: { - title: "모든 프로덕트에 대한 스터디", - body: "", - linkedStudyId: null, - }, - writer: { - userId: "hanyoojun", - name: "한유준", - role: "user", - position: "개발자", - profileUrl: "", - }, - createdAt: "2024-06-29 20:00:00", - view: 188, - like: 15, - }, - { - postId: encodeNumToStr(101349), - category: { - value: "study", - label: "스터디 홍보", - isRecruiting: true, - }, - contents: { - title: - "[면접 스터디] 강남 오프라인 프론트엔드 면접 준비 ( 기술면접, CS 등 ) - 추가 모집중입니다!!", - body: "", - linkedStudyId: null, - }, - writer: { - userId: "hanyoojun", - name: "한유준", - role: "user", - position: "개발자", - profileUrl: "", - }, - createdAt: "2024-06-29 00:00:00", - view: 188, - like: 15, - }, - { - postId: encodeNumToStr(101348), - category: { - value: "study", - label: "스터디 홍보", - isRecruiting: false, - }, - contents: { - title: "안드로이드 면접 스터디", - body: "", - linkedStudyId: null, - }, - writer: { - userId: "hanyoojun", - name: "한유준", - role: "user", - position: "개발자", - profileUrl: "", - }, - createdAt: "2024-06-25 00:00:00", - view: 188, - like: 15, - }, - { - postId: encodeNumToStr(101347), - category: { - value: "free", - label: "자유게시판", - isRecruiting: null, - }, - contents: { - title: "가나다라", - body: "

조금 더 공부하면서 성장하는게 목적인 온라인 디스코드 스터디원을 모집합니다.

스터디 목표는 단순히 저녁에 공부하는 습관을 만드는 것입니다.

하나의 공통된 주제는 없고

원하시는 공부를 하시면 됩니다.

장기간 성장을 바라보는 분들을 환영합니다.

진행 시간

월, 화, 목 오후 20시~오후 21시입니다.

최소 주 2회 참여 해주세요.

진행 방식

공부할 것을 공유하며 간단히 이야기하고

한시간동안 공부합니다.

관심이 있으시면 댓글로 간단하게 남겨주세요.

", - linkedStudyId: null, - }, - writer: { - userId: "hanyoojun", - name: "한유준", - role: "user", - position: "개발자", - profileUrl: "", - }, - createdAt: "2024-06-29 22:10:00", - view: 188, - like: 15, - }, - { - postId: encodeNumToStr(101346), - category: { - value: "study", - label: "스터디 홍보", - isRecruiting: true, - }, - contents: { - title: "모든 프로덕트에 대한 스터디", - body: "", - linkedStudyId: null, - }, - writer: { - userId: "hanyoojun", - name: "한유준", - role: "user", - position: "개발자", - profileUrl: "", - }, - createdAt: "2024-06-29 20:00:00", - view: 188, - like: 15, - }, - { - postId: encodeNumToStr(101345), - category: { - value: "study", - label: "스터디 홍보", - isRecruiting: true, - }, - contents: { - title: - "[면접 스터디] 강남 오프라인 프론트엔드 면접 준비 ( 기술면접, CS 등 ) - 추가 모집중입니다!!", - body: "", - linkedStudyId: null, - }, - writer: { - userId: "hanyoojun", - name: "한유준", - role: "user", - position: "개발자", - profileUrl: "", - }, - createdAt: "2024-06-29 00:00:00", - view: 188, - like: 15, - }, - { - postId: encodeNumToStr(101344), - category: { - value: "study", - label: "스터디 홍보", - isRecruiting: false, - }, - contents: { - title: "안드로이드 면접 스터디", - body: "", - linkedStudyId: null, - }, - writer: { - userId: "hanyoojun", - name: "한유준", - role: "user", - position: "개발자", - profileUrl: "", - }, - createdAt: "2024-06-25 00:00:00", - view: 188, - like: 15, - }, - { - postId: encodeNumToStr(101343), - category: { - value: "free", - label: "자유게시판", - isRecruiting: null, - }, - contents: { - title: "가나다라", - body: "

조금 더 공부하면서 성장하는게 목적인 온라인 디스코드 스터디원을 모집합니다.

스터디 목표는 단순히 저녁에 공부하는 습관을 만드는 것입니다.

하나의 공통된 주제는 없고

원하시는 공부를 하시면 됩니다.

장기간 성장을 바라보는 분들을 환영합니다.

진행 시간

월, 화, 목 오후 20시~오후 21시입니다.

최소 주 2회 참여 해주세요.

진행 방식

공부할 것을 공유하며 간단히 이야기하고

한시간동안 공부합니다.

관심이 있으시면 댓글로 간단하게 남겨주세요.

", - linkedStudyId: null, - }, - writer: { - userId: "hanyoojun", - name: "한유준", - role: "user", - position: "개발자", - profileUrl: "", - }, - createdAt: "2024-06-29 22:10:00", - view: 188, - like: 15, - }, - { - postId: encodeNumToStr(101342), - category: { - value: "study", - label: "스터디 홍보", - isRecruiting: true, - }, - contents: { - title: "모든 프로덕트에 대한 스터디", - body: "", - linkedStudyId: null, - }, - writer: { - userId: "hanyoojun", - name: "한유준", - role: "user", - position: "개발자", - profileUrl: "", - }, - createdAt: "2024-06-29 20:00:00", - view: 188, - like: 15, - }, - { - postId: encodeNumToStr(101341), - category: { - value: "study", - label: "스터디 홍보", - isRecruiting: true, - }, - contents: { - title: - "[면접 스터디] 강남 오프라인 프론트엔드 면접 준비 ( 기술면접, CS 등 ) - 추가 모집중입니다!!", - body: "", - linkedStudyId: null, - }, - writer: { - userId: "hanyoojun", - name: "한유준", - role: "user", - position: "개발자", - profileUrl: "", - }, - createdAt: "2024-06-29 00:00:00", - view: 188, - like: 15, - }, - { - postId: encodeNumToStr(101340), - category: { - value: "study", - label: "스터디 홍보", - isRecruiting: false, - }, - contents: { - title: "안드로이드 면접 스터디", - body: "", - linkedStudyId: null, - }, - writer: { - userId: "hanyoojun", - name: "한유준", - role: "user", - position: "개발자", - profileUrl: "", - }, - createdAt: "2024-06-25 00:00:00", - view: 188, - like: 15, - }, - { - postId: encodeNumToStr(101339), - category: { - value: "free", - label: "자유게시판", - isRecruiting: null, - }, - contents: { - title: "가나다라", - body: "

조금 더 공부하면서 성장하는게 목적인 온라인 디스코드 스터디원을 모집합니다.

스터디 목표는 단순히 저녁에 공부하는 습관을 만드는 것입니다.

하나의 공통된 주제는 없고

원하시는 공부를 하시면 됩니다.

장기간 성장을 바라보는 분들을 환영합니다.

진행 시간

월, 화, 목 오후 20시~오후 21시입니다.

최소 주 2회 참여 해주세요.

진행 방식

공부할 것을 공유하며 간단히 이야기하고

한시간동안 공부합니다.

관심이 있으시면 댓글로 간단하게 남겨주세요.

", - linkedStudyId: null, - }, - writer: { - userId: "hanyoojun", - name: "한유준", - role: "user", - position: "개발자", - profileUrl: "", - }, - createdAt: "2024-06-29 22:10:00", - view: 188, - like: 15, - }, - { - postId: encodeNumToStr(101338), - category: { - value: "study", - label: "스터디 홍보", - isRecruiting: true, - }, - contents: { - title: "모든 프로덕트에 대한 스터디", - body: "", - linkedStudyId: null, - }, - writer: { - userId: "hanyoojun", - name: "한유준", - role: "user", - position: "개발자", - profileUrl: "", - }, - createdAt: "2024-06-29 20:00:00", - view: 188, - like: 15, - }, - { - postId: encodeNumToStr(101337), - category: { - value: "study", - label: "스터디 홍보", - isRecruiting: true, - }, - contents: { - title: - "[면접 스터디] 강남 오프라인 프론트엔드 면접 준비 ( 기술면접, CS 등 ) - 추가 모집중입니다!!", - body: "", - linkedStudyId: null, - }, - writer: { - userId: "hanyoojun", - name: "한유준", - role: "user", - position: "개발자", - profileUrl: "", - }, - createdAt: "2024-06-29 00:00:00", - view: 188, - like: 15, - }, - { - postId: encodeNumToStr(101336), - category: { - value: "study", - label: "스터디 홍보", - isRecruiting: false, - }, - contents: { - title: "안드로이드 면접 스터디", - body: "", - linkedStudyId: null, - }, - writer: { - userId: "hanyoojun", - name: "한유준", - role: "user", - position: "개발자", - profileUrl: "", - }, - createdAt: "2024-06-25 00:00:00", - view: 188, - like: 15, - }, - { - postId: encodeNumToStr(101335), - category: { - value: "free", - label: "자유게시판", - isRecruiting: null, - }, - contents: { - title: "가나다라", - body: "

조금 더 공부하면서 성장하는게 목적인 온라인 디스코드 스터디원을 모집합니다.

스터디 목표는 단순히 저녁에 공부하는 습관을 만드는 것입니다.

하나의 공통된 주제는 없고

원하시는 공부를 하시면 됩니다.

장기간 성장을 바라보는 분들을 환영합니다.

진행 시간

월, 화, 목 오후 20시~오후 21시입니다.

최소 주 2회 참여 해주세요.

진행 방식

공부할 것을 공유하며 간단히 이야기하고

한시간동안 공부합니다.

관심이 있으시면 댓글로 간단하게 남겨주세요.

", - linkedStudyId: null, - }, - writer: { - userId: "hanyoojun", - name: "한유준", - role: "user", - position: "개발자", - profileUrl: "", - }, - createdAt: "2024-06-29 22:10:00", - view: 188, - like: 15, - }, - { - postId: encodeNumToStr(101334), - category: { - value: "study", - label: "스터디 홍보", - isRecruiting: true, - }, - contents: { - title: "모든 프로덕트에 대한 스터디", - body: "", - linkedStudyId: null, - }, - writer: { - userId: "hanyoojun", - name: "한유준", - role: "user", - position: "개발자", - profileUrl: "", - }, - createdAt: "2024-06-29 20:00:00", - view: 188, - like: 15, - }, - { - postId: encodeNumToStr(101333), - category: { - value: "study", - label: "스터디 홍보", - isRecruiting: true, - }, - contents: { - title: - "[면접 스터디] 강남 오프라인 프론트엔드 면접 준비 ( 기술면접, CS 등 ) - 추가 모집중입니다!!", - body: "", - linkedStudyId: null, - }, - writer: { - userId: "hanyoojun", - name: "한유준", - role: "user", - position: "개발자", - profileUrl: "", - }, - createdAt: "2024-06-29 00:00:00", - view: 188, - like: 15, - }, - { - postId: encodeNumToStr(101332), - category: { - value: "study", - label: "스터디 홍보", - isRecruiting: false, - }, - contents: { - title: "안드로이드 면접 스터디", - body: "", - linkedStudyId: null, - }, - writer: { - userId: "hanyoojun", - name: "한유준", - role: "user", - position: "개발자", - profileUrl: "", - }, - createdAt: "2024-06-25 00:00:00", - view: 188, - like: 15, - }, - { - postId: encodeNumToStr(101331), - category: { - value: "free", - label: "자유게시판", - isRecruiting: null, - }, - contents: { - title: "가나다라", - body: "

조금 더 공부하면서 성장하는게 목적인 온라인 디스코드 스터디원을 모집합니다.

스터디 목표는 단순히 저녁에 공부하는 습관을 만드는 것입니다.

하나의 공통된 주제는 없고

원하시는 공부를 하시면 됩니다.

장기간 성장을 바라보는 분들을 환영합니다.

진행 시간

월, 화, 목 오후 20시~오후 21시입니다.

최소 주 2회 참여 해주세요.

진행 방식

공부할 것을 공유하며 간단히 이야기하고

한시간동안 공부합니다.

관심이 있으시면 댓글로 간단하게 남겨주세요.

", - linkedStudyId: null, - }, - writer: { - userId: "hanyoojun", - name: "한유준", - role: "user", - position: "개발자", - profileUrl: "", - }, - createdAt: "2024-06-29 22:10:00", - view: 188, - like: 15, - }, - { - postId: encodeNumToStr(101330), - category: { - value: "study", - label: "스터디 홍보", - isRecruiting: true, - }, - contents: { - title: "모든 프로덕트에 대한 스터디", - body: "", - linkedStudyId: null, - }, - writer: { - userId: "hanyoojun", - name: "한유준", - role: "user", - position: "개발자", - profileUrl: "", - }, - createdAt: "2024-06-29 20:00:00", - view: 188, - like: 15, - }, - { - postId: encodeNumToStr(101329), - category: { - value: "study", - label: "스터디 홍보", - isRecruiting: true, - }, - contents: { - title: - "[면접 스터디] 강남 오프라인 프론트엔드 면접 준비 ( 기술면접, CS 등 ) - 추가 모집중입니다!!", - body: "", - linkedStudyId: null, - }, - writer: { - userId: "hanyoojun", - name: "한유준", - role: "user", - position: "개발자", - profileUrl: "", - }, - createdAt: "2024-06-29 00:00:00", - view: 188, - like: 15, - }, - { - postId: encodeNumToStr(101328), - category: { - value: "study", - label: "스터디 홍보", - isRecruiting: false, - }, - contents: { - title: "안드로이드 면접 스터디", - body: "", - linkedStudyId: null, - }, - writer: { - userId: "hanyoojun", - name: "한유준", - role: "user", - position: "개발자", - profileUrl: "", - }, - createdAt: "2024-06-25 00:00:00", - view: 188, - like: 15, + view: 18, + like: 6, + comments: [ + { + commentId: "comment-1", + content: "This is comment number 1", + writer: { + userId: "hanyoojun", + name: "한유준", + role: "user", + position: "개발자", + profileUrl: "", + }, + createdAt: "2024-07-24T14:08:54.101Z", + reply: [ + { + originId: "origin-1", + commentId: "reply-1", + content: "Reply to comment number 1", + writer: { + userId: "hanyoojun", + name: "한유준", + role: "user", + position: "개발자", + profileUrl: "", + }, + createdAt: "2024-07-24T14:08:54.101Z", + }, + ], + }, + { + commentId: "comment-2", + content: "This is comment number 2", + writer: { + userId: "kimjihyeon", + name: "김지현", + role: "user", + position: "", + profileUrl: "", + }, + createdAt: "2024-07-24T14:08:54.101Z", + reply: [], + }, + ], }, ]; -export function getPosts(): TPost[] { - return example; +export function getPosts(category?: string): TPost[] { + if (category === undefined || category === "all") { + return example; + } + return example.filter((post) => post.category.value === category); } export function getPost(id: string): TPost { diff --git a/src/hooks/useQueryString.tsx b/src/hooks/useQueryString.tsx index 3c11636..6c38ab9 100644 --- a/src/hooks/useQueryString.tsx +++ b/src/hooks/useQueryString.tsx @@ -12,7 +12,9 @@ const useQueryString = ({ const router = useRouter(); const pathname = usePathname(); - const url = pathname?.includes(queryInclude) ? pathname : `${pathname}/search`; + const url = pathname?.includes(queryInclude) + ? pathname + : `${pathname}/search`; const onEventQueryString = (value: string) => { newSearchParams.set(paramsKey, value); From 180e144bdf0ef750282c72ed7cd76ed06842f705 Mon Sep 17 00:00:00 2001 From: YI Na-yeon <2n.ayeon.yi@gmail.com> Date: Thu, 25 Jul 2024 03:26:01 +0900 Subject: [PATCH 24/33] [Refactor] --- .../(route)/post/_components/NonePostItem.tsx | 11 +++++++ .../post/_components/ReturnToListButton.tsx | 33 +++++++++++++++++++ .../study/_components/NoneStudyComponent.tsx | 5 +-- src/app/_components/NoneContentItemBase.tsx | 9 +++++ 4 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 src/app/(route)/post/_components/NonePostItem.tsx create mode 100644 src/app/(route)/post/_components/ReturnToListButton.tsx create mode 100644 src/app/_components/NoneContentItemBase.tsx diff --git a/src/app/(route)/post/_components/NonePostItem.tsx b/src/app/(route)/post/_components/NonePostItem.tsx new file mode 100644 index 0000000..2d10a7a --- /dev/null +++ b/src/app/(route)/post/_components/NonePostItem.tsx @@ -0,0 +1,11 @@ +import NoneContentItemBase from "@/app/_components/NoneContentItemBase"; + +export default function NonePostItem() { + return ( + +

+ 조건에 맞는 글이 존재하지 않습니다. +

+
+ ); +} diff --git a/src/app/(route)/post/_components/ReturnToListButton.tsx b/src/app/(route)/post/_components/ReturnToListButton.tsx new file mode 100644 index 0000000..848c54b --- /dev/null +++ b/src/app/(route)/post/_components/ReturnToListButton.tsx @@ -0,0 +1,33 @@ +"use client"; + +import { useRouter } from "next/navigation"; + +export default function ReturnToListButton() { + const router = useRouter(); + function returnBack() { + router.back(); + } + return ( + + ); +} diff --git a/src/app/(route)/study/_components/NoneStudyComponent.tsx b/src/app/(route)/study/_components/NoneStudyComponent.tsx index e3c7754..19e4349 100644 --- a/src/app/(route)/study/_components/NoneStudyComponent.tsx +++ b/src/app/(route)/study/_components/NoneStudyComponent.tsx @@ -1,8 +1,9 @@ import Link from "next/link"; +import NoneContentItemBase from "@/app/_components/NoneContentItemBase"; export default function NoneStudyComponent() { return ( -
+

모집 중인 스터디가 없습니다.
첫 스터디를 만들어보세요! @@ -13,6 +14,6 @@ export default function NoneStudyComponent() { > 스터디 개설하기 -

+ ); } diff --git a/src/app/_components/NoneContentItemBase.tsx b/src/app/_components/NoneContentItemBase.tsx new file mode 100644 index 0000000..55ebe3d --- /dev/null +++ b/src/app/_components/NoneContentItemBase.tsx @@ -0,0 +1,9 @@ +import { TProps } from "@/types/component/props"; + +export default function NoneContentItemBase({ children }: TProps) { + return ( +
+ {children} +
+ ); +} From 8a31bac47d6bdab38f303f02db142ff0944beb5f Mon Sep 17 00:00:00 2001 From: YI Na-yeon <2n.ayeon.yi@gmail.com> Date: Thu, 25 Jul 2024 03:26:11 +0900 Subject: [PATCH 25/33] =?UTF-8?q?[Chore]=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../(route)/post/{[postId] => }/_components/LinkedStudyCard.tsx | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/app/(route)/post/{[postId] => }/_components/LinkedStudyCard.tsx (100%) diff --git a/src/app/(route)/post/[postId]/_components/LinkedStudyCard.tsx b/src/app/(route)/post/_components/LinkedStudyCard.tsx similarity index 100% rename from src/app/(route)/post/[postId]/_components/LinkedStudyCard.tsx rename to src/app/(route)/post/_components/LinkedStudyCard.tsx From c131b1abc4d07774ef575daab509119363a21205 Mon Sep 17 00:00:00 2001 From: YI Na-yeon <2n.ayeon.yi@gmail.com> Date: Thu, 25 Jul 2024 03:26:36 +0900 Subject: [PATCH 26/33] [Refactor] --- src/app/(route)/my/like-study/page.tsx | 30 +++++++++++++++++--------- src/app/(route)/my/post/page.tsx | 29 ++++++++++++++----------- 2 files changed, 37 insertions(+), 22 deletions(-) diff --git a/src/app/(route)/my/like-study/page.tsx b/src/app/(route)/my/like-study/page.tsx index 28b81a8..ebac32b 100644 --- a/src/app/(route)/my/like-study/page.tsx +++ b/src/app/(route)/my/like-study/page.tsx @@ -1,26 +1,36 @@ -import NoneStudyComponent from "@/app/(route)/study/_components/NoneStudyComponent"; +import Link from "next/link"; +import NoneContentItemBase from "@/app/_components/NoneContentItemBase"; import SectionTitle from "@/common/Atoms/Text/SectionTitle"; import StudyCardItem from "@/common/Organisms/StudyCardItem"; -import StudyCardList from "@/common/Templates/CardList"; -import { getStudiesData } from "@/dummies/studies"; +import { getStudiesData, TStudyCard } from "@/dummies/studies"; export default function MyStudyLiked() { - const studyCard = getStudiesData(); + const studyCards: TStudyCard[] = getStudiesData(); return ( <> 찜한 스터디
- {/* TODO: 스터디 카드에서 찜한 스터디 표시 추가 필요 */} - {studyCard.length === 0 ? ( - + {studyCards.length === 0 ? ( + +

+ 찜한 스터디가 없습니다. +
첫 스터디를 찜해보세요! +

+ + 스터디 구경가기 + +
) : ( -
- {studyCard.map((card) => ( +
    + {studyCards.map((card) => ( ))} -
+ )}
diff --git a/src/app/(route)/my/post/page.tsx b/src/app/(route)/my/post/page.tsx index 22ec3a2..f04e586 100644 --- a/src/app/(route)/my/post/page.tsx +++ b/src/app/(route)/my/post/page.tsx @@ -3,10 +3,11 @@ import { getPosts } from "@/dummies/posts"; import SectionTitle from "@/common/Atoms/Text/SectionTitle"; import Dropdown from "@/common/Molecules/Dropdown"; import LinkButton from "@/common/Atoms/LinkButton"; -import PostListItem from "@/common/Organisms/PostListItem"; import NotFound from "@/app/not-found"; import PostListWithPagination from "@/common/Templates/PostListWithPagination"; import { WriteIcon } from "@/common/Atoms/Image/Icon"; +import { TPost } from "@/types/model/PostItem"; +import NonePostItem from "../../post/_components/NonePostItem"; const POST_FROM = [ { key: "community", label: "커뮤니티" }, @@ -16,7 +17,7 @@ const POST_FROM = [ type TQuery = { from?: string }; export default function MyPost({ searchParams }: { searchParams: TQuery }) { - const posts = getPosts(); + const posts: TPost[] = []; //getPosts(); const from = searchParams?.from || "community"; const postFrom = POST_FROM.find((item) => item.key === from); if (postFrom === undefined) { @@ -28,7 +29,7 @@ export default function MyPost({ searchParams }: { searchParams: TQuery }) { 찜한 스터디
- (
  • ))} /> - {postFrom.key === "community" && ( - - - 커뮤니티 글 작성하기 - - )} -
  • -
    - + {postFrom.key === "community" && ( */} + + + 커뮤니티 글 작성하기 + + {/* )} */}
    + {posts.length > 0 ? ( +
    + +
    + ) : ( + + )} ); } From 6741b8d8f1c651e34567f3a281687d80eddd8690 Mon Sep 17 00:00:00 2001 From: YI Na-yeon <2n.ayeon.yi@gmail.com> Date: Thu, 25 Jul 2024 03:27:20 +0900 Subject: [PATCH 27/33] =?UTF-8?q?[Feat]=20session=20=EC=B2=B4=ED=81=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/(route)/post/[postId]/page.tsx | 66 +++++++++------------ src/common/Layout/Header.tsx | 11 +--- src/common/Templates/CommentArea.tsx | 79 ++++---------------------- 3 files changed, 38 insertions(+), 118 deletions(-) diff --git a/src/app/(route)/post/[postId]/page.tsx b/src/app/(route)/post/[postId]/page.tsx index 35be853..65040bf 100644 --- a/src/app/(route)/post/[postId]/page.tsx +++ b/src/app/(route)/post/[postId]/page.tsx @@ -4,63 +4,45 @@ import Button from "@/common/Atoms/Form/Button"; import LinkButton from "@/common/Atoms/LinkButton"; import Profile from "@/common/Molecules/Profile"; import ContentArea from "@/common/Organisms/ContentArea"; -import CommentArea, { TComment } from "@/common/Templates/CommentArea"; -import LinkedStudyCard from "./_components/LinkedStudyCard"; +import CommentArea from "@/common/Templates/CommentArea"; import ShareIconButton from "../../_components/ShareIconButton"; +import { getSession } from "@/auth"; +import ReturnToListButton from "../_components/ReturnToListButton"; +import LinkedStudyCard from "../_components/LinkedStudyCard"; -export default function PostDetail({ +export default async function PostDetail({ params: { postId }, }: { params: { postId: string }; }) { + const session = await getSession(); const post = getPost(postId); - const comments: TComment[] = []; return ( -
    - - - - - 목록으로 돌아가기 - +
    +

    {post.category.label}

    -

    - {post.contents.title} #{postId} -

    +

    {post.contents.title}

    1일 전 {/* 본인이 작성한 글이라면 수정하기 버튼 show */} - - 수정하기 - + {session?.user.id === post.writer.userId && ( + + 수정하기 + + )}

    @@ -85,15 +67,19 @@ export default function PostDetail({
    - - {/* TODO: 추후 Link 추가 필요 */} +
    + +
    {post.contents.linkedStudyId && ( )}
    - +
    ); } diff --git a/src/common/Layout/Header.tsx b/src/common/Layout/Header.tsx index 4352a8b..c86c167 100644 --- a/src/common/Layout/Header.tsx +++ b/src/common/Layout/Header.tsx @@ -1,14 +1,5 @@ import Link from "next/link"; -import { - AlarmIcon, - CreateStudyIcon, - Logo, - LogoutIcon, - PostIcon, - SaveHeartIcon, - SettingProfileIcon, - StudyIcon, -} from "@public/icons"; +import { Logo } from "@public/icons"; import Image from "next/image"; import { DummyProfileImg } from "@public/images"; import Container from "./Container"; diff --git a/src/common/Templates/CommentArea.tsx b/src/common/Templates/CommentArea.tsx index 9298af5..c70ad18 100644 --- a/src/common/Templates/CommentArea.tsx +++ b/src/common/Templates/CommentArea.tsx @@ -1,79 +1,16 @@ import ProfileImg from "../Atoms/Image/ProfileImg"; import CommentItem from "../Organisms/Comment/CommentItem"; import CommentInput from "../Organisms/Comment/CommentInput"; -import { TUserBase } from "@/types/model/User"; +import { CommentSchema } from "@/types/model/Comment"; -// 데이터 없이 화면 테스트 시 컴포넌트 내부에서 comments 대신 example로 변경 후 확인 -export const example: TComment[] = [ - { - commentId: "0", - content: "디자인 초보도 참여 가능할까요?", - writer: { - userId: "kimjihyeon", - name: "김지현", - role: "user", - position: "", - profileUrl: "", - }, - createdAt: "2024-05-01 11:02", - reply: [ - { - originId: "0", - commentId: "1", - content: - "네, 가능합니다. 서로 공유하면서 배워나가는 스터디 모임입니다!", - writer: { - userId: "leesunhyeong", - name: "이선형", - role: "pro", - position: "UIUX 디자이너", - profileUrl: "", - }, - createdAt: "2024.05.02 13:02", - }, - { - originId: "0", - commentId: "2", - content: "스터디 참여 신청서 작성 부탁드려요", - writer: { - userId: "leesunhyeong", - name: "이선형", - role: "pro", - position: "UIUX 디자이너", - profileUrl: "", - }, - createdAt: "2024.05.02 13:03", - }, - ], - }, - { - commentId: "3", - content: "저도 참여하고 싶어요! 진행중인데 참여 가능할까요?", - writer: { - userId: "shinjiwoo", - name: "신지우", - role: "user", - position: "", - profileUrl: "", - }, - createdAt: "2024.05.03 13:52", - reply: [], - }, -]; - -export type TComment = { - commentId: string; - content: string; - writer: TUserBase; - createdAt: string; - reply: Array & { originId: string }>; -}; export default function CommentArea({ titleText = "댓글", comments, + sessionId, }: { titleText?: string; - comments: TComment[]; + comments: CommentSchema[]; + sessionId: string; }) { return (
    @@ -102,7 +39,13 @@ export default function CommentArea({ 첫번째로 댓글을 남겨보세요! ) : ( - comments.map((c) => ) + comments.map((c) => ( + + )) )}
    From cdaf1cb53a91ebc14cecff8582435a350058796c Mon Sep 17 00:00:00 2001 From: YI Na-yeon <2n.ayeon.yi@gmail.com> Date: Thu, 25 Jul 2024 03:27:48 +0900 Subject: [PATCH 28/33] =?UTF-8?q?[Feat]=20=EA=B2=80=EC=83=89=EC=96=B4=20?= =?UTF-8?q?=EC=BF=BC=EB=A6=AC=EC=97=90=20=EB=94=B0=EB=9D=BC=20=EC=BB=A4?= =?UTF-8?q?=EB=AE=A4=EB=8B=88=ED=8B=B0=20post=20=ED=95=84=ED=84=B0?= =?UTF-8?q?=EB=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/Templates/PostListWithPagination.tsx | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/common/Templates/PostListWithPagination.tsx b/src/common/Templates/PostListWithPagination.tsx index ae9344a..ebc1657 100644 --- a/src/common/Templates/PostListWithPagination.tsx +++ b/src/common/Templates/PostListWithPagination.tsx @@ -3,16 +3,24 @@ import { TPost } from "@/types/model/PostItem"; import PostList from "./PostList"; import Pagination from "../Molecules/Pagination"; import { useState } from "react"; +import { useSearchParams } from "next/navigation"; +import NonePostItem from "@/app/(route)/post/_components/NonePostItem"; const POSTS_PER_PAGE = 20; export default function PostListWithPagination({ posts }: { posts: TPost[] }) { + const searchParams = useSearchParams(); + const searchQuery = searchParams.get("q"); const [current, setCurrent] = useState(1); - const pageLength = Math.ceil(posts.length / POSTS_PER_PAGE); + + const postsData = searchQuery + ? posts.filter((post) => post.contents.title.includes(searchQuery)) + : posts; + const pageLength = Math.ceil(postsData.length / POSTS_PER_PAGE); const startPost = (current - 1) * POSTS_PER_PAGE; const endPost = current * POSTS_PER_PAGE + 1; - const currentPosts = posts.slice(startPost, endPost); - return ( + const currentPosts = postsData.slice(startPost, endPost); + return postsData.length > 0 ? ( <> + ) : ( + ); } From e9a5764eda169e82859970063da89962b01bdbaf Mon Sep 17 00:00:00 2001 From: YI Na-yeon <2n.ayeon.yi@gmail.com> Date: Thu, 25 Jul 2024 03:29:27 +0900 Subject: [PATCH 29/33] =?UTF-8?q?[Feat]=20=EB=8C=93=EA=B8=80=20=EC=97=85?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/Organisms/Comment/CommentInput.tsx | 16 ++++++- src/common/Organisms/Comment/CommentItem.tsx | 45 ++++++++++++++----- 2 files changed, 49 insertions(+), 12 deletions(-) diff --git a/src/common/Organisms/Comment/CommentInput.tsx b/src/common/Organisms/Comment/CommentInput.tsx index 66ab8f7..0ad1057 100644 --- a/src/common/Organisms/Comment/CommentInput.tsx +++ b/src/common/Organisms/Comment/CommentInput.tsx @@ -1,15 +1,19 @@ "use client"; -import { useRef, useState } from "react"; +import { MouseEventHandler, useRef, useState } from "react"; import Button from "@/common/Atoms/Form/Button"; import Input from "@/common/Molecules/Form/Input"; export default function CommentInput({ init = false, placeholder = "댓글을 작성해보세요", + onCancel, + onSubmit, }: { init?: boolean; placeholder?: string; + onCancel?: () => void; + onSubmit?: () => void; }) { const [focus, setFocus] = useState(init); const commentRef = useRef(null); @@ -29,11 +33,19 @@ export default function CommentInput({ commentRef.current.reset(); } setFocus(false); + onCancel && onCancel(); }} > 취소 - diff --git a/src/common/Organisms/Comment/CommentItem.tsx b/src/common/Organisms/Comment/CommentItem.tsx index bc41310..0e95504 100644 --- a/src/common/Organisms/Comment/CommentItem.tsx +++ b/src/common/Organisms/Comment/CommentItem.tsx @@ -1,41 +1,66 @@ "use client"; import Profile from "@/common/Molecules/Profile"; -import { TComment } from "@/common/Templates/CommentArea"; +import { CommentSchema } from "@/types/model/Comment"; +import { useState } from "react"; +import CommentInput from "./CommentInput"; function CommentBodyLayout({ comment, + canEdit, canReply = true, }: { - comment: Omit; + comment: Omit; + canEdit: boolean; canReply?: boolean; }) { + const [writeReply, setWrite] = useState(false); + const createdAt = new Intl.DateTimeFormat("ko-KR", { + dateStyle: "medium", + timeStyle: "medium", + }); return ( <>

    {comment.content}

    - {comment.createdAt} - {canReply && } - {/* 아래 수정, 삭제 버튼은 작성자=로그인한 사용자인 경우, */} - - + {createdAt.format(Date.parse(comment.createdAt))} + {canReply && } + {canEdit && ( + <> + + + + )}

    + {writeReply && ( + setWrite(false)} /> + )} ); } -export default function CommentItem({ comment }: { comment: TComment }) { +export default function CommentItem({ + comment, + canEdit, +}: { + comment: CommentSchema; + canEdit: boolean; +}) { return (
    - + {comment?.reply && comment.reply.length > 0 && comment.reply.map((reply) => (
    - +
    ))} From e381a8e8a6416004d59e6886b055eec4f0349306 Mon Sep 17 00:00:00 2001 From: YI Na-yeon <2n.ayeon.yi@gmail.com> Date: Thu, 25 Jul 2024 03:29:35 +0900 Subject: [PATCH 30/33] =?UTF-8?q?[Chore]=20=EB=8D=94=EB=AF=B8=20=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/dummies/comments.ts | 486 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 486 insertions(+) create mode 100644 src/dummies/comments.ts diff --git a/src/dummies/comments.ts b/src/dummies/comments.ts new file mode 100644 index 0000000..fd354c8 --- /dev/null +++ b/src/dummies/comments.ts @@ -0,0 +1,486 @@ +import { CommentSchema } from "@/types/model/Comment"; + +const comments: CommentSchema[] = [ + { + commentId: "comment-12345", + content: "디자인 초보도 참여 가능할까요?", + writer: { + userId: "kimjihyeon", + name: "김지현", + role: "user", + position: "", + profileUrl: "", + }, + createdAt: "2024-05-01 11:02", + reply: [ + { + originId: "comment-12345", + commentId: "comment-123451", + content: + "네, 가능합니다. 서로 공유하면서 배워나가는 스터디 모임입니다!", + writer: { + userId: "leesunhyeong", + name: "이선형", + role: "pro", + position: "UIUX 디자이너", + profileUrl: "", + }, + createdAt: "2024.05.02 13:02", + }, + { + originId: "comment-12345", + commentId: "comment-123452", + content: "스터디 참여 신청서 작성 부탁드려요", + writer: { + userId: "leesunhyeong", + name: "이선형", + role: "pro", + position: "UIUX 디자이너", + profileUrl: "", + }, + createdAt: "2024.05.02 13:03", + }, + ], + }, + { + commentId: "comment-12357", + content: "저도 참여하고 싶어요! 진행중인데 참여 가능할까요?", + writer: { + userId: "shinjiwoo", + name: "신지우", + role: "user", + position: "", + profileUrl: "", + }, + createdAt: "2024.05.03 13:52", + reply: [], + }, + { + commentId: "comment-1", + content: "This is comment number 1", + writer: { + userId: "hanyoojun", + name: "한유준", + role: "user", + position: "개발자", + profileUrl: "", + }, + createdAt: "2024-07-24T14:08:54.101Z", + reply: [ + { + originId: "origin-1", + commentId: "reply-1", + content: "Reply to comment number 1", + writer: { + userId: "shinjiwoo", + name: "신지우", + role: "user", + position: "", + profileUrl: "", + }, + createdAt: "2024-07-24T14:08:54.101Z", + }, + ], + }, + { + commentId: "comment-2", + content: "This is comment number 2", + writer: { + userId: "hanyoojun", + name: "한유준", + role: "user", + position: "개발자", + profileUrl: "", + }, + createdAt: "2024-07-24T14:08:54.101Z", + reply: [ + { + originId: "origin-2", + commentId: "reply-2", + content: "Reply to comment number 2", + writer: { + userId: "shinjiwoo", + name: "신지우", + role: "user", + position: "", + profileUrl: "", + }, + createdAt: "2024-07-24T14:08:54.101Z", + }, + ], + }, + { + commentId: "comment-3", + content: "This is comment number 3", + writer: { + userId: "hanyoojun", + name: "한유준", + role: "user", + position: "개발자", + profileUrl: "", + }, + createdAt: "2024-07-24T14:08:54.101Z", + reply: [ + { + originId: "origin-3", + commentId: "reply-3", + content: "Reply to comment number 3", + writer: { + userId: "shinjiwoo", + name: "신지우", + role: "user", + position: "", + profileUrl: "", + }, + createdAt: "2024-07-24T14:08:54.101Z", + }, + ], + }, + { + commentId: "comment-4", + content: "This is comment number 4", + writer: { + userId: "hanyoojun", + name: "한유준", + role: "user", + position: "개발자", + profileUrl: "", + }, + createdAt: "2024-07-24T14:08:54.101Z", + reply: [ + { + originId: "origin-4", + commentId: "reply-4", + content: "Reply to comment number 4", + writer: { + userId: "hanyoojun", + name: "한유준", + role: "user", + position: "개발자", + profileUrl: "", + }, + createdAt: "2024-07-24T14:08:54.101Z", + }, + ], + }, + { + commentId: "comment-5", + content: "This is comment number 5", + writer: { + userId: "hanyoojun", + name: "한유준", + role: "user", + position: "개발자", + profileUrl: "", + }, + createdAt: "2024-07-24T14:08:54.101Z", + reply: [ + { + originId: "origin-5", + commentId: "reply-5", + content: "Reply to comment number 5", + writer: { + userId: "hanyoojun", + name: "한유준", + role: "user", + position: "개발자", + profileUrl: "", + }, + createdAt: "2024-07-24T14:08:54.101Z", + }, + ], + }, + { + commentId: "comment-6", + content: "This is comment number 6", + writer: { + userId: "hanyoojun", + name: "한유준", + role: "user", + position: "개발자", + profileUrl: "", + }, + createdAt: "2024-07-24T14:08:54.101Z", + reply: [ + { + originId: "origin-6", + commentId: "reply-6", + content: "Reply to comment number 6", + writer: { + userId: "hanyoojun", + name: "한유준", + role: "user", + position: "개발자", + profileUrl: "", + }, + createdAt: "2024-07-24T14:08:54.101Z", + }, + ], + }, + { + commentId: "comment-7", + content: "This is comment number 7", + writer: { + userId: "hanyoojun", + name: "한유준", + role: "user", + position: "개발자", + profileUrl: "", + }, + createdAt: "2024-07-24T14:08:54.101Z", + reply: [ + { + originId: "origin-7", + commentId: "reply-7", + content: "Reply to comment number 7", + writer: { + userId: "hanyoojun", + name: "한유준", + role: "user", + position: "개발자", + profileUrl: "", + }, + createdAt: "2024-07-24T14:08:54.101Z", + }, + ], + }, + { + commentId: "comment-8", + content: "This is comment number 8", + writer: { + userId: "shinjiwoo", + name: "신지우", + role: "user", + position: "", + profileUrl: "", + }, + createdAt: "2024-07-24T14:08:54.101Z", + reply: [ + { + originId: "origin-8", + commentId: "reply-8", + content: "Reply to comment number 8", + writer: { + userId: "hanyoojun", + name: "한유준", + role: "user", + position: "개발자", + profileUrl: "", + }, + createdAt: "2024-07-24T14:08:54.101Z", + }, + ], + }, + { + commentId: "comment-9", + content: "This is comment number 9", + writer: { + userId: "shinjiwoo", + name: "신지우", + role: "user", + position: "", + profileUrl: "", + }, + createdAt: "2024-07-24T14:08:54.101Z", + reply: [ + { + originId: "origin-9", + commentId: "reply-9", + content: "Reply to comment number 9", + writer: { + userId: "hanyoojun", + name: "한유준", + role: "user", + position: "개발자", + profileUrl: "", + }, + createdAt: "2024-07-24T14:08:54.101Z", + }, + ], + }, + { + commentId: "comment-10", + content: "This is comment number 10", + writer: { + userId: "leesunhyeong", + name: "이선형", + role: "pro", + position: "UIUX 디자이너", + profileUrl: "", + }, + createdAt: "2024-07-24T14:08:54.101Z", + reply: [ + { + originId: "origin-10", + commentId: "reply-10", + content: "Reply to comment number 10", + writer: { + userId: "leesunhyeong", + name: "이선형", + role: "pro", + position: "UIUX 디자이너", + profileUrl: "", + }, + createdAt: "2024-07-24T14:08:54.101Z", + }, + ], + }, + { + commentId: "comment-11", + content: "This is comment number 11", + writer: { + userId: "hanyoojun", + name: "한유준", + role: "user", + position: "개발자", + profileUrl: "", + }, + createdAt: "2024-07-24T14:08:54.101Z", + reply: [ + { + originId: "origin-11", + commentId: "reply-11", + content: "Reply to comment number 11", + writer: { + userId: "hanyoojun", + name: "한유준", + role: "user", + position: "개발자", + profileUrl: "", + }, + createdAt: "2024-07-24T14:08:54.101Z", + }, + ], + }, + { + commentId: "comment-12", + content: "This is comment number 12", + writer: { + userId: "leesunhyeong", + name: "이선형", + role: "pro", + position: "UIUX 디자이너", + profileUrl: "", + }, + createdAt: "2024-07-24T14:08:54.101Z", + reply: [ + { + originId: "origin-12", + commentId: "reply-12", + content: "Reply to comment number 12", + writer: { + userId: "hanyoojun", + name: "한유준", + role: "user", + position: "개발자", + profileUrl: "", + }, + createdAt: "2024-07-24T14:08:54.101Z", + }, + ], + }, + { + commentId: "comment-13", + content: "This is comment number 13", + writer: { + userId: "kimjihyeon", + name: "김지현", + role: "user", + position: "", + profileUrl: "", + }, + createdAt: "2024-07-24T14:08:54.101Z", + reply: [], + }, + { + commentId: "comment-14", + content: "This is comment number 14", + writer: { + userId: "hanyoojun", + name: "한유준", + role: "user", + position: "개발자", + profileUrl: "", + }, + createdAt: "2024-07-24T14:08:54.101Z", + reply: [], + }, + { + commentId: "comment-15", + content: "This is comment number 15", + writer: { + userId: "hanyoojun", + name: "한유준", + role: "user", + position: "개발자", + profileUrl: "", + }, + createdAt: "2024-07-24T14:08:54.101Z", + reply: [], + }, + { + commentId: "comment-16", + content: "This is comment number 16", + writer: { + userId: "hanyoojun", + name: "한유준", + role: "user", + position: "개발자", + profileUrl: "", + }, + createdAt: "2024-07-24T14:08:54.101Z", + reply: [], + }, + { + commentId: "comment-17", + content: "This is comment number 17", + writer: { + userId: "hanyoojun", + name: "한유준", + role: "user", + position: "개발자", + profileUrl: "", + }, + createdAt: "2024-07-24T14:08:54.101Z", + reply: [], + }, + { + commentId: "comment-18", + content: "This is comment number 18", + writer: { + userId: "hanyoojun", + name: "한유준", + role: "user", + position: "개발자", + profileUrl: "", + }, + createdAt: "2024-07-24T14:08:54.101Z", + reply: [], + }, + { + commentId: "comment-19", + content: "This is comment number 19", + writer: { + userId: "hanyoojun", + name: "한유준", + role: "user", + position: "개발자", + profileUrl: "", + }, + createdAt: "2024-07-24T14:08:54.101Z", + reply: [], + }, + { + commentId: "comment-20", + content: "This is comment number 20", + writer: { + userId: "hanyoojun", + name: "한유준", + role: "user", + position: "개발자", + profileUrl: "", + }, + createdAt: "2024-07-24T14:08:54.101Z", + reply: [], + }, +]; From 9b1955389dcaeeb3d3095eb58abe30833eb03d8a Mon Sep 17 00:00:00 2001 From: YI Na-yeon <2n.ayeon.yi@gmail.com> Date: Thu, 25 Jul 2024 03:34:45 +0900 Subject: [PATCH 31/33] =?UTF-8?q?[Chore]=20=EA=B2=BD=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../(route)/study/[studyPostId]/_components/StudyDetail.tsx | 5 +++-- src/dummies/comments.ts | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/app/(route)/study/[studyPostId]/_components/StudyDetail.tsx b/src/app/(route)/study/[studyPostId]/_components/StudyDetail.tsx index 7501a7f..a2ef9d8 100644 --- a/src/app/(route)/study/[studyPostId]/_components/StudyDetail.tsx +++ b/src/app/(route)/study/[studyPostId]/_components/StudyDetail.tsx @@ -4,7 +4,8 @@ import { } from "@/dummies/studypostdetail"; import StudyDetailContent from "./StudyDetailContent"; import StudyDetailThumbnail from "./StudyDetailThumbnail"; -import CommentArea, { example } from "@/common/Templates/CommentArea"; +import CommentArea from "@/common/Templates/CommentArea"; +import { comments } from "@/dummies/comments"; export default function StudyDetail() { const user = getStudyLeaderUser(); @@ -14,7 +15,7 @@ export default function StudyDetail() {
    - +
    ); } diff --git a/src/dummies/comments.ts b/src/dummies/comments.ts index fd354c8..083da3d 100644 --- a/src/dummies/comments.ts +++ b/src/dummies/comments.ts @@ -1,6 +1,6 @@ import { CommentSchema } from "@/types/model/Comment"; -const comments: CommentSchema[] = [ +export const comments: CommentSchema[] = [ { commentId: "comment-12345", content: "디자인 초보도 참여 가능할까요?", From 9cd9284be63544315e275cf139914d9ba2fe08f7 Mon Sep 17 00:00:00 2001 From: YI Na-yeon <2n.ayeon.yi@gmail.com> Date: Thu, 25 Jul 2024 03:43:29 +0900 Subject: [PATCH 32/33] [Fix] rollback and make optional index to reduce error --- src/dummies/getImages.ts | 9 +++++---- src/dummies/studies.ts | 36 ++++++++++++++++++------------------ 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/dummies/getImages.ts b/src/dummies/getImages.ts index 34e08b5..f241f07 100644 --- a/src/dummies/getImages.ts +++ b/src/dummies/getImages.ts @@ -17,19 +17,20 @@ type IdTypes = | "all"; export function getImageUrl( - index: number, type?: IdTypes, width = 200, - height = 200 + height = 200, + index?: number ): string { const key = type || "all"; const idsByKey = key === "all" ? Object.values(ids).reduce((prev, curr) => [...prev, ...curr], []) : ids[key]; - // const randomIndex = Math.floor(Math.random() * idsByKey.length); + const randomIndex = Math.floor(Math.random() * idsByKey.length); + const random = index ? idsByKey.at(index) : idsByKey[randomIndex]; // console.log({ randomIndex }); - return `https://picsum.photos/id/${idsByKey.at(index)}/${width}/${height}`; + return `https://picsum.photos/id/${random}/${width}/${height}`; } export function getImageUrls( diff --git a/src/dummies/studies.ts b/src/dummies/studies.ts index bbf0f5f..39d6b85 100644 --- a/src/dummies/studies.ts +++ b/src/dummies/studies.ts @@ -57,7 +57,7 @@ const studyCards: TStudyCard[] = [ user: { userType: "user", nickname: "디자이너 이수빈", - image: getImageUrl(0, "animal", 48, 48), + image: getImageUrl("animal", 48, 48, 0), }, study: { title: "내가 디자인한 앱을 출시하기까지", @@ -65,7 +65,7 @@ const studyCards: TStudyCard[] = [ people: "모집 8명", deadline: "8/13 마감", RecruitmentStatus: "모집중", - image: getImageUrl(4, "tech", 268, 180), + image: getImageUrl("tech", 268, 180, 4), }, }, { @@ -73,7 +73,7 @@ const studyCards: TStudyCard[] = [ user: { userType: "pro", nickname: "과학자 김민수", - image: getImageUrl(11, "animal", 48, 48), + image: getImageUrl("animal", 48, 48, 11), }, study: { title: "재밌는 생명과학 실험 스터디", @@ -81,7 +81,7 @@ const studyCards: TStudyCard[] = [ people: "모집 12명", deadline: "8/23 마감", RecruitmentStatus: "모집중", - image: getImageUrl(7, "nature", 268, 180), + image: getImageUrl("nature", 268, 180, 7), }, }, { @@ -89,7 +89,7 @@ const studyCards: TStudyCard[] = [ user: { userType: "pro", nickname: "과학자 김민수", - image: getImageUrl(12, "animal", 48, 48), + image: getImageUrl("animal", 48, 48, 12), }, study: { title: "재밌는 생명과학 실험 스터디", @@ -97,7 +97,7 @@ const studyCards: TStudyCard[] = [ people: "모집 12명", deadline: "8/23 마감", RecruitmentStatus: "모집중", - image: getImageUrl(4, "nature", 268, 180), + image: getImageUrl("nature", 268, 180, 4), }, }, { @@ -105,7 +105,7 @@ const studyCards: TStudyCard[] = [ user: { userType: "user", nickname: "디자이너 이수빈", - image: getImageUrl(8, "animal", 48, 48), + image: getImageUrl("animal", 48, 48, 8), }, study: { title: "내가 디자인한 앱을 출시하기까지", @@ -113,7 +113,7 @@ const studyCards: TStudyCard[] = [ people: "모집 8명", deadline: "8/13 마감", RecruitmentStatus: "모집중", - image: getImageUrl(7, "desk", 268, 180), + image: getImageUrl("desk", 268, 180, 7), }, }, { @@ -121,7 +121,7 @@ const studyCards: TStudyCard[] = [ user: { userType: "pro", nickname: "과학자 김민수", - image: getImageUrl(9, "animal", 48, 48), + image: getImageUrl("animal", 48, 48, 9), }, study: { title: "재밌는 생명과학 실험 스터디", @@ -129,7 +129,7 @@ const studyCards: TStudyCard[] = [ people: "모집 12명", deadline: "8/23 마감", RecruitmentStatus: "모집중", - image: getImageUrl(10, "nature", 268, 180), + image: getImageUrl("nature", 268, 180, 10), }, }, { @@ -137,7 +137,7 @@ const studyCards: TStudyCard[] = [ user: { userType: "pro", nickname: "과학자 김민수", - image: getImageUrl(11, "animal", 48, 48), + image: getImageUrl("animal", 48, 48, 11), }, study: { title: "재밌는 생명과학 실험 스터디", @@ -145,7 +145,7 @@ const studyCards: TStudyCard[] = [ people: "모집 12명", deadline: "8/23 마감", RecruitmentStatus: "모집중", - image: getImageUrl(5, "nature", 268, 180), + image: getImageUrl("nature", 268, 180, 5), }, }, { @@ -153,7 +153,7 @@ const studyCards: TStudyCard[] = [ user: { userType: "user", nickname: "디자이너 이수빈", - image: getImageUrl(6, "animal", 48, 48), + image: getImageUrl("animal", 48, 48, 6), }, study: { title: "내가 디자인한 앱을 출시하기까지", @@ -161,7 +161,7 @@ const studyCards: TStudyCard[] = [ people: "모집 8명", deadline: "8/13 마감", RecruitmentStatus: "모집중", - image: getImageUrl(1, "desk", 268, 180), + image: getImageUrl("desk", 268, 180, 1), }, }, { @@ -169,7 +169,7 @@ const studyCards: TStudyCard[] = [ user: { userType: "pro", nickname: "과학자 김민수", - image: getImageUrl(11, "animal", 48, 48), + image: getImageUrl("animal", 48, 48, 11), }, study: { title: "재밌는 생명과학 실험 스터디", @@ -177,7 +177,7 @@ const studyCards: TStudyCard[] = [ people: "모집 12명", deadline: "8/23 마감", RecruitmentStatus: "모집중", - image: getImageUrl(4, "nature", 268, 180), + image: getImageUrl("nature", 268, 180, 4), }, }, { @@ -185,7 +185,7 @@ const studyCards: TStudyCard[] = [ user: { userType: "pro", nickname: "과학자 김민수", - image: getImageUrl(11, "animal", 48, 48), + image: getImageUrl("animal", 48, 48, 11), }, study: { title: "재밌는 생명과학 실험 스터디", @@ -193,7 +193,7 @@ const studyCards: TStudyCard[] = [ people: "모집 12명", deadline: "8/23 마감", RecruitmentStatus: "모집중", - image: getImageUrl(4, "nature", 268, 180), + image: getImageUrl("nature", 268, 180, 4), }, }, ]; From d2cbdd5241b0d4fe1bb3924ffdcc11344fd9a900 Mon Sep 17 00:00:00 2001 From: YI Na-yeon <2n.ayeon.yi@gmail.com> Date: Thu, 25 Jul 2024 10:23:12 +0900 Subject: [PATCH 33/33] =?UTF-8?q?[Style]=20MobileMenu=20=EB=B0=98=EC=9D=91?= =?UTF-8?q?=ED=98=95=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/Layout/ProfileMenu/MobileMenu.tsx | 2 +- src/common/Molecules/SidePopup.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/Layout/ProfileMenu/MobileMenu.tsx b/src/common/Layout/ProfileMenu/MobileMenu.tsx index 2373cb7..cf6692d 100644 --- a/src/common/Layout/ProfileMenu/MobileMenu.tsx +++ b/src/common/Layout/ProfileMenu/MobileMenu.tsx @@ -43,7 +43,7 @@ export default function MobileMenu({ profileImage }: TProfileImage) { }, []); return ( -
    +
    diff --git a/src/common/Molecules/SidePopup.tsx b/src/common/Molecules/SidePopup.tsx index 2c994c3..b6d66ad 100644 --- a/src/common/Molecules/SidePopup.tsx +++ b/src/common/Molecules/SidePopup.tsx @@ -16,7 +16,7 @@ const SidePopup = forwardRef( return (