Repository navigation
[FEAT] 약관 페이지 및 설정 약관 탭 구현 / 약관 API 연결 #167
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
Changes from 2 commits
442fbd2
6c7af2e
f1c0fe4
e8c6223
35568b2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,22 @@ | ||
| "use client"; | ||
|
|
||
| import { useTranslations } from "next-intl"; | ||
|
|
||
| import { PolicyDocument } from "@/components/policy/PolicyDocument"; | ||
| import { useTerms } from "@/queries/use-terms"; | ||
|
|
||
| export const SettingsPolicyContainer = () => { | ||
| const t = useTranslations("Policy"); | ||
| const { data: terms } = useTerms("SERVICE"); | ||
| const term = terms[0]; | ||
|
|
||
| return ( | ||
| <div className="flex flex-col gap-5 px-15 pt-7.5"> | ||
| <h1 className="typo-headline-m-16 text-timo-gray-900">약관</h1> | ||
| <hr className="border-timo-gray-500" /> | ||
| <div className="px-15 pt-7.5"> | ||
| {term ? ( | ||
| <PolicyDocument title={term.title} content={term.content} /> | ||
| ) : ( | ||
| <p className="typo-body-m-12 text-timo-gray-700">{t("empty")}</p> | ||
| )} | ||
|
coderabbitai[bot] marked this conversation as resolved.
Outdated
|
||
| </div> | ||
| ); | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| "use client"; | ||
|
|
||
| import { useTranslations } from "next-intl"; | ||
|
|
||
| import { PolicyDocument } from "@/components/policy/PolicyDocument"; | ||
| import { useTerms } from "@/queries/use-terms"; | ||
|
|
||
| export const SettingsPrivacyContainer = () => { | ||
| const t = useTranslations("Policy"); | ||
| const { data: terms } = useTerms("PRIVACY"); | ||
| const term = terms[0]; | ||
|
|
||
| return ( | ||
| <div className="px-15 pt-7.5"> | ||
| {term ? ( | ||
| <PolicyDocument title={term.title} content={term.content} /> | ||
| ) : ( | ||
| <p className="typo-body-m-12 text-timo-gray-700">{t("empty")}</p> | ||
| )} | ||
| </div> | ||
| ); | ||
| }; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
이 패턴을 공통 컴포넌트로 추출하면 유지보수성이 향상됩니다. 예를 들어 ♻️ 공통 PolicyContent 컴포넌트 추출 제안// components/policy/PolicyContent.tsx
"use client";
import { useTranslations } from "next-intl";
import type { TermsType } from "`@/types/terms-type`";
import { PolicyDocument } from "`@/components/policy/PolicyDocument`";
import { useTerms } from "`@/queries/use-terms`";
export interface PolicyContentProps {
type: TermsType;
headingLevel?: "h1" | "h2";
}
export const PolicyContent = ({ type, headingLevel = "h1" }: PolicyContentProps) => {
const t = useTranslations("Policy");
const { data: terms } = useTerms(type);
const term = terms.find((item) => item.type === type);
if (!term) {
return <p className="typo-body-m-12 text-timo-gray-700">{t("empty")}</p>;
}
return <PolicyDocument title={term.title} content={term.content} headingLevel={headingLevel} />;
};그 후 "use client";
-import { useTranslations } from "next-intl";
-
-import { PolicyDocument } from "`@/components/policy/PolicyDocument`";
-import { useTerms } from "`@/queries/use-terms`";
+import { PolicyContent } from "`@/components/policy/PolicyContent`";
export const SettingsPrivacyContainer = () => {
- const t = useTranslations("Policy");
- const { data: terms } = useTerms("PRIVACY");
- const term = terms[0];
-
return (
<div className="px-15 pt-7.5">
- {term ? (
- <PolicyDocument title={term.title} content={term.content} />
- ) : (
- <p className="typo-body-m-12 text-timo-gray-700">{t("empty")}</p>
- )}
+ <PolicyContent type="PRIVACY" headingLevel="h2" />
</div>
);
};🤖 Prompt for AI Agents |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| "use client"; | ||
|
|
||
| import { useTranslations } from "next-intl"; | ||
|
|
||
| import type { TermsType } from "@/types/terms-type"; | ||
|
|
||
| import { PolicyDocument } from "@/components/policy/PolicyDocument"; | ||
| import { useTerms } from "@/queries/use-terms"; | ||
|
|
||
| export interface PolicyContainerProps { | ||
| type: TermsType; | ||
| } | ||
|
|
||
| export const PolicyContainer = ({ type }: PolicyContainerProps) => { | ||
| const t = useTranslations("Policy"); | ||
| const { data: terms } = useTerms(type); | ||
| const term = terms.find((item) => item.type === type) ?? terms[0]; | ||
|
|
||
| if (!term) { | ||
| return <p className="typo-body-m-12 text-timo-gray-700">{t("empty")}</p>; | ||
| } | ||
|
|
||
| return <PolicyDocument title={term.title} content={term.content} />; | ||
| }; | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| import timoTextLogo from "@repo/timo-design-system/assets/images/logo/timo-text-logo.svg"; | ||
| import Image from "next/image"; | ||
|
|
||
| import type { TermsType } from "@/types/terms-type"; | ||
|
|
||
| import { PolicyContainer } from "@/app/[locale]/policy/_containers/PolicyContainer"; | ||
| import { AsyncBoundary } from "@/components/boundary/AsyncBoundary"; | ||
| import { ROUTES } from "@/constants/routes"; | ||
| import { Link } from "@/i18n/navigation"; | ||
|
|
||
| const isTermsType = (value: string | undefined): value is TermsType => | ||
| value === "SERVICE" || value === "PRIVACY"; | ||
|
coderabbitai[bot] marked this conversation as resolved.
Outdated
|
||
|
|
||
| interface PolicyPageProps { | ||
| searchParams: Promise<{ type?: string }>; | ||
| } | ||
|
|
||
| export default async function PolicyPage({ searchParams }: PolicyPageProps) { | ||
| const { type } = await searchParams; | ||
|
|
||
| return ( | ||
| <div className="flex min-h-screen w-full flex-col items-center gap-12.5 bg-white"> | ||
| <div className="flex w-full items-center justify-between px-37 py-6.75"> | ||
| <Link href={ROUTES.LOGIN}> | ||
| <Image src={timoTextLogo} alt="Timo" width={92} height={35} /> | ||
| </Link> | ||
| </div> | ||
|
|
||
| <div className="flex w-full justify-center px-8 pb-20"> | ||
| <AsyncBoundary> | ||
| <PolicyContainer type={isTermsType(type) ? type : "SERVICE"} /> | ||
| </AsyncBoundary> | ||
| </div> | ||
| </div> | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| export interface PolicyDocumentProps { | ||
| title: string; | ||
| content: string; | ||
| } | ||
|
|
||
| export const PolicyDocument = ({ title, content }: PolicyDocumentProps) => { | ||
| return ( | ||
| <div className="flex w-full max-w-[1147px] flex-col gap-7.5"> | ||
| <div className="flex flex-col gap-5"> | ||
| <h1 className="typo-headline-b-16 text-timo-gray-900 w-full"> | ||
| {title} | ||
| </h1> | ||
| <hr className="border-timo-gray-500 w-full" /> | ||
| </div> | ||
| <p className="typo-body-m-12 text-timo-gray-900 whitespace-pre-wrap"> | ||
| {content} | ||
| </p> | ||
| </div> | ||
| ); | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| "use client"; | ||
|
|
||
| import { useSuspenseQuery } from "@tanstack/react-query"; | ||
|
|
||
| import { | ||
| getGetTermsQueryKey, | ||
| getTerms, | ||
| } from "@/api/generated/endpoints/terms/terms"; | ||
| import { termsListSchema, type TermsType } from "@/types/terms-type"; | ||
|
|
||
| export const useTerms = (type?: TermsType) => { | ||
| const params = type ? { type } : undefined; | ||
|
|
||
| return useSuspenseQuery({ | ||
| queryKey: getGetTermsQueryKey(params), | ||
| queryFn: ({ signal }) => getTerms(params, undefined, signal), | ||
| select: ({ data }) => termsListSchema.parse(data).terms, | ||
| }); | ||
| }; |
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 해당 스키마가
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
또한 그래서 혜원님은 어떻게 생각하시나요?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 아하 설명 감사합니다! ✌🏻
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TermsTypeSchema 부분만 별도로 사용하면 될 것 같아요~ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| import { z } from "zod"; | ||
|
|
||
| export const termsTypeSchema = z.enum(["SERVICE", "PRIVACY"]); | ||
|
|
||
| export const termsItemSchema = z.object({ | ||
| termsId: z.number(), | ||
| type: termsTypeSchema, | ||
| title: z.string(), | ||
| content: z.string(), | ||
| }); | ||
|
|
||
| export const termsListSchema = z.object({ | ||
| terms: z.array(termsItemSchema), | ||
| }); | ||
|
|
||
| export type TermsType = z.infer<typeof termsTypeSchema>; | ||
| export type TermsItem = z.infer<typeof termsItemSchema>; |
Uh oh!
There was an error while loading. Please reload this page.