feat: integrate EdgeProvider for alert management and add Suitable components for roof material compatibility checks

This commit is contained in:
yoosangwook 2025-05-08 17:55:24 +09:00
parent 4467c04321
commit 1746c91742
13 changed files with 397 additions and 32 deletions

View File

@ -1,6 +1,7 @@
import type { Metadata } from 'next'
import ReactQueryProviders from '@/providers/ReactQueryProvider'
import EdgeProvider from '@/providers/EdgeProvider'
import PopupController from '@/components/ui/PopupController'
import '@/styles/style.scss'
@ -22,17 +23,19 @@ interface RootLayoutProps {
export default async function RootLayout({ children, header, footer, floatBtn }: RootLayoutProps): Promise<ReactNode> {
return (
<ReactQueryProviders>
<html lang="en">
<body>
<div className="wrap">
{header}
{children}
{footer}
{floatBtn}
</div>
<PopupController />
</body>
</html>
<EdgeProvider>
<html lang="en">
<body>
<div className="wrap">
{header}
{children}
{footer}
{floatBtn}
</div>
<PopupController />
</body>
</html>
</EdgeProvider>
</ReactQueryProviders>
)
}

View File

@ -0,0 +1,24 @@
import { ReactNode } from 'react'
interface SuitableLayoutProps {
children: ReactNode
}
export default function layout({ children }: SuitableLayoutProps) {
return (
<>
<div className="container">
<div className="sale-contents">
<div className="border-frame">
<div className="pw-guide">
<div className="pw-guide-txt">使.</div>
<div className="pw-guide-txt">11.</div>
<div className="pw-guide-txt">or屋根材名を直接入力してください.</div>
</div>
</div>
{children}
</div>
</div>
</>
)
}

View File

@ -1,7 +1,9 @@
import Suitable from '@/components/suitable/Suitable'
export default function page() {
return (
<>
<h1> </h1>
<Suitable />
</>
)
}

View File

@ -0,0 +1,32 @@
export default function SuitableDetailPopup() {
return (
<div className="modal-popup">
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<div className="modal-header-inner">
<div className="modal-name-wrap">
<div className="modal-img">
<img src="/assets/images/layout/modal_header_icon03.svg" alt="" />
</div>
<div className="modal-name"> </div>
</div>
<button className="modal-close"></button>
</div>
</div>
<div className="modal-body">
<div className={`compliance-check-bx act`}>
<div className="check-name-wrap">
<div className="check-name"></div>
<div className="check-name-btn">
<button className="bx-btn"></button>
</div>
</div>
<div className="compliance-check-pop-contents"></div>
</div>
</div>
</div>
</div>
</div>
)
}

View File

@ -0,0 +1,87 @@
'use client'
import { useState } from 'react'
import SuitableCheckData from './SuitableCheckData'
import SuitableNoData from './SuitableNoData'
export default function Suitable() {
const [reference, setReference] = useState(false)
return (
<div className="border-frame">
<div className="sale-form-bx">
<select className="select-form" name="" id="">
<option value="">.</option>
<option value="">.</option>
<option value="">.</option>
<option value="">.</option>
<option value="">.</option>
</select>
</div>
<div className="sale-form-bx">
<div className="search-input">
<input type="text" className="search-frame" placeholder="屋根材 製品名を入力してください." />
<button className="search-icon"></button>
</div>
</div>
<div className="compliance-check-wrap">
<div className={`compliance-check-bx ${reference ? 'act' : ''}`}>
<div className="check-name-wrap">
<div className="check-name"></div>
<div className="check-name-btn">
<button className="bx-btn" onClick={() => setReference(!reference)}></button>
</div>
</div>
<ul className="reference-list">
<li className="reference-item">
<div className="reference-item-bx">
<i className="compliance-icon check"></i>
</div>
</li>
<li className="reference-item">
<div className="reference-item-bx">
<i className="compliance-icon x"></i>
</div>
</li>
<li className="reference-item">
<div className="reference-item-bx">
<i className="compliance-icon quest"></i>
</div>
</li>
<li className="reference-item">
<div className="reference-item-bx">
<i className="compliance-icon tip"></i>
</div>
</li>
</ul>
</div>
{/* checkData */}
{/* 데이터 없을경우 버튼 영역 안보여야함 */}
<SuitableCheckData />
<SuitableCheckData />
<SuitableCheckData />
<SuitableCheckData />
</div>
{/* 데이터 없을경우 버튼 영역 안보여야함 */}
<div className="btn-flex-wrap com">
<div className="btn-bx">
<button className="btn-frame n-blue icon">
<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 className="btn-bx">
<button className="btn-frame n-blue icon">
<i className="btn-arr"></i>
</button>
</div>
</div>
{/* 검색기록 없을떄 위에 두 영역 안보이고 이 부분만 보여야 함*/}
{/* <SuitableNoData /> */}
</div>
)
}

View File

@ -0,0 +1,68 @@
'use client'
export default function SuitableCheckData() {
return (
<>
<div className={`compliance-check-bx act`}>
<div className="check-name-wrap">
<div className="check-form-box com-tit">
<input type="checkbox" id="ch01" />
<label htmlFor="ch01"></label>
</div>
<div className="check-name-btn">
<button className="bx-btn"></button>
</div>
</div>
<ul className="reference-list check">
<li className="reference-item">
<div className="check-item-wrap">
<div className="check-form-box com-txt">
<input type="checkbox" id="ch02" />
<label htmlFor="ch02"> </label>
</div>
<div className="compliance-icon-wrap">
<i className="compliance-icon check"></i>
<i className="compliance-icon x"></i>
</div>
</div>
</li>
<li className="reference-item">
<div className="check-item-wrap">
<div className="check-form-box com-txt">
<input type="checkbox" id="ch03" />
<label htmlFor="ch03"> </label>
</div>
<div className="compliance-icon-wrap">
<i className="compliance-icon x"></i>
<i className="compliance-icon tip"></i>
</div>
</div>
</li>
<li className="reference-item">
<div className="check-item-wrap">
<div className="check-form-box com-txt">
<input type="checkbox" id="ch04" />
<label htmlFor="ch04">YGアンカー</label>
</div>
<div className="compliance-icon-wrap">
<i className="compliance-icon tip"></i>
<i className="compliance-icon quest"></i>
</div>
</div>
</li>
<li className="reference-item">
<div className="check-item-wrap">
<div className="check-form-box com-txt">
<input type="checkbox" id="ch05" />
<label htmlFor="ch05"></label>
</div>
<div className="compliance-icon-wrap">
<i className="compliance-icon check"></i>
</div>
</div>
</li>
</ul>
</div>
</>
)
}

View File

@ -0,0 +1,15 @@
export default function SuitableNoData() {
return (
<>
<div className="compliace-nosearch">
<span className="mb10"></span>
<span className="mb10"> </span>
<span>
<button className="btn-frame n-blue icon">
<i className="btn-arr"></i>
</button>
</span>
</div>
</>
)
}

View File

@ -1,27 +1,9 @@
'use client'
import { useHeaderStore } from '@/store/header'
import { useSideNavState } from '@/store/sideNavState'
import { usePathname, useRouter } from 'next/navigation'
import { useEffect } from 'react'
import { useRouter } from 'next/navigation'
export default function Main() {
const router = useRouter()
const pathname = usePathname()
const { setBackBtn } = useHeaderStore()
const { reset } = useSideNavState()
/**
*
*
*/
useEffect(() => {
if (pathname === '/') {
setBackBtn(false)
}
//사이드바 초기화
reset()
}, [pathname])
return (
<>
@ -30,7 +12,7 @@ export default function Main() {
<div className="head-block-tit"></div>
<div className="head-block-text">使</div>
<div className="head-block-link-wrap">
<button className="head-block-link">
<button className="head-block-link" onClick={() => alert('test')}>
<i className="block-arr"></i>
</button>
</div>

View File

@ -1,8 +1,12 @@
'use client'
import { usePopupController } from '@/store/popupController'
import MemberInfomationPopup from '../popup/MemberInformationPopup'
import ZipCodePopup from '../popup/ZipCodePopup'
import Alert from './common/Alert'
import DoubleBtnAlert from './common/DoubleBtnAlert'
import SuitableDetailPopup from '../popup/SuitableDetailPopup'
export default function PopupController() {
const popupController = usePopupController()
@ -11,6 +15,9 @@ export default function PopupController() {
<>
{popupController.memberInfomationPopup && <MemberInfomationPopup />}
{popupController.zipCodePopup && <ZipCodePopup />}
{popupController.alert && <Alert />}
{popupController.alert2 && <DoubleBtnAlert />}
{popupController.suitableDetailPopup && <SuitableDetailPopup />}
</>
)
}

View File

@ -0,0 +1,24 @@
'use client'
import { usePopupController } from '@/store/popupController'
export default function Alert() {
const { alertMsg, alertBtn } = usePopupController()
return (
<div className="modal-popup alert">
<div className="modal-dialog">
<div className="modal-content">
<div className="alert-tit">{alertMsg}</div>
<div className="alert-btn-wrap">
<div className="alert-btn-bx">
<button className="btn-frame red min" onClick={() => alertBtn()}>
</button>
</div>
</div>
</div>
</div>
</div>
)
}

View File

@ -0,0 +1,21 @@
import React from 'react'
export default function DoubleBtnAlert() {
return (
<div className="modal-popup alert">
<div className="modal-dialog">
<div className="modal-content">
<div className="alert-tit">?</div>
<div className="alert-btn-wrap">
<div className="alert-btn-bx">
<button className="btn-frame red min"></button>
</div>
<div className="alert-btn-bx">
<button className="btn-frame n-blue min"></button>
</div>
</div>
</div>
</div>
</div>
)
}

View File

@ -0,0 +1,64 @@
'use client'
import { useHeaderStore } from '@/store/header'
import { usePopupController } from '@/store/popupController'
import { useSideNavState } from '@/store/sideNavState'
import { usePathname } from 'next/navigation'
import { useEffect } from 'react'
declare global {
interface Window {
alert2: (msg: string, alert2BtnYes?: () => void, alert2BtnNo?: () => void) => void
}
}
export default function EdgeProvider({ children }: React.PropsWithChildren) {
const pathname = usePathname()
const { setBackBtn } = useHeaderStore()
const { reset } = useSideNavState()
const { setAlertMsg, setAlertBtn, setAlert, setAlert2, setAlert2BtnYes, setAlert2BtnNo } = usePopupController()
const alertFunc = (msg: string, alertBtn: Function) => {
console.log('🚀 ~ alertFunc ~ msg:', msg)
setAlertMsg(msg)
setAlertBtn(alertBtn)
setAlert(true)
}
/**
* alert2
* @param msg alert
* @param alertBtn2Yes alert
* @param alertBtn2No alert
*/
const alertFunc2 = (msg: string, alertBtn2Yes: Function, alertBtn2No: Function) => {
console.log('🚀 ~ alertFunc ~ msg:', msg)
setAlertMsg(msg)
setAlert2BtnYes(alertBtn2Yes)
setAlert2BtnNo(alertBtn2No)
setAlert2(true)
}
useEffect(() => {
window.alert = function (msg, alertBtn = () => setAlert(false)) {
alertFunc(msg, alertBtn)
}
window.alert2 = function (msg, alert2BtnYes = () => setAlert2(false), alert2BtnNo = () => setAlert2(false)) {
alertFunc2(msg, alert2BtnYes, alert2BtnNo)
}
}, [])
/**
*
*
*/
useEffect(() => {
if (pathname === '/') {
setBackBtn(false)
}
//사이드바 초기화
reset()
}, [pathname])
return <>{children}</>
}

View File

@ -3,23 +3,59 @@ import { create } from 'zustand'
type PoupControllerState = {
memberInfomationPopup: boolean
zipCodePopup: boolean
alertMsg: string
setAlertMsg: (value: string) => void
alert: boolean
alertBtn: Function
alert2: boolean
alert2BtnYes: Function
alert2BtnNo: Function
setMemberInfomationPopup: (value: boolean) => void
setZipCodePopup: (value: boolean) => void
setAlert: (value: boolean) => void
setAlertBtn: (value: Function) => void
setAlert2: (value: boolean) => void
setAlert2BtnYes: (value: Function) => void
setAlert2BtnNo: (value: Function) => void
suitableDetailPopup: boolean
setSuitableDetailPopup: (value: boolean) => void
reset: () => void
}
type InitialState = {
memberInfomationPopup: boolean
zipCodePopup: boolean
alertMsg: string
alert: boolean
alertBtn: Function
alert2: boolean
alert2BtnYes: Function
alert2BtnNo: Function
suitableDetailPopup: boolean
}
const initialState: InitialState = {
memberInfomationPopup: false,
zipCodePopup: false,
alertMsg: '',
alert: false,
alertBtn: () => {},
alert2: false,
alert2BtnYes: () => {},
alert2BtnNo: () => {},
suitableDetailPopup: false,
}
export const usePopupController = create<PoupControllerState>((set) => ({
...initialState,
setMemberInfomationPopup: (value: boolean) => set((state) => ({ ...state, memberInfomationPopup: value })),
setZipCodePopup: (value: boolean) => set((state) => ({ ...state, zipCodePopup: value })),
setAlertMsg: (value: string) => set((state) => ({ ...state, alertMsg: value })),
setAlert: (value: boolean) => set((state) => ({ ...state, alert: value })),
setAlertBtn: (value: Function) => set((state) => ({ ...state, alertBtn: value })),
setAlert2: (value: boolean) => set((state) => ({ ...state, alert2: value })),
setAlert2BtnYes: (value: Function) => set((state) => ({ ...state, alert2BtnYes: value })),
setAlert2BtnNo: (value: Function) => set((state) => ({ ...state, alert2BtnNo: value })),
setSuitableDetailPopup: (value: boolean) => set((state) => ({ ...state, suitableDetailPopup: value })),
reset: () => set(initialState),
}))