feat(WEB): 동적 게시판, 파트너 관리, 공지 팝업 모달 추가

- 동적 게시판 시스템 구현 (/boards/[boardCode])
- 파트너 관리 페이지 및 폼 추가
- 공지 팝업 모달 컴포넌트 (NoticePopupModal)
  - localStorage 기반 1일간 숨김 기능
  - 테스트 페이지 (/test/popup)
- IntegratedListTemplateV2 개선
- 기타 버그 수정 및 타입 개선

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
byeongcheolryu
2025-12-30 21:56:01 +09:00
parent 7b917fcbcd
commit f8dbc6b2ae
43 changed files with 6395 additions and 113 deletions

View File

@@ -16,6 +16,7 @@ import {
SelectTrigger,
SelectValue,
} from '@/components/ui/select';
import { Checkbox } from '@/components/ui/checkbox';
import { ClipboardList, ArrowLeft, Save } from 'lucide-react';
import type { Board, BoardFormData, BoardTarget, BoardStatus } from './types';
import { BOARD_TARGETS, BOARD_STATUS_LABELS } from './types';
@@ -29,6 +30,14 @@ const MOCK_DEPARTMENTS = [
{ id: 5, name: '마케팅팀' },
];
// TODO: API에서 권한 목록 가져오기
const MOCK_PERMISSIONS = [
{ code: 'admin', name: '관리자' },
{ code: 'manager', name: '매니저' },
{ code: 'staff', name: '직원' },
{ code: 'guest', name: '게스트' },
];
interface BoardFormProps {
mode: 'create' | 'edit';
board?: Board;
@@ -56,6 +65,7 @@ export function BoardForm({ mode, board, onSubmit }: BoardFormProps) {
const [formData, setFormData] = useState<BoardFormData>({
target: 'all',
targetName: '',
permissions: [],
boardName: '',
status: 'active',
});
@@ -66,6 +76,7 @@ export function BoardForm({ mode, board, onSubmit }: BoardFormProps) {
setFormData({
target: board.target,
targetName: board.targetName || '',
permissions: board.permissions || [],
boardName: board.boardName,
status: board.status,
});
@@ -89,7 +100,18 @@ export function BoardForm({ mode, board, onSubmit }: BoardFormProps) {
setFormData(prev => ({
...prev,
target: value,
targetName: value === 'all' ? '' : prev.targetName,
targetName: value === 'department' ? prev.targetName : '',
permissions: value === 'permission' ? prev.permissions : [],
}));
};
// 권한 체크박스 핸들러
const handlePermissionChange = (code: string, checked: boolean) => {
setFormData(prev => ({
...prev,
permissions: checked
? [...(prev.permissions || []), code]
: (prev.permissions || []).filter(p => p !== code),
}));
};
@@ -151,6 +173,25 @@ export function BoardForm({ mode, board, onSubmit }: BoardFormProps) {
</SelectContent>
</Select>
)}
{formData.target === 'permission' && (
<div className="flex-1 flex flex-wrap gap-4 items-center border rounded-md px-3 py-2">
{MOCK_PERMISSIONS.map((perm) => (
<div key={perm.code} className="flex items-center space-x-2">
<Checkbox
id={`perm-${perm.code}`}
checked={(formData.permissions || []).includes(perm.code)}
onCheckedChange={(checked) => handlePermissionChange(perm.code, checked as boolean)}
/>
<Label
htmlFor={`perm-${perm.code}`}
className="font-normal cursor-pointer text-sm"
>
{perm.name}
</Label>
</div>
))}
</div>
)}
</div>
</div>