From 8aaa3063306f1df955ce198f0f2627335c94c2a4 Mon Sep 17 00:00:00 2001 From: junyeokk Date: Fri, 27 Dec 2024 00:54:20 +0900 Subject: [PATCH 1/9] =?UTF-8?q?=E2=9C=A8=20feat:=20rSS=20=ED=94=8C?= =?UTF-8?q?=EB=9E=AB=ED=8F=BC=20=EC=83=81=EC=88=98=EC=99=80=20=ED=83=80?= =?UTF-8?q?=EC=9E=85=20=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/constants/rss.ts | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 client/src/constants/rss.ts diff --git a/client/src/constants/rss.ts b/client/src/constants/rss.ts new file mode 100644 index 00000000..aea8dbf1 --- /dev/null +++ b/client/src/constants/rss.ts @@ -0,0 +1,30 @@ +export const PLATFORM_TYPES = ["tistory", "velog", "medium"] as const; +export type PlatformType = (typeof PLATFORM_TYPES)[number]; + +interface Platform { + name: string; + prefix: string; + suffix: string; + placeholder: string; +} + +export const PLATFORMS: Record = { + tistory: { + name: "Tistory", + prefix: "https://", + suffix: ".tistory.com/rss", + placeholder: "블로그명", + }, + velog: { + name: "Velog", + prefix: "https://v2.velog.io/rss/@", + suffix: "", + placeholder: "사용자명", + }, + medium: { + name: "Medium", + prefix: "https://medium.com/feed/@", + suffix: "", + placeholder: "사용자명", + }, +}; From f332aa467f62920bfef9becb0172792f0ba76fca Mon Sep 17 00:00:00 2001 From: junyeokk Date: Fri, 27 Dec 2024 00:57:46 +0900 Subject: [PATCH 2/9] =?UTF-8?q?=F0=9F=92=84=20style:=20formInput=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=8A=A4=ED=83=80?= =?UTF-8?q?=EC=9D=BC=20=EA=B0=9C=EC=84=A0=20-=20input=20=ED=95=84=EB=93=9C?= =?UTF-8?q?=EC=97=90=20=EB=B0=91=EC=A4=84=20=EC=95=A0=EB=8B=88=EB=A9=94?= =?UTF-8?q?=EC=9D=B4=EC=85=98=20=EC=B6=94=EA=B0=80=20-=20=EC=A0=84?= =?UTF-8?q?=EC=B2=B4=EC=A0=81=EC=9D=B8=20=ED=85=8C=EB=91=90=EB=A6=AC?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EB=B0=91=EC=A4=84=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 --- .../components/RssRegistration/FormInput.tsx | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/client/src/components/RssRegistration/FormInput.tsx b/client/src/components/RssRegistration/FormInput.tsx index 29111655..48658848 100644 --- a/client/src/components/RssRegistration/FormInput.tsx +++ b/client/src/components/RssRegistration/FormInput.tsx @@ -16,15 +16,18 @@ export default function FormInput({ id, label, value, placeholder, type = "text" - onChange(e.target.value)} - placeholder={placeholder} - autoComplete="off" - className="flex-grow w-auto border-input focus:border-primary focus-visible:ring-primary placeholder:text-muted-foreground placeholder:text-sm" - type={type} - /> +
+ onChange(e.target.value)} + placeholder={placeholder} + autoComplete="off" + className="w-full peer border-0 border-b border-input bg-transparent focus:outline-none focus-visible:ring-0 focus-visible:ring-offset-0 rounded-none placeholder:text-muted-foreground placeholder:text-sm" + type={type} + /> +
+
); } From 4e7fc9c29b3660ae488fea1ba61834ec3285524e Mon Sep 17 00:00:00 2001 From: junyeokk Date: Fri, 27 Dec 2024 01:00:09 +0900 Subject: [PATCH 3/9] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor:=20rSS=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D=20=EB=AA=A8=EB=8B=AC=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EA=B5=AC=EC=A1=B0=20=EA=B0=9C=EC=84=A0=20?= =?UTF-8?q?-=20=EC=BB=A4=EC=8A=A4=ED=85=80=20=ED=9B=85=EC=9C=BC=EB=A1=9C?= =?UTF-8?q?=20form=20=EB=A1=9C=EC=A7=81=20=EB=B6=84=EB=A6=AC=20-=20Platfor?= =?UTF-8?q?mSelector=EC=9D=98=20RssUrlInput=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=EB=A1=9C=20URL=20=EC=9E=85=EB=A0=A5=20=EB=B0=A9?= =?UTF-8?q?=EC=8B=9D=20=EA=B0=9C=EC=84=A0=20-=20=EC=98=88=EC=8B=9C=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20UI=20=EC=A0=9C=EA=B1=B0=20-=20=ED=95=B8?= =?UTF-8?q?=EB=93=A4=EB=9F=AC=20=EB=A1=9C=EC=A7=81=20=EB=8B=A8=EC=88=9C?= =?UTF-8?q?=ED=99=94=20=EB=B0=8F=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RssRegistration/RssRegistrationModal.tsx | 176 ++++++------------ 1 file changed, 59 insertions(+), 117 deletions(-) diff --git a/client/src/components/RssRegistration/RssRegistrationModal.tsx b/client/src/components/RssRegistration/RssRegistrationModal.tsx index a1609fe6..bb3432b0 100644 --- a/client/src/components/RssRegistration/RssRegistrationModal.tsx +++ b/client/src/components/RssRegistration/RssRegistrationModal.tsx @@ -1,8 +1,9 @@ import { useState } from "react"; import FormInput from "@/components/RssRegistration/FormInput"; +import { PlatformSelector } from "@/components/RssRegistration/PlatformSelector.tsx"; +import { RssUrlInput } from "@/components/RssRegistration/RssUrlInput"; import Alert from "@/components/common/Alert"; -import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion"; import { Button } from "@/components/ui/button"; import { Dialog, @@ -12,84 +13,50 @@ import { DialogHeader, DialogTitle, } from "@/components/ui/dialog"; -import { Separator } from "@/components/ui/separator"; -import { useRegisterRss } from "@/hooks/queries/useRegisterRss"; +import { useRssRegistrationForm } from "@/hooks/common/useRssRegistrationForm.ts"; +import { useRegisterRss } from "@/hooks/queries/useRegisterRss.ts"; -import { validateRssUrl, validateName, validateEmail, validateBlogger } from "./RssValidation"; -import { useRegisterModalStore } from "@/store/useRegisterModalStrore"; -import { AlertType } from "@/types/alert"; -import { RegisterRss } from "@/types/rss"; - -const Rss = [ - { - name: "Tistory", - url: "https://{blogname}.tistory.com/rss", - }, - { - name: "Velog", - url: "https://v2.velog.io/rss/@{username}", - }, - { - name: "Medium", - url: "https://medium.com/feed/@{username}", - }, -]; +import { AlertType } from "@/types/alert.ts"; +import { RegisterRss } from "@/types/rss.ts"; export default function RssRegistrationModal({ onClose, rssOpen }: { onClose: () => void; rssOpen: boolean }) { const [alertOpen, setAlertOpen] = useState({ title: "", content: "", isOpen: false }); - const { - rssUrl, - bloggerName, - userName, - email, - setRssUrl, - setBloggerName, - setUserName, - setEmail, - setRssUrlValid, - setBloggerNameValid, - setUserNameValid, - setEmailValid, - resetInputs, - handleInputChange, - isFormValid, - } = useRegisterModalStore(); - - const onSuccess = () => { - setAlertOpen({ - title: "RSS 요청 성공!", - content: "관리자가 검토후 처리 결과를 입력해주신 메일을 통해 전달드릴 예정이에요!", - isOpen: true, - }); - }; - - const onError = () => { - setAlertOpen({ - title: "RSS 요청 실패!", - content: "입력한 정보를 확인하거나 다시 시도해주세요. 문제가 계속되면 관리자에게 문의하세요!", - isOpen: true, - }); - }; - - const { mutate } = useRegisterRss(onSuccess, onError); + const { platform, values, handlers, formState } = useRssRegistrationForm(); + const { mutate } = useRegisterRss( + () => { + setAlertOpen({ + title: "RSS 요청 성공!", + content: "관리자가 검토후 처리 결과를 입력해주신 메일을 통해 전달드릴 예정이에요!", + isOpen: true, + }); + }, + () => { + setAlertOpen({ + title: "RSS 요청 실패!", + content: "입력한 정보를 확인하거나 다시 시도해주세요. 문제가 계속되면 관리자에게 문의하세요!", + isOpen: true, + }); + } + ); const handleAlertClose = () => { setAlertOpen({ title: "", content: "", isOpen: false }); - resetInputs(); + formState.reset(); onClose(); }; + const handleRegister = () => { const data: RegisterRss = { - rssUrl: rssUrl, - blog: bloggerName, - name: userName, - email: email, + rssUrl: values.rssUrl, + blog: values.bloggerName, + name: values.userName, + email: values.email, }; - mutate(data); }; + return ( @@ -100,50 +67,41 @@ export default function RssRegistrationModal({ onClose, rssOpen }: { onClose: () 검토 및 등록에는 영업일 기준 3-5일이 소요될 수 있습니다. - - - RSS 예시 - - - - - -
- handleInputChange(value, setRssUrl, setRssUrlValid, validateRssUrl)} - placeholder="https://example.com/rss" - value={rssUrl} - /> - handleInputChange(value, setBloggerName, setBloggerNameValid, validateBlogger)} - placeholder="블로그명을 입력하세요" - value={bloggerName} - /> - handleInputChange(value, setUserName, setUserNameValid, validateName)} - placeholder="이름을 입력하세요" - value={userName} - /> - handleInputChange(value, setEmail, setEmailValid, validateEmail)} - placeholder="example@denamu.com" - value={email} - /> +
+ + + +
+ + + +
+
); } - -function InfoCard() { - return ( - <> - {Rss.map((r) => { - return ( -
- {r.name} -

{r.url}

- -
- ); - })} - - ); -} From ff8180b364d0536a076175fe5ed085f18f2411b1 Mon Sep 17 00:00:00 2001 From: junyeokk Date: Fri, 27 Dec 2024 01:05:21 +0900 Subject: [PATCH 4/9] =?UTF-8?q?=F0=9F=93=A6=20chore:=20rSS=20=EB=93=B1?= =?UTF-8?q?=EB=A1=9D=20store=20=ED=8C=8C=EC=9D=BC=EB=AA=85=20=EC=98=A4?= =?UTF-8?q?=ED=83=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/store/useRegisterModalStrore.ts | 90 ---------------------- 1 file changed, 90 deletions(-) delete mode 100644 client/src/store/useRegisterModalStrore.ts diff --git a/client/src/store/useRegisterModalStrore.ts b/client/src/store/useRegisterModalStrore.ts deleted file mode 100644 index 2d2c8308..00000000 --- a/client/src/store/useRegisterModalStrore.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { create } from "zustand"; - -interface RegisterModalState { - //Form Value - rssUrl: string; - bloggerName: string; - userName: string; - email: string; - - //Vaildation state - rssUrlValid: boolean; - bloggerNameValid: boolean; - userNameValid: boolean; - emailValid: boolean; - - //Setting Form Value - setRssUrl: (url: string) => void; - setBloggerName: (name: string) => void; - setUserName: (name: string) => void; - setEmail: (email: string) => void; - - //Setting Vaildation State - setRssUrlValid: (valid: boolean) => void; - setBloggerNameValid: (valid: boolean) => void; - setUserNameValid: (valid: boolean) => void; - setEmailValid: (valid: boolean) => void; - - //Vaildation Handler - handleInputChange: ( - value: string, - setValue: (value: string) => void, - setValid: (valid: boolean) => void, - validate: (value: string) => boolean - ) => void; - - //Other - resetInputs: () => void; - isFormValid: () => boolean; -} - -export const useRegisterModalStore = create((set, get) => ({ - // Initial Form Values - rssUrl: "", - bloggerName: "", - userName: "", - email: "", - - // Initial Validation States - rssUrlValid: false, - bloggerNameValid: false, - userNameValid: false, - emailValid: false, - - // Setters Form Values - setRssUrl: (url) => set({ rssUrl: url }), - setBloggerName: (name) => set({ bloggerName: name }), - setUserName: (name) => set({ userName: name }), - setEmail: (email) => set({ email }), - - // Setters Validation States - setRssUrlValid: (valid) => set({ rssUrlValid: valid }), - setBloggerNameValid: (valid) => set({ bloggerNameValid: valid }), - setUserNameValid: (valid) => set({ userNameValid: valid }), - setEmailValid: (valid) => set({ emailValid: valid }), - - // Reset - resetInputs: () => - set({ - rssUrl: "", - bloggerName: "", - userName: "", - email: "", - rssUrlValid: false, - bloggerNameValid: false, - userNameValid: false, - emailValid: false, - }), - - // Check Form Vaildation - isFormValid: () => { - const state = get(); - return state.rssUrlValid && state.bloggerNameValid && state.userNameValid && state.emailValid; - }, - - // Handle input change with validation - handleInputChange: (value, setValue, setValid, validate) => { - setValue(value); - setValid(validate(value)); - }, -})); From 1c8d7a28616d5bfb6d4d998c287f8abb1165f00a Mon Sep 17 00:00:00 2001 From: junyeokk Date: Fri, 27 Dec 2024 01:06:16 +0900 Subject: [PATCH 5/9] =?UTF-8?q?=F0=9F=A7=BC=20clean:=20gitkeep=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/store/.gitkeep | 0 client/src/store/useRegisterModalStore.ts | 90 +++++++++++++++++++++++ 2 files changed, 90 insertions(+) delete mode 100644 client/src/store/.gitkeep create mode 100644 client/src/store/useRegisterModalStore.ts diff --git a/client/src/store/.gitkeep b/client/src/store/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/client/src/store/useRegisterModalStore.ts b/client/src/store/useRegisterModalStore.ts new file mode 100644 index 00000000..2d2c8308 --- /dev/null +++ b/client/src/store/useRegisterModalStore.ts @@ -0,0 +1,90 @@ +import { create } from "zustand"; + +interface RegisterModalState { + //Form Value + rssUrl: string; + bloggerName: string; + userName: string; + email: string; + + //Vaildation state + rssUrlValid: boolean; + bloggerNameValid: boolean; + userNameValid: boolean; + emailValid: boolean; + + //Setting Form Value + setRssUrl: (url: string) => void; + setBloggerName: (name: string) => void; + setUserName: (name: string) => void; + setEmail: (email: string) => void; + + //Setting Vaildation State + setRssUrlValid: (valid: boolean) => void; + setBloggerNameValid: (valid: boolean) => void; + setUserNameValid: (valid: boolean) => void; + setEmailValid: (valid: boolean) => void; + + //Vaildation Handler + handleInputChange: ( + value: string, + setValue: (value: string) => void, + setValid: (valid: boolean) => void, + validate: (value: string) => boolean + ) => void; + + //Other + resetInputs: () => void; + isFormValid: () => boolean; +} + +export const useRegisterModalStore = create((set, get) => ({ + // Initial Form Values + rssUrl: "", + bloggerName: "", + userName: "", + email: "", + + // Initial Validation States + rssUrlValid: false, + bloggerNameValid: false, + userNameValid: false, + emailValid: false, + + // Setters Form Values + setRssUrl: (url) => set({ rssUrl: url }), + setBloggerName: (name) => set({ bloggerName: name }), + setUserName: (name) => set({ userName: name }), + setEmail: (email) => set({ email }), + + // Setters Validation States + setRssUrlValid: (valid) => set({ rssUrlValid: valid }), + setBloggerNameValid: (valid) => set({ bloggerNameValid: valid }), + setUserNameValid: (valid) => set({ userNameValid: valid }), + setEmailValid: (valid) => set({ emailValid: valid }), + + // Reset + resetInputs: () => + set({ + rssUrl: "", + bloggerName: "", + userName: "", + email: "", + rssUrlValid: false, + bloggerNameValid: false, + userNameValid: false, + emailValid: false, + }), + + // Check Form Vaildation + isFormValid: () => { + const state = get(); + return state.rssUrlValid && state.bloggerNameValid && state.userNameValid && state.emailValid; + }, + + // Handle input change with validation + handleInputChange: (value, setValue, setValid, validate) => { + setValue(value); + setValid(validate(value)); + }, +})); From df438ebf191d967700af49ac94b940a822f08fae Mon Sep 17 00:00:00 2001 From: junyeokk Date: Fri, 27 Dec 2024 01:07:33 +0900 Subject: [PATCH 6/9] =?UTF-8?q?=E2=9C=A8=20feat:=20rSS=20=ED=94=8C?= =?UTF-8?q?=EB=9E=AB=ED=8F=BC=20selector=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EC=B6=94=EA=B0=80=20-=20Tistory,=20Velog,=20Medium?= =?UTF-8?q?=E3=85=8D=20=ED=94=8C=EB=9E=AB=ED=8F=BC=20=EC=84=A0=ED=83=9D?= =?UTF-8?q?=EC=9D=84=20=EC=9C=84=ED=95=9C=20Tabs=20=EA=B5=AC=ED=98=84=20-?= =?UTF-8?q?=20PLATFORMS=20=EC=83=81=EC=88=98=EB=A1=9C=20=ED=94=8C=EB=9E=AB?= =?UTF-8?q?=ED=8F=BC=20=EC=82=AC=EC=9A=A9=20-=20=ED=94=8C=EB=9E=AB?= =?UTF-8?q?=ED=8F=BC=20=EB=B3=80=EA=B2=BD=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20?= =?UTF-8?q?=ED=95=B8=EB=93=A4=EB=A7=81=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RssRegistration/PlatformSelector.tsx | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 client/src/components/RssRegistration/PlatformSelector.tsx diff --git a/client/src/components/RssRegistration/PlatformSelector.tsx b/client/src/components/RssRegistration/PlatformSelector.tsx new file mode 100644 index 00000000..fdf37e6f --- /dev/null +++ b/client/src/components/RssRegistration/PlatformSelector.tsx @@ -0,0 +1,22 @@ +import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs.tsx"; + +import { PLATFORMS, PlatformType } from "@/constants/rss"; + +interface PlatformSelectorProps { + platform: PlatformType; + onPlatformChange: (platform: string) => void; +} + +export const PlatformSelector = ({ platform, onPlatformChange }: PlatformSelectorProps) => { + return ( + + + {Object.entries(PLATFORMS).map(([key, { name }]) => ( + + {name} + + ))} + + + ); +}; From c597a5e639d3513492b732c1aa4ee5abc2339e8a Mon Sep 17 00:00:00 2001 From: junyeokk Date: Fri, 27 Dec 2024 01:09:18 +0900 Subject: [PATCH 7/9] =?UTF-8?q?=E2=9C=A8=20feat:=20rSS=20URL=20=EC=9E=85?= =?UTF-8?q?=EB=A0=A5=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20-=20=ED=94=8C=EB=9E=AB=ED=8F=BC=EB=B3=84=20URL=20?= =?UTF-8?q?=ED=98=95=EC=8B=9D=EC=97=90=20=EB=A7=9E=EB=8A=94=20=EC=9E=85?= =?UTF-8?q?=EB=A0=A5=20=ED=95=84=EB=93=9C=20=EA=B5=AC=ED=98=84=20-=20prefi?= =?UTF-8?q?x,=20suffix=20=EC=9E=90=EB=8F=99=20=ED=91=9C=EC=8B=9C=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84=20-=20=EC=9E=85?= =?UTF-8?q?=EB=A0=A5=20=ED=95=84=EB=93=9C=EC=97=90=20=EB=B0=91=EC=A4=84=20?= =?UTF-8?q?=EC=95=A0=EB=8B=88=EB=A9=94=EC=9D=B4=EC=85=98=20=ED=9A=A8?= =?UTF-8?q?=EA=B3=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RssRegistration/RssUrlInput.tsx | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 client/src/components/RssRegistration/RssUrlInput.tsx diff --git a/client/src/components/RssRegistration/RssUrlInput.tsx b/client/src/components/RssRegistration/RssUrlInput.tsx new file mode 100644 index 00000000..c6e34af3 --- /dev/null +++ b/client/src/components/RssRegistration/RssUrlInput.tsx @@ -0,0 +1,40 @@ +import { Input } from "@/components/ui/input.tsx"; +import { Label } from "@/components/ui/label.tsx"; + +import { PLATFORMS, PlatformType } from "@/constants/rss"; + +interface RssUrlInputProps { + platform: PlatformType; + value: string; + onChange: (e: React.ChangeEvent) => void; + placeholder?: string; +} + +export const RssUrlInput = ({ platform, value, onChange }: RssUrlInputProps) => { + const { prefix, suffix, placeholder } = PLATFORMS[platform]; + + return ( +
+ +
+
+ {prefix} +
+
+ +
+
+ {suffix && ( +
+ {suffix} +
+ )} +
+
+ ); +}; From 8042a8ec71d715c87dd0a1c686a69ba66e0cf80f Mon Sep 17 00:00:00 2001 From: junyeokk Date: Fri, 27 Dec 2024 01:20:13 +0900 Subject: [PATCH 8/9] =?UTF-8?q?=E2=9C=A8=20feat:=20rSS=20=EB=93=B1?= =?UTF-8?q?=EB=A1=9D=20=ED=8F=BC=20=EC=BB=A4=EC=8A=A4=ED=85=80=20=ED=9B=85?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80=20-=20form=20=EC=83=81=ED=83=9C=20?= =?UTF-8?q?=EA=B4=80=EB=A6=AC=20=EB=A1=9C=EC=A7=81=20=EC=BB=A4=EC=8A=A4?= =?UTF-8?q?=ED=85=80=20=ED=9B=85=EC=9C=BC=EB=A1=9C=20=EB=B6=84=EB=A6=AC=20?= =?UTF-8?q?-=20=ED=94=8C=EB=9E=AB=ED=8F=BC=20=EC=84=A0=ED=83=9D=20?= =?UTF-8?q?=EB=B0=8F=20URL=20=EA=B5=AC=EC=84=B1=20=EB=A1=9C=EC=A7=80=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20-=20=EC=9E=85=EB=A0=A5=EA=B0=92=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=20=EB=B0=8F=20=ED=95=B8=EB=93=A4=EB=9F=AC=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=ED=86=B5=ED=95=A9=20-=20values,=20handler?= =?UTF-8?q?s,=20formState=20=EA=B0=9D=EC=B2=B4=EB=A1=9C=20=EC=9D=91?= =?UTF-8?q?=EC=A7=91=EB=8F=84=20=ED=96=A5=EC=83=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hooks/common/useRssRegistrationForm.ts | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 client/src/hooks/common/useRssRegistrationForm.ts diff --git a/client/src/hooks/common/useRssRegistrationForm.ts b/client/src/hooks/common/useRssRegistrationForm.ts new file mode 100644 index 00000000..625a5119 --- /dev/null +++ b/client/src/hooks/common/useRssRegistrationForm.ts @@ -0,0 +1,61 @@ +import { useState } from "react"; + +import { + validateRssUrl, + validateName, + validateEmail, + validateBlogger, +} from "@/components/RssRegistration/RssValidation"; + +import { PLATFORMS, PlatformType } from "@/constants/rss"; + +import { useRegisterModalStore } from "@/store/useRegisterModalStore"; + +export const useRssRegistrationForm = () => { + const [platform, setPlatform] = useState("tistory"); + const store = useRegisterModalStore(); + + const handlePlatformChange = (newPlatform: string) => { + setPlatform(newPlatform as PlatformType); + store.handleInputChange("", store.setRssUrl, store.setRssUrlValid, validateRssUrl); + }; + + const handleUsernameChange = (e: React.ChangeEvent) => { + const username = e.target.value; + const { prefix, suffix } = PLATFORMS[platform]; + const fullUrl = `${prefix}${username}${suffix}`; + store.handleInputChange(fullUrl, store.setRssUrl, store.setRssUrlValid, validateRssUrl); + }; + + const getUsernameFromUrl = () => { + const { prefix, suffix } = PLATFORMS[platform]; + return store.rssUrl.replace(prefix, "").replace(suffix, ""); + }; + + return { + platform, + values: { + rssUrl: store.rssUrl, + bloggerName: store.bloggerName, + userName: store.userName, + email: store.email, + urlUsername: getUsernameFromUrl(), + }, + + handlers: { + handlePlatformChange, + handleUsernameChange, + handleBloggerName: (value: string) => + store.handleInputChange(value, store.setBloggerName, store.setBloggerNameValid, validateBlogger), + handleUserName: (value: string) => + store.handleInputChange(value, store.setUserName, store.setUserNameValid, validateName), + handleEmail: (value: string) => + store.handleInputChange(value, store.setEmail, store.setEmailValid, validateEmail), + }, + + formState: { + isValid: store.isFormValid(), + reset: store.resetInputs, + }, + }; +}; From 13c893fadf208ef672d2e8b0a7bf88d1f809589e Mon Sep 17 00:00:00 2001 From: junyeokk Date: Fri, 27 Dec 2024 02:06:25 +0900 Subject: [PATCH 9/9] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor:=20=EA=B0=9C?= =?UTF-8?q?=EC=9D=B8=20=EB=B8=94=EB=A1=9C=EA=B7=B8=20=ED=83=AD=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/RssRegistration/PlatformSelector.tsx | 2 +- client/src/constants/rss.ts | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/client/src/components/RssRegistration/PlatformSelector.tsx b/client/src/components/RssRegistration/PlatformSelector.tsx index fdf37e6f..0877e728 100644 --- a/client/src/components/RssRegistration/PlatformSelector.tsx +++ b/client/src/components/RssRegistration/PlatformSelector.tsx @@ -10,7 +10,7 @@ interface PlatformSelectorProps { export const PlatformSelector = ({ platform, onPlatformChange }: PlatformSelectorProps) => { return ( - + {Object.entries(PLATFORMS).map(([key, { name }]) => ( {name} diff --git a/client/src/constants/rss.ts b/client/src/constants/rss.ts index aea8dbf1..817c7f42 100644 --- a/client/src/constants/rss.ts +++ b/client/src/constants/rss.ts @@ -1,4 +1,4 @@ -export const PLATFORM_TYPES = ["tistory", "velog", "medium"] as const; +export const PLATFORM_TYPES = ["tistory", "velog", "medium", "personal_blog"] as const; export type PlatformType = (typeof PLATFORM_TYPES)[number]; interface Platform { @@ -13,7 +13,7 @@ export const PLATFORMS: Record = { name: "Tistory", prefix: "https://", suffix: ".tistory.com/rss", - placeholder: "블로그명", + placeholder: "서브도메인", }, velog: { name: "Velog", @@ -27,4 +27,10 @@ export const PLATFORMS: Record = { suffix: "", placeholder: "사용자명", }, + personal_blog: { + name: "개인 블로그", + prefix: "https://", + suffix: "", + placeholder: "블로그 주소", + }, };