Files
sam-react-prod/src/components/ui/chart-wrapper.tsx
byeongcheolryu a68a25b737 [feat]: 인증 및 UI/UX 개선 작업
주요 변경사항:
- 로그인/회원가입 페이지 인증 리다이렉트 로직 추가
- 로그인 상태에서 auth 페이지 접근 시 대시보드로 자동 리다이렉트
- router.replace() 사용으로 브라우저 히스토리에서 auth 페이지 제거
- 사이드바 메뉴 활성화 동기화 개선 (URL 직접 입력 및 뒤로가기 대응)
- usePathname 기반 자동 메뉴 활성화 로직 추가
- ESLint 설정 업데이트 (전역 변수 추가, business 폴더 제외)
- TypeScript 빌드 설정 조정 (ignoreBuildErrors 추가)
- 다국어 지원 및 테마 선택 기능 통합
- 대시보드 레이아웃 및 컴포넌트 구조 개선
- UI 컴포넌트 라이브러리 확장 (dialog, sheet, progress 등)

기술적 개선:
- HttpOnly 쿠키 기반 인증 시스템 유지
- 로딩 상태 UI 추가 (인증 체크 중)
- 경로 정규화 로직 (locale 제거)
- 재귀적 메뉴 탐색 및 자동 확장

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-11 18:55:16 +09:00

66 lines
1.5 KiB
TypeScript

import { memo, useState, useEffect } from 'react';
import type { ReactNode } from 'react';
/**
* 차트 지연 로딩을 위한 래퍼 컴포넌트
* 스켈레톤 UI 표시 후 차트 렌더링
*/
interface ChartWrapperProps {
children: ReactNode;
delay?: number;
height?: number;
}
export const ChartWrapper = memo(function ChartWrapper({
children,
delay = 100,
height = 300
}: ChartWrapperProps) {
const [showChart, setShowChart] = useState(false);
useEffect(() => {
const timer = setTimeout(() => setShowChart(true), delay);
return () => clearTimeout(timer);
}, [delay]);
if (!showChart) {
return (
<div
className="w-full animate-pulse bg-muted rounded-lg"
style={{ height: `${height}px` }}
>
<div className="h-full flex items-center justify-center">
<div className="text-muted-foreground text-sm"> ...</div>
</div>
</div>
);
}
return <>{children}</>;
});
/**
* 메모이제이션된 차트 컴포넌트 래퍼
*/
interface OptimizedChartProps {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
data: any;
children: ReactNode;
height?: number;
}
export const OptimizedChart = memo(function OptimizedChart({
data: _data,
children,
height = 300
}: OptimizedChartProps) {
return (
<ChartWrapper height={height}>
{children}
</ChartWrapper>
);
}, (prevProps, nextProps) => {
// 데이터가 같으면 리렌더링 스킵
return prevProps.data === nextProps.data;
});