from .location_card import InactiveLocationCard from gi.repository import Gtk import gi gi.require_version('Gtk', '3.0') def escape_markup(text: str) -> str: """Escape special characters for Pango markup.""" return text.replace('&', '&').replace('<', '<').replace('>', '>') class InactiveCustomerCard: def __init__(self, customer, callbacks): self.customer = customer self.callbacks = callbacks self.expanded = False # Start collapsed by default for inactive self.widget = self._create_widget() def _create_widget(self): # GNOME-style card container card_frame = Gtk.Frame() card_frame.get_style_context().add_class("card") card_frame.set_shadow_type( Gtk.ShadowType.NONE) # Shadow handled by CSS card_vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=12) card_frame.add(card_vbox) # Customer header with expand/collapse button - muted header_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=8) card_vbox.pack_start(header_box, False, False, 0) # Expand/collapse arrow button self.expand_button = Gtk.Button() self.expand_button.set_relief(Gtk.ReliefStyle.NONE) self.expand_button.set_can_focus(False) self._update_expand_button() self.expand_button.connect("clicked", self._on_expand_toggle) header_box.pack_start(self.expand_button, False, False, 0) # Customer name - muted customer_label = Gtk.Label() escaped_name = escape_markup(self.customer.name) customer_label.set_markup( f"🏢 {escaped_name}") customer_label.set_halign(Gtk.Align.START) header_box.pack_start(customer_label, False, False, 0) # Location count badge inactive_count = len(self.customer.locations) if inactive_count > 0: count_label = Gtk.Label() count_label.set_markup( f"({inactive_count})") header_box.pack_start(count_label, False, False, 0) # Content container (collapsible) self.content_box = Gtk.Box( orientation=Gtk.Orientation.VERTICAL, spacing=12) self.content_box.set_visible(self.expanded) # Start hidden card_vbox.pack_start(self.content_box, False, False, 0) # Customer services section - list format for inactive if self.customer.services: services_label = Gtk.Label() services_label.set_markup( "Cloud Services") services_label.set_halign(Gtk.Align.START) services_label.set_margin_top(8) self.content_box.pack_start(services_label, False, False, 0) # Services list with indent services_vbox = Gtk.Box( orientation=Gtk.Orientation.VERTICAL, spacing=2) services_vbox.set_margin_start(16) services_vbox.set_margin_bottom(8) self.content_box.pack_start(services_vbox, False, False, 0) for service in self.customer.services: service_label = Gtk.Label() # Escape special characters in markup text escaped_name = escape_markup(service.name) escaped_type = escape_markup(service.service_type) service_label.set_markup( f"• {escaped_name} ({escaped_type})") service_label.set_halign(Gtk.Align.START) services_vbox.pack_start(service_label, False, False, 0) # Locations section for i, location in enumerate(self.customer.locations): if i > 0: # Add separator between locations separator = Gtk.Separator( orientation=Gtk.Orientation.HORIZONTAL) separator.set_margin_top(8) separator.set_margin_bottom(8) self.content_box.pack_start(separator, False, False, 0) location_card = InactiveLocationCard( location, self.customer.name, self.callbacks) self.content_box.pack_start(location_card.widget, False, False, 0) # Show all content in the box (but box itself may be hidden) self.content_box.show_all() return card_frame def _update_expand_button(self): """Update the expand button arrow direction.""" if self.expanded: self.expand_button.set_label("▼") else: self.expand_button.set_label("▶") def _on_expand_toggle(self, button): """Toggle the expanded state.""" self.expanded = not self.expanded self._update_expand_button() self.content_box.set_visible(self.expanded)