Newer
Older
smart-home-server / webclient / src / features / modes / pages / ModesListPage.vue
<template>
  <section class="page">
    <GnPageHeader title="Modes" kicker="System" />

    <AppLoadingState v-if="modesStore.isLoading" text="Loading modes" />

    <AppErrorState
      v-else-if="modesStore.error"
      title="Modes loading failed"
      :error="modesStore.error"
      :retry="modesStore.loadModes"
    />

    <AppEmptyState
      v-else-if="modesStore.modes.length === 0"
      title="No modes"
      message="No system modes configured."
    />

    <div v-else class="modes-grid">
      <div
        v-for="mode in modesStore.modes"
        :key="mode.tag"
        class="mode-card-item"
      >
        <GnActionCard :title="mode.label || mode.tag">
          <template #default>
            <p v-if="mode.description">{{ mode.description }}</p>
            <div class="mode-meta">
              <GnBadge
                :variant="modesStore.isActive(mode.tag) ? 'success' : 'secondary'"
              >
                {{ modesStore.isActive(mode.tag) ? 'On' : 'Off' }}
              </GnBadge>
            </div>
          </template>
          <template #actions>
            <GnButton
              :variant="modesStore.isActive(mode.tag) ? 'danger' : 'primary'"
              :icon="modesStore.isActive(mode.tag) ? 'ph-moon' : 'ph-sun'"
              :loading="modesStore.isLoadingToggle && activeTag === mode.tag"
              @click="toggle(mode.tag)"
            >
              {{ modesStore.isActive(mode.tag) ? 'Disable' : 'Enable' }}
            </GnButton>
          </template>
        </GnActionCard>
      </div>
    </div>
  </section>
</template>

<script setup>
import { ref, onMounted } from "vue";
import { useModesStore } from "../../../stores/modes";
import {
  GnPageHeader,
  GnBadge,
  GnButton,
  GnActionCard,
  useToast,
} from "gnexus-ui-kit/vue";
import AppEmptyState from "../../../components/feedback/AppEmptyState.vue";
import AppErrorState from "../../../components/feedback/AppErrorState.vue";
import AppLoadingState from "../../../components/feedback/AppLoadingState.vue";

const modesStore = useModesStore();
const toast = useToast();

const activeTag = ref(null);

onMounted(() => {
  modesStore.loadModes();
});

async function toggle(tag) {
  activeTag.value = tag;
  const result = await modesStore.toggleMode(tag);
  activeTag.value = null;

  if (result?.ok) {
    toast.success({
      title: modesStore.isActive(tag) ? `"${tag}" enabled` : `"${tag}" disabled`,
    });
  } else {
    toast.error({
      title: `Failed to toggle "${tag}"`,
      text: result?.error?.message || "Unknown error",
    });
  }
}
</script>

<style scoped>
.modes-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
}

.mode-card-item {
  flex: 1 1 280px;
  min-width: 260px;
  max-width: 100%;
}

.mode-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}
</style>