テーマの準備

This commit is contained in:
joe 2026-02-24 02:26:13 +09:00
parent 25032d3b9b
commit 3e4af336f8
2 changed files with 92 additions and 81 deletions

View file

@ -111,10 +111,13 @@ def build_invoice_items_edit_table(
products: List[Product],
on_product_select: Callable[[int], None] | None = None,
row_refs: Optional[dict] = None,
enable_reorder: bool = False,
on_reorder: Optional[Callable[[int, int], None]] = None,
) -> ft.Column:
"""編集モードの明細テーブル。"""
header_row = ft.Row(
[
ft.Container(width=28),
ft.Text("商品", size=12, weight=ft.FontWeight.BOLD, width=180),
ft.Text("", size=12, weight=ft.FontWeight.BOLD, width=35),
ft.Text("単価", size=12, weight=ft.FontWeight.BOLD, width=70),
@ -190,20 +193,40 @@ def build_invoice_items_edit_table(
"subtotal": subtotal_text,
}
data_rows.append(
ft.Row(
[
product_field,
quantity_field,
unit_price_field,
subtotal_text,
delete_button,
],
key=f"row-{i}-{item.description}",
)
handle = ft.Icon(
ft.Icons.DRAG_HANDLE,
size=18,
color=ft.Colors.BLUE_GREY_400,
visible=enable_reorder and not is_locked,
)
list_control: ft.Control = ft.Column(data_rows, spacing=4)
row_control = ft.Row(
[
handle,
product_field,
quantity_field,
unit_price_field,
subtotal_text,
delete_button,
],
vertical_alignment=ft.CrossAxisAlignment.CENTER,
key=f"row-{i}-{item.description}",
)
data_rows.append(row_control)
if enable_reorder and on_reorder and not is_locked:
reorder_items = [
ft.ReorderableListViewItem(key=str(idx), content=row)
for idx, row in enumerate(data_rows)
]
list_control = ft.ReorderableListView(
controls=reorder_items,
on_reorder=lambda e: on_reorder(e.old_index, e.new_index),
shrink_wrap=True,
)
else:
list_control = ft.Column(data_rows, spacing=4)
return ft.Column(
[

126
main.py
View file

@ -205,48 +205,9 @@ class FlutterStyleDashboard:
# 保存後遷移設定True: 詳細に留まる, False: 一覧へ戻る)
self.stay_on_detail_after_save = True
self.invoice_card_theme = {
"page_bg": "#F3F2FB",
"card_bg": ft.Colors.WHITE,
"card_radius": 18,
"shadow": ft.BoxShadow(
blur_radius=16,
spread_radius=0,
color="#D5D8F0",
offset=ft.Offset(0, 6),
),
"icon_fg": ft.Colors.WHITE,
"icon_default_bg": "#5C6BC0",
"title_color": ft.Colors.BLUE_GREY_900,
"subtitle_color": ft.Colors.BLUE_GREY_500,
"amount_color": "#2F3C7E",
"tag_text_color": "#4B4F67",
"tag_bg": "#E7E9FB",
"draft_card_bg": "#F5EEE4",
"draft_border": "#D7C4AF",
"draft_badge_bg": "#A7743A",
"draft_shadow_highlight": ft.BoxShadow(
blur_radius=8,
spread_radius=0,
color="#FFFFFF",
offset=ft.Offset(-2, -2),
),
"draft_shadow_depth": ft.BoxShadow(
blur_radius=14,
spread_radius=2,
color="#C3A88C",
offset=ft.Offset(4, 6),
),
"badge_bg": "#35C46B",
}
self.doc_type_palette = {
DocumentType.INVOICE.value: "#5C6BC0",
DocumentType.ESTIMATE.value: "#7E57C2",
DocumentType.DELIVERY.value: "#26A69A",
DocumentType.RECEIPT.value: "#FF7043",
DocumentType.SALES.value: "#42A5F5",
DocumentType.DRAFT.value: "#90A4AE",
}
self.current_theme = "light"
self.theme_presets = self._build_theme_presets()
self.apply_theme(self.current_theme)
# ビジネスロジックサービス
self.app_service = AppService()
@ -254,6 +215,8 @@ class FlutterStyleDashboard:
self.customers = []
self._item_row_refs: Dict[int, Dict[str, ft.Control]] = {}
self._total_amount_text: Optional[ft.Text] = None
self._tax_amount_text: Optional[ft.Text] = None
self._subtotal_text: Optional[ft.Text] = None
self.setup_page()
self.setup_database()
@ -1657,6 +1620,31 @@ class FlutterStyleDashboard:
else:
draft_control = ft.Container()
date_time_row = ft.Row(
[
date_button if date_button else ft.Text(
self.editing_invoice.date.strftime("%Y/%m/%d"),
size=12,
color=ft.Colors.BLUE_GREY_600,
),
time_button if time_button else ft.Text(
self.editing_invoice.date.strftime("%H:%M"),
size=12,
color=ft.Colors.BLUE_GREY_600,
),
],
spacing=8,
)
customer_block = ft.Column(
[
customer_control,
date_time_row,
],
spacing=4,
alignment=ft.MainAxisAlignment.START,
)
summary_card = ft.Container(
content=ft.Column(
[
@ -1690,25 +1678,11 @@ class FlutterStyleDashboard:
),
ft.Row(
[
customer_control,
self._build_total_amount_text(),
customer_block,
self._build_totals_row(),
],
alignment=ft.MainAxisAlignment.SPACE_BETWEEN,
),
ft.Row(
[
date_button if date_button else ft.Text(
self.editing_invoice.date.strftime("%Y/%m/%d"),
size=12,
color=ft.Colors.BLUE_GREY_600,
),
time_button if time_button else ft.Text(
self.editing_invoice.date.strftime("%H:%M"),
size=12,
color=ft.Colors.BLUE_GREY_600,
),
],
spacing=12,
vertical_alignment=ft.CrossAxisAlignment.CENTER,
),
summary_badges,
],
@ -1968,6 +1942,8 @@ class FlutterStyleDashboard:
products=self.app_service.product.get_all_products(),
on_product_select=self._open_product_picker_for_row,
row_refs=self._ensure_item_row_refs(),
enable_reorder=not is_locked,
on_reorder=lambda old, new: self._reorder_item_row(old, new),
)
def _open_product_picker_for_row(self, item_index: int):
@ -2085,21 +2061,33 @@ class FlutterStyleDashboard:
self._close_dialog()
self.update_main_content()
def _build_total_amount_text(self) -> ft.Text:
total = self.editing_invoice.total_amount if self.editing_invoice else 0
def _build_totals_row(self) -> ft.Column:
subtotal = self.editing_invoice.subtotal if self.editing_invoice else 0
tax = self.editing_invoice.tax if self.editing_invoice else 0
total = subtotal + tax
self._tax_amount_text = ft.Text(f"消費税 ¥{tax:,}", size=12, color=ft.Colors.BLUE_GREY_700)
self._total_amount_text = ft.Text(
f"¥{total:,} (税込)",
size=15,
weight=ft.FontWeight.BOLD,
color=ft.Colors.BLUE_700,
f"合計 ¥{total:,}", size=15, weight=ft.FontWeight.BOLD, color=ft.Colors.BLUE_700
)
return ft.Column(
[
self._tax_amount_text,
self._total_amount_text,
],
spacing=2,
alignment=ft.MainAxisAlignment.END,
)
return self._total_amount_text
def _refresh_total_amount_display(self):
if not self._total_amount_text:
if not self.editing_invoice:
return
total = self.editing_invoice.total_amount if self.editing_invoice else 0
self._total_amount_text.value = f"¥{total:,} (税込)"
if self._tax_amount_text:
self._tax_amount_text.value = f"消費税 ¥{self.editing_invoice.tax:,}"
if self._total_amount_text:
total = self.editing_invoice.total_amount
self._total_amount_text.value = f"合計 ¥{total:,}"
def _ensure_item_row_refs(self) -> Dict[int, Dict[str, ft.Control]]:
self._item_row_refs = {}