dm_new: 수요처등록수정

This commit is contained in:
2026-02-20 17:31:46 +09:00
parent b0baff824b
commit 46c1d33750
10 changed files with 944 additions and 133 deletions
+26 -42
View File
@@ -3,9 +3,8 @@
import { useEffect, useId, useState } from "react";
import { useRouter } from "next/navigation";
import { useDmStore } from "@/app/store";
import type { DemandCompType } from "@common/business_components/ui/sdmInsertForm/form";
import { sha512 } from 'js-sha512';
import toast from "react-hot-toast";
import { Button, Input } from "@common/components";
type LoginModalProps = {
open: boolean;
@@ -18,7 +17,7 @@ type FieldKey = "bizNo" | "workerNo" | "pw";
const REGISTER_HREF = "/apply/dmdco";
function isBizNoValid(v: string) {
return /^\d{3}-\d{2}-\d{5}$/.test(v);
return /^\d{10}$/.test(v);
}
function inputCls(opts: { hasError?: boolean; disabled?: boolean }) {
@@ -31,6 +30,7 @@ function inputCls(opts: { hasError?: boolean; disabled?: boolean }) {
export default function LoginModal({ open, onClose, onSuccess }: LoginModalProps) {
const titleId = useId();
const router = useRouter();
const { actionLogin } = useDmStore((state) => state);
const [bizNo, setBizNo] = useState(""); // 사업자번호
const [workerNo, setWorkerNo] = useState(""); // 종사업자번호
@@ -67,8 +67,9 @@ export default function LoginModal({ open, onClose, onSuccess }: LoginModalProps
if (noWorker) {
setWorkerNo("");
setErrors((p) => {
const { workerNo: _unused, ...rest } = p;
return rest;
const nextErrors = { ...p };
delete nextErrors.workerNo;
return nextErrors;
});
}
}, [noWorker]);
@@ -84,11 +85,15 @@ export default function LoginModal({ open, onClose, onSuccess }: LoginModalProps
if (!b) next.bizNo = "사업자등록번호를 입력해주세요.";
else if (!isBizNoValid(b))
next.bizNo = "사업자등록번호 형식이 올바르지 않습니다. (예: 123-45-67890)";
next.bizNo = "사업자등록번호는 10자리 숫자만 입력 가능합니다.";
if (!noWorker && !w) next.workerNo = "종사자등록번호를 입력해주세요.";
if (!noWorker && !w) next.workerNo = "종사업자등록번호를 입력해주세요.";
else if (!noWorker && !/^\d{4}$/.test(w))
next.workerNo = "종사업자등록번호는 4자리 숫자만 입력 가능합니다.";
if (!p) next.pw = "비밀번호를 입력해주세요.";
else if (p.length < 8) next.pw = "비밀번호는 8자 이상 입력해주세요.";
else if (p.length > 16) next.pw = "비밀번호는 16자 이내로 입력해주세요.";
setErrors(next);
return next;
@@ -126,44 +131,24 @@ export default function LoginModal({ open, onClose, onSuccess }: LoginModalProps
try {
setSubmitting(true);
const param = {
dmdInfoId: bizNo + (noWorker ? "0000" : workerNo), // 종사업자번호 해당없음 "0000"으로 채움
dmdAplyPswd: sha512.hex(pw),
};
await actionLogin(param as DemandCompType);
// ✅ TODO: 실제 로그인 API 연결 지점
// const res = await fetch("/api/demand/login", {
// method: "POST",
// headers: { "Content-Type": "application/json" },
// body: JSON.stringify({ bizNo, workerNo: noWorker ? null : workerNo, pw }),
// });
// if (!res.ok) { ... }
// const data = await res.json();
// onSuccess?.({ userName: data.userName, accessToken: data.token });
// --- 데모: 비밀번호가 "1234"면 성공 처리(원하면 제거) ---
const serverOk = pw.trim() === "1234";
if (!serverOk) {
setErrors((p) => ({ ...p, pw: "잘못된 비밀번호입니다. (데모: 1234 입력 시 성공)" }));
setTouched((p) => ({ ...p, pw: true }));
return;
const sessionUser = sessionStorage.getItem("user");
if (sessionUser) {
const parsed = JSON.parse(sessionUser) as { dmdCoNm?: string };
onSuccess?.({ userName: parsed.dmdCoNm ?? "수요처" });
onClose();
router.refresh();
}
onSuccess?.({ userName: "마인드원", accessToken: "demo_token" });
onClose();
router.refresh();
} finally {
setSubmitting(false);
}
};
// const handleLogin = () => {
// const data = form.getValues();
// const passwordStr = sha512.hex(data.password)
// data.dmdAplyPswd = passwordStr;
// const param = {
// dmdInfoId: data.dmdInfoId + (isBznmTotNoDisabled ? '0000' : data.bznmTotNo),
// dmdAplyPswd: data.dmdAplyPswd,
// }
// actionLogin(param as unknown as DemandCompType);
// };
const initPassword = () => {
alert("관리자(031-0000-0000)에게 비밀번호 초기화 요청을 유선으로 하시기 바랍니다.");
}
@@ -192,7 +177,7 @@ export default function LoginModal({ open, onClose, onSuccess }: LoginModalProps
type="button"
onClick={onClose}
aria-label="닫기"
className="absolute right-8 top-8 h-10 w-10 grid place-items-center rounded-full hover:bg-gray-100"
className="absolute right-8 top-8 z-40 h-10 w-10 grid place-items-center rounded-full hover:bg-gray-100"
>
<span className="text-2xl leading-none">×</span>
</button>
@@ -219,7 +204,7 @@ export default function LoginModal({ open, onClose, onSuccess }: LoginModalProps
<input
value={formatBusinessNumber(bizNo)}
onChange={(e) => {
setBizNo(e.target.value);
setBizNo(e.target.value.replace(/\D/g, "").slice(0, 10));
setErrors((p) => ({ ...p, bizNo: undefined }));
}}
onBlur={() => {
@@ -257,7 +242,7 @@ export default function LoginModal({ open, onClose, onSuccess }: LoginModalProps
<input
value={workerNo}
onChange={(e) => {
setWorkerNo(e.target.value);
setWorkerNo(e.target.value.replace(/\D/g, "").slice(0, 4));
setErrors((p) => ({ ...p, workerNo: undefined }));
}}
onBlur={() => {
@@ -315,7 +300,6 @@ export default function LoginModal({ open, onClose, onSuccess }: LoginModalProps
? "bg-sky-300 cursor-not-allowed"
: "bg-sky-500 hover:bg-sky-600 active:bg-sky-700",
].join(" ")}
onClick={handleLogin}
>
{submitting ? "로그인 중..." : "로그인"}
</button>
+5 -3
View File
@@ -5,8 +5,8 @@ import { usePathname, useRouter } from "next/navigation";
import { useEffect, useMemo, useState } from "react";
import LoginModal from "@/components/LoginModal";
import { fetchAnonymousMenu, isMenuActive, type MenuItem } from "@/app/store/common";
import { useDmStore } from "@/app/store";
// const REGISTER_HREF = "/reuse/apply/place";
const LS_TOKEN_KEY = "reuse_accessToken";
const LS_USER_KEY = "reuse_userName";
@@ -21,6 +21,7 @@ export default function TopNav() {
const router = useRouter();
const pathname = usePathname();
const { actionLogout } = useDmStore((state) => state);
const [loginOpen, setLoginOpen] = useState(false);
const [userName, setUserName] = useState<string | null>(null);
const [topMenus, setTopMenus] = useState<MenuItem[]>([]);
@@ -68,11 +69,12 @@ export default function TopNav() {
const openLogin = () => setLoginOpen(true);
const logout = () => {
const logout = async () => {
localStorage.removeItem(LS_TOKEN_KEY);
localStorage.removeItem(LS_USER_KEY);
setUserName(null);
router.refresh();
await actionLogout();
router.push("/main");
};
return (