import 'package:flutter/material.dart'; import 'package:superport/models/company_model.dart'; import 'package:superport/screens/company/widgets/company_info_card.dart'; import 'package:pdf/widgets.dart' as pw; // PDF 생성용 import 'package:printing/printing.dart'; // PDF 프린트/미리보기용 import 'dart:typed_data'; // Uint8List import 'package:pdf/pdf.dart'; // PdfColors, PageFormat 등 전체 임포트 import 'package:superport/screens/common/custom_widgets.dart'; // DataTableCard 사용을 위한 import import 'package:flutter/services.dart'; // rootBundle 사용을 위한 import /// 본사와 지점 리스트를 보여주는 다이얼로그 위젯 class CompanyBranchDialog extends StatelessWidget { final Company mainCompany; const CompanyBranchDialog({super.key, required this.mainCompany}); // 본사+지점 정보를 PDF로 생성하는 함수 Future _buildPdf(final pw.Document pdf) async { // 한글 폰트 로드 (lib/assets/fonts/NotoSansKR-VariableFont_wght.ttf) final fontData = await rootBundle.load( 'lib/assets/fonts/NotoSansKR-VariableFont_wght.ttf', ); final ttf = pw.Font.ttf(fontData); final List branchList = mainCompany.branches ?? []; pdf.addPage( pw.Page( build: (pw.Context context) { return pw.Column( crossAxisAlignment: pw.CrossAxisAlignment.start, children: [ pw.Text( '본사 및 지점 목록', style: pw.TextStyle( font: ttf, // 한글 폰트 적용 fontSize: 20, fontWeight: pw.FontWeight.bold, ), ), pw.SizedBox(height: 16), pw.Table( border: pw.TableBorder.all(color: PdfColors.grey800), defaultVerticalAlignment: pw.TableCellVerticalAlignment.middle, children: [ pw.TableRow( decoration: pw.BoxDecoration(color: PdfColors.grey300), children: [ pw.Padding( padding: const pw.EdgeInsets.all(4), child: pw.Text('구분', style: pw.TextStyle(font: ttf)), ), pw.Padding( padding: const pw.EdgeInsets.all(4), child: pw.Text('이름', style: pw.TextStyle(font: ttf)), ), pw.Padding( padding: const pw.EdgeInsets.all(4), child: pw.Text('우편번호', style: pw.TextStyle(font: ttf)), ), pw.Padding( padding: const pw.EdgeInsets.all(4), child: pw.Text('담당자', style: pw.TextStyle(font: ttf)), ), pw.Padding( padding: const pw.EdgeInsets.all(4), child: pw.Text('직책', style: pw.TextStyle(font: ttf)), ), pw.Padding( padding: const pw.EdgeInsets.all(4), child: pw.Text('전화번호', style: pw.TextStyle(font: ttf)), ), pw.Padding( padding: const pw.EdgeInsets.all(4), child: pw.Text('이메일', style: pw.TextStyle(font: ttf)), ), ], ), // 본사 pw.TableRow( children: [ pw.Padding( padding: const pw.EdgeInsets.all(4), child: pw.Text('본사', style: pw.TextStyle(font: ttf)), ), pw.Padding( padding: const pw.EdgeInsets.all(4), child: pw.Text( mainCompany.name, style: pw.TextStyle(font: ttf), ), ), pw.Padding( padding: const pw.EdgeInsets.all(4), child: pw.Text( mainCompany.address.zipCode, style: pw.TextStyle(font: ttf), ), ), pw.Padding( padding: const pw.EdgeInsets.all(4), child: pw.Text( mainCompany.contactName ?? '', style: pw.TextStyle(font: ttf), ), ), pw.Padding( padding: const pw.EdgeInsets.all(4), child: pw.Text( mainCompany.contactPosition ?? '', style: pw.TextStyle(font: ttf), ), ), pw.Padding( padding: const pw.EdgeInsets.all(4), child: pw.Text( mainCompany.contactPhone ?? '', style: pw.TextStyle(font: ttf), ), ), pw.Padding( padding: const pw.EdgeInsets.all(4), child: pw.Text( mainCompany.contactEmail ?? '', style: pw.TextStyle(font: ttf), ), ), ], ), // 지점 ...branchList.map( (branch) => pw.TableRow( children: [ pw.Padding( padding: const pw.EdgeInsets.all(4), child: pw.Text('지점', style: pw.TextStyle(font: ttf)), ), pw.Padding( padding: const pw.EdgeInsets.all(4), child: pw.Text( branch.name, style: pw.TextStyle(font: ttf), ), ), pw.Padding( padding: const pw.EdgeInsets.all(4), child: pw.Text( branch.address.zipCode, style: pw.TextStyle(font: ttf), ), ), pw.Padding( padding: const pw.EdgeInsets.all(4), child: pw.Text( branch.contactName ?? '', style: pw.TextStyle(font: ttf), ), ), pw.Padding( padding: const pw.EdgeInsets.all(4), child: pw.Text( branch.contactPosition ?? '', style: pw.TextStyle(font: ttf), ), ), pw.Padding( padding: const pw.EdgeInsets.all(4), child: pw.Text( branch.contactPhone ?? '', style: pw.TextStyle(font: ttf), ), ), pw.Padding( padding: const pw.EdgeInsets.all(4), child: pw.Text( branch.contactEmail ?? '', style: pw.TextStyle(font: ttf), ), ), ], ), ), ], ), ], ); }, ), ); return pdf.save(); } // 프린트 버튼 클릭 시 PDF 미리보기 및 인쇄 void _printPopupData() async { final pdf = pw.Document(); await Printing.layoutPdf( onLayout: (format) async { return _buildPdf(pdf); }, ); } @override Widget build(BuildContext context) { final List branchList = mainCompany.branches ?? []; // 본사와 지점 정보를 한 리스트로 합침 final List> displayList = [ { 'type': '본사', 'name': mainCompany.name, 'companyTypes': mainCompany.companyTypes, 'address': mainCompany.address, 'contactName': mainCompany.contactName, 'contactPosition': mainCompany.contactPosition, 'contactPhone': mainCompany.contactPhone, 'contactEmail': mainCompany.contactEmail, }, ...branchList.map( (branch) => { 'type': '지점', 'name': branch.name, 'companyTypes': mainCompany.companyTypes, 'address': branch.address, 'contactName': branch.contactName, 'contactPosition': branch.contactPosition, 'contactPhone': branch.contactPhone, 'contactEmail': branch.contactEmail, }, ), ]; final double maxDialogHeight = MediaQuery.of(context).size.height * 0.7; final double maxDialogWidth = MediaQuery.of(context).size.width * 0.8; return Dialog( child: ConstrainedBox( constraints: BoxConstraints( maxHeight: maxDialogHeight, maxWidth: maxDialogWidth, ), child: Padding( padding: const EdgeInsets.all(24.0), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text( '본사 및 지점 목록', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), ), Row( children: [ IconButton( icon: const Icon(Icons.print), tooltip: '프린트', onPressed: _printPopupData, ), IconButton( icon: const Icon(Icons.close), onPressed: () => Navigator.of(context).pop(), ), ], ), ], ), const SizedBox(height: 16), Expanded( child: DataTableCard( width: maxDialogWidth - 48, child: SingleChildScrollView( scrollDirection: Axis.horizontal, child: Container( width: maxDialogWidth - 48, constraints: BoxConstraints(minWidth: 900), child: SingleChildScrollView( scrollDirection: Axis.vertical, child: DataTable( columns: const [ DataColumn(label: Text('번호')), DataColumn(label: Text('구분')), DataColumn(label: Text('회사명')), DataColumn(label: Text('유형')), DataColumn(label: Text('주소')), DataColumn(label: Text('담당자')), DataColumn(label: Text('직책')), DataColumn(label: Text('전화번호')), DataColumn(label: Text('이메일')), ], rows: displayList.asMap().entries.map((entry) { final int index = entry.key; final data = entry.value; return DataRow( cells: [ DataCell(Text('${index + 1}')), DataCell(Text(data['type'])), DataCell(Text(data['name'])), DataCell( Row( children: (data['companyTypes'] as List) .map( (type) => Container( margin: const EdgeInsets.only( right: 4, ), padding: const EdgeInsets.symmetric( horizontal: 8, vertical: 2, ), decoration: BoxDecoration( color: type == CompanyType .customer ? Colors .blue .shade50 : Colors .green .shade50, borderRadius: BorderRadius.circular( 8, ), ), child: Text( companyTypeToString(type), style: TextStyle( color: type == CompanyType .customer ? Colors .blue .shade800 : Colors .green .shade800, fontWeight: FontWeight.bold, fontSize: 14, ), ), ), ) .toList(), ), ), DataCell(Text(data['address'].toString())), DataCell(Text(data['contactName'] ?? '')), DataCell( Text(data['contactPosition'] ?? ''), ), DataCell(Text(data['contactPhone'] ?? '')), DataCell(Text(data['contactEmail'] ?? '')), ], ); }).toList(), ), ), ), ), ), ), ], ), ), ), ); } }