158 lines
5.6 KiB
Python
158 lines
5.6 KiB
Python
"""
|
|
顧客選択モーダルコンポーネント
|
|
Flutter風のModalBottomSheetをFletで実装
|
|
"""
|
|
|
|
import flet as ft
|
|
from typing import List, Callable, Optional
|
|
from models.invoice_models import Customer
|
|
|
|
class CustomerPickerModal:
|
|
"""顧客選択モーダル"""
|
|
|
|
def __init__(self, page: ft.Page, customers: List[Customer],
|
|
on_customer_selected: Callable[[Customer], None],
|
|
on_customer_deleted: Callable[[Customer], None] = None):
|
|
self.page = page
|
|
self.customers = customers
|
|
self.on_customer_selected = on_customer_selected
|
|
self.on_customer_deleted = on_customer_deleted
|
|
self.is_open = False
|
|
|
|
def open(self):
|
|
"""モーダルを開く"""
|
|
self.is_open = True
|
|
self.show_modal()
|
|
|
|
def close(self):
|
|
"""モーダルを閉じる"""
|
|
self.is_open = False
|
|
self.hide_modal()
|
|
|
|
def show_modal(self):
|
|
"""モーダル表示"""
|
|
# 検索テキストフィールド
|
|
search_field = ft.TextField(
|
|
label="顧客検索",
|
|
prefix_icon=ft.Icons.SEARCH,
|
|
on_change=self.filter_customers,
|
|
expand=True,
|
|
)
|
|
|
|
# 顧客リスト
|
|
customer_list = ft.Column([], scroll=ft.ScrollMode.AUTO, expand=True)
|
|
|
|
# モーダルダイアログ
|
|
modal_dialog = ft.AlertDialog(
|
|
title=ft.Text("顧客選択"),
|
|
content=ft.Column([
|
|
search_field,
|
|
ft.Container(height=10),
|
|
ft.Container(
|
|
content=customer_list,
|
|
height=300,
|
|
width=400,
|
|
),
|
|
ft.Container(height=10),
|
|
ft.Button(
|
|
content=ft.Row([
|
|
ft.Icon(ft.Icons.ADD),
|
|
ft.Text("新規顧客を登録"),
|
|
], alignment=ft.MainAxisAlignment.CENTER),
|
|
on_click=self.add_new_customer,
|
|
bgcolor=ft.Colors.BLUE_GREY_800,
|
|
),
|
|
], tight=True),
|
|
actions=[
|
|
ft.TextButton("キャンセル", on_click=lambda _: self.close()),
|
|
],
|
|
actions_alignment=ft.MainAxisAlignment.END,
|
|
)
|
|
|
|
# ダイアログを開く
|
|
self.page.dialog = modal_dialog
|
|
modal_dialog.open = True
|
|
self.page.update()
|
|
|
|
# 初期データ表示
|
|
self.update_customer_list_simple(customer_list, self.customers)
|
|
|
|
def hide_modal(self):
|
|
"""モーダルを非表示"""
|
|
self.page.overlay.clear()
|
|
self.page.update()
|
|
|
|
def filter_customers(self, e=None):
|
|
"""顧客フィルタリング"""
|
|
search_text = e.control.value.lower() if e else ""
|
|
|
|
filtered_customers = [
|
|
customer for customer in self.customers
|
|
if search_text in customer.name.lower() or
|
|
search_text in customer.formal_name.lower()
|
|
]
|
|
|
|
self.update_customer_list(filtered_customers)
|
|
|
|
def update_customer_list_simple(self, customer_list, customers: List[Customer]):
|
|
"""顧客リスト更新(シンプル版)"""
|
|
customer_list.controls.clear()
|
|
|
|
for customer in customers:
|
|
card = self.create_customer_card(customer)
|
|
customer_list.controls.append(card)
|
|
|
|
self.page.update()
|
|
|
|
def update_customer_list(self, customers: List[Customer]):
|
|
"""顧客リスト更新"""
|
|
# ダイアログの顧客リストを更新
|
|
if hasattr(self.page, 'dialog') and self.page.dialog:
|
|
customer_list = self.page.dialog.content.controls[2].content
|
|
self.update_customer_list_simple(customer_list, customers)
|
|
|
|
def create_customer_card(self, customer: Customer) -> ft.Container:
|
|
"""顧客カード作成"""
|
|
return ft.Container(
|
|
content=ft.Card(
|
|
content=ft.Container(
|
|
content=ft.Column([
|
|
ft.Row([
|
|
ft.Text(
|
|
customer.formal_name,
|
|
size=16,
|
|
weight=ft.FontWeight.BOLD,
|
|
expand=True,
|
|
),
|
|
ft.IconButton(
|
|
ft.Icons.DELETE,
|
|
on_click=lambda _, c=customer: self.delete_customer(c),
|
|
icon_color=ft.Colors.RED_400,
|
|
),
|
|
]),
|
|
ft.Container(height=5),
|
|
ft.Text(customer.address, size=12, color=ft.Colors.GREY_600),
|
|
ft.Text(customer.phone, size=12, color=ft.Colors.GREY_600),
|
|
]),
|
|
padding=ft.padding.all(15),
|
|
),
|
|
elevation=2,
|
|
),
|
|
on_click=lambda _, c=customer: self.select_customer(c),
|
|
)
|
|
|
|
def select_customer(self, customer: Customer):
|
|
"""顧客選択"""
|
|
if self.on_customer_selected:
|
|
self.on_customer_selected(customer)
|
|
self.close()
|
|
|
|
def delete_customer(self, customer: Customer):
|
|
"""顧客削除"""
|
|
if self.on_customer_deleted:
|
|
self.on_customer_deleted(customer)
|
|
|
|
def add_new_customer(self, e=None):
|
|
"""新規顧客追加"""
|
|
# TODO: 新規顧客登録画面を開く
|
|
logging.info("新規顧客登録")
|