summaryrefslogtreecommitdiff
path: root/lib/admin-users
diff options
context:
space:
mode:
authordujinkim <dujin.kim@dtsolution.co.kr>2025-08-29 05:00:16 +0000
committerdujinkim <dujin.kim@dtsolution.co.kr>2025-08-29 05:00:16 +0000
commit69648a25c2ac62bbc3354b3a0e41abc932273b7c (patch)
treee64c912678cf061e22ae1b8e68c320d9245ad3da /lib/admin-users
parentb917cb0d43b4b4524e931b75ff971e5620d52ac1 (diff)
(최겸) vendor 유저 등록 시 국가 설정에 따른 국가코드 placeholder 등록
Diffstat (limited to 'lib/admin-users')
-rw-r--r--lib/admin-users/table/add-ausers-dialog.tsx135
-rw-r--r--lib/admin-users/table/update-auser-sheet.tsx149
2 files changed, 278 insertions, 6 deletions
diff --git a/lib/admin-users/table/add-ausers-dialog.tsx b/lib/admin-users/table/add-ausers-dialog.tsx
index 3b29adcf..5ed9b8cc 100644
--- a/lib/admin-users/table/add-ausers-dialog.tsx
+++ b/lib/admin-users/table/add-ausers-dialog.tsx
@@ -48,6 +48,76 @@ import { cn } from "@/lib/utils"
import { toast } from "sonner"
import { Vendor } from "@/db/schema/vendors"
import { FormDescription } from "@/components/ui/form"
+import { ScrollArea } from "@/components/ui/scroll-area"
+
+// i18n-iso-countries import
+import i18nIsoCountries from "i18n-iso-countries"
+import enLocale from "i18n-iso-countries/langs/en.json"
+import koLocale from "i18n-iso-countries/langs/ko.json"
+
+i18nIsoCountries.registerLocale(enLocale)
+i18nIsoCountries.registerLocale(koLocale)
+
+const locale = "ko"
+const countryMap = i18nIsoCountries.getNames(locale, { select: "official" })
+const countryArray = Object.entries(countryMap).map(([code, label]) => ({
+ code,
+ label,
+}))
+
+// Sort countries to put Korea first, then alphabetically
+const sortedCountryArray = [...countryArray].sort((a, b) => {
+ if (a.code === "KR") return -1;
+ if (b.code === "KR") return 1;
+ return a.label.localeCompare(b.label);
+});
+
+// Add English names for Korean locale
+const enhancedCountryArray = sortedCountryArray.map(country => ({
+ ...country,
+ label: locale === "ko" && country.code === "KR"
+ ? "대한민국 (South Korea)"
+ : country.label
+}));
+
+// Comprehensive list of country dial codes
+const countryDialCodes: { [key: string]: string } = {
+ AF: "+93", AL: "+355", DZ: "+213", AS: "+1-684", AD: "+376", AO: "+244",
+ AI: "+1-264", AG: "+1-268", AR: "+54", AM: "+374", AW: "+297", AU: "+61",
+ AT: "+43", AZ: "+994", BS: "+1-242", BH: "+973", BD: "+880", BB: "+1-246",
+ BY: "+375", BE: "+32", BZ: "+501", BJ: "+229", BM: "+1-441", BT: "+975",
+ BO: "+591", BA: "+387", BW: "+267", BR: "+55", BN: "+673", BG: "+359",
+ BF: "+226", BI: "+257", KH: "+855", CM: "+237", CA: "+1", CV: "+238",
+ KY: "+1-345", CF: "+236", TD: "+235", CL: "+56", CN: "+86", CO: "+57",
+ KM: "+269", CG: "+242", CD: "+243", CR: "+506", CI: "+225", HR: "+385",
+ CU: "+53", CY: "+357", CZ: "+420", DK: "+45", DJ: "+253", DM: "+1-767",
+ DO: "+1-809", EC: "+593", EG: "+20", SV: "+503", GQ: "+240", ER: "+291",
+ EE: "+372", ET: "+251", FJ: "+679", FI: "+358", FR: "+33", GA: "+241",
+ GM: "+220", GE: "+995", DE: "+49", GH: "+233", GR: "+30", GD: "+1-473",
+ GT: "+502", GN: "+224", GW: "+245", GY: "+592", HT: "+509", HN: "+504",
+ HK: "+852", HU: "+36", IS: "+354", IN: "+91", ID: "+62", IR: "+98",
+ IQ: "+964", IE: "+353", IL: "+972", IT: "+39", JM: "+1-876", JP: "+81",
+ JO: "+962", KZ: "+7", KE: "+254", KI: "+686", KR: "+82", KW: "+965",
+ KG: "+996", LA: "+856", LV: "+371", LB: "+961", LS: "+266", LR: "+231",
+ LY: "+218", LI: "+423", LT: "+370", LU: "+352", MK: "+389", MG: "+261",
+ MW: "+265", MY: "+60", MV: "+960", ML: "+223", MT: "+356", MH: "+692",
+ MR: "+222", MU: "+230", MX: "+52", FM: "+691", MD: "+373", MC: "+377",
+ MN: "+976", ME: "+382", MA: "+212", MZ: "+258", MM: "+95", NA: "+264",
+ NR: "+674", NP: "+977", NL: "+31", NZ: "+64", NI: "+505", NE: "+227",
+ NG: "+234", NU: "+683", KP: "+850", NO: "+47", OM: "+968", PK: "+92",
+ PW: "+680", PS: "+970", PA: "+507", PG: "+675", PY: "+595", PE: "+51",
+ PH: "+63", PL: "+48", PT: "+351", PR: "+1-787", QA: "+974", RO: "+40",
+ RU: "+7", RW: "+250", KN: "+1-869", LC: "+1-758", VC: "+1-784", WS: "+685",
+ SM: "+378", ST: "+239", SA: "+966", SN: "+221", RS: "+381", SC: "+248",
+ SL: "+232", SG: "+65", SK: "+421", SI: "+386", SB: "+677", SO: "+252",
+ ZA: "+27", SS: "+211", ES: "+34", LK: "+94", SD: "+249", SR: "+597",
+ SZ: "+268", SE: "+46", CH: "+41", SY: "+963", TW: "+886", TJ: "+992",
+ TZ: "+255", TH: "+66", TL: "+670", TG: "+228", TK: "+690", TO: "+676",
+ TT: "+1-868", TN: "+216", TR: "+90", TM: "+993", TV: "+688", UG: "+256",
+ UA: "+380", AE: "+971", GB: "+44", US: "+1", UY: "+598", UZ: "+998",
+ VU: "+678", VA: "+39-06", VE: "+58", VN: "+84", YE: "+967", ZM: "+260",
+ ZW: "+263"
+};
const languageOptions = [
{ value: "ko", label: "한국어" },
@@ -63,8 +133,9 @@ const validatePhoneNumber = (phone: string): boolean => {
};
// Get phone placeholder
-const getPhonePlaceholder = (): string => {
- return "+82-10-1234-5678";
+const getPhonePlaceholder = (countryCode: string | undefined) => {
+ if (!countryCode || !countryDialCodes[countryCode]) return "전화번호";
+ return `${countryDialCodes[countryCode]} 전화번호`;
};
// Get phone description
@@ -193,6 +264,64 @@ export function AddUserDialog() {
)}
/>
+ {/* 국가 선택 */}
+ <FormField
+ control={form.control}
+ name="country"
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>Country</FormLabel>
+ <Popover>
+ <PopoverTrigger asChild>
+ <FormControl>
+ <Button
+ variant="outline"
+ role="combobox"
+ className={cn(
+ "w-full justify-between",
+ !field.value && "text-muted-foreground"
+ )}
+ >
+ {field.value
+ ? i18nIsoCountries.getName(field.value, "ko")
+ : "국가를 선택하세요"}
+ <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
+ </Button>
+ </FormControl>
+ </PopoverTrigger>
+ <PopoverContent className="w-full p-0">
+ <Command>
+ <CommandInput placeholder="국가를 검색하세요..." />
+ <CommandEmpty>국가를 찾을 수 없습니다.</CommandEmpty>
+ <CommandGroup>
+ <ScrollArea className="h-72">
+ {Object.entries(i18nIsoCountries.getNames("ko")).map(([code, name]) => (
+ <CommandItem
+ key={code}
+ value={`${code} ${name}`}
+ onSelect={() => {
+ form.setValue("country", code);
+ }}
+ >
+ <Check
+ className={cn(
+ "mr-2 h-4 w-4",
+ code === field.value ? "opacity-100" : "opacity-0"
+ )}
+ />
+ {name}
+ </CommandItem>
+ ))}
+ </ScrollArea>
+ </CommandGroup>
+ </Command>
+ </PopoverContent>
+ </Popover>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
+
{/* 전화번호 - 새로 추가 */}
<FormField
control={form.control}
@@ -202,7 +331,7 @@ export function AddUserDialog() {
<FormLabel>Phone Number</FormLabel>
<FormControl>
<Input
- placeholder={getPhonePlaceholder()}
+ placeholder={getPhonePlaceholder(form.watch("country"))}
{...field}
className={cn(
field.value && !validatePhoneNumber(field.value) && "border-red-500"
diff --git a/lib/admin-users/table/update-auser-sheet.tsx b/lib/admin-users/table/update-auser-sheet.tsx
index fbd3a42f..d84d21f3 100644
--- a/lib/admin-users/table/update-auser-sheet.tsx
+++ b/lib/admin-users/table/update-auser-sheet.tsx
@@ -40,6 +40,90 @@ import { cn } from "@/lib/utils"
import { type UserView } from "@/db/schema/users"
import { updateUserSchema, type UpdateUserSchema } from "@/lib/admin-users/validations"
import { modifiUser } from "@/lib/admin-users/service"
+import {
+ Popover,
+ PopoverTrigger,
+ PopoverContent,
+} from "@/components/ui/popover"
+import {
+ Command,
+ CommandInput,
+ CommandList,
+ CommandGroup,
+ CommandItem,
+ CommandEmpty,
+} from "@/components/ui/command"
+import { Check, ChevronsUpDown } from "lucide-react"
+import { ScrollArea } from "@/components/ui/scroll-area"
+
+// i18n-iso-countries import
+import i18nIsoCountries from "i18n-iso-countries"
+import enLocale from "i18n-iso-countries/langs/en.json"
+import koLocale from "i18n-iso-countries/langs/ko.json"
+
+i18nIsoCountries.registerLocale(enLocale)
+i18nIsoCountries.registerLocale(koLocale)
+
+const locale = "ko"
+const countryMap = i18nIsoCountries.getNames(locale, { select: "official" })
+const countryArray = Object.entries(countryMap).map(([code, label]) => ({
+ code,
+ label,
+}))
+
+// Sort countries to put Korea first, then alphabetically
+const sortedCountryArray = [...countryArray].sort((a, b) => {
+ if (a.code === "KR") return -1;
+ if (b.code === "KR") return 1;
+ return a.label.localeCompare(b.label);
+});
+
+// Add English names for Korean locale
+const enhancedCountryArray = sortedCountryArray.map(country => ({
+ ...country,
+ label: locale === "ko" && country.code === "KR"
+ ? "대한민국 (South Korea)"
+ : country.label
+}));
+
+// Comprehensive list of country dial codes
+const countryDialCodes: { [key: string]: string } = {
+ AF: "+93", AL: "+355", DZ: "+213", AS: "+1-684", AD: "+376", AO: "+244",
+ AI: "+1-264", AG: "+1-268", AR: "+54", AM: "+374", AW: "+297", AU: "+61",
+ AT: "+43", AZ: "+994", BS: "+1-242", BH: "+973", BD: "+880", BB: "+1-246",
+ BY: "+375", BE: "+32", BZ: "+501", BJ: "+229", BM: "+1-441", BT: "+975",
+ BO: "+591", BA: "+387", BW: "+267", BR: "+55", BN: "+673", BG: "+359",
+ BF: "+226", BI: "+257", KH: "+855", CM: "+237", CA: "+1", CV: "+238",
+ KY: "+1-345", CF: "+236", TD: "+235", CL: "+56", CN: "+86", CO: "+57",
+ KM: "+269", CG: "+242", CD: "+243", CR: "+506", CI: "+225", HR: "+385",
+ CU: "+53", CY: "+357", CZ: "+420", DK: "+45", DJ: "+253", DM: "+1-767",
+ DO: "+1-809", EC: "+593", EG: "+20", SV: "+503", GQ: "+240", ER: "+291",
+ EE: "+372", ET: "+251", FJ: "+679", FI: "+358", FR: "+33", GA: "+241",
+ GM: "+220", GE: "+995", DE: "+49", GH: "+233", GR: "+30", GD: "+1-473",
+ GT: "+502", GN: "+224", GW: "+245", GY: "+592", HT: "+509", HN: "+504",
+ HK: "+852", HU: "+36", IS: "+354", IN: "+91", ID: "+62", IR: "+98",
+ IQ: "+964", IE: "+353", IL: "+972", IT: "+39", JM: "+1-876", JP: "+81",
+ JO: "+962", KZ: "+7", KE: "+254", KI: "+686", KR: "+82", KW: "+965",
+ KG: "+996", LA: "+856", LV: "+371", LB: "+961", LS: "+266", LR: "+231",
+ LY: "+218", LI: "+423", LT: "+370", LU: "+352", MK: "+389", MG: "+261",
+ MW: "+265", MY: "+60", MV: "+960", ML: "+223", MT: "+356", MH: "+692",
+ MR: "+222", MU: "+230", MX: "+52", FM: "+691", MD: "+373", MC: "+377",
+ MN: "+976", ME: "+382", MA: "+212", MZ: "+258", MM: "+95", NA: "+264",
+ NR: "+674", NP: "+977", NL: "+31", NZ: "+64", NI: "+505", NE: "+227",
+ NG: "+234", NU: "+683", KP: "+850", NO: "+47", OM: "+968", PK: "+92",
+ PW: "+680", PS: "+970", PA: "+507", PG: "+675", PY: "+595", PE: "+51",
+ PH: "+63", PL: "+48", PT: "+351", PR: "+1-787", QA: "+974", RO: "+40",
+ RU: "+7", RW: "+250", KN: "+1-869", LC: "+1-758", VC: "+1-784", WS: "+685",
+ SM: "+378", ST: "+239", SA: "+966", SN: "+221", RS: "+381", SC: "+248",
+ SL: "+232", SG: "+65", SK: "+421", SI: "+386", SB: "+677", SO: "+252",
+ ZA: "+27", SS: "+211", ES: "+34", LK: "+94", SD: "+249", SR: "+597",
+ SZ: "+268", SE: "+46", CH: "+41", SY: "+963", TW: "+886", TJ: "+992",
+ TZ: "+255", TH: "+66", TL: "+670", TG: "+228", TK: "+690", TO: "+676",
+ TT: "+1-868", TN: "+216", TR: "+90", TM: "+993", TV: "+688", UG: "+256",
+ UA: "+380", AE: "+971", GB: "+44", US: "+1", UY: "+598", UZ: "+998",
+ VU: "+678", VA: "+39-06", VE: "+58", VN: "+84", YE: "+967", ZM: "+260",
+ ZW: "+263"
+};
export interface UpdateAuserSheetProps
extends React.ComponentPropsWithRef<typeof Sheet> {
@@ -60,8 +144,9 @@ const validatePhoneNumber = (phone: string): boolean => {
};
// Get phone placeholder
-const getPhonePlaceholder = (): string => {
- return "+82-10-1234-5678";
+const getPhonePlaceholder = (countryCode: string | undefined) => {
+ if (!countryCode || !countryDialCodes[countryCode]) return "전화번호";
+ return `${countryDialCodes[countryCode]} 전화번호`;
};
// Get phone description
@@ -171,6 +256,64 @@ export function UpdateAuserSheet({ user, ...props }: UpdateAuserSheetProps) {
)}
/>
+ {/* 국가 선택 */}
+ <FormField
+ control={form.control}
+ name="country"
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>Country</FormLabel>
+ <Popover>
+ <PopoverTrigger asChild>
+ <FormControl>
+ <Button
+ variant="outline"
+ role="combobox"
+ className={cn(
+ "w-full justify-between",
+ !field.value && "text-muted-foreground"
+ )}
+ >
+ {field.value
+ ? i18nIsoCountries.getName(field.value, "ko")
+ : "국가를 선택하세요"}
+ <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
+ </Button>
+ </FormControl>
+ </PopoverTrigger>
+ <PopoverContent className="w-full p-0">
+ <Command>
+ <CommandInput placeholder="국가를 검색하세요..." />
+ <CommandEmpty>국가를 찾을 수 없습니다.</CommandEmpty>
+ <CommandGroup>
+ <ScrollArea className="h-72">
+ {Object.entries(i18nIsoCountries.getNames("ko")).map(([code, name]) => (
+ <CommandItem
+ key={code}
+ value={`${code} ${name}`}
+ onSelect={() => {
+ form.setValue("country", code);
+ }}
+ >
+ <Check
+ className={cn(
+ "mr-2 h-4 w-4",
+ code === field.value ? "opacity-100" : "opacity-0"
+ )}
+ />
+ {name}
+ </CommandItem>
+ ))}
+ </ScrollArea>
+ </CommandGroup>
+ </Command>
+ </PopoverContent>
+ </Popover>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
+
{/* 전화번호 - 새로 추가 */}
<FormField
control={form.control}
@@ -180,7 +323,7 @@ export function UpdateAuserSheet({ user, ...props }: UpdateAuserSheetProps) {
<FormLabel>Phone Number</FormLabel>
<FormControl>
<Input
- placeholder={getPhonePlaceholder()}
+ placeholder={getPhonePlaceholder(form.watch("country"))}
{...field}
className={cn(
field.value && !validatePhoneNumber(field.value) && "border-red-500"