Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: current generation 업데이트 #157

Merged
merged 15 commits into from
Aug 24, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 1 addition & 11 deletions frontend/app/(WithNavbar)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,12 @@
import CommonNavbar from "@/components/common/navbar/Navbar";
import { PropsWithChildren } from "react";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

type import를 사용해봅시다 :)

Suggested change
import { PropsWithChildren } from "react";
import { type PropsWithChildren } from "react";

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵 수정하겠습니다!

import { headers } from "next/headers";

interface WithNavbarLayout extends PropsWithChildren {}

const ApplicantPage = ({ children }: WithNavbarLayout) => {
const headersList = headers();
const header_url = headersList.get("x-url") || "";
const [_, __, currentPath, generation, ___] = header_url.split(/[/?]+/);
const isShort = currentPath === "kanban";

return (
<div className="px-24 min-w-[1280px] flex p-12">
<CommonNavbar
generation={generation}
currentPath={currentPath}
isShort={isShort}
/>
Comment on lines -8 to -19
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기서 데이터를 받아와 뿌려주어 생기는 리렌더링이었군요!!
다른 곳에서 navbar를 사용할 줄 알아, 위에서 내리도록 작성했는데 이는 성급한 일반화로 발전한 것 같네요

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이제 안깜빡 거리나요 ㅎ 원래 네브바 나올때마다 깜빡였던거같던데

<CommonNavbar />
{children}
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion frontend/app/kanban/[generation]/detail/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const KanbanBoardDetailPage = ({
return (
<main className="flex mt-8 overflow-auto pt-12 pl-12">
<KanbanColumnDetailCard
columnIndex={+columnIndex ?? 0}
columnIndex={+(columnIndex ?? 0)}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • 바꾸기 전 코드와 바꾼 코드 둘 다 문자형을 숫자형으로 바꿔준다고 생각하는데 어떤 차이가 있나요?

  • KanbanColumnDetailCard 컴포넌트에서 columnIndex가 0으로 넘겨받는다면 useQuery에 enabled 속성을 넣어서 api 호출을 안하는게 좋아보입니다.

  • page.tsx에서 columnIndex를 props로 넘기는 것 대신에 KanbanColumnDetailCard 컴포넌트에서 아래와 같이 사용하면 props를 지울 수 있을 것 같아요

const searchParams = useSearchParams();
searchParams.get("columnIndex");

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아이고 맞네요.. 수정하도록 하겠습니다!

제가 이전에 몇번의 삽질을 했었는데요,
그때 CURRENT_GENERATION 상수값을 .env로 관리하는 게 어떨지 생각하면서 변경했었습니다.
이렇게 되면 CURRENT_GENERATION의 값이 undefined가 될 수 있어서, 단순히 +columnIndex 를 하면 NaN 이 나올 수 있기에 위와같이 수정했었습니다.
결론적으로 현재는 .env로 관리하지 않기 때문에 해당 코드를 불필요하게 좋지 않은 방향으로 변경하게 되었네요..

generation={generation}
cardId={cardId}
applicantId={applicantId}
Expand Down
33 changes: 11 additions & 22 deletions frontend/components/common/navbar/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
"use client";
import { MainNavbar } from "@/src/constants";
import CommonNavbarCell from "./NavbarCell";
import NavbarUserInfo from "./UserInfo";
import { NavbarOperation } from "./NavbarOperation";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { NavbarToggle } from "./NavbarToggle";

interface CommonNavbarProps {
generation: string;
isShort?: boolean;
currentPath: string;
}
const CommonNavbar = () => {
const currentPath = usePathname();
const isShort = currentPath.split("/")[1] === "kanban";
const generation = currentPath.split("/")[2];

const CommonNavbar = ({
generation,
isShort = false,
currentPath,
}: CommonNavbarProps) => {
return (
<nav className="flex flex-col transition-all">
<Link
Expand All @@ -26,19 +23,11 @@ const CommonNavbar = ({
<div>{generation}th</div>
</Link>
<div className="flex flex-col gap-8 mt-8 text-xl">
{MainNavbar.map((item) => (
<CommonNavbarCell
key={item.type}
currentPath={currentPath}
isShort={isShort}
item={item}
/>
{MainNavbar(+generation).map((item) => (
<CommonNavbarCell key={item.type} item={item} />
))}
<NavbarOperation
currentPath={currentPath}
generation={generation}
isShort={isShort}
/>
<NavbarToggle />
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Toggle이라.. 맞는거 같지만 더 좋은 이름이 없을까유?? 항상 이런 부분이 어려운거 같네요 ㅠㅠ

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

맞아요.. 사실 토글이긴 한데 보여질 기수를 변경해주는 토글이니 NavbarGenerationToggle 은 어떠신가요..?

<NavbarOperation />
</div>
<NavbarUserInfo />
</nav>
Expand Down
44 changes: 26 additions & 18 deletions frontend/components/common/navbar/NavbarCell.tsx
Original file line number Diff line number Diff line change
@@ -1,43 +1,51 @@
"use client";

import Image from "next/image";
import LtIcon from "@/public/icons/lt.icon.svg";
import LtIconWhite from "@/public/icons/lt.icon.white.svg";
import Link from "next/link";
import { cn } from "@/src/utils/cn";
import { usePathname } from "next/navigation";

type CommonNavbarCellProps = {
currentPath: string;
item: {
type: string;
type: string; //TODO: 타입 정의하기
href: string;
target: string;
short_title: string;
title: string;
};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

item으로 한번 감싸진 이유가 무엇인가요? 이전의 코드로 인한거군요 !
추가로 short_title에서 파이썬의 향기가 나네요ㅋ_ㅋ

isShort: boolean;
};

const CommonNavbarCell = ({
currentPath,
item,
isShort,
}: CommonNavbarCellProps) => {
const CommonNavbarCell = ({ item }: CommonNavbarCellProps) => {
const currentPath = usePathname();
const currentType = currentPath.split("/")[1];
const isShort = currentType === "kanban";

const generation = currentPath.split("/")[2];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

소소한... 레펙토링...

Suggested change
const currentPath = usePathname();
const currentType = currentPath.split("/")[1];
const isShort = currentType === "kanban";
const generation = currentPath.split("/")[2];
const [_, currentType, generation] = usePathname().split("/");
const isShort = currentType === "kanban";

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

바로 적용해보도록 하겠습니다!


const linkButtonClassName =
"flex justify-between p-4 hover:bg-secondary-100 hover:text-white rounded-lg";

const { href, short_title, target, title, type } = item;

return (
<a
className={
currentPath === item.type
<Link
className={cn(
currentType === type
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이렇게는 안될까용?

      className={cn(
        linkButtonClassName,
        currentType === type && "!bg-black !text-white"
      )}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

수정해보겠습니다!

? `${linkButtonClassName} !bg-black !text-white`
: linkButtonClassName
}
href={item.href}
target={item.target === "_blank" ? "_blank" : ""}
key={item.type}
)}
href={href}
target={target === "_blank" ? "_blank" : ""}
Copy link
Collaborator

@2yunseong 2yunseong Aug 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기서 조건부로 연산하는 것 (target) 보다 props로 받아오는 타입을 강제하는 건 어떤가요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

좋습니다! props로 받을 수 있는 값의 타입을 정의해보도록 하겠습니다!

key={type}
>
{isShort ? item.short_title : item.title}
{isShort ? short_title : title}
<Image
src={currentPath !== item.type ? LtIcon : LtIconWhite}
src={currentPath !== type ? LtIcon : LtIconWhite}
alt="right arrow"
/>
</a>
</Link>
);
};

Expand Down
17 changes: 4 additions & 13 deletions frontend/components/common/navbar/NavbarOperation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,11 @@
import { useQuery } from "@tanstack/react-query";
import CommonNavbarCell from "./NavbarCell";
import { getMyInfo } from "@/src/apis/interview";
import { usePathname } from "next/navigation";

interface NavbarOperationProps {
generation: string;
isShort?: boolean;
currentPath: string;
}

export const NavbarOperation = ({
generation,
isShort = false,
currentPath,
}: NavbarOperationProps) => {
export const NavbarOperation = () => {
const currentPath = usePathname();
const generation = currentPath.split("/")[2];
const { data: userData } = useQuery(["user"], getMyInfo);
if (!userData) {
return <div></div>;
Expand All @@ -26,8 +19,6 @@ export const NavbarOperation = ({

return (
<CommonNavbarCell
currentPath={currentPath}
isShort={isShort}
item={{
href: `/admin/${generation}`,
short_title: "관리자",
Expand Down
30 changes: 30 additions & 0 deletions frontend/components/common/navbar/NavbarToggle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { usePathname } from "next/navigation";
import CommonNavbarCell from "./NavbarCell";
import { CURRENT_GENERATION } from "@/src/constants";

export const NavbarToggle = () => {
const currentPath = usePathname();
const selectedGeneration = +currentPath.split("/")[2];

const isCurrentGeneration = selectedGeneration === CURRENT_GENERATION;
const generation = isCurrentGeneration
? CURRENT_GENERATION - 1
: CURRENT_GENERATION;

const short_title = isCurrentGeneration ? "지난 모집" : "현재 모집";
const title = isCurrentGeneration
? "지난 신입모집 보기"
: "현재 신입모집 보기";

return (
<CommonNavbarCell
item={{
href: `/kanban/${generation}`,
short_title,
title,
target: "_self",
type: "toggle",
}}
/>
);
};
84 changes: 84 additions & 0 deletions frontend/src/constants/applicant/28.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
const APPLICANT: ApplicantNode[] = [
{
id: 1,
title: "프로젝트 희망 분야를 선택해주세요.*",
type: "customField",
value: {
name: "field",
},
subValue: [
{ title: "1순위", name: "field1" },
{ title: "2순위", name: "field2" },
],
},
{
id: 2,
title: "기본 인적 사항을 입력해주세요.",
type: "customHuman",
value: {
hunamName: { name: "name" },
humanEmail: { name: "email" },
humanPhone: { name: "contacted" },
humanEtc: [
{ name: "classOf" },
{ name: "major" },
{ name: "doubleMajor" },
{ name: "minor" },
{ name: "grade" },
{ name: "semester" },
{ name: "registered" },
],
},
},
{
id: 3,
title: "기타 질문 사항에 답변해주세요.",
type: "shortSplit",
value: [
{ title: "향후 계획 활동", name: "activity" },
{ title: "지원 경로* (중복 선택 가능)", name: "channel" },
],
},
];

export type ScoreKeyword =
| "실천력"
| "동아리 활동의지"
| "협업"
| "베풀려는 마음";

// type ScoreKeywordName =
// | "passion"
// | "clubInvolvement"
// | "collaboration"
// | "devotion";

export const ScoreSequence: {
[key: number]: ScoreKeyword;
} = {
0: "실천력",
1: "동아리 활동의지",
2: "협업",
3: "베풀려는 마음",
};

export type Score = {
fieldName: ScoreKeyword;
score: number | "";
};

// type ScoreKeywordType = {
// title: ScoreKeyword;
// name: ScoreKeywordName;
// };

// const INTERVIEW_SCORE_KEYWORD: ScoreKeywordType[] = [
// { title: "실천력", name: "passion" },
// { title: "동아리 활동의지", name: "clubInvolvement" },
// { title: "협업", name: "collaboration" },
// { title: "베풀려는 마음", name: "devotion" },
// ];

const FIELD_NAME: ScoreKeyword[] = Object.values(ScoreSequence);

export { APPLICANT, FIELD_NAME };
76 changes: 76 additions & 0 deletions frontend/src/constants/applicant/28/designer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
export const APPLICANT_DESIGNER = [
{
id: 5,
title: "자기소개 및 에코노베이션에 지원하게 된 계기를 서술해 주세요.",
type: "textarea",
value: { name: "reason" },
} as ApplicantTextareaNode,
{
id: 6,
title:
"본인이 계획하고 있는 진로가 무엇인가요?(IT 분야가 아니어도 괜찮습니다)",
type: "textarea",
value: { name: "future" },
} as ApplicantTextareaNode,
{
id: 7,
title:
"UI/UX 디자인 작업물들 중 가장 자신 있는 디자인 작업물을 설명하고, 이를 통해 배우게 된 점이 있다면 서술해 주세요.",
type: "textarea",
value: { name: "workDescript" },
} as ApplicantTextareaNode,
{
id: 8,
title:
"UI/UX 디자인을 할 때, 가장 중요한 것은 무엇이라고 생각하나요? 한가지 키워드를 중심으로 서술해주세요.",
type: "textarea",
value: { name: "keyword" },
} as ApplicantTextareaNode,
{
id: 9,
title:
"우리 주변의 IT 서비스 중에 UI/UX를 개선하고 싶은 서비스가 있다면, 어떤 점을 '왜' 그리고 '어떻게' 개선하고 싶은지 서술해 주세요.",
type: "textarea",
value: { name: "betterment" },
} as ApplicantTextareaNode,
{
id: 10,
title:
"어떤 일에 도전하고 실패해 본 경험이 있나요? 그 실패를 어떻게 극복했는지 서술해 주세요.(소프트웨어 분야 관련 경험이 아니어도 좋습니다.)",
type: "textarea",
value: { name: "failure" },
} as ApplicantTextareaNode,
{
id: 11,
title:
"무언가에 깊게 빠지거나 파고 들어본 적이 있나요? 좋아하는 것을 위해서 주변에서 인정할 정도로 깊게 빠져본 적이 있다면 서술해주세요.",
type: "textarea",
value: { name: "drain" },
} as ApplicantTextareaNode,
{
id: 12,
title:
"협업(프로젝트, 팀 활동)에 있어서 가장 중요하다고 생각되는 것은 무엇인지 그 이유와 함께 서술해주세요.",
type: "textarea",
value: { name: "collaboration" },
} as ApplicantTextareaNode,
{
id: 13,
title:
"에코노베이션에 최종 합격 시 신입 기수로 구성된 팀으로 개발 프로젝트에 참여하고, 목표를 달성하기 위해 스스로 끊임없이 배우고 노력합니다. 에코노베이션에 들어오게 된다면 어떤 목표와 학습 계획을 바탕으로 활동하고 싶나요?",
type: "textarea",
value: { name: "studyPlan" },
} as ApplicantTextareaNode,
{
id: 14,
title:
"에코노베이션은 3학기 이상의 활동을 권장하고 있으며 매주 금요일 17시에는 주간발표가 있습니다. 위 내용을 확인하셨으면 '확인했습니다'를 기입해주세요.",
type: "textarea",
value: { name: "check" },
} as ApplicantTextareaNode,
{
id: 15,
title: "면접 가능시간을 선택해주세요. (중복 선택 가능)",
type: "timeline",
} as ApplicantTimelineNode,
];
Loading