Skip to content

Commit

Permalink
Merge pull request #57 from dnd-side-project/feature/51-mypage-settin…
Browse files Browse the repository at this point in the history
…gs-publishing

마이페이지 세팅 페이지 퍼블리싱
  • Loading branch information
froggy1014 authored Oct 6, 2024
2 parents 623bf05 + 6fdef6d commit 843f0cf
Show file tree
Hide file tree
Showing 13 changed files with 535 additions and 13 deletions.
118 changes: 118 additions & 0 deletions src/app/mypage/settings/_components/MypageSettingsKeywords.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
"use client";

import { zodResolver } from "@hookform/resolvers/zod";
import { FC } from "react";
import { Controller, useForm } from "react-hook-form";

import {
FestivalCategory,
FestivalCompanion,
FestivalMood,
FestivalPriority,
} from "@/apis/onboarding/onboardingType";
import { BasicButton } from "@/components/core/Button";
import {
CategoryKeywordInput,
MoodKeywordInput,
} from "@/components/core/Input";
import { PriorityKeywordInput } from "@/components/core/Input/KeywordInput";
import CompanionKeywordInput from "@/components/core/Input/KeywordInput/ConpanionKeywordInput";
import {
ProfileUpdateSchema,
ProfileUpdateSchemaType,
} from "@/validations/ProfileUpdateSchema";

interface Props {
categories: Array<FestivalCategory>;
companions: Array<FestivalCompanion>;
priorities: Array<FestivalPriority>;
moods: Array<FestivalMood>;
}

const MypageSettingsKeywords: FC<Props> = ({
categories,
companions,
priorities,
moods,
}) => {
const { handleSubmit, control } = useForm<ProfileUpdateSchemaType>({
defaultValues: {
categoryIds: [],
moodIds: [],
companionIds: [],
priorityIds: [],
},
resolver: zodResolver(ProfileUpdateSchema),
});

const onSubmit = (data: ProfileUpdateSchemaType) => {
console.log(data);
};

return (
<form
onSubmit={handleSubmit(onSubmit)}
className="flex h-full w-full flex-col justify-between gap-[28px]"
>
<Controller
control={control}
name="categoryIds"
render={({ field: { onChange, value } }) => (
<CategoryKeywordInput
categories={categories}
selectedCategories={value}
onChange={onChange}
maxCount={2}
label="관심있는 페스티벌 분야"
isPrimaryLabel
/>
)}
/>

<Controller
control={control}
name="moodIds"
render={({ field: { onChange, value } }) => (
<MoodKeywordInput
moods={moods}
selectedMoods={value}
onChange={onChange}
maxCount={3}
label="선호하는 페스티벌 분위기"
isPrimaryLabel
/>
)}
/>
<Controller
control={control}
name="companionIds"
render={({ field: { onChange, value } }) => (
<CompanionKeywordInput
companions={companions}
selectedCompanions={value}
onChange={onChange}
isPrimaryLabel
/>
)}
/>
<Controller
control={control}
name="priorityIds"
render={({ field: { onChange, value } }) => (
<PriorityKeywordInput
priorities={priorities}
selectedPriorities={value}
onChange={onChange}
maxCount={3}
label="페스티벌 우선순위"
isPrimaryLabel
/>
)}
/>

<BasicButton type="submit" label="완료" />
</form>
);
};

export default MypageSettingsKeywords;
61 changes: 61 additions & 0 deletions src/app/mypage/settings/_components/MypageSettingsProfile.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
"use client";

import React from "react";
import { Controller, useForm } from "react-hook-form";

import { BasicButton } from "@/components/core/Button";
import { TextInput } from "@/components/core/Input";

const MypageSettingsProfile = () => {
const { control, handleSubmit } = useForm({
values: {
nickname: "",
statusMessage: "",
},
});

const onSubmit = () => {};

return (
<form
onSubmit={handleSubmit(onSubmit)}
className="flex h-full w-full flex-col justify-between gap-[28px]"
>
<Controller
control={control}
name="nickname"
render={({ field: { onChange, value }, formState: { errors } }) => (
<TextInput
label="닉네임"
placeholder="페스티벌 명을 입력해주세요."
value={value}
onChange={onChange}
currentLength={value?.length ?? 0}
maxLength={10}
error={errors.nickname?.message}
/>
)}
/>

<Controller
control={control}
name="statusMessage"
render={({ field: { onChange, value }, formState: { errors } }) => (
<TextInput
label="상태메세지"
placeholder="페스티벌 명을 입력해주세요."
value={value}
onChange={onChange}
currentLength={value?.length ?? 0}
maxLength={30}
error={errors.statusMessage?.message}
/>
)}
/>

<BasicButton type="submit" label="완료" />
</form>
);
};

export default MypageSettingsProfile;
85 changes: 85 additions & 0 deletions src/app/mypage/settings/_components/MypageSettingsTab.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
"use client";

import * as Tabs from "@radix-ui/react-tabs";
import { FC } from "react";

import {
FestivalCategory,
FestivalCompanion,
FestivalMood,
FestivalPriority,
} from "@/apis/onboarding/onboardingType";

import MypageSettingsKeywords from "./MypageSettingsKeywords";
import MypageSettingsProfile from "./MypageSettingsProfile";

interface Props {
categories: Array<FestivalCategory>;
companions: Array<FestivalCompanion>;
priorities: Array<FestivalPriority>;
moods: Array<FestivalMood>;
}

const MypageSettingsTab: FC<Props> = ({
categories,
companions,
priorities,
moods,
}) => {
const TabList = [
{
name: "기본정보",
contentComponent: <MypageSettingsProfile />,
},
{
name: "맞춤 필터",
contentComponent: (
<MypageSettingsKeywords
categories={categories}
companions={companions}
priorities={priorities}
moods={moods}
/>
),
},
];

const handleTabChange = () => {
const tabElement = document.getElementById(`tab`);
if (tabElement) {
tabElement.scrollIntoView({ behavior: "smooth" });
}
};

return (
<Tabs.Root className="w-full " defaultValue={TabList[0].name}>
<Tabs.List
id={"tab"}
className="mb-[30px] flex h-[47px] w-full"
aria-label="Manage your account"
>
{TabList.map(({ name }, index) => (
<Tabs.Trigger
key={name}
className="TabsTrigger w-full border-b-[1px] border-gray-scale-400 text-subtitle-semi text-gray-scale-400"
value={name}
onClick={handleTabChange}
>
{name}
</Tabs.Trigger>
))}
</Tabs.List>
{TabList.map(({ name, contentComponent }) => (
<Tabs.Content
key={name}
className="flex flex-col gap-[18px] px-[16px]"
value={name}
>
{contentComponent}
</Tabs.Content>
))}
</Tabs.Root>
);
};

export default MypageSettingsTab;
21 changes: 21 additions & 0 deletions src/app/mypage/settings/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { getOnboardingData } from "@/apis/onboarding/onboarding";
import { DefaultHeader } from "@/layout/Mobile/MobileHeader";

import MypageSettingsView from "./view";

export default async function MypageSettingsPage() {
const { moods, categories, companions, priorities } =
await getOnboardingData();

return (
<div className="mt-[44px]">
<DefaultHeader label="프로필 수정" />
<MypageSettingsView
categories={categories}
companions={companions}
priorities={priorities}
moods={moods}
/>
</div>
);
}
35 changes: 35 additions & 0 deletions src/app/mypage/settings/view.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { FC } from "react";

import {
FestivalCategory,
FestivalCompanion,
FestivalMood,
FestivalPriority,
} from "@/apis/onboarding/onboardingType";

import MypageSettingsTab from "./_components/MypageSettingsTab";

interface Props {
categories: Array<FestivalCategory>;
companions: Array<FestivalCompanion>;
priorities: Array<FestivalPriority>;
moods: Array<FestivalMood>;
}

const MypageSettingsView: FC<Props> = ({
categories,
companions,
priorities,
moods,
}) => {
return (
<MypageSettingsTab
categories={categories}
companions={companions}
priorities={priorities}
moods={moods}
/>
);
};

export default MypageSettingsView;
3 changes: 3 additions & 0 deletions src/components/core/Chip/BasicChip/BasicChip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ interface Props extends ComponentPropsWithoutRef<"button"> {
active?: boolean;
label: string;
onClick?: () => void;
disabled?: boolean;
}

const BasicChip: FC<Props> = ({
active = false,
label,
className,
onClick,
disabled,
}) => {
return (
<button
Expand All @@ -27,6 +29,7 @@ const BasicChip: FC<Props> = ({
className,
)}
onClick={onClick}
disabled={disabled}
>
{label}
</button>
Expand Down
Loading

0 comments on commit 843f0cf

Please sign in to comment.