-
Notifications
You must be signed in to change notification settings - Fork 3
refactor: 호스트 대학교 표시명 영문명 기반 자동 생성 #589
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 all commits
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 |
|---|---|---|
|
|
@@ -19,18 +19,25 @@ import { normalizeImageUrlToUploadCdn } from "@/lib/utils/cdnUrl"; | |
|
|
||
| type ModalState = { open: false } | { open: true; mode: "create" } | { open: true; mode: "edit"; id: number }; | ||
|
|
||
| interface HostUniversityFormState extends HostUniversityPayload { | ||
| interface HostUniversityFormState extends Omit<HostUniversityPayload, "formatName"> { | ||
| logoImageUrl: string; | ||
| backgroundImageUrl: string; | ||
| } | ||
|
|
||
| const REQUIRED_FIELDS = ["koreanName", "englishName", "formatName", "countryCode", "regionCode"] as const; | ||
| function toFormatName(englishName: string): string { | ||
| return englishName | ||
| .trim() | ||
| .toLowerCase() | ||
| .replace(/[^a-z0-9]+/g, "_") | ||
| .replace(/^_+|_+$/g, ""); | ||
| } | ||
|
|
||
| const REQUIRED_FIELDS = ["koreanName", "englishName", "countryCode", "regionCode"] as const; | ||
|
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.
When the admin Vitest tests are run, removing Useful? React with 👍 / 👎. |
||
| const OPTIONAL_FIELDS = ["homepageUrl", "englishCourseUrl", "accommodationUrl"] as const; | ||
|
|
||
| const FIELD_LABELS: Record<string, string> = { | ||
| koreanName: "한글명", | ||
| englishName: "영문명", | ||
| formatName: "표시명", | ||
| countryCode: "국가코드", | ||
| regionCode: "권역코드", | ||
| homepageUrl: "홈페이지 URL", | ||
|
|
@@ -42,7 +49,6 @@ const FIELD_LABELS: Record<string, string> = { | |
| const EMPTY_FORM: HostUniversityFormState = { | ||
| koreanName: "", | ||
| englishName: "", | ||
| formatName: "", | ||
| logoImageUrl: "", | ||
| backgroundImageUrl: "", | ||
| countryCode: "", | ||
|
|
@@ -57,7 +63,6 @@ function detailToForm(detail: HostUniversityDetailResponse): HostUniversityFormS | |
| return { | ||
| koreanName: detail.koreanName, | ||
| englishName: detail.englishName, | ||
| formatName: detail.formatName, | ||
| logoImageUrl: detail.logoImageUrl, | ||
| backgroundImageUrl: detail.backgroundImageUrl, | ||
| countryCode: detail.countryCode, | ||
|
|
@@ -73,7 +78,7 @@ function toPayload(form: HostUniversityFormState): HostUniversityPayload { | |
| return { | ||
| koreanName: form.koreanName, | ||
| englishName: form.englishName, | ||
| formatName: form.formatName, | ||
| formatName: toFormatName(form.englishName), | ||
| countryCode: form.countryCode, | ||
| regionCode: form.regionCode, | ||
| homepageUrl: form.homepageUrl || undefined, | ||
|
|
@@ -141,7 +146,7 @@ export function HostUniversityTab() { | |
| onSuccess: async () => { | ||
| await invalidate(); | ||
| closeModal(); | ||
| toast.success("호스트 대학교를 생성했습니다."); | ||
| toast.success("해외 대학을 생성했습니다."); | ||
| }, | ||
| onError: (e: unknown) => { | ||
| const msg = e instanceof Error ? e.message : "생성에 실패했습니다."; | ||
|
|
@@ -164,7 +169,7 @@ export function HostUniversityTab() { | |
| onSuccess: async () => { | ||
| await invalidate(); | ||
| closeModal(); | ||
| toast.success("호스트 대학교를 수정했습니다."); | ||
| toast.success("해외 대학을 수정했습니다."); | ||
| }, | ||
| onError: (e: unknown) => { | ||
| const msg = e instanceof Error ? e.message : "수정에 실패했습니다."; | ||
|
|
@@ -176,7 +181,7 @@ export function HostUniversityTab() { | |
| mutationFn: (id: number) => adminApi.deleteHostUniversity(id), | ||
| onSuccess: async () => { | ||
| await invalidate(); | ||
| toast.success("호스트 대학교를 삭제했습니다."); | ||
| toast.success("해외 대학을 삭제했습니다."); | ||
| }, | ||
| onError: (e: unknown) => { | ||
| const msg = e instanceof Error ? e.message : "삭제에 실패했습니다."; | ||
|
|
@@ -266,9 +271,9 @@ export function HostUniversityTab() { | |
| <div className="space-y-4"> | ||
| <section className="rounded-xl border border-k-100 bg-k-0 p-4"> | ||
| <div className="flex items-center justify-between gap-3"> | ||
| <h2 className="typo-sb-9 text-k-900">호스트 대학교</h2> | ||
| <h2 className="typo-sb-9 text-k-900">해외 대학</h2> | ||
| <Button type="button" onClick={handleOpenCreate}> | ||
| 호스트 대학교 생성 | ||
| 해외 대학 생성 | ||
| </Button> | ||
| </div> | ||
| <form onSubmit={handleSearch} className="mt-3 flex flex-wrap gap-2"> | ||
|
|
@@ -432,9 +437,7 @@ export function HostUniversityTab() { | |
| className="relative flex max-h-[90vh] w-full max-w-lg flex-col overflow-y-auto rounded-xl bg-k-0 shadow-xl" | ||
| > | ||
| <div className="flex items-center justify-between border-b border-k-100 px-5 py-4"> | ||
| <p className="typo-sb-9 text-k-900"> | ||
| {modal.mode === "create" ? "호스트 대학교 생성" : "호스트 대학교 수정"} | ||
| </p> | ||
| <p className="typo-sb-9 text-k-900">{modal.mode === "create" ? "해외 대학 생성" : "해외 대학 수정"}</p> | ||
| <button type="button" onClick={closeModal} className="typo-regular-4 text-k-400 hover:text-k-700"> | ||
| ✕ | ||
| </button> | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win
1. 정규화 결과가 빈
formatName이 될 수 있습니다.englishName이 공백뿐이거나 정규화 과정에서 전부 제거되는 값이면 여기서formatName이""가 됩니다. 지금은 제출 전에 이 케이스를 막지 않아서 필수 API 필드에 빈 값이 실려 나갈 수 있습니다.Also applies to: 77-81
🤖 Prompt for AI Agents