fix(WEB): 토큰 만료 시 무한 로딩 대신 로그인 리다이렉트 처리

- 52개 이상의 컴포넌트에 isNextRedirectError 처리 추가
- Server Action의 redirect() 에러가 catch 블록에서 삼켜지는 문제 해결
- access_token + refresh_token 모두 만료 시 정상적으로 로그인 페이지로 리다이렉트

수정된 영역:
- accounting: 10개 컴포넌트
- production: 12개 컴포넌트
- hr: 5개 컴포넌트
- settings: 8개 컴포넌트
- approval: 5개 컴포넌트
- items: 20개+ 컴포넌트
- board: 5개 컴포넌트
- quality: 4개 컴포넌트
- material, outbound, quotes 등 기타 컴포넌트

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
byeongcheolryu
2026-01-11 17:19:11 +09:00
parent 8bc4b90fe9
commit e56b7d53a4
131 changed files with 3320 additions and 1979 deletions

View File

@@ -4,6 +4,7 @@ import { useState, useEffect, useCallback } from 'react';
import { PageLayout } from '@/components/organisms/PageLayout';
import { PageHeader } from '@/components/organisms/PageHeader';
import { Award, Plus, GripVertical, Pencil, Trash2, Loader2 } from 'lucide-react';
import { ContentLoadingSpinner } from '@/components/ui/loading-spinner';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Card, CardContent } from '@/components/ui/card';
@@ -27,6 +28,7 @@ import {
deleteRank,
reorderRanks,
} from './actions';
import { isNextRedirectError } from '@/lib/utils/redirect-error';
export function RankManagement() {
// 직급 데이터
@@ -60,6 +62,7 @@ export function RankManagement() {
toast.error(result.error || '직급 목록을 불러오는데 실패했습니다.');
}
} catch (error) {
if (isNextRedirectError(error)) throw error;
console.error('직급 목록 조회 실패:', error);
toast.error('직급 목록을 불러오는데 실패했습니다.');
} finally {
@@ -87,6 +90,7 @@ export function RankManagement() {
toast.error(result.error || '직급 추가에 실패했습니다.');
}
} catch (error) {
if (isNextRedirectError(error)) throw error;
console.error('직급 추가 실패:', error);
toast.error('직급 추가에 실패했습니다.');
} finally {
@@ -121,6 +125,7 @@ export function RankManagement() {
toast.error(result.error || '직급 삭제에 실패했습니다.');
}
} catch (error) {
if (isNextRedirectError(error)) throw error;
console.error('직급 삭제 실패:', error);
toast.error('직급 삭제에 실패했습니다.');
} finally {
@@ -145,6 +150,7 @@ export function RankManagement() {
toast.error(result.error || '직급 수정에 실패했습니다.');
}
} catch (error) {
if (isNextRedirectError(error)) throw error;
console.error('직급 수정 실패:', error);
toast.error('직급 수정에 실패했습니다.');
} finally {
@@ -180,6 +186,7 @@ export function RankManagement() {
loadRanks();
}
} catch (error) {
if (isNextRedirectError(error)) throw error;
console.error('순서 변경 실패:', error);
toast.error('순서 변경에 실패했습니다.');
// 실패시 원래 순서로 복구
@@ -254,10 +261,7 @@ export function RankManagement() {
<Card>
<CardContent className="p-0">
{isLoading ? (
<div className="flex items-center justify-center py-8">
<Loader2 className="h-6 w-6 animate-spin text-muted-foreground" />
<span className="ml-2 text-muted-foreground"> ...</span>
</div>
<ContentLoadingSpinner text="직급 목록을 불러오는 중..." />
) : (
<div className="divide-y">
{ranks.map((rank, index) => (