diff --git a/src/constants/wage.ts b/src/constants/wage.ts new file mode 100644 index 0000000..dfb6685 --- /dev/null +++ b/src/constants/wage.ts @@ -0,0 +1,2 @@ +export const MIN_WAGE = 10030; +export const MAX_WAGE = 1_000_000_000; diff --git a/src/pages/ShopEditPage.tsx b/src/pages/ShopEditPage.tsx index d5fc113..38ee42a 100644 --- a/src/pages/ShopEditPage.tsx +++ b/src/pages/ShopEditPage.tsx @@ -17,6 +17,7 @@ import Select from "@/components/Select"; import TextField from "@/components/TextField"; import { ROUTES } from "@/constants/router"; import { CATEGORY_OPTIONS } from "@/constants/shopCategory"; +import { MAX_WAGE, MIN_WAGE } from "@/constants/wage"; import { useUserStore } from "@/hooks/useUserStore"; import { useModalStore } from "@/store/useModalStore"; import { extractDigits, numberCommaFormatter } from "@/utils/number"; @@ -39,7 +40,7 @@ const FIELD_LABELS: Record = { description: "가게 설명", }; -export default function ShopRegisterPage() { +export default function ShopEditPage() { const navigate = useNavigate(); const { user } = useUserStore(); const shopId = user?.shopId; @@ -59,8 +60,33 @@ export default function ShopRegisterPage() { }); useEffect(() => { - async function fetchShop() { - if (!shopId) return; + if (!user) { + openModal({ + type: "alert", + iconType: "warning", + message: "로그인 후에 이용 가능한 기능입니다.", + onClose: () => navigate(ROUTES.AUTH.SIGNIN), + }); + return; + } + + if (user.type === "employee") { + openModal({ + type: "alert", + iconType: "warning", + message: "사장님 계정으로만 이용 가능한 기능입니다.", + onClose: () => navigate(ROUTES.PROFILE.ROOT), + }); + return; + } + }, []); + + useEffect(() => { + const fetchShop = async () => { + if (!shopId) { + navigate(ROUTES.SHOP.REGISTER); + return; + } const res = await getShop(shopId); const { name, @@ -80,9 +106,9 @@ export default function ShopRegisterPage() { description, }); if (imageUrl) setImagePreview(imageUrl); - } + }; fetchShop(); - }, [shopId]); + }, [shopId, navigate]); const handleChange = ( key: keyof FormType, @@ -125,11 +151,20 @@ export default function ShopRegisterPage() { } const hourlyPay = Number(extractDigits(form.originalHourlyPay)); - if (isNaN(hourlyPay) || hourlyPay <= 0) { + const formattedMaxWage = numberCommaFormatter(MAX_WAGE); + + if (hourlyPay < MIN_WAGE) { + openModal({ + type: "alert", + iconType: "warning", + message: "시급은 최저시급 이상이어야 합니다.", + }); + return; + } else if (hourlyPay > MAX_WAGE) { openModal({ type: "alert", iconType: "warning", - message: "유효한 시급을 입력해 주세요.", + message: `시급은 ${formattedMaxWage}원 이하여야 합니다.`, }); return; } @@ -176,118 +211,120 @@ export default function ShopRegisterPage() { }; return ( -
{ - e.preventDefault(); - handleSubmit(); - }} - > -
-

- 가게 정보 -

- -
+
+ { + e.preventDefault(); + handleSubmit(); + }} + > +
+

+ 가게 정보 +

+ +
-
- handleChange("name", e.target.value)} - /> - ({ label: d, value: d }))} - value={form.address1} - onValueChange={(value) => handleChange("address1", value)} - /> - handleChange("address2", e.target.value)} - /> - { - const rawValue = e.target.value; - const digitsOnly = extractDigits(rawValue); - const formatted = digitsOnly - ? numberCommaFormatter(Number(digitsOnly)) - : ""; - handleChange("originalHourlyPay", formatted); - }} - postfix={} - /> -
-
- -
fileInputRef.current?.click()} - > - {imagePreview && ( - preview - )} -
-
- - 이미지 변경하기 +
+ handleChange("name", e.target.value)} + /> + ({ label: d, value: d }))} + value={form.address1} + onValueChange={(value) => handleChange("address1", value)} + /> + handleChange("address2", e.target.value)} + /> + { + const rawValue = e.target.value; + const digitsOnly = extractDigits(rawValue); + const formatted = digitsOnly + ? numberCommaFormatter(Number(digitsOnly)) + : ""; + handleChange("originalHourlyPay", formatted); + }} + postfix={} + /> +
+
+ +
fileInputRef.current?.click()} + > + {imagePreview && ( + preview + )} +
+
+ + 이미지 변경하기 +
+ +
+
+ handleChange("description", e.target.value)} + /> +
+
+
- -
-
- handleChange("description", e.target.value)} - /> -
-
- -
- + +
); } diff --git a/src/pages/ShopRegisterPage.tsx b/src/pages/ShopRegisterPage.tsx index b1b232d..a42a450 100644 --- a/src/pages/ShopRegisterPage.tsx +++ b/src/pages/ShopRegisterPage.tsx @@ -1,4 +1,4 @@ -import { ChangeEvent, useRef, useState } from "react"; +import { ChangeEvent, useEffect, useRef, useState } from "react"; import type { AxiosError } from "axios"; import { useNavigate } from "react-router-dom"; @@ -17,6 +17,7 @@ import Select from "@/components/Select"; import TextField from "@/components/TextField"; import { ROUTES } from "@/constants/router"; import { CATEGORY_OPTIONS } from "@/constants/shopCategory"; +import { MIN_WAGE, MAX_WAGE } from "@/constants/wage"; import { useUserStore } from "@/hooks/useUserStore"; import { useModalStore } from "@/store/useModalStore"; import { extractDigits, numberCommaFormatter } from "@/utils/number"; @@ -45,6 +46,7 @@ export default function ShopRegisterPage() { const [imagePreview, setImagePreview] = useState(null); const [imageFile, setImageFile] = useState(null); const [isSubmitting, setIsSubmitting] = useState(false); + const user = useUserStore((state) => state.user); const updateShopId = useUserStore((state) => state.updateShopId); const openModal = useModalStore((state) => state.openModal); @@ -57,6 +59,33 @@ export default function ShopRegisterPage() { description: "", }); + useEffect(() => { + if (!user) { + openModal({ + type: "alert", + iconType: "warning", + message: "로그인 후에 이용 가능한 기능입니다.", + onClose: () => navigate(ROUTES.AUTH.SIGNIN), + }); + return; + } + + if (user.type === "employee") { + openModal({ + type: "alert", + iconType: "warning", + message: "사장님 계정으로만 이용 가능한 기능입니다.", + onClose: () => navigate(ROUTES.PROFILE.ROOT), + }); + return; + } + + if (user.shopId) { + navigate(ROUTES.SHOP.EDIT); + return; + } + }, []); + const handleChange = ( key: keyof FormType, value: string | SeoulDistrict | ShopCategory, @@ -100,11 +129,20 @@ export default function ShopRegisterPage() { } const hourlyPay = Number(extractDigits(form.originalHourlyPay)); - if (isNaN(hourlyPay) || hourlyPay <= 0) { + const formattedMaxWage = numberCommaFormatter(MAX_WAGE); + + if (hourlyPay < MIN_WAGE) { openModal({ type: "alert", iconType: "warning", - message: "유효한 시급을 입력해 주세요.", + message: "시급은 최저시급 이상이어야 합니다.", + }); + return; + } else if (hourlyPay > MAX_WAGE) { + openModal({ + type: "alert", + iconType: "warning", + message: `시급은 ${formattedMaxWage}원 이하여야 합니다.`, }); return; } @@ -163,118 +201,120 @@ export default function ShopRegisterPage() { }; return ( -
{ - e.preventDefault(); - handleSubmit(); - }} - > -
-

- 가게 정보 -

- -
+
+ { + e.preventDefault(); + handleSubmit(); + }} + > +
+

+ 가게 정보 +

+ +
-
- handleChange("name", e.target.value)} - /> - ({ label: d, value: d }))} - value={form.address1} - onValueChange={(value) => handleChange("address1", value)} - /> - handleChange("address2", e.target.value)} - /> - { - const rawValue = e.target.value; - const digitsOnly = extractDigits(rawValue); - const formatted = digitsOnly - ? numberCommaFormatter(Number(digitsOnly)) - : ""; - handleChange("originalHourlyPay", formatted); - }} - postfix={} - /> -
-
- -
fileInputRef.current?.click()} - > - {imagePreview ? ( - preview - ) : ( -
- - 이미지 추가하기 -
- )} +
+ handleChange("name", e.target.value)} + /> + ({ label: d, value: d }))} + value={form.address1} + onValueChange={(value) => handleChange("address1", value)} + /> + handleChange("address2", e.target.value)} + /> + { + const rawValue = e.target.value; + const digitsOnly = extractDigits(rawValue); + const formatted = digitsOnly + ? numberCommaFormatter(Number(digitsOnly)) + : ""; + handleChange("originalHourlyPay", formatted); + }} + postfix={} + /> +
+
+ +
fileInputRef.current?.click()} + > + {imagePreview ? ( + preview + ) : ( +
+ + 이미지 추가하기 +
+ )} +
+ +
+
+ handleChange("description", e.target.value)} + /> +
+
+
- -
-
- handleChange("description", e.target.value)} - /> -
-
- -
- + +
); }