Newer
Older
smart-home-server / webclient-vue / src / features / areas / components / AreaTreeNode.vue
@Eugene Sukhodolskiy Eugene Sukhodolskiy on 25 Apr 2 KB Add Vue areas tree page
<template>
  <li v-if="!isCycle" class="area-tree-node" :class="{ 'is-open': isOpen, 'is-leaf': isLeaf }">
    <article class="area-tree-card">
      <button
        class="tree-toggle"
        type="button"
        :disabled="isLeaf"
        :aria-expanded="isOpen"
        @click="isOpen = !isOpen"
      >
        {{ isLeaf ? "·" : isOpen ? "−" : "+" }}
      </button>

      <div class="area-tree-info">
        <h2>{{ area.display_name }}</h2>
        <p>
          <UiBadge variant="neutral">{{ area.type }}</UiBadge>
          <code>{{ area.alias }}</code>
        </p>
      </div>

      <div class="area-tree-actions">
        <UiButton variant="secondary" disabled>Actions</UiButton>
        <UiButton variant="secondary" disabled>Devices</UiButton>
        <UiButton variant="primary" disabled>Details</UiButton>
        <UiButton :variant="isFavorite ? 'warning' : 'secondary'" @click="favoritesStore.toggle(area.id)">
          {{ isFavorite ? "Unstar" : "Star" }}
        </UiButton>
      </div>
    </article>

    <ul v-if="area.children?.length && isOpen" class="area-tree-children">
      <AreaTreeNode
        v-for="child in area.children"
        :key="child.id"
        :area="child"
        :ancestors="nextAncestors"
      />
    </ul>
  </li>
  <li v-else class="area-tree-node">
    <article class="area-tree-card area-tree-cycle">
      Cycle skipped for area ID {{ area.id }}
    </article>
  </li>
</template>

<script setup>
import { computed, ref } from "vue";
import { useFavoritesStore } from "../../../stores/favorites";
import UiBadge from "../../../components/ui/UiBadge.vue";
import UiButton from "../../../components/ui/UiButton.vue";

const props = defineProps({
  area: {
    type: Object,
    required: true,
  },
  ancestors: {
    type: Array,
    default: () => [],
  },
});

const favoritesStore = useFavoritesStore();
const isOpen = ref(false);
const isLeaf = computed(() => !props.area.children?.length);
const isFavorite = computed(() => favoritesStore.has(props.area.id));
const isCycle = computed(() => props.ancestors.includes(String(props.area.id)));
const nextAncestors = computed(() => [...props.ancestors, String(props.area.id)]);
</script>