Add Customs page to Common Information menu
This commit is contained in:
@@ -4,6 +4,7 @@ import { Layout } from '@/components/layout';
|
||||
import { Dashboard, Todo, Kuntae, Jobreport, Project, Login, CommonCodePage, ItemsPage, UserListPage, MonthlyWorkPage, MailFormPage, UserAuthPage, Note } from '@/pages';
|
||||
import { PatchList } from '@/pages/PatchList';
|
||||
import { MailList } from '@/pages/MailList';
|
||||
import { Customs } from '@/pages/Customs';
|
||||
import { comms } from '@/communication';
|
||||
import { UserInfo } from '@/types';
|
||||
import { Loader2 } from 'lucide-react';
|
||||
@@ -90,6 +91,7 @@ export default function App() {
|
||||
<Route path="/project" element={<Project />} />
|
||||
<Route path="/common" element={<CommonCodePage />} />
|
||||
<Route path="/items" element={<ItemsPage />} />
|
||||
<Route path="/customs" element={<Customs />} />
|
||||
<Route path="/user/list" element={<UserListPage />} />
|
||||
<Route path="/user/auth" element={<UserAuthPage />} />
|
||||
<Route path="/monthly-work" element={<MonthlyWorkPage />} />
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
Shield,
|
||||
List,
|
||||
AlertTriangle,
|
||||
Building,
|
||||
Star,
|
||||
} from 'lucide-react';
|
||||
import { clsx } from 'clsx';
|
||||
@@ -96,6 +97,7 @@ const dropdownMenus: DropdownMenuConfig[] = [
|
||||
items: [
|
||||
{ type: 'link', path: '/common', icon: Code, label: '공용코드' },
|
||||
{ type: 'link', path: '/items', icon: Package, label: '품목정보' },
|
||||
{ type: 'link', path: '/customs', icon: Building, label: '업체정보' },
|
||||
{
|
||||
type: 'submenu',
|
||||
icon: Users,
|
||||
|
||||
137
Project/frontend/src/pages/Customs.tsx
Normal file
137
Project/frontend/src/pages/Customs.tsx
Normal file
@@ -0,0 +1,137 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { Building, Search, RefreshCw } from 'lucide-react';
|
||||
|
||||
// 임시 타입 정의 (실제 타입은 백엔드에 맞게 수정 필요)
|
||||
interface CustomItem {
|
||||
idx: number;
|
||||
ccode: string;
|
||||
cname: string;
|
||||
gubun: string;
|
||||
addr: string;
|
||||
tel: string;
|
||||
fax: string;
|
||||
email: string;
|
||||
ceo: string;
|
||||
busino: string;
|
||||
uptae: string;
|
||||
jongmok: string;
|
||||
}
|
||||
|
||||
export function Customs() {
|
||||
const [customsList, setCustomsList] = useState<CustomItem[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [searchKey, setSearchKey] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
loadData();
|
||||
}, []);
|
||||
|
||||
const loadData = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
// TODO: 실제 API 호출로 변경 필요
|
||||
// const response = await comms.getCustomsList(searchKey);
|
||||
// if (response.Success && response.Data) {
|
||||
// setCustomsList(response.Data);
|
||||
// }
|
||||
|
||||
// 임시 데이터
|
||||
console.log('업체정보 조회 (구현 필요):', { searchKey });
|
||||
alert('업체정보 API가 아직 구현되지 않았습니다.');
|
||||
setCustomsList([]);
|
||||
} catch (error) {
|
||||
console.error('업체정보 로드 오류:', error);
|
||||
alert('데이터를 불러오는 중 오류가 발생했습니다.');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSearch = () => {
|
||||
loadData();
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="space-y-6 animate-fade-in">
|
||||
{/* 검색 필터 */}
|
||||
<div className="glass-effect rounded-2xl p-6">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="flex items-center gap-2 flex-1">
|
||||
<label className="text-white/70 text-sm font-medium whitespace-nowrap">검색어</label>
|
||||
<input
|
||||
type="text"
|
||||
value={searchKey}
|
||||
onChange={(e) => setSearchKey(e.target.value)}
|
||||
onKeyDown={(e) => e.key === 'Enter' && handleSearch()}
|
||||
placeholder="업체명, 사업자번호, 대표자 등"
|
||||
className="flex-1 h-10 bg-white/20 border border-white/30 rounded-lg px-3 text-white placeholder-white/50 focus:outline-none focus:ring-2 focus:ring-primary-400"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<button
|
||||
onClick={handleSearch}
|
||||
disabled={loading}
|
||||
className="h-10 bg-primary-500 hover:bg-primary-600 text-white px-6 rounded-lg transition-colors flex items-center justify-center disabled:opacity-50"
|
||||
>
|
||||
{loading ? (
|
||||
<RefreshCw className="w-4 h-4 mr-2 animate-spin" />
|
||||
) : (
|
||||
<Search className="w-4 h-4 mr-2" />
|
||||
)}
|
||||
조회
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 업체 목록 */}
|
||||
<div className="glass-effect rounded-2xl overflow-hidden">
|
||||
<div className="px-6 py-4 border-b border-white/10 flex items-center justify-between">
|
||||
<h3 className="text-lg font-semibold text-white flex items-center">
|
||||
<Building className="w-5 h-5 mr-2" />
|
||||
업체 정보
|
||||
</h3>
|
||||
<span className="text-white/60 text-sm">{customsList.length}건</span>
|
||||
</div>
|
||||
|
||||
<div className="divide-y divide-white/10 max-h-[calc(100vh-300px)] overflow-y-auto">
|
||||
{loading ? (
|
||||
<div className="px-6 py-8 text-center">
|
||||
<div className="flex items-center justify-center">
|
||||
<RefreshCw className="w-5 h-5 mr-2 animate-spin text-white/50" />
|
||||
<span className="text-white/50">데이터를 불러오는 중...</span>
|
||||
</div>
|
||||
</div>
|
||||
) : customsList.length === 0 ? (
|
||||
<div className="px-6 py-8 text-center">
|
||||
<Building className="w-12 h-12 mx-auto mb-3 text-white/30" />
|
||||
<p className="text-white/50">조회된 데이터가 없습니다.</p>
|
||||
<p className="text-white/40 text-sm mt-2">업체정보 API 구현이 필요합니다.</p>
|
||||
</div>
|
||||
) : (
|
||||
customsList.map((item) => (
|
||||
<div
|
||||
key={item.idx}
|
||||
className="px-6 py-4 hover:bg-white/5 transition-colors"
|
||||
>
|
||||
<div className="flex items-center justify-between gap-4">
|
||||
<div className="flex-1 min-w-0">
|
||||
<h4 className="text-white font-medium mb-1">{item.cname}</h4>
|
||||
<div className="flex items-center gap-4 text-white/60 text-sm">
|
||||
<div>대표: {item.ceo}</div>
|
||||
<div>사업자: {item.busino}</div>
|
||||
<div>업태: {item.uptae}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col items-end gap-1 flex-shrink-0 text-white/60 text-sm">
|
||||
<div>{item.tel}</div>
|
||||
<div>{item.email}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user