diff --git a/prisma/schema.prisma b/prisma/schema.prisma index e11395a..3a511a3 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -19,73 +19,39 @@ model User { updated_at DateTime @updatedAt } -// 지붕재 적합성 정보 model MS_SUITABLE { - //일련번호 id Int @id @default(autoincrement()) - //제품명 product_name String @db.VarChar(200) - //제조업체명 manufacturer String? @db.VarChar(200) - //지붕재 roof_material String? @db.VarChar(100) - //금구형태(쇠붙이형) shape String? @db.VarChar(200) - //지지 기와 support_roof_tile String? @db.VarChar(2) - //지지 기와 메모 support_roof_tile_memo String? @db.VarChar(500) - //지지 금구 support_roof_bracket String? @db.VarChar(200) - //지지 금구 메모 support_roof_bracket_memo String? @db.VarChar(500) - //yg 앵커 yg_anchor String? @db.VarChar(200) - //yg 앵커 메모 yg_anchor_memo String? @db.VarChar(500) - //rg 지붕판 rg_roof_tile_part String? @db.VarChar(200) - //rg 지붕판 메모 rg_roof_tile_part_memo String? @db.VarChar(500) - //다이도헌트 지지 기와2 dido_hunt_support_tile_2 String? @db.VarChar(200) - //다이도헌트 지지 기와2 메모 dido_hunt_support_tile_2_memo String? @db.VarChar(500) - //타카시마 파워 베이스 takashima_power_base String? @db.VarChar(200) - //타카시마 파워 베이스 메모 takashima_power_base_memo String? @db.VarChar(500) - //타카시마용 금구 takashima_tile_bracket String? @db.VarChar(200) - //타카시마용 금구 메모 takashima_tile_bracket_memo String? @db.VarChar(500) - //슬레이트 금구4 slate_bracket_4 String? @db.VarChar(200) - //슬레이트 금구4 메모 slate_bracket_4_memo String? @db.VarChar(500) - //슬레이트 판금 금구(슬레이트, 싱글) slate_single_metal_bracket String? @db.VarChar(200) - //슬레이트 판금 금구 메모(슬레이트, 싱글) slate_single_metal_bracket_memo String? @db.VarChar(500) - //다이도헌트 짧은 트랙4 dido_hunt_short_rack_4 String? @db.VarChar(200) - //다이도헌트 짧은 트랙4 메모 dido_hunt_short_rack_4_memo String? @db.VarChar(500) - //타카시마 슬레이트 금구 takashima_slate_bracket_slate_single String? @db.VarChar(200) - //타카시마 슬레이트 금구 메모 takashima_slate_bracket_slate_single_memo String? @db.VarChar(500) - //df 판금 금구 df_metal_bracket String? @db.VarChar(200) - //df 판금 금구 메모 df_metal_bracket_memo String? @db.VarChar(500) - //슬레이트 판금 금구(금속 지붕) slate_metal_bracket String? @db.VarChar(200) - //슬레이트 판금 금구(금속 지붕) 메모 slate_metal_bracket_memo String? @db.VarChar(500) - //타카시마 슬레이트 금구(금속 지붕) takashima_slate_bracket_metal_roof String? @db.VarChar(200) - //타카시마 슬레이트 금구(금속 지붕) 메모 takashima_slate_bracket_metal_roof_memo String? @db.VarChar(500) created_at DateTime @default(now()) updated_at DateTime @updatedAt @@ -151,3 +117,63 @@ model SD_SERVEY_SALES_DETAIL_INFO { basic_info_id Int @unique basic_info SD_SERVEY_SALES_BASIC_INFO @relation(fields: [basic_info_id], references: [id]) } + +model BC_COMM_H { + HEAD_CD String @id(map: "PK_BC_COMM_H") @db.NVarChar(6) + HEAD_ID String @db.NVarChar(100) + HEAD_NM String @db.NVarChar(100) + HEAD_JP String @db.NVarChar(100) + HEAD_4TH String @db.NVarChar(100) + REF_CHR1 String @db.NVarChar(100) + REF_CHR2 String @db.NVarChar(100) + REF_CHR3 String @db.NVarChar(100) + REF_CHR4 String @db.NVarChar(100) + REF_CHR5 String @db.NVarChar(100) + REF_NUM1 String @db.NVarChar(100) + REF_NUM2 String @db.NVarChar(100) + REF_NUM3 String @db.NVarChar(100) + REF_NUM4 String @db.NVarChar(100) + REF_NUM5 String @db.NVarChar(100) + REMARKS String @db.NVarChar(200) + SAP_YN String @db.NVarChar(1) + STAT_CD String @db.NVarChar(1) + DEL_YN String @db.NVarChar(1) + REG_DT DateTime? @db.DateTime + REG_ID String @db.NVarChar(50) + UPT_DT DateTime? @db.DateTime + UPT_ID String @db.NVarChar(50) + QC_COMM_YN String? @default("N", map: "DF__BC_COMM_H__QC_CO__48CFD27E") @db.NVarChar(1) + BC_COMM_L BC_COMM_L[] + + @@index([HEAD_ID], map: "BC_COMM_H_HEAD_ID_IDX") +} + +model BC_COMM_L { + HEAD_CD String @db.NVarChar(6) + CODE String @db.NVarChar(50) + READ_CD String? @db.NVarChar(50) + CODE_NM String? @db.NVarChar(100) + CODE_JP String? @db.NVarChar(100) + CODE_4TH String? @db.NVarChar(100) + REF_CHR1 String? @db.NVarChar(150) + REF_CHR2 String? @db.NVarChar(150) + REF_CHR3 String? @db.NVarChar(150) + REF_CHR4 String? @db.NVarChar(150) + REF_CHR5 String? @db.NVarChar(150) + REF_NUM1 Decimal? @db.Decimal(22, 5) + REF_NUM2 Decimal? @db.Decimal(22, 5) + REF_NUM3 Decimal? @db.Decimal(22, 5) + REF_NUM4 Decimal? @db.Decimal(22, 5) + REF_NUM5 Decimal? @db.Decimal(22, 5) + PRIORITY Decimal? @db.Decimal(3, 0) + REF_CNT String? @db.NVarChar(5) + STAT_CD String? @db.NVarChar(1) + DEL_YN String? @db.NVarChar(1) + REG_DT DateTime? @db.DateTime + REG_ID String? @db.NVarChar(50) + UPT_DT DateTime? @db.DateTime + UPT_ID String? @db.NVarChar(50) + BC_COMM_H BC_COMM_H @relation(fields: [HEAD_CD], references: [HEAD_CD], onUpdate: NoAction, map: "FK_BC_COMM_L") + + @@id([HEAD_CD, CODE], map: "PK_BC_COMM_L") +} diff --git a/src/app/@header/default.tsx b/src/app/@header/default.tsx index aff8409..9ff80c3 100644 --- a/src/app/@header/default.tsx +++ b/src/app/@header/default.tsx @@ -1,5 +1,5 @@ import Header from '@/components/ui/common/Header' export default async function page() { - return
+ return
} diff --git a/src/app/api/auth/route.ts b/src/app/api/auth/route.ts index 8cbbc1a..1c74952 100644 --- a/src/app/api/auth/route.ts +++ b/src/app/api/auth/route.ts @@ -14,7 +14,7 @@ export async function POST(request: Request) { loginId, pwd, }) - console.log('🚀 ~ result ~ result:', result) + // console.log('🚀 ~ result ~ result:', result) if (result.data.result.code === 200) { const cookieStore = await cookies() @@ -54,5 +54,5 @@ export async function POST(request: Request) { await session.save() } - return NextResponse.json({ code: 200, message: 'Login is Succecss!!' }) + return NextResponse.json({ code: 200, message: 'Login is Succecss!!', result: result.data.data }) } diff --git a/src/app/inquiry/layout.tsx b/src/app/inquiry/layout.tsx index 755fe06..292ae27 100644 --- a/src/app/inquiry/layout.tsx +++ b/src/app/inquiry/layout.tsx @@ -1,3 +1,5 @@ -export default function layout({ children }: { children: React.ReactNode }) { +import type { ReactNode } from 'react' + +export default function layout({ children }: { children: ReactNode }) { return
{children}
} diff --git a/src/app/pw-reset/layout.tsx b/src/app/pw-reset/layout.tsx new file mode 100644 index 0000000..eb72abf --- /dev/null +++ b/src/app/pw-reset/layout.tsx @@ -0,0 +1,23 @@ +import type { ReactNode } from 'react' + +interface PwResetLayoutProps { + children: ReactNode +} + +export default function layout({ children }: PwResetLayoutProps) { + return ( + <> +
+
+
+
+
パスワードをリセットする
+
新しいパスワードを入力してください.
+
+
+ {children} +
+
+ + ) +} diff --git a/src/app/pw-reset/page.tsx b/src/app/pw-reset/page.tsx new file mode 100644 index 0000000..a1ac7f3 --- /dev/null +++ b/src/app/pw-reset/page.tsx @@ -0,0 +1,9 @@ +import PwResetForm from '@/components/pw-reset/PwResetForm' + +export default function page() { + return ( + <> + + + ) +} diff --git a/src/app/sample/page.tsx b/src/app/sample/page.tsx new file mode 100644 index 0000000..c4c30d3 --- /dev/null +++ b/src/app/sample/page.tsx @@ -0,0 +1,240 @@ +'use client' + +import { useState } from 'react' + +export default function page() { + const [fileName, setFileName] = useState(null) //file name value + + return ( + <> +
+
+

Input

+
+ + + + + + +
+ + setFileName(e.target.files?.[0] ?? null)} /> +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+

Button

+
+ + + + + + + + + + + + + + +
+
+
+

Check Box

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+

Radio Button

+
+
+ + +
+
+ + +
+
+ + +
+
+
+
+

Toggle Button

+
+
+ +
+
+ +
Q.PARTNERS
+
+
+
+
+

Select Box

+
+ + +
+ + + +
+
+
+
+

TextArea

+
+ + +
+
+ +
+ + ) +} diff --git a/src/app/suitable/layout.tsx b/src/app/suitable/layout.tsx index 25e2615..e5e7c3f 100644 --- a/src/app/suitable/layout.tsx +++ b/src/app/suitable/layout.tsx @@ -1,4 +1,4 @@ -import { ReactNode } from 'react' +import type { ReactNode } from 'react' interface SuitableLayoutProps { children: ReactNode diff --git a/src/app/survey-sale/layout.tsx b/src/app/survey-sale/layout.tsx index c4e7854..f558ad6 100644 --- a/src/app/survey-sale/layout.tsx +++ b/src/app/survey-sale/layout.tsx @@ -1,4 +1,4 @@ -import { ReactNode } from 'react' +import type { ReactNode } from 'react' interface SurveySaleLayoutProps { children: ReactNode diff --git a/src/components/Login.tsx b/src/components/Login.tsx index 66a3f0c..13b4cc8 100644 --- a/src/components/Login.tsx +++ b/src/components/Login.tsx @@ -1,9 +1,11 @@ 'use client' -import { useReducer, useState } from 'react' +import type { SessionData } from '@/types/Auth' +import { useEffect, useReducer, useState } from 'react' import { useRouter } from 'next/navigation' import { useQuery } from '@tanstack/react-query' import { axiosInstance } from '@/libs/axios' +import { useSessionStore } from '@/store/session' interface AccountState { loginId: string @@ -21,6 +23,8 @@ export default function Login() { //로그인 상태 const [isLogin, setIsLogin] = useState(false) + const { session, setSession } = useSessionStore() + const reducer = (state: AccountState, newState: Partial) => ({ ...state, ...newState }) const [account, setAccount] = useReducer(reducer, { loginId: '', @@ -30,6 +34,7 @@ export default function Login() { interface LoginData { code: number message: string | null + result: SessionData } const { @@ -43,7 +48,7 @@ export default function Login() { loginId: account.loginId, pwd: account.pwd, }) - router.push('/') + // router.push('/') return data }, @@ -52,6 +57,17 @@ export default function Login() { retry: false, }) + useEffect(() => { + setIsLogin(false) + if (loginData?.code === 200) { + setSession({ + ...session, + ...loginData?.result, + }) + router.push('/') + } + }, [loginData]) + return ( <>
diff --git a/src/components/pw-reset/PwResetForm.tsx b/src/components/pw-reset/PwResetForm.tsx new file mode 100644 index 0000000..1dd3d85 --- /dev/null +++ b/src/components/pw-reset/PwResetForm.tsx @@ -0,0 +1,59 @@ +'use client' + +import { useState } from 'react' +import { useRouter } from 'next/navigation' + +export default function PwResetForm() { + const [pwShow01, setPwShow01] = useState(false) //비밀번호 확인 보이기 숨기기 + const [pwShow02, setPwShow02] = useState(false) //비밀번호 재확인 보이기 숨기기 + const router = useRouter() + + return ( + <> +
+
+
+
+ 新規パスワード再入力 * +
+
+
+ + +
+
+
10文字以内
+
+
+
+ 新規パスワード入力 * +
+
+
+ + +
+
+
10文字以内
+
+
+
+
+ +
+
+ +
+
+
+ + ) +} diff --git a/src/components/ui/common/DoubleBtnAlert.tsx b/src/components/ui/common/DoubleBtnAlert.tsx index 34af34b..43129b7 100644 --- a/src/components/ui/common/DoubleBtnAlert.tsx +++ b/src/components/ui/common/DoubleBtnAlert.tsx @@ -1,17 +1,26 @@ +'use client' + +import { usePopupController } from '@/store/popupController' import React from 'react' export default function DoubleBtnAlert() { + const { alertMsg, alert2BtnYes, alert2BtnNo } = usePopupController() + return (
-
本当に削除しますか?
+
{alertMsg}
- +
- +
diff --git a/src/components/ui/common/Header.tsx b/src/components/ui/common/Header.tsx index 443e078..6630e1a 100644 --- a/src/components/ui/common/Header.tsx +++ b/src/components/ui/common/Header.tsx @@ -4,33 +4,36 @@ import Link from 'next/link' import { usePathname, useRouter } from 'next/navigation' import { Swiper, SwiperSlide } from 'swiper/react' +import { useQueryClient } from '@tanstack/react-query' import { useSideNavState } from '@/store/sideNavState' import { useHeaderStore } from '@/store/header' +import { useSessionStore } from '@/store/session' +import { useTitle } from '@/hooks/useTitle' -import type { HeaderProps } from '@/types/Header' - -import 'swiper/css' import { axiosInstance } from '@/libs/axios' -// type HeaderProps = { -// name: string //header 이름 -// backBtn: boolean // 뒤로가기 버튼 유무 -// } +import 'swiper/css' -export default function Header({ name }: HeaderProps) { +export default function Header() { const router = useRouter() const pathname = usePathname() const { sideNavIsOpen, setSideNavIsOpen } = useSideNavState() const { backBtn } = useHeaderStore() + const { getTitle } = useTitle() + + const { session, reset } = useSessionStore() + const queryClient = useQueryClient() if (pathname === '/login') { return null } const handleLogout = async () => { + reset() const { data } = await axiosInstance(null).get('/api/auth/logout') if (data.code === 200) { + queryClient.clear() router.push('/login') } } @@ -46,7 +49,7 @@ export default function Header({ name }: HeaderProps) {
)}

- {name} + {getTitle(pathname)}

@@ -60,8 +63,8 @@ export default function Header({ name }: HeaderProps) { profile
-
HONG GILDONG
-
Interplug corp.
+
{session.userNm}
+
{session.category}
@@ -105,7 +108,7 @@ export default function Header({ name }: HeaderProps) {
  • - +
  • diff --git a/src/hooks/useTitle.ts b/src/hooks/useTitle.ts new file mode 100644 index 0000000..d2f2aa0 --- /dev/null +++ b/src/hooks/useTitle.ts @@ -0,0 +1,37 @@ +export const useTitle = () => { + const getTitle = (pathname: string) => { + // Handle dynamic routes first + if (pathname.startsWith('/survey-sale/') && pathname !== '/survey-sale/basic-info' && pathname !== '/survey-sale/roof-info') { + return '調査物件一覧' + } + + if (pathname.startsWith('/inquiry/') && pathname !== '/inquiry/list' && pathname !== '/inquiry/regist') { + return '1:1お問い合わせ詳細' + } + + // Handle static routes + switch (pathname) { + case '/': + return 'Hanasys 現地調査' + case '/suitable': + return '屋根材適合性の確認' + case '/survey-sale': + return '調査物件一覧' + case '/survey-sale/basic-info': + return '調査物件登録' + case '/survey-sale/roof-info': + return '調査物件新規登録' + case '/inquiry/list': + return '1:1お問い合わせ' + case '/inquiry/regist': + return '1:1お問い合わせ' + case '/pw-reset': + return 'パスワードリセット' + + default: + return 'Hanasys 現地調査' + } + } + + return { getTitle } +} diff --git a/src/providers/EdgeProvider.tsx b/src/providers/EdgeProvider.tsx index 5c4e53c..3d8ea42 100644 --- a/src/providers/EdgeProvider.tsx +++ b/src/providers/EdgeProvider.tsx @@ -1,5 +1,6 @@ 'use client' +import { useAlertSwitch } from '@/store/alertSwitch' import { useHeaderStore } from '@/store/header' import { usePopupController } from '@/store/popupController' import { useSideNavState } from '@/store/sideNavState' @@ -17,6 +18,7 @@ export default function EdgeProvider({ children }: React.PropsWithChildren) { const { setBackBtn } = useHeaderStore() const { reset } = useSideNavState() const { setAlertMsg, setAlertBtn, setAlert, setAlert2, setAlert2BtnYes, setAlert2BtnNo } = usePopupController() + const { alertKind } = useAlertSwitch() const alertFunc = (msg: string, alertBtn: Function) => { console.log('🚀 ~ alertFunc ~ msg:', msg) @@ -38,15 +40,18 @@ export default function EdgeProvider({ children }: React.PropsWithChildren) { setAlert2(true) } + //alert 함수 변경해서 바인딩 useEffect(() => { - window.alert = function (msg, alertBtn = () => setAlert(false)) { - alertFunc(msg, alertBtn) + if (alertKind === 'single') { + window.alert = function (msg, alertBtn = () => setAlert(false)) { + alertFunc(msg, alertBtn) + } + } else if (alertKind === 'multi') { + window.alert = function (msg, alert2BtnYes = () => setAlert2(false), alert2BtnNo = () => setAlert2(false)) { + alertFunc2(msg, alert2BtnYes, alert2BtnNo) + } } - - window.alert2 = function (msg, alert2BtnYes = () => setAlert2(false), alert2BtnNo = () => setAlert2(false)) { - alertFunc2(msg, alert2BtnYes, alert2BtnNo) - } - }, []) + }, [alertKind]) /** * 헤더 뒤로가기 버튼 컨트롤 diff --git a/src/store/alertSwitch.ts b/src/store/alertSwitch.ts new file mode 100644 index 0000000..54c9d00 --- /dev/null +++ b/src/store/alertSwitch.ts @@ -0,0 +1,21 @@ +import { create } from 'zustand' + +type AlertSwitchState = { + alertKind: string + setAlertKind: (value: string) => void + reset: () => void +} + +type InitialState = { + alertKind: string +} + +const initialState: InitialState = { + alertKind: 'single', +} + +export const useAlertSwitch = create((set) => ({ + ...initialState, + setAlertKind: (value: string) => set((state) => ({ ...state, alertKind: value })), + reset: () => set(initialState), +})) diff --git a/src/store/session.ts b/src/store/session.ts new file mode 100644 index 0000000..a0e828d --- /dev/null +++ b/src/store/session.ts @@ -0,0 +1,51 @@ +import type { SessionData } from '@/types/Auth' +import { create } from 'zustand' + +type SessionState = { + session: SessionData + setSession: (session: SessionData) => void + reset: () => void +} + +type InitialState = { + session: SessionData +} + +const initialState: InitialState = { + session: { + langCd: null, + currPage: 0, + rowCount: 0, + startRow: null, + endRow: null, + compCd: null, + agencyStoreId: null, + storeId: null, + userId: null, + category: null, + userNm: null, + userNmKana: null, + telNo: null, + fax: null, + email: null, + lastEditUser: null, + storeGubun: null, + pwCurr: null, + pwdInitYn: null, + apprStatCd: null, + loginFailCnt: 0, + loginFailMinYn: null, + priceViewStatCd: null, + groupId: null, + storeLvl: null, + custCd: null, + builderNo: null, + isLoggedIn: false, + }, +} + +export const useSessionStore = create((set) => ({ + ...initialState, + setSession: (value: SessionData) => set((state) => ({ ...state, session: { ...state.session, ...value } })), + reset: () => set(initialState), +}))