feat(WEB): 리스트 페이지 권한 시스템 통합 및 중복 권한 로직 제거
- PermissionContext 기능 확장 (권한 조회 액션 추가) - usePermission 훅 개선 - 회계 모듈 권한 통합: 매입/매출/입금/지출/채권/거래처/어음/일보/부실채권 - 인사 모듈 권한 통합: 근태/카드/급여 관리 - 전자결재 권한 통합: 기안함/결재함 - 게시판/품목/단가/팝업/구독 리스트 권한 적용 - UniversalListPage 권한 연동 - 각 컴포넌트 중복 권한 체크 코드 제거 (-828줄) - 권한 검증 QA 체크리스트 추가 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -11,8 +11,7 @@
|
||||
|
||||
import { useMemo, useCallback } from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { Megaphone, Pencil, Trash2 } from 'lucide-react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Megaphone } from 'lucide-react';
|
||||
import { Checkbox } from '@/components/ui/checkbox';
|
||||
import { TableCell, TableRow } from '@/components/ui/table';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
@@ -41,13 +40,6 @@ export function PopupList({ initialData }: PopupListProps) {
|
||||
[router]
|
||||
);
|
||||
|
||||
const handleEdit = useCallback(
|
||||
(id: string) => {
|
||||
router.push(`/ko/settings/popup-management/${id}?mode=edit`);
|
||||
},
|
||||
[router]
|
||||
);
|
||||
|
||||
const handleCreate = useCallback(() => {
|
||||
router.push('/ko/settings/popup-management?mode=new');
|
||||
}, [router]);
|
||||
@@ -85,7 +77,6 @@ export function PopupList({ initialData }: PopupListProps) {
|
||||
{ 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: 'actions', label: '작업', className: 'w-[180px] text-center' },
|
||||
],
|
||||
|
||||
// 클라이언트 사이드 필터링
|
||||
@@ -148,29 +139,6 @@ export function PopupList({ initialData }: PopupListProps) {
|
||||
<TableCell className="text-center">
|
||||
{item.startDate}~{item.endDate}
|
||||
</TableCell>
|
||||
<TableCell className="text-center" onClick={(e) => e.stopPropagation()}>
|
||||
{handlers.isSelected && (
|
||||
<div className="flex items-center justify-center gap-1">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => handleEdit(item.id)}
|
||||
title="수정"
|
||||
>
|
||||
<Pencil className="h-4 w-4" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => handlers.onDelete?.(item)}
|
||||
title="삭제"
|
||||
className="text-destructive hover:text-destructive"
|
||||
>
|
||||
<Trash2 className="h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
},
|
||||
@@ -213,21 +181,6 @@ export function PopupList({ initialData }: PopupListProps) {
|
||||
<div className="text-sm text-muted-foreground">
|
||||
기간: {item.startDate} ~ {item.endDate}
|
||||
</div>
|
||||
{handlers.isSelected && (
|
||||
<div className="flex gap-2 pt-2" onClick={(e) => e.stopPropagation()}>
|
||||
<Button variant="outline" size="sm" onClick={() => handleEdit(item.id)}>
|
||||
수정
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="text-destructive"
|
||||
onClick={() => handlers.onDelete?.(item)}
|
||||
>
|
||||
삭제
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
@@ -235,7 +188,7 @@ export function PopupList({ initialData }: PopupListProps) {
|
||||
);
|
||||
},
|
||||
}),
|
||||
[handleRowClick, handleEdit, handleCreate]
|
||||
[handleRowClick, handleCreate]
|
||||
);
|
||||
|
||||
return <UniversalListPage config={config} initialData={initialData} />;
|
||||
|
||||
@@ -10,6 +10,7 @@ import { ConfirmDialog } from '@/components/ui/confirm-dialog';
|
||||
import { PageLayout } from '@/components/organisms/PageLayout';
|
||||
import { PageHeader } from '@/components/organisms/PageHeader';
|
||||
import { toast } from 'sonner';
|
||||
import { usePermission } from '@/hooks/usePermission';
|
||||
import { cancelSubscription, requestDataExport } from './actions';
|
||||
import type { SubscriptionInfo } from './types';
|
||||
import { PLAN_LABELS, SUBSCRIPTION_STATUS_LABELS } from './types';
|
||||
@@ -36,6 +37,7 @@ const formatCurrency = (amount: number): string => {
|
||||
};
|
||||
|
||||
export function SubscriptionClient({ initialData }: SubscriptionClientProps) {
|
||||
const { canExport } = usePermission();
|
||||
const [subscription, setSubscription] = useState<SubscriptionInfo>(initialData);
|
||||
const [showCancelDialog, setShowCancelDialog] = useState(false);
|
||||
const [isExporting, setIsExporting] = useState(false);
|
||||
@@ -101,14 +103,16 @@ export function SubscriptionClient({ initialData }: SubscriptionClientProps) {
|
||||
icon={CreditCard}
|
||||
actions={
|
||||
<div className="flex items-center gap-2">
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={handleExportData}
|
||||
disabled={isExporting}
|
||||
>
|
||||
<Download className="w-4 h-4 mr-2" />
|
||||
{isExporting ? '처리 중...' : '자료 내보내기'}
|
||||
</Button>
|
||||
{canExport && (
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={handleExportData}
|
||||
disabled={isExporting}
|
||||
>
|
||||
<Download className="w-4 h-4 mr-2" />
|
||||
{isExporting ? '처리 중...' : '자료 내보내기'}
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
variant="outline"
|
||||
className="border-red-200 text-red-600 hover:bg-red-50 hover:border-red-300"
|
||||
|
||||
Reference in New Issue
Block a user