Skip to content
Snippets Groups Projects
ListResourcesView.vue 4.09 KiB
Newer Older
  • Learn to ignore specific revisions
  • <script setup lang="ts">
    import { computed, onMounted, reactive } from "vue";
    import { useResourceStore } from "@/stores/resources";
    import ResourceCard from "@/components/resources/ResourceCard.vue";
    import CardTransitionGroup from "@/components/transitions/CardTransitionGroup.vue";
    import { useAuthStore } from "@/stores/users";
    import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue";
    import type { ResourceOut } from "@/client/resource";
    
    const resourceRepository = useResourceStore();
    const userRepository = useAuthStore();
    
    const resourceState = reactive<{
      loading: boolean;
      filterString: string;
      sortDesc: boolean;
    }>({
      loading: true,
      filterString: "",
      sortDesc: true,
    });
    
    const sortedResourcesByName = computed<ResourceOut[]>(() => {
      return [...resourceRepository.resources].sort((a, b) =>
        a.name < b.name ? 1 : -1,
      );
    });
    
    const sortedResources = computed<ResourceOut[]>(() => {
      if (resourceState.sortDesc) {
        return [...sortedResourcesByName.value].reverse();
      }
      return sortedResourcesByName.value;
    });
    
    const filteredSortedResources = computed<ResourceOut[]>(() => {
      return sortedResources.value.filter((resource) => {
        return resourceState.filterString.length > 0
          ? resource.name.includes(resourceState.filterString)
          : true;
      });
    });
    
    onMounted(() => {
      resourceRepository
        .fetchPublicResources(() => {
          resourceState.loading = false;
        })
        .then((resources) => {
          userRepository.fetchUsernames(resources.map((r) => r.maintainer_id));
        });
    });
    </script>
    
    <template>
    
      <div class="row border-bottom mb-4">
    
        <h2 class="mb-2">Available Resources</h2>
      </div>
      <div class="d-flex m-2 mb-3 align-items-center justify-content-start">
        <div class="col-5">
          <div class="input-group rounded shadow-sm">
            <span class="input-group-text" id="resources-search-wrapping"
              ><font-awesome-icon icon="fa-solid fa-magnifying-glass"
            /></span>
            <input
              type="text"
              id="filterResourcesInput"
              class="form-control"
              placeholder="Filter Resources"
              aria-label="Filter Resources"
              aria-describedby="resources-search-wrapping"
              :disabled="resourceState.loading"
              v-model.trim="resourceState.filterString"
              maxlength="20"
            />
          </div>
        </div>
        <font-awesome-icon
          :icon="
            resourceState.sortDesc
              ? 'fa-solid fa-arrow-down-wide-short'
              : 'fa-solid fa-arrow-up-wide-short'
          "
          @click="resourceState.sortDesc = !resourceState.sortDesc"
          class="fs-5 ms-3 cursor-pointer"
        />
      </div>
      <div v-if="!resourceState.loading">
        <div
          v-if="resourceRepository.resources.length === 0"
          class="text-center fs-2 mt-5"
        >
          <font-awesome-icon
            icon="fa-solid fa-x"
            class="my-5 fs-0"
            style="color: var(--bs-secondary)"
          />
          <p>There are no resources in the system. Please come again later.</p>
        </div>
        <div
          v-else-if="filteredSortedResources.length === 0"
          class="text-center fs-2 mt-5"
        >
          <font-awesome-icon
            icon="fa-solid fa-magnifying-glass"
            class="my-5 fs-0"
            style="color: var(--bs-secondary)"
          />
          <p>
            Could not find any Resources containing<br />'{{
              resourceState.filterString
            }}'
          </p>
        </div>
        <CardTransitionGroup
          v-else
          class="d-flex flex-wrap align-items-center justify-content-between"
        >
          <resource-card
            v-for="resource in filteredSortedResources"
            :key="resource.resource_id"
            :resource="resource"
            :loading="false"
    
            style="min-width: 47%; max-width: 48%"
    
          />
        </CardTransitionGroup>
      </div>
      <div
        v-else
        class="d-flex flex-wrap align-items-center justify-content-between"
      >
        <resource-card
          v-for="resource in 4"
          :key="resource"
          :resource="{
            name: '',
            description: '',
            source: '',
            resource_id: '',
            versions: [],
            maintainer_id: '',
          }"
          style="min-width: 48%"
          loading
        />
      </div>
    </template>
    
    <style scoped></style>