Compare commits

...

11 Commits

Author SHA1 Message Date
34319dadcd fix: Change the policy to allow Update, Delete, Submit to writer only
- 담당자가 로그인 한 유저 이름과 같을 때 수정, 삭제, 제출 가능하도록 변경
2025-05-12 15:45:37 +09:00
bd89552cc7 Merge branch 'feature/survey' of https://git.hanasys.jp/qcast3/onsitesurvey into feature/survey 2025-05-12 14:47:07 +09:00
6bbd1a6174 Merge branch 'feature/survey' of https://git.hanasys.jp/qcast3/onsitesurvey into feature/survey 2025-05-12 14:40:10 +09:00
7173ec2496 feat: implement UserType custom hook for filtering login user type 2025-05-12 14:37:47 +09:00
901b7b1ae8 Merge branch 'dev' of https://git.hanasys.jp/qcast3/onsitesurvey into feature/survey 2025-05-12 11:13:54 +09:00
29488b2412 feat: implement survey list filter by Member Type for temporary
- 로그인 유저 타입 별 조사매물 필터링 임시 구현
- 로그인 유저 타입 구현 이후 변경 예정
2025-05-12 11:11:52 +09:00
6cab9cdde3 feat: implement session management in RootLayout and pass session data to EdgeProvider for enhanced state handling 2025-05-12 11:01:07 +09:00
2eacdda23e refactor: remove alertSwitch store and simplify alert handling in EdgeProvider 2025-05-12 10:37:58 +09:00
ce00cc2ba7 refactor: simplify Header component by removing unused props and updating button action for password reset 2025-05-09 18:21:35 +09:00
e6d346c5da refactor: remove unused title variable in Header component to streamline code 2025-05-09 18:14:55 +09:00
178e9c0d3e refactor: update layout components to use 'import type' for ReactNode and enhance Header component with dynamic title retrieval 2025-05-09 18:13:40 +09:00
23 changed files with 317 additions and 109 deletions

View File

@ -1,5 +1,5 @@
import Header from '@/components/ui/common/Header' import Header from '@/components/ui/common/Header'
export default async function page() { export default async function page() {
return <Header name={'調査物件一覧'} /> return <Header />
} }

View File

@ -17,6 +17,8 @@ export async function GET(request: Request) {
const isMySurvey = searchParams.get('isMySurvey') const isMySurvey = searchParams.get('isMySurvey')
const sort = searchParams.get('sort') const sort = searchParams.get('sort')
const offset = searchParams.get('offset') const offset = searchParams.get('offset')
const store = searchParams.get('store')
const construction_point = searchParams.get('construction_point')
const searchOptions = ['building_name', 'representative', 'store', 'construction_point', 'customer_name', 'post_code', 'address', 'address_detail'] const searchOptions = ['building_name', 'representative', 'store', 'construction_point', 'customer_name', 'post_code', 'address', 'address_detail']
try { try {
@ -54,6 +56,22 @@ export async function GET(request: Request) {
} }
} }
where.AND = []
if (store) {
where.AND.push({
store: {
equals: store,
},
})
}
if (construction_point) {
where.AND.push({
construction_point: {
equals: construction_point,
},
})
}
if (offset) { if (offset) {
// @ts-ignore // @ts-ignore
const res = await prisma.SD_SERVEY_SALES_BASIC_INFO.findMany({ const res = await prisma.SD_SERVEY_SALES_BASIC_INFO.findMany({

View File

@ -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 <div className="container">{children}</div> return <div className="container">{children}</div>
} }

View File

@ -1,12 +1,16 @@
import type { ReactNode } from 'react'
import type { Metadata } from 'next' import type { Metadata } from 'next'
import type { SessionData } from '@/types/Auth'
import ReactQueryProviders from '@/providers/ReactQueryProvider' import ReactQueryProviders from '@/providers/ReactQueryProvider'
import EdgeProvider from '@/providers/EdgeProvider' import EdgeProvider from '@/providers/EdgeProvider'
import PopupController from '@/components/ui/PopupController' import PopupController from '@/components/ui/PopupController'
import '@/styles/style.scss' import { cookies } from 'next/headers'
import { getIronSession } from 'iron-session'
import { sessionOptions } from '@/libs/session'
import type { ReactNode } from 'react' import '@/styles/style.scss'
export const metadata: Metadata = { export const metadata: Metadata = {
title: 'Create Next App', title: 'Create Next App',
@ -21,9 +25,14 @@ interface RootLayoutProps {
}6 }6
export default async function RootLayout({ children, header, footer, floatBtn }: RootLayoutProps): Promise<ReactNode> { export default async function RootLayout({ children, header, footer, floatBtn }: RootLayoutProps): Promise<ReactNode> {
const cookieStore = await cookies()
const session = await getIronSession<SessionData>(cookieStore, sessionOptions)
const sessionData = JSON.stringify(session)
return ( return (
<ReactQueryProviders> <ReactQueryProviders>
<EdgeProvider> <EdgeProvider sessionData={sessionData}>
<html lang="ja" suppressHydrationWarning> <html lang="ja" suppressHydrationWarning>
<body> <body>
<div className="wrap"> <div className="wrap">

View File

@ -0,0 +1,23 @@
import type { ReactNode } from 'react'
interface PwResetLayoutProps {
children: ReactNode
}
export default function layout({ children }: PwResetLayoutProps) {
return (
<>
<div className="container">
<div className="sale-contents">
<div className="border-frame">
<div className="pw-guide">
<div className="pw-guide-tit"></div>
<div className="pw-guide-txt">.</div>
</div>
</div>
{children}
</div>
</div>
</>
)
}

View File

@ -0,0 +1,9 @@
import PwResetForm from '@/components/pw-reset/PwResetForm'
export default function page() {
return (
<>
<PwResetForm />
</>
)
}

View File

@ -1,4 +1,4 @@
import { ReactNode } from 'react' import type { ReactNode } from 'react'
interface SuitableLayoutProps { interface SuitableLayoutProps {
children: ReactNode children: ReactNode

View File

@ -1,4 +1,4 @@
import { ReactNode } from 'react' import type { ReactNode } from 'react'
interface SurveySaleLayoutProps { interface SurveySaleLayoutProps {
children: ReactNode children: ReactNode

View File

@ -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 (
<>
<div className="border-frame">
<div className="data-form-wrap">
<div className="data-input-form-bx">
<div className="data-input-form-tit">
<i className="import">*</i>
</div>
<div className="data-input">
<div className="login-input pw change">
<input type={`${pwShow01 ? 'text' : 'password'}`} className="login-frame" placeholder="●●●●" />
<button className={`login-icon ${pwShow01 ? 'act' : ''}`} onClick={() => setPwShow01(!pwShow01)}>
<i className="show-icon"></i>
</button>
</div>
</div>
<div className="data-input-guide">10</div>
</div>
<div className="data-input-form-bx">
<div className="data-input-form-tit">
<i className="import">*</i>
</div>
<div className="data-input">
<div className="login-input pw change">
<input type={`${pwShow02 ? 'text' : 'password'}`} className="login-frame" placeholder="●●●●" />
<button className={`login-icon ${pwShow02 ? 'act' : ''}`} onClick={() => setPwShow02(!pwShow02)}>
<i className="show-icon"></i>
</button>
</div>
</div>
<div className="data-input-guide">10</div>
</div>
</div>
<div className="btn-flex-wrap">
<div className="btn-bx">
<button className="btn-frame n-blue icon" onClick={() => router.back()}>
<i className="btn-arr"></i>
</button>
</div>
<div className="btn-bx">
<button className="btn-frame red icon">
<i className="btn-arr"></i>
</button>
</div>
</div>
</div>
</>
)
}

View File

@ -1,33 +1,54 @@
'use client' 'use client'
import { useRouter } from 'next/navigation' import { useRouter } from 'next/navigation'
import { useServey } from '@/hooks/useSurvey' import { useServey } from '@/hooks/useSurvey'
import { useSessionStore } from '@/store/session'
import { useEffect, useState } from 'react'
export default function DetailButton({ isTemporary, surveyId }: { isTemporary: boolean; surveyId: number }) { export default function DetailButton({ isTemporary, surveyId, representative }: { isTemporary: boolean; surveyId: number; representative: string }) {
const router = useRouter() const router = useRouter()
const { session } = useSessionStore()
const { submitSurvey, deleteSurvey } = useServey(surveyId) const { submitSurvey, deleteSurvey } = useServey(surveyId)
const [userNm, setUserNm] = useState('')
useEffect(() => {
if (session?.isLoggedIn) {
setUserNm(session?.userNm ?? '')
}
}, [session, setUserNm])
const handleSubmit = async () => { const handleSubmit = async () => {
if (isTemporary) { if (isTemporary) {
alert('一時保存されたデータは提出できません。') alert('一時保存されたデータは提出できません。')
return return
} }
if (confirm('提出しますか??')) { if (userNm === representative) {
if (surveyId) { if (confirm('提出しますか??')) {
// TODO: 제출 페이지 추가 if (surveyId) {
alert('SUBMIT POPUP!!!!!!!!!!!') // TODO: 제출 페이지 추가
await submitSurvey() alert('SUBMIT POPUP!!!!!!!!!!!')
await submitSurvey()
}
} }
} else {
alert('担当者のみ提出可能です。')
} }
} }
const handleUpdate = () => { const handleUpdate = () => {
router.push(`/survey-sale/basic-info?id=${surveyId}&isTemp=${isTemporary}`) if (userNm === representative) {
router.push(`/survey-sale/basic-info?id=${surveyId}&isTemp=${isTemporary}`)
} else {
alert('担当者のみ修正可能です。')
}
} }
const handleDelete = async () => { const handleDelete = async () => {
if (confirm('削除しますか?')) { if (confirm('削除しますか?')) {
if (surveyId) { if (surveyId) {
await deleteSurvey() if (userNm === representative) {
router.push('/survey-sale') await deleteSurvey()
router.push('/survey-sale')
} else {
alert('担当者のみ削除可能です。')
}
} }
} }
} }

View File

@ -56,7 +56,7 @@ export default function DetailForm({
<input type="text" className="input-frame" disabled defaultValue={surveyDetail?.customer_name ?? ''} /> <input type="text" className="input-frame" disabled defaultValue={surveyDetail?.customer_name ?? ''} />
</div> </div>
</div> </div>
<DetailButton isTemporary={isTemporary} surveyId={Number(surveyDetail?.id)} /> <DetailButton isTemporary={isTemporary} surveyId={Number(surveyDetail?.id)} representative={surveyDetail?.representative ?? ''} />
</div> </div>
</> </>
) )

View File

@ -196,7 +196,7 @@ export default function RoofDetailForm({
</div> </div>
</div> </div>
</div> </div>
<DetailButton isTemporary={false} surveyId={Number(surveyDetail?.id)} /> <DetailButton isTemporary={false} surveyId={Number(surveyDetail?.id)} representative={surveyDetail?.representative ?? ''} />
</div> </div>
</> </>
) )

View File

@ -8,6 +8,7 @@ import { useSurveySaleTabState } from '@/store/surveySaleTabState'
import { usePopupController } from '@/store/popupController' import { usePopupController } from '@/store/popupController'
import { useAddressStore } from '@/store/addressStore' import { useAddressStore } from '@/store/addressStore'
import { useSessionStore } from '@/store/session' import { useSessionStore } from '@/store/session'
import { useUserType } from '@/hooks/useUserType'
const defaultBasicInfoForm: SurveyBasicRequest = { const defaultBasicInfoForm: SurveyBasicRequest = {
representative: '', representative: '',
@ -23,7 +24,7 @@ const defaultBasicInfoForm: SurveyBasicRequest = {
submission_date: null, submission_date: null,
} }
const REQUIRED_FIELDS: (keyof SurveyBasicRequest)[] = ['representative', 'store', 'construction_point'] const REQUIRED_FIELDS: (keyof SurveyBasicRequest)[] = ['representative', 'building_name', 'customer_name']
export default function BasicForm() { export default function BasicForm() {
const searchParams = useSearchParams() const searchParams = useSearchParams()
@ -36,6 +37,8 @@ export default function BasicForm() {
const [basicInfoData, setBasicInfoData] = useState<SurveyBasicRequest>(defaultBasicInfoForm) const [basicInfoData, setBasicInfoData] = useState<SurveyBasicRequest>(defaultBasicInfoForm)
const { addressData } = useAddressStore() const { addressData } = useAddressStore()
const { userType, store, construction_point } = useUserType()
const { session } = useSessionStore()
const popupController = usePopupController() const popupController = usePopupController()
@ -52,8 +55,14 @@ export default function BasicForm() {
address_detail: addressData.address_detail, address_detail: addressData.address_detail,
}) })
} }
if (session?.isLoggedIn) {
setBasicInfoData((prev) => ({
...prev,
representative: session?.userNm ?? '',
}))
}
setBasicInfoSelected() setBasicInfoSelected()
}, [surveyDetail, addressData]) }, [surveyDetail, addressData, session?.isLoggedIn, session?.userNm])
const focusInput = (input: keyof SurveyBasicRequest) => { const focusInput = (input: keyof SurveyBasicRequest) => {
const inputElement = document.getElementById(input) const inputElement = document.getElementById(input)
@ -64,7 +73,6 @@ export default function BasicForm() {
const validateSurvey = (basicInfoData: SurveyBasicRequest) => { const validateSurvey = (basicInfoData: SurveyBasicRequest) => {
const emptyField = REQUIRED_FIELDS.find((field) => !basicInfoData[field]) const emptyField = REQUIRED_FIELDS.find((field) => !basicInfoData[field])
if (emptyField) { if (emptyField) {
focusInput(emptyField) focusInput(emptyField)
return false return false
@ -109,30 +117,36 @@ export default function BasicForm() {
type="text" type="text"
className="input-frame" className="input-frame"
id="representative" id="representative"
value={basicInfoData.representative} value={session?.userNm ? session?.userNm : basicInfoData.representative}
onChange={(e) => handleChange('representative', e.target.value)} onChange={(e) => handleChange('representative', e.target.value)}
/> />
</div> </div>
<div className="data-input-form-bx"> {(userType === 'order' || userType?.includes('musubi')) && (
<div className="data-input-form-tit"></div> <>
<input <div className="data-input-form-bx">
type="text" <div className="data-input-form-tit"></div>
className="input-frame" <input
id="store" type="text"
value={basicInfoData.store ?? ''} className="input-frame"
onChange={(e) => handleChange('store', e.target.value)} id="store"
/> value={store ? store : basicInfoData.store ?? ''}
</div> onChange={(e) => handleChange('store', e.target.value)}
<div className="data-input-form-bx"> />
<div className="data-input-form-tit"></div> </div>
<input </>
type="text" )}
className="input-frame" {(userType === 'partner' || userType === 'musubi_con') && (
id="construction_point" <div className="data-input-form-bx">
value={basicInfoData.construction_point ?? ''} <div className="data-input-form-tit"></div>
onChange={(e) => handleChange('construction_point', e.target.value)} <input
/> type="text"
</div> className="input-frame"
id="construction_point"
value={construction_point ? construction_point : basicInfoData.construction_point ?? ''}
onChange={(e) => handleChange('construction_point', e.target.value)}
/>
</div>
)}
</div> </div>
</div> </div>
@ -188,10 +202,6 @@ export default function BasicForm() {
onChange={(e) => handleChange('address', e.target.value)} onChange={(e) => handleChange('address', e.target.value)}
> >
<option value=""></option> <option value=""></option>
<option value=""></option>
<option value=""></option>
<option value=""></option>
<option value=""></option>
</select> </select>
</div> </div>
</div> </div>

View File

@ -6,7 +6,7 @@ import { useEffect, useState } from 'react'
import { useRouter } from 'next/navigation' import { useRouter } from 'next/navigation'
import SearchForm from './SearchForm' import SearchForm from './SearchForm'
import { useSurveyFilterStore } from '@/store/surveyFilterStore' import { useSurveyFilterStore } from '@/store/surveyFilterStore'
import { useSessionStore } from '@/store/session' import { UserType } from '@/hooks/useUserType'
export default function ListTable() { export default function ListTable() {
const router = useRouter() const router = useRouter()
@ -15,9 +15,7 @@ export default function ListTable() {
const [heldSurveyList, setHeldSurveyList] = useState<typeof surveyList>([]) const [heldSurveyList, setHeldSurveyList] = useState<typeof surveyList>([])
const [hasMore, setHasMore] = useState(false) const [hasMore, setHasMore] = useState(false)
const [memberType, setMemberType] = useState<UserType>('hwj')
const { session } = useSessionStore()
console.log('session:: ', session)
useEffect(() => { useEffect(() => {
if (surveyList && surveyList.length > 0) { if (surveyList && surveyList.length > 0) {
@ -31,6 +29,8 @@ export default function ListTable() {
} }
setHasMore(surveyListCount > offset + 10) setHasMore(surveyListCount > offset + 10)
} }
// 회원 유형 설정 이후 변경
setMemberType('hwj')
}, [surveyList, surveyListCount, offset]) }, [surveyList, surveyListCount, offset])
const handleDetailClick = (id: number) => { const handleDetailClick = (id: number) => {
@ -45,7 +45,7 @@ export default function ListTable() {
return ( return (
<> <>
<SearchForm onItemsInit={handleItemsInit} /> <SearchForm onItemsInit={handleItemsInit} memberType={memberType} />
{heldSurveyList.length > 0 ? ( {heldSurveyList.length > 0 ? (
<div className="sale-frame"> <div className="sale-frame">
<ul className="sale-list-wrap"> <ul className="sale-list-wrap">

View File

@ -1,10 +1,11 @@
'use client' 'use client'
import { SEARCH_OPTIONS, SEARCH_OPTIONS_ENUM, useSurveyFilterStore } from '@/store/surveyFilterStore' import { SEARCH_OPTIONS, SEARCH_OPTIONS_ENUM, SEARCH_OPTIONS_PARTNERS, useSurveyFilterStore } from '@/store/surveyFilterStore'
import { UserType } from '@/hooks/useUserType'
import { useRouter } from 'next/navigation' import { useRouter } from 'next/navigation'
import { useState } from 'react' import { useState } from 'react'
export default function SearchForm({ onItemsInit }: { onItemsInit: () => void }) { export default function SearchForm({ onItemsInit, memberType }: { onItemsInit: () => void; memberType: UserType }) {
const router = useRouter() const router = useRouter()
const { setSearchOption, setSort, setIsMySurvey, setKeyword, isMySurvey, keyword, searchOption, sort } = useSurveyFilterStore() const { setSearchOption, setSort, setIsMySurvey, setKeyword, isMySurvey, keyword, searchOption, sort } = useSurveyFilterStore()
const [searchKeyword, setSearchKeyword] = useState(keyword) const [searchKeyword, setSearchKeyword] = useState(keyword)
@ -19,6 +20,7 @@ export default function SearchForm({ onItemsInit }: { onItemsInit: () => void })
setKeyword(searchKeyword) setKeyword(searchKeyword)
onItemsInit() onItemsInit()
} }
const searchOptions = memberType === 'partner' ? SEARCH_OPTIONS_PARTNERS : SEARCH_OPTIONS
return ( return (
<div className="sale-frame"> <div className="sale-frame">
@ -35,7 +37,7 @@ export default function SearchForm({ onItemsInit }: { onItemsInit: () => void })
value={searchOption} value={searchOption}
onChange={(e) => setSearchOption(e.target.value as SEARCH_OPTIONS_ENUM)} onChange={(e) => setSearchOption(e.target.value as SEARCH_OPTIONS_ENUM)}
> >
{SEARCH_OPTIONS.map((option) => ( {searchOptions.map((option) => (
<option key={option.id} value={option.id}> <option key={option.id} value={option.id}>
{option.label} {option.label}
</option> </option>

View File

@ -4,27 +4,23 @@ import Link from 'next/link'
import { usePathname, useRouter } from 'next/navigation' import { usePathname, useRouter } from 'next/navigation'
import { Swiper, SwiperSlide } from 'swiper/react' import { Swiper, SwiperSlide } from 'swiper/react'
import { useQueryClient } from '@tanstack/react-query'
import { useSideNavState } from '@/store/sideNavState' import { useSideNavState } from '@/store/sideNavState'
import { useHeaderStore } from '@/store/header' import { useHeaderStore } from '@/store/header'
import { useSessionStore } from '@/store/session'
import { useTitle } from '@/hooks/useTitle'
import type { HeaderProps } from '@/types/Header' import { axiosInstance } from '@/libs/axios'
import 'swiper/css' import 'swiper/css'
import { axiosInstance } from '@/libs/axios'
import { useSessionStore } from '@/store/session'
import { useQueryClient } from '@tanstack/react-query'
// type HeaderProps = { export default function Header() {
// name: string //header 이름
// backBtn: boolean // 뒤로가기 버튼 유무
// }
export default function Header({ name }: HeaderProps) {
const router = useRouter() const router = useRouter()
const pathname = usePathname() const pathname = usePathname()
const { sideNavIsOpen, setSideNavIsOpen } = useSideNavState() const { sideNavIsOpen, setSideNavIsOpen } = useSideNavState()
const { backBtn } = useHeaderStore() const { backBtn } = useHeaderStore()
const { getTitle } = useTitle()
const { session, reset } = useSessionStore() const { session, reset } = useSessionStore()
const queryClient = useQueryClient() const queryClient = useQueryClient()
@ -53,7 +49,7 @@ export default function Header({ name }: HeaderProps) {
</div> </div>
)} )}
<h2 className="logo"> <h2 className="logo">
<Link href={'/'}>{name}</Link> <Link href={'/'}>{getTitle(pathname)}</Link>
</h2> </h2>
<div className="side-button-wrap"> <div className="side-button-wrap">
<button className="side-button" onClick={() => setSideNavIsOpen(true)}></button> <button className="side-button" onClick={() => setSideNavIsOpen(true)}></button>
@ -112,7 +108,7 @@ export default function Header({ name }: HeaderProps) {
<button onClick={() => router.push('/inquiry/regist')}>1:1お問い合わせ登録</button> <button onClick={() => router.push('/inquiry/regist')}>1:1お問い合わせ登録</button>
</li> </li>
<li className="side-nav-item"> <li className="side-nav-item">
<button></button> <button onClick={() => router.push('/pw-reset')}></button>
</li> </li>
</ul> </ul>
</nav> </nav>

View File

@ -3,6 +3,7 @@ import type { SurveyBasicInfo, SurveyBasicRequest, SurveyDetailInfo, SurveyDetai
import { axiosInstance } from '@/libs/axios' import { axiosInstance } from '@/libs/axios'
import { useSurveyFilterStore } from '@/store/surveyFilterStore' import { useSurveyFilterStore } from '@/store/surveyFilterStore'
import { queryStringFormatter } from '@/utils/common-utils' import { queryStringFormatter } from '@/utils/common-utils'
interface ZipCodeResponse { interface ZipCodeResponse {
status: number status: number
message: string | null message: string | null
@ -19,6 +20,8 @@ type ZipCode = {
kana2: string kana2: string
kana3: string kana3: string
} }
import { useUserType } from './useUserType'
export function useServey(id?: number): { export function useServey(id?: number): {
surveyList: SurveyBasicInfo[] | [] surveyList: SurveyBasicInfo[] | []
surveyDetail: SurveyBasicInfo | null surveyDetail: SurveyBasicInfo | null
@ -38,12 +41,13 @@ export function useServey(id?: number): {
} { } {
const queryClient = useQueryClient() const queryClient = useQueryClient()
const { keyword, searchOption, isMySurvey, sort, offset } = useSurveyFilterStore() const { keyword, searchOption, isMySurvey, sort, offset } = useSurveyFilterStore()
const { store, construction_point } = useUserType()
const { data: surveyList, isLoading: isLoadingSurveyList } = useQuery({ const { data: surveyList, isLoading: isLoadingSurveyList } = useQuery({
queryKey: ['survey', 'list', keyword, searchOption, isMySurvey, sort, offset], queryKey: ['survey', 'list', keyword, searchOption, isMySurvey, sort, offset, store, construction_point],
queryFn: async () => { queryFn: async () => {
const resp = await axiosInstance(null).get<SurveyBasicInfo[]>('/api/survey-sales', { const resp = await axiosInstance(null).get<SurveyBasicInfo[]>('/api/survey-sales', {
params: { keyword, searchOption, isMySurvey, sort, offset }, params: { keyword, searchOption, isMySurvey, sort, offset, store, construction_point },
}) })
return resp.data return resp.data
}, },

37
src/hooks/useTitle.ts Normal file
View File

@ -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 }
}

24
src/hooks/useUserType.ts Normal file
View File

@ -0,0 +1,24 @@
import { useSessionStore } from '@/store/session'
import { useEffect, useState } from 'react'
export type UserType = 'hwj' | 'order' | 'musubi' | 'musubi_con' | 'partner'
// 로그인 된 회원 유형에 따라 조사 매물 목록 변경됨
export function useUserType() {
const { session } = useSessionStore()
const [userType, setUserType] = useState<UserType | null>(null)
const [store, setStore] = useState<string | null>(null)
const [construction_point, setConstructionPoint] = useState<string | null>(null)
// TODO: 회원 유형 설정
useEffect(() => {
if (!session?.isLoggedIn) return
setUserType('musubi_con')
}, [session])
return {
userType,
store,
construction_point,
}
}

View File

@ -1,25 +1,29 @@
'use client' 'use client'
import { useAlertSwitch } from '@/store/alertSwitch'
import { useHeaderStore } from '@/store/header' import { useHeaderStore } from '@/store/header'
import { usePopupController } from '@/store/popupController' import { usePopupController } from '@/store/popupController'
import { useSideNavState } from '@/store/sideNavState' import { useSideNavState } from '@/store/sideNavState'
import { usePathname } from 'next/navigation' import { usePathname } from 'next/navigation'
import { useEffect } from 'react' import { useEffect } from 'react'
import { useSessionStore } from '@/store/session'
declare global { interface EdgeProviderProps {
interface Window { children: React.ReactNode
alert2: (msg: string, alert2BtnYes?: () => void, alert2BtnNo?: () => void) => void sessionData: string
}
} }
export default function EdgeProvider({ children }: React.PropsWithChildren) { export default function EdgeProvider({ children, sessionData }: EdgeProviderProps) {
const pathname = usePathname() const pathname = usePathname()
const { setBackBtn } = useHeaderStore() const { setBackBtn } = useHeaderStore()
const { reset } = useSideNavState() const { reset } = useSideNavState()
const { setAlertMsg, setAlertBtn, setAlert, setAlert2, setAlert2BtnYes, setAlert2BtnNo } = usePopupController() const { setAlertMsg, setAlertBtn, setAlert, setAlert2, setAlert2BtnYes, setAlert2BtnNo } = usePopupController()
const { alertKind } = useAlertSwitch() const { session, setSession } = useSessionStore()
/**
* alert - window.alert
* @param msg
* @param alertBtn
*/
const alertFunc = (msg: string, alertBtn: Function) => { const alertFunc = (msg: string, alertBtn: Function) => {
console.log('🚀 ~ alertFunc ~ msg:', msg) console.log('🚀 ~ alertFunc ~ msg:', msg)
setAlertMsg(msg) setAlertMsg(msg)
@ -27,7 +31,7 @@ export default function EdgeProvider({ children }: React.PropsWithChildren) {
setAlert(true) setAlert(true)
} }
/** /**
* alert2 * alert2 - window.confirm
* @param msg alert * @param msg alert
* @param alertBtn2Yes alert * @param alertBtn2Yes alert
* @param alertBtn2No alert * @param alertBtn2No alert
@ -42,16 +46,28 @@ export default function EdgeProvider({ children }: React.PropsWithChildren) {
//alert 함수 변경해서 바인딩 //alert 함수 변경해서 바인딩
useEffect(() => { useEffect(() => {
if (alertKind === 'single') { window.alert = function (msg, alertBtn = () => setAlert(false)) {
window.alert = function (msg, alertBtn = () => setAlert(false)) { alertFunc(msg, alertBtn)
alertFunc(msg, alertBtn)
}
} else if (alertKind === 'multi') {
window.alert = function (msg, alert2BtnYes = () => setAlert2(false), alert2BtnNo = () => setAlert2(false)) {
alertFunc2(msg, alert2BtnYes, alert2BtnNo)
}
} }
}, [alertKind]) window.confirm = function (msg = '', alert2BtnYes = () => setAlert2(false), alert2BtnNo = () => setAlert2(false)) {
alertFunc2(
msg,
() => {
alert2BtnYes()
return true
},
() => {
alert2BtnNo()
return false
},
)
return false
}
setSession({
...session,
...JSON.parse(sessionData),
})
}, [])
/** /**
* *

View File

@ -1,21 +0,0 @@
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<AlertSwitchState>((set) => ({
...initialState,
setAlertKind: (value: string) => set((state) => ({ ...state, alertKind: value })),
reset: () => set(initialState),
}))

View File

@ -60,7 +60,6 @@ export const SEARCH_OPTIONS_PARTNERS = [
}, },
] ]
export type MEMBER_TYPE = 'hwj' | 'order' | 'musubi' | 'partner'
export type SEARCH_OPTIONS_ENUM = (typeof SEARCH_OPTIONS)[number]['id'] export type SEARCH_OPTIONS_ENUM = (typeof SEARCH_OPTIONS)[number]['id']
export type SEARCH_OPTIONS_PARTNERS_ENUM = (typeof SEARCH_OPTIONS_PARTNERS)[number]['id'] export type SEARCH_OPTIONS_PARTNERS_ENUM = (typeof SEARCH_OPTIONS_PARTNERS)[number]['id']
export type SORT_OPTIONS_ENUM = 'created' | 'updated' export type SORT_OPTIONS_ENUM = 'created' | 'updated'

View File

@ -1,4 +1,4 @@
import { SEARCH_OPTIONS_ENUM, SEARCH_OPTIONS_PARTNERS_ENUM, SORT_OPTIONS_ENUM } from "@/store/surveyFilterStore" import { SEARCH_OPTIONS_ENUM, SEARCH_OPTIONS_PARTNERS_ENUM, SORT_OPTIONS_ENUM } from '@/store/surveyFilterStore'
export type SurveyBasicInfo = { export type SurveyBasicInfo = {
id: number id: number