import { defineStore } from "pinia"; import { ref, computed } from "vue"; import { invoke } from "@tauri-apps/api/core"; export interface Connection { id: number; name: string; hostname: string; port: number; protocol: "ssh" | "rdp"; groupId: number | null; credentialId?: number | null; color?: string; tags?: string[]; notes?: string; options?: string; sortOrder?: number; lastConnected?: string | null; createdAt?: string; updatedAt?: string; } export interface Group { id: number; name: string; parentId: number | null; sortOrder?: number; icon?: string; children?: Group[]; } /** * Connection store. * Manages connections, groups, and search state. * Loads data from the Rust backend via Tauri invoke. */ export const useConnectionStore = defineStore("connection", () => { const connections = ref([]); const groups = ref([]); const searchQuery = ref(""); /** Filter connections by search query. */ const filteredConnections = computed(() => { const q = searchQuery.value.toLowerCase().trim(); if (!q) return connections.value; return connections.value.filter( (c) => c.name.toLowerCase().includes(q) || c.hostname.toLowerCase().includes(q) || c.tags?.some((t) => t.toLowerCase().includes(q)), ); }); /** Get connections belonging to a specific group. */ function connectionsByGroup(groupId: number): Connection[] { const q = searchQuery.value.toLowerCase().trim(); const groupConns = connections.value.filter((c) => c.groupId === groupId); if (!q) return groupConns; return groupConns.filter( (c) => c.name.toLowerCase().includes(q) || c.hostname.toLowerCase().includes(q) || c.tags?.some((t) => t.toLowerCase().includes(q)), ); } /** Check if a group has any matching connections (for search filtering). */ function groupHasResults(groupId: number): boolean { return connectionsByGroup(groupId).length > 0; } /** Load connections from the Rust backend. */ async function loadConnections(): Promise { try { const conns = await invoke("list_connections"); connections.value = conns || []; } catch (err) { console.error("Failed to load connections:", err); connections.value = []; } } /** Load groups from the Rust backend. */ async function loadGroups(): Promise { try { const grps = await invoke("list_groups"); groups.value = grps || []; } catch (err) { console.error("Failed to load groups:", err); groups.value = []; } } /** Load both connections and groups from the Rust backend. */ async function loadAll(): Promise { await Promise.all([loadConnections(), loadGroups()]); } return { connections, groups, searchQuery, filteredConnections, connectionsByGroup, groupHasResults, loadConnections, loadGroups, loadAll, }; });