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

refactor: 포트폴리오 URL 입력 형식 변경 #233

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
2 changes: 2 additions & 0 deletions frontend/components/application/Junction.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import ApplicationCheckboxWithEtc from "./applicationNode/CheckboxWithEtc.compon
import ApplicationTextarea from "./applicationNode/Textarea.component";
import ApplicationBar from "./applicationNode/Bar.component";
import ApplicationJustText from "./applicationNode/JustText.component";
import ApplicationAddText from "./applicationNode/AddText";

interface JunctionQuestionProps {
applicationNodeData: ApplicationNode;
Expand All @@ -28,6 +29,7 @@ export const JunctionQuestion = ({
checkboxWithEtc: <ApplicationCheckboxWithEtc data={applicationNodeData} />,
checkbox: <></>,
timeline: <></>,
addText: <ApplicationAddText data={applicationNodeData} />,
};

return jsxNode[applicationNodeData.type];
Expand Down
6 changes: 2 additions & 4 deletions frontend/components/application/JunctionOrLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,10 @@ const checkQuestion = (
return "id" in node;
};

// FIXME: 타입 오타 수정 바람 (Junctin -> Junction)
interface JunctinOrLayoutProps {
interface JunctionOrLayoutProps {
node: ApplicationQuestion | ApplicationNode;
}
// FIXME: 컴포넌트 오타 수정 바람 (Junctin -> Junction)
export const JunctinOrLayout = ({ node }: JunctinOrLayoutProps) => {
export const JunctionOrLayout = ({ node }: JunctionOrLayoutProps) => {
return checkQuestion(node) ? (
<ApplicationLayout applicationQuestion={node} />
) : (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import Txt from "@/components/common/Txt.component";
import type { ApplicationQuestion } from "@/src/constants/application/type";
import { JunctinOrLayout } from "../JunctionOrLayout";
import { JunctionOrLayout } from "../JunctionOrLayout";

interface ApplicationHorizontalLayoutProps {
applicationQuestion: ApplicationQuestion;
Expand All @@ -25,7 +25,7 @@ const ApplicationHorizontalLayout = ({
<Txt className="text-sm">{applicationQuestion.subtitle}</Txt>
{applicationQuestion.alert && (
<div className="mt-4">
<Txt className=" underline font-semibold">
<Txt className="font-semibold border-b-2 border-solid pb-1 border-black">
⚠️ {applicationQuestion.alert}
</Txt>
</div>
Expand All @@ -36,7 +36,7 @@ const ApplicationHorizontalLayout = ({
<div className="flex-1">
{applicationQuestion.nodes.map((node, index) => (
<div key={`${applicationQuestion.id} ${index}`} className="mb-4">
<JunctinOrLayout node={node} />
<JunctionOrLayout node={node} />
</div>
))}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import Txt from "@/components/common/Txt.component";
import type { ApplicationQuestion } from "@/src/constants/application/type";
import { JunctinOrLayout } from "../JunctionOrLayout";
import { JunctionOrLayout } from "../JunctionOrLayout";
import { cn } from "@/src/utils/cn";

interface ApplicationVerticalLayoutProps {
Expand All @@ -28,7 +28,7 @@ const ApplicationVerticalLayout = ({
)}
{applicationQuestion.nodes.map((node, index) => (
<div key={index} className="mb-4">
<JunctinOrLayout node={node} />
<JunctionOrLayout node={node} />
</div>
))}
</div>
Expand Down
146 changes: 146 additions & 0 deletions frontend/components/application/applicationNode/AddText.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
"use client";

import Txt from "@/components/common/Txt.component";
import {
type ApplicationAddText,
ApplicationNode,
} from "@/src/constants/application/type";

import { useState } from "react";
import ApplicationText from "./Text.component";
import { getLocalStorage } from "@/src/utils/applicant";

interface ApplicationAddTextProps {
data: ApplicationNode;
}

const ApplicationAddText = ({ data }: ApplicationAddTextProps) => {
const localStorageData = getLocalStorage([
"Github",
"Blog",
"Notion",
"Website",
"기타",
]);

const textData = data as ApplicationAddText;

const id = Date.now().toString();
const [selectedCategories, setSelectedCategories] = useState<
{ category: string; id: string; value: string }[]
>(localStorageData || [{ category: "Github", id: id, value: "" }]);

const onAddCategory = () => {
const newId = Date.now().toString();

setSelectedCategories([
...selectedCategories,
{ category: "Github", id: newId, value: "" },
]);
};

return (
<>
{textData.title && (
<div className="flex flex-row justify-between">
<label>
<Txt typography="h6">{`${textData.title} ${textData.alert}`}</Txt>
</label>
<button
onClick={onAddCategory}
className="ml-2 border p-2 rounded-lg"
>
+추가
</button>
</div>
)}
{selectedCategories.map((selectedCategory) => (
<ApplicationUrlText
selectedCategory={selectedCategory}
selectedCategories={selectedCategories}
setSelectedCategories={setSelectedCategories}
textData={textData}
key={selectedCategory.id}
/>
))}
</>
);
};

export default ApplicationAddText;

interface ApplicationUrlTextProps {
selectedCategory: { category: string; id: string; value: string };
selectedCategories: { category: string; id: string; value: string }[];
setSelectedCategories: (
categories: { category: string; id: string; value: string }[]
) => void;
textData: ApplicationAddText;
}

const ApplicationUrlText = ({
selectedCategory,
selectedCategories,
setSelectedCategories,
textData,
}: ApplicationUrlTextProps) => {
const onCategoryChange = (id: string, value: string) => {
const prevCategory = selectedCategory.category;
const prevCategoryData = localStorage.getItem(`${prevCategory} - ${id}`);
const newCategories = [...selectedCategories];

localStorage.removeItem(`${prevCategory} - ${id}`);

newCategories.forEach((category) => {
if (category.id === id) {
category.category = value;
}
});

prevCategoryData &&
localStorage.setItem(`${value} - ${id}`, prevCategoryData);

setSelectedCategories(newCategories);
};

const onRemoveCategory = (
id: string,
selectedCategory: { category: string; id: string }
) => {
const newCategories = selectedCategories.filter(
(category) => category.id !== id
);

localStorage.removeItem(`${selectedCategory.category} - ${id}`);
setSelectedCategories(newCategories);
};

return (
<div className="flex flex-row gap-2 items-center">
<select
onChange={(e) => onCategoryChange(selectedCategory.id, e.target.value)}
className="border my-2 rounded-lg p-4"
value={selectedCategory.category}
>
{textData.category.map((category) => (
<option key={category} value={category}>
{category}
</option>
))}
</select>
<ApplicationText
data={{
...textData,
title: "",
name: `${selectedCategory.category} - ${selectedCategory.id}`,
}}
/>
<button
onClick={() => onRemoveCategory(selectedCategory.id, selectedCategory)}
className="border rounded-full h-10 my-2 p-2 w-10"
>
-
</button>
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const ApplicationText = ({ data }: ApplicationTextProps) => {
const [isError, setIsError] = useState(false);

return (
<div className="relative">
<div className="relative w-full">
{textData.title && (
<label>
<Txt typography="h6">{`${textData.title}${
Expand Down
12 changes: 3 additions & 9 deletions frontend/src/constants/application/28/developer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,18 +132,12 @@ export const APPLICATION_DEVELOPER: ApplicationQuestion[] = [
direction: "horizontal",
nodes: [
{
type: "addText",
name: "portfolio",
require: false,
type: "text",
title: "참고 URL",
subtitle: "Github, Blog, Notion, Website 등",
},
{
name: "fileUrl",
require: false,
type: "text",
title: "파일 URL",
subtitle: "Google Drive 등",
category: ["Github", "Blog", "Notion", "Website", "기타"],
alert: "(입력창 하나당 하나의 URL을 입력해주세요.)",
},
],
},
Expand Down
9 changes: 8 additions & 1 deletion frontend/src/constants/application/type.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ interface ApplicationText extends ApplicationNodeBase {
minLength?: number;
}

interface ApplicationAddText extends ApplicationNodeBase {
type: "addText";
category: ("Github" | "Blog" | "Notion" | "Website" | "기타")[];
alert: string;
}

interface ApplicationTextarea extends ApplicationNodeBase {
type: "textarea";
}
Expand Down Expand Up @@ -103,7 +109,8 @@ type ApplicationNode =
| ApplicationJustText
| ApplicationCheckboxType
| ApplicationCheckboxWithEtcType
| ApplicationTimelineType;
| ApplicationTimelineType
| ApplicationAddText;

type ApplicationQuestion = {
id: number;
Expand Down
16 changes: 16 additions & 0 deletions frontend/src/hooks/useApplication.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
applicationDataAtom,
applicationIndexAtom,
} from "../stores/application";
import { getLocalStorage } from "../utils/applicant";

export const useApplication = () => {
// TODO: 질문의 이름마다 side effect가 있으니 주의하면 좋을 것
Expand Down Expand Up @@ -132,6 +133,21 @@ export const useApplication = () => {
answer: JSON.stringify(timeline),
});

const portfolioUrls = getLocalStorage([
"Github",
"Blog",
"Notion",
"Website",
"기타",
]);

portfolioUrls.forEach((portfolioUrl) => {
sendValues.push({
name: `${portfolioUrl.category} - ${portfolioUrl.id}`,
answer: JSON.parse(portfolioUrl.value),
});
});

const applicationName = Array.from(
{ length: applicationData.length },
(_, i) => Array.from(getApplicationNames(applicationData[i].nodes))
Expand Down
25 changes: 25 additions & 0 deletions frontend/src/utils/applicant/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,28 @@ export const findApplicantState = (
return cardsData.find((card) => card.applicantId === applicantId)?.state
.passState;
};

export const getLocalStorage = (category: string[]) => {
const data = [];

for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);

if (key && category.some((cat) => key.includes(cat))) {
const value = localStorage.getItem(key);

const parts = key.split(" - ");
if (parts.length === 2) {
const category = parts[0];
const id = parts[1];
data.push({
category,
id,
value: value || "",
});
}
}
}

return data;
};