56 lines
1.5 KiB
JavaScript
56 lines
1.5 KiB
JavaScript
|
|
/**
|
||
|
|
* 기능 자동 등록 시스템
|
||
|
|
*
|
||
|
|
* - features/{kebab-case}/{PascalCase}.jsx : 사용자 페이지
|
||
|
|
* - features/{kebab-case}/{PascalCase}Admin.jsx : 관리자 페이지
|
||
|
|
*
|
||
|
|
* 예시:
|
||
|
|
* /boss-crystal → features/boss-crystal/BossCrystal.jsx
|
||
|
|
* /admin/boss-crystal → features/boss-crystal/BossCrystalAdmin.jsx
|
||
|
|
*/
|
||
|
|
|
||
|
|
import { lazy } from 'react'
|
||
|
|
|
||
|
|
// Vite의 import.meta.glob으로 features 폴더 전체를 스캔
|
||
|
|
const userPages = import.meta.glob('./*/*.jsx')
|
||
|
|
|
||
|
|
function slugToPascal(slug) {
|
||
|
|
return slug
|
||
|
|
.split('-')
|
||
|
|
.map((s) => s.charAt(0).toUpperCase() + s.slice(1))
|
||
|
|
.join('')
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* slug에 해당하는 사용자 페이지 컴포넌트 반환
|
||
|
|
* @returns {React.LazyExoticComponent | null}
|
||
|
|
*/
|
||
|
|
export function getUserComponent(slug) {
|
||
|
|
const pascal = slugToPascal(slug)
|
||
|
|
const path = `./${slug}/${pascal}.jsx`
|
||
|
|
const loader = userPages[path]
|
||
|
|
if (!loader) return null
|
||
|
|
return lazy(loader)
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* slug에 해당하는 관리자 페이지 컴포넌트 반환
|
||
|
|
*/
|
||
|
|
export function getAdminComponent(slug) {
|
||
|
|
const pascal = slugToPascal(slug)
|
||
|
|
const path = `./${slug}/${pascal}Admin.jsx`
|
||
|
|
const loader = userPages[path]
|
||
|
|
if (!loader) return null
|
||
|
|
return lazy(loader)
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* slug에 해당하는 관리자 페이지가 존재하는지
|
||
|
|
*/
|
||
|
|
export function hasAdminPage(slug) {
|
||
|
|
if (!slug) return false
|
||
|
|
const cleaned = slug.replace(/^\/+/, '').split('/')[0]
|
||
|
|
const pascal = slugToPascal(cleaned)
|
||
|
|
return !!userPages[`./${cleaned}/${pascal}Admin.jsx`]
|
||
|
|
}
|