feat: ESLint 정리 및 전체 코드 품질 개선
- eslint.config.mjs 규칙 강화 및 정리 - 전역 unused import/변수 제거 (312개 파일) - next.config.ts, middleware, proxy route 개선 - CopyableCell molecule 추가 - 회계/결재/HR/생산/건설/품질/영업 등 전 도메인 lint 정리 - IntegratedListTemplateV2, DataTable, MobileCard 등 공통 컴포넌트 개선 - execute-server-action 에러 핸들링 보강
This commit is contained in:
@@ -40,7 +40,7 @@ import {
|
||||
type StatCard,
|
||||
} from '@/components/templates/UniversalListPage';
|
||||
import { ListMobileCard, InfoField } from '@/components/organisms/MobileCard';
|
||||
import type { Account, AccountCategory } from './types';
|
||||
import type { Account } from './types';
|
||||
import {
|
||||
BANK_LABELS,
|
||||
ACCOUNT_CATEGORY_LABELS,
|
||||
@@ -215,11 +215,11 @@ export function AccountManagement() {
|
||||
// 테이블 컬럼
|
||||
columns: [
|
||||
{ key: 'no', label: 'No.', className: 'text-center w-[60px]' },
|
||||
{ key: 'category', label: '구분', className: 'min-w-[80px]' },
|
||||
{ key: 'accountType', label: '유형', className: 'min-w-[80px]' },
|
||||
{ key: 'institution', label: '금융기관', className: 'min-w-[100px]' },
|
||||
{ key: 'accountNumber', label: '계좌번호', className: 'min-w-[160px]' },
|
||||
{ key: 'accountName', label: '계좌명', className: 'min-w-[120px]' },
|
||||
{ key: 'category', label: '구분', className: 'min-w-[80px]', copyable: true },
|
||||
{ key: 'accountType', label: '유형', className: 'min-w-[80px]', copyable: true },
|
||||
{ key: 'institution', label: '금융기관', className: 'min-w-[100px]', copyable: true },
|
||||
{ key: 'accountNumber', label: '계좌번호', className: 'min-w-[160px]', copyable: true },
|
||||
{ key: 'accountName', label: '계좌명', className: 'min-w-[120px]', copyable: true },
|
||||
{ key: 'status', label: '상태', className: 'min-w-[70px]' },
|
||||
],
|
||||
|
||||
@@ -279,7 +279,7 @@ export function AccountManagement() {
|
||||
item: Account,
|
||||
_index: number,
|
||||
globalIndex: number,
|
||||
handlers: SelectionHandlers & RowClickHandlers<Account>
|
||||
_handlers: SelectionHandlers & RowClickHandlers<Account>
|
||||
) => {
|
||||
return (
|
||||
<TableRow
|
||||
@@ -321,8 +321,8 @@ export function AccountManagement() {
|
||||
renderMobileCard: (
|
||||
item: Account,
|
||||
_index: number,
|
||||
globalIndex: number,
|
||||
handlers: SelectionHandlers & RowClickHandlers<Account>
|
||||
_globalIndex: number,
|
||||
_handlers: SelectionHandlers & RowClickHandlers<Account>
|
||||
) => {
|
||||
return (
|
||||
<ListMobileCard
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import { X } from 'lucide-react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Label } from '@/components/ui/label';
|
||||
@@ -83,7 +82,7 @@ export function AddCompanyDialog({ open, onOpenChange }: AddCompanyDialogProps)
|
||||
}
|
||||
|
||||
setAlertOpen(true);
|
||||
} catch (error) {
|
||||
} catch (_error) {
|
||||
setAlertMessage('사업자등록번호 조회 중 오류가 발생했습니다.');
|
||||
setAlertOpen(true);
|
||||
} finally {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use client';
|
||||
|
||||
import { useState, useRef, useCallback, useEffect } from 'react';
|
||||
import { useState, useCallback, useEffect } from 'react';
|
||||
import { useDaumPostcode } from '@/hooks/useDaumPostcode';
|
||||
import { Building2, Plus, Save, X, Loader2 } from 'lucide-react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
|
||||
@@ -7,7 +7,6 @@ import { CalendarDays, Loader2 } from 'lucide-react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { ContentSkeleton } from '@/components/ui/skeleton';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { QuantityInput } from '@/components/ui/quantity-input';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
import { Switch } from '@/components/ui/switch';
|
||||
@@ -27,7 +26,6 @@ import {
|
||||
MONTH_OPTIONS,
|
||||
DAY_OPTIONS,
|
||||
} from './types';
|
||||
import { isNextRedirectError } from '@/lib/utils/redirect-error';
|
||||
|
||||
export function LeavePolicyManagement() {
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
@@ -49,12 +49,12 @@ export function PaymentHistoryClient({
|
||||
initialPagination,
|
||||
}: PaymentHistoryClientProps) {
|
||||
// ===== 상태 관리 =====
|
||||
const [sortOption, setSortOption] = useState<SortOption>('latest');
|
||||
const [, _setSortOption] = useState<SortOption>('latest');
|
||||
const itemsPerPage = initialPagination.perPage;
|
||||
|
||||
// 거래명세서 팝업 상태
|
||||
const [showInvoiceDialog, setShowInvoiceDialog] = useState(false);
|
||||
const [selectedPaymentId, setSelectedPaymentId] = useState<string | null>(null);
|
||||
const [, setSelectedPaymentId] = useState<string | null>(null);
|
||||
|
||||
// ===== 거래명세서 버튼 클릭 =====
|
||||
const handleViewInvoice = useCallback((paymentId: string) => {
|
||||
@@ -101,11 +101,11 @@ export function PaymentHistoryClient({
|
||||
|
||||
// 테이블 컬럼
|
||||
columns: [
|
||||
{ key: 'paymentDate', label: '결제일' },
|
||||
{ key: 'subscriptionName', label: '구독명' },
|
||||
{ key: 'paymentMethod', label: '결제 수단' },
|
||||
{ key: 'subscriptionPeriod', label: '구독 기간' },
|
||||
{ key: 'amount', label: '금액', className: 'text-right' },
|
||||
{ key: 'paymentDate', label: '결제일', copyable: true },
|
||||
{ key: 'subscriptionName', label: '구독명', copyable: true },
|
||||
{ key: 'paymentMethod', label: '결제 수단', copyable: true },
|
||||
{ key: 'subscriptionPeriod', label: '구독 기간', copyable: true },
|
||||
{ key: 'amount', label: '금액', className: 'text-right', copyable: true },
|
||||
{ key: 'invoice', label: '거래명세서', className: 'text-center' },
|
||||
],
|
||||
|
||||
@@ -124,8 +124,8 @@ export function PaymentHistoryClient({
|
||||
renderTableRow: (
|
||||
item: PaymentHistory,
|
||||
index: number,
|
||||
globalIndex: number,
|
||||
handlers: SelectionHandlers & RowClickHandlers<PaymentHistory>
|
||||
_globalIndex: number,
|
||||
_handlers: SelectionHandlers & RowClickHandlers<PaymentHistory>
|
||||
) => {
|
||||
const isLatest = index === 0;
|
||||
|
||||
@@ -175,7 +175,7 @@ export function PaymentHistoryClient({
|
||||
item: PaymentHistory,
|
||||
index: number,
|
||||
globalIndex: number,
|
||||
handlers: SelectionHandlers & RowClickHandlers<PaymentHistory>
|
||||
_handlers: SelectionHandlers & RowClickHandlers<PaymentHistory>
|
||||
) => {
|
||||
const isLatest = globalIndex === 1;
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
type UniversalListConfig,
|
||||
type TableColumn,
|
||||
} from '@/components/templates/UniversalListPage';
|
||||
import { ListMobileCard, InfoField } from '@/components/organisms/MobileCard';
|
||||
import { ListMobileCard } from '@/components/organisms/MobileCard';
|
||||
import { formatNumber } from '@/lib/utils/amount';
|
||||
import type { PaymentHistory, SortOption } from './types';
|
||||
|
||||
@@ -36,8 +36,8 @@ export function PaymentHistoryManagement({
|
||||
initialPagination,
|
||||
}: PaymentHistoryManagementProps) {
|
||||
// ===== 상태 관리 =====
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
const [sortOption, setSortOption] = useState<SortOption>('latest');
|
||||
const [searchQuery, _setSearchQuery] = useState('');
|
||||
const [sortOption, _setSortOption] = useState<SortOption>('latest');
|
||||
const [currentPage, setCurrentPage] = useState(initialPagination.currentPage);
|
||||
const itemsPerPage = initialPagination.perPage;
|
||||
|
||||
@@ -74,7 +74,7 @@ export function PaymentHistoryManagement({
|
||||
return result;
|
||||
}, [data, searchQuery, sortOption]);
|
||||
|
||||
const paginatedData = useMemo(() => {
|
||||
const _paginatedData = useMemo(() => {
|
||||
const startIndex = (currentPage - 1) * itemsPerPage;
|
||||
return filteredData.slice(startIndex, startIndex + itemsPerPage);
|
||||
}, [filteredData, currentPage, itemsPerPage]);
|
||||
@@ -88,11 +88,11 @@ export function PaymentHistoryManagement({
|
||||
|
||||
// ===== 테이블 컬럼 =====
|
||||
const tableColumns: TableColumn[] = useMemo(() => [
|
||||
{ key: 'paymentDate', label: '결제일' },
|
||||
{ key: 'subscriptionName', label: '구독명' },
|
||||
{ key: 'paymentMethod', label: '결제 수단' },
|
||||
{ key: 'subscriptionPeriod', label: '구독 기간' },
|
||||
{ key: 'amount', label: '금액', className: 'text-right' },
|
||||
{ key: 'paymentDate', label: '결제일', copyable: true },
|
||||
{ key: 'subscriptionName', label: '구독명', copyable: true },
|
||||
{ key: 'paymentMethod', label: '결제 수단', copyable: true },
|
||||
{ key: 'subscriptionPeriod', label: '구독 기간', copyable: true },
|
||||
{ key: 'amount', label: '금액', className: 'text-right', copyable: true },
|
||||
{ key: 'invoice', label: '거래명세서', className: 'text-center' },
|
||||
], []);
|
||||
|
||||
@@ -100,8 +100,8 @@ export function PaymentHistoryManagement({
|
||||
const renderTableRow = useCallback((
|
||||
item: PaymentHistory,
|
||||
index: number,
|
||||
globalIndex: number,
|
||||
handlers: { isSelected: boolean; onToggle: () => void; onRowClick?: () => void }
|
||||
_globalIndex: number,
|
||||
_handlers: { isSelected: boolean; onToggle: () => void; onRowClick?: () => void }
|
||||
) => {
|
||||
const isLatest = index === 0; // 최신 항목 (초록색 버튼)
|
||||
|
||||
@@ -145,7 +145,7 @@ export function PaymentHistoryManagement({
|
||||
item: PaymentHistory,
|
||||
index: number,
|
||||
globalIndex: number,
|
||||
handlers: { isSelected: boolean; onToggle: () => void; onRowClick?: () => void }
|
||||
_handlers: { isSelected: boolean; onToggle: () => void; onRowClick?: () => void }
|
||||
) => {
|
||||
const isLatest = globalIndex === 1;
|
||||
|
||||
|
||||
@@ -140,7 +140,7 @@ export function PermissionDetailClient({ permissionId, isNew = false, mode = 'vi
|
||||
|
||||
// 권한 매트릭스 데이터
|
||||
const [menuTree, setMenuTree] = useState<MenuTreeItem[]>([]);
|
||||
const [permissionTypes, setPermissionTypes] = useState<string[]>([]);
|
||||
const [, setPermissionTypes] = useState<string[]>([]);
|
||||
const [matrix, setMatrix] = useState<PermissionMatrix | null>(null);
|
||||
|
||||
// UI 상태
|
||||
|
||||
@@ -7,13 +7,11 @@ import {
|
||||
Shield,
|
||||
Plus,
|
||||
Pencil,
|
||||
Edit,
|
||||
Trash2,
|
||||
Settings,
|
||||
Eye,
|
||||
EyeOff,
|
||||
Users,
|
||||
Loader2,
|
||||
} from 'lucide-react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Checkbox } from '@/components/ui/checkbox';
|
||||
@@ -102,7 +100,7 @@ export function PermissionManagement() {
|
||||
});
|
||||
}, []);
|
||||
|
||||
const toggleSelectAll = useCallback(() => {
|
||||
const _toggleSelectAll = useCallback(() => {
|
||||
if (selectedItems.size === filteredData.length && filteredData.length > 0) {
|
||||
setSelectedItems(new Set());
|
||||
} else {
|
||||
@@ -247,10 +245,10 @@ export function PermissionManagement() {
|
||||
const tableColumns: TableColumn[] = useMemo(() => {
|
||||
const baseColumns: TableColumn[] = [
|
||||
{ key: 'index', label: '번호', className: 'text-center w-[80px]' },
|
||||
{ key: 'name', label: '역할', className: 'flex-1' },
|
||||
{ key: 'description', label: '설명', className: 'flex-1' },
|
||||
{ key: 'name', label: '역할', className: 'flex-1', copyable: true },
|
||||
{ key: 'description', label: '설명', className: 'flex-1', copyable: true },
|
||||
{ key: 'status', label: '상태', className: 'text-center w-[100px]' },
|
||||
{ key: 'createdAt', label: '등록일', className: 'text-center w-[120px]' },
|
||||
{ key: 'createdAt', label: '등록일', className: 'text-center w-[120px]', copyable: true },
|
||||
];
|
||||
|
||||
if (selectedItems.size > 0) {
|
||||
|
||||
@@ -71,12 +71,12 @@ export function PopupList({ initialData }: PopupListProps) {
|
||||
// 테이블 컬럼
|
||||
columns: [
|
||||
{ key: 'no', label: '번호', className: 'w-[60px] text-center' },
|
||||
{ key: 'target', label: '대상', className: 'w-[80px] text-center' },
|
||||
{ key: 'title', label: '제목', className: 'min-w-[150px]' },
|
||||
{ key: 'target', label: '대상', className: 'w-[80px] text-center', copyable: true },
|
||||
{ key: 'title', label: '제목', className: 'min-w-[150px]', copyable: true },
|
||||
{ key: 'status', label: '상태', className: 'w-[80px] text-center' },
|
||||
{ key: 'author', label: '작성자', className: 'w-[100px] text-center' },
|
||||
{ key: 'createdAt', label: '등록일', className: 'w-[110px] text-center' },
|
||||
{ key: 'period', label: '기간', className: 'w-[180px] text-center' },
|
||||
{ key: 'author', label: '작성자', className: 'w-[100px] text-center', copyable: true },
|
||||
{ key: 'createdAt', label: '등록일', className: 'w-[110px] text-center', copyable: true },
|
||||
{ key: 'period', label: '기간', className: 'w-[180px] text-center', copyable: true },
|
||||
],
|
||||
|
||||
// 클라이언트 사이드 필터링
|
||||
|
||||
@@ -49,7 +49,7 @@ export function SubscriptionClient({ initialData }: SubscriptionClientProps) {
|
||||
} else {
|
||||
toast.error(result.error || '내보내기 요청에 실패했습니다.');
|
||||
}
|
||||
} catch (error) {
|
||||
} catch (_error) {
|
||||
toast.error('서버 오류가 발생했습니다.');
|
||||
} finally {
|
||||
setIsExporting(false);
|
||||
|
||||
@@ -6,7 +6,6 @@ import { PageHeader } from '@/components/organisms/PageHeader';
|
||||
import { Clock, Save, Loader2 } from 'lucide-react';
|
||||
import { getWorkSetting, updateWorkSetting } from './actions';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { TimePicker } from '@/components/ui/time-picker';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { QuantityInput } from '@/components/ui/quantity-input';
|
||||
|
||||
Reference in New Issue
Block a user