import 'package:flutter/material.dart'; import 'package:superport/models/company_model.dart'; import 'package:superport/screens/common/theme_shadcn.dart'; import 'package:superport/screens/common/components/shadcn_components.dart'; import 'package:superport/services/mock_data_service.dart'; import 'package:superport/screens/company/widgets/company_branch_dialog.dart'; /// shadcn/ui 스타일로 재설계된 회사 관리 화면 class CompanyListRedesign extends StatefulWidget { const CompanyListRedesign({super.key}); @override State createState() => _CompanyListRedesignState(); } class _CompanyListRedesignState extends State { final MockDataService _dataService = MockDataService(); List _companies = []; int _currentPage = 1; final int _pageSize = 10; @override void initState() { super.initState(); _loadData(); } /// 데이터 로드 void _loadData() { setState(() { _companies = _dataService.getAllCompanies(); _currentPage = 1; }); } /// 회사 추가 화면으로 이동 void _navigateToAddScreen() async { final result = await Navigator.pushNamed(context, '/company/add'); if (result == true) { _loadData(); } } /// 회사 삭제 처리 void _deleteCompany(int id) { showDialog( context: context, builder: (context) => AlertDialog( title: const Text('삭제 확인'), content: const Text('이 회사 정보를 삭제하시겠습니까?'), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: const Text('취소'), ), TextButton( onPressed: () { _dataService.deleteCompany(id); Navigator.pop(context); _loadData(); }, child: const Text('삭제'), ), ], ), ); } /// 지점 다이얼로그 표시 void _showBranchDialog(Company mainCompany) { showDialog( context: context, builder: (context) => CompanyBranchDialog(mainCompany: mainCompany), ); } /// Branch 객체를 Company 객체로 변환 Company _convertBranchToCompany(Branch branch) { return Company( id: branch.id, name: branch.name, address: branch.address, contactName: branch.contactName, contactPosition: branch.contactPosition, contactPhone: branch.contactPhone, contactEmail: branch.contactEmail, companyTypes: [], remark: branch.remark, ); } /// 회사 유형 배지 생성 Widget _buildCompanyTypeChips(List types) { return Wrap( spacing: ShadcnTheme.spacing1, children: types.map((type) { return ShadcnBadge( text: companyTypeToString(type), variant: type == CompanyType.customer ? ShadcnBadgeVariant.primary : ShadcnBadgeVariant.secondary, size: ShadcnBadgeSize.small, ); }).toList(), ); } /// 본사/지점 구분 배지 생성 Widget _buildCompanyTypeLabel(bool isBranch) { return ShadcnBadge( text: isBranch ? '지점' : '본사', variant: isBranch ? ShadcnBadgeVariant.outline : ShadcnBadgeVariant.primary, size: ShadcnBadgeSize.small, ); } /// 회사 이름 표시 (지점인 경우 본사명 포함) Widget _buildCompanyNameText( Company company, bool isBranch, { String? mainCompanyName, }) { if (isBranch && mainCompanyName != null) { return Text.rich( TextSpan( children: [ TextSpan(text: '$mainCompanyName > ', style: ShadcnTheme.bodyMuted), TextSpan(text: company.name, style: ShadcnTheme.bodyMedium), ], ), ); } else { return Text(company.name, style: ShadcnTheme.bodyMedium); } } @override Widget build(BuildContext context) { // 본사와 지점 구분하기 위한 데이터 준비 final List> displayCompanies = []; for (final company in _companies) { displayCompanies.add({ 'company': company, 'isBranch': false, 'mainCompanyName': null, }); if (company.branches != null) { for (final branch in company.branches!) { displayCompanies.add({ 'branch': branch, 'companyId': company.id, 'isBranch': true, 'mainCompanyName': company.name, }); } } } // 페이지네이션 처리 final int totalCount = displayCompanies.length; final int startIndex = (_currentPage - 1) * _pageSize; final int endIndex = (startIndex + _pageSize) > totalCount ? totalCount : (startIndex + _pageSize); final List> pagedCompanies = displayCompanies.sublist( startIndex, endIndex, ); return SingleChildScrollView( padding: const EdgeInsets.all(ShadcnTheme.spacing6), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 헤더 액션 바 Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('총 $totalCount개 회사', style: ShadcnTheme.bodyMuted), ShadcnButton( text: '회사 추가', onPressed: _navigateToAddScreen, variant: ShadcnButtonVariant.primary, textColor: Colors.white, icon: Icon(Icons.add), ), ], ), const SizedBox(height: ShadcnTheme.spacing4), // 테이블 카드 Container( width: double.infinity, decoration: BoxDecoration( color: ShadcnTheme.card, borderRadius: BorderRadius.circular(ShadcnTheme.radiusLg), border: Border.all(color: ShadcnTheme.border), boxShadow: ShadcnTheme.cardShadow, ), child: pagedCompanies.isEmpty ? Container( padding: const EdgeInsets.all(ShadcnTheme.spacing8), child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.business_outlined, size: 48, color: ShadcnTheme.muted, ), const SizedBox(height: ShadcnTheme.spacing4), Text('등록된 회사가 없습니다', style: ShadcnTheme.bodyMuted), ], ), ), ) : Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 테이블 헤더 Container( padding: const EdgeInsets.symmetric( horizontal: ShadcnTheme.spacing4, vertical: ShadcnTheme.spacing3, ), decoration: BoxDecoration( color: ShadcnTheme.muted.withValues(alpha: 0.3), border: Border( bottom: BorderSide(color: ShadcnTheme.border), ), ), child: Row( children: [ Expanded( flex: 1, child: Text( '번호', style: ShadcnTheme.bodyMedium, ), ), Expanded( flex: 3, child: Text( '회사명', style: ShadcnTheme.bodyMedium, ), ), Expanded( flex: 2, child: Text( '구분', style: ShadcnTheme.bodyMedium, ), ), Expanded( flex: 2, child: Text( '유형', style: ShadcnTheme.bodyMedium, ), ), Expanded( flex: 2, child: Text( '연락처', style: ShadcnTheme.bodyMedium, ), ), Expanded( flex: 2, child: Text( '관리', style: ShadcnTheme.bodyMedium, ), ), ], ), ), // 테이블 데이터 ...pagedCompanies.asMap().entries.map((entry) { final int index = entry.key; final companyData = entry.value; final bool isBranch = companyData['isBranch'] as bool; final Company company = isBranch ? _convertBranchToCompany(companyData['branch'] as Branch) : companyData['company'] as Company; final String? mainCompanyName = companyData['mainCompanyName'] as String?; return Container( padding: const EdgeInsets.symmetric( horizontal: ShadcnTheme.spacing4, vertical: ShadcnTheme.spacing3, ), decoration: BoxDecoration( border: Border( bottom: BorderSide(color: ShadcnTheme.border), ), ), child: Row( children: [ // 번호 Expanded( flex: 1, child: Text( '${startIndex + index + 1}', style: ShadcnTheme.bodySmall, ), ), // 회사명 Expanded( flex: 3, child: _buildCompanyNameText( company, isBranch, mainCompanyName: mainCompanyName, ), ), // 구분 Expanded( flex: 2, child: _buildCompanyTypeLabel(isBranch), ), // 유형 Expanded( flex: 2, child: _buildCompanyTypeChips( company.companyTypes, ), ), // 연락처 Expanded( flex: 2, child: Text( company.contactPhone ?? '-', style: ShadcnTheme.bodySmall, ), ), // 관리 Expanded( flex: 2, child: Row( mainAxisSize: MainAxisSize.min, children: [ if (!isBranch && company.branches != null && company.branches!.isNotEmpty) ShadcnButton( text: '지점보기', onPressed: () => _showBranchDialog(company), variant: ShadcnButtonVariant.secondary, size: ShadcnButtonSize.small, ), if (!isBranch && company.branches != null && company.branches!.isNotEmpty) const SizedBox( width: ShadcnTheme.spacing2, ), ShadcnButton( text: '수정', onPressed: company.id != null ? () { if (isBranch) { Navigator.pushNamed( context, '/company/edit', arguments: { 'companyId': companyData['companyId'], 'isBranch': true, 'mainCompanyName': mainCompanyName, 'branchId': company.id, }, ).then((result) { if (result == true) _loadData(); }); } else { Navigator.pushNamed( context, '/company/edit', arguments: { 'companyId': company.id, 'isBranch': false, }, ).then((result) { if (result == true) _loadData(); }); } } : null, variant: ShadcnButtonVariant.secondary, size: ShadcnButtonSize.small, ), const SizedBox( width: ShadcnTheme.spacing2, ), ShadcnButton( text: '삭제', onPressed: (!isBranch && company.id != null) ? () => _deleteCompany(company.id!) : null, variant: ShadcnButtonVariant.destructive, size: ShadcnButtonSize.small, ), ], ), ), ], ), ); }), ], ), ), // 페이지네이션 if (totalCount > _pageSize) Container( padding: const EdgeInsets.symmetric( vertical: ShadcnTheme.spacing4, ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ // 이전 페이지 버튼 ShadcnButton( text: '이전', onPressed: _currentPage > 1 ? () => setState(() => _currentPage--) : null, variant: ShadcnButtonVariant.secondary, size: ShadcnButtonSize.small, ), const SizedBox(width: ShadcnTheme.spacing4), // 페이지 정보 Text( '$_currentPage / ${((totalCount - 1) ~/ _pageSize) + 1}', style: ShadcnTheme.bodyMedium, ), const SizedBox(width: ShadcnTheme.spacing4), // 다음 페이지 버튼 ShadcnButton( text: '다음', onPressed: _currentPage < ((totalCount - 1) ~/ _pageSize) + 1 ? () => setState(() => _currentPage++) : null, variant: ShadcnButtonVariant.secondary, size: ShadcnButtonSize.small, ), ], ), ), ], ), ); } }