UPD: Fancy profile manager
This commit is contained in:
@@ -15,7 +15,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<div class="flex w-full h-12 items-center">
|
<div class="flex w-full h-12 items-center">
|
||||||
<label for="filter" class="flex h-full items-center cursor-text">
|
<label for="filter" class="flex h-full items-center cursor-text">
|
||||||
<MagnifyingGlassIcon class="ml-4 mr-1 mb-0.5 h-4 w-4 shrink-0 opacity-50 float-left" />
|
<MagnifyingGlassIcon class="ml-4 mr-2 mb-0.5 h-4 w-4 shrink-0 opacity-50 float-left" />
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
id="filter"
|
id="filter"
|
||||||
@@ -24,19 +24,31 @@
|
|||||||
class="grow h-full bg-transparent text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-0 disabled:cursor-not-allowed disabled:opacity-50">
|
class="grow h-full bg-transparent text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-0 disabled:cursor-not-allowed disabled:opacity-50">
|
||||||
</div>
|
</div>
|
||||||
<Separator />
|
<Separator />
|
||||||
<template v-if="filter===''">
|
<div v-if="filteredProfiles.length === 0">
|
||||||
<div v-for="[profileTag, tagProfiles] in profilesByTag" :key="profileTag">
|
<div class="flex flex-col items-center justify-center h-32">
|
||||||
{{ profileTag }}
|
<p class="text-sm text-muted-foreground">
|
||||||
<div v-for="profile in tagProfiles" :key="profile.id" class="ml-4">
|
{{ $t('profiles.not_found') }}
|
||||||
{{ profile.name }} {{ profile.id }}
|
</p>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</div>
|
||||||
<template v-else>
|
<div>
|
||||||
<div v-for="profile in filteredProfiles" :key="profile.id">
|
<Collapsible
|
||||||
{{ profile.name }} {{ profile.id }}
|
v-for="[profileTag, tagProfiles] in filteredProfilesByTag" :key="profileTag" :default-open="true"
|
||||||
</div>
|
:open="collapse[profileTag]">
|
||||||
</template>
|
<CollapsibleTrigger
|
||||||
|
v-model="collapse[profileTag]"
|
||||||
|
class="w-full py-2 text-left text-muted-foreground text-sm">
|
||||||
|
<ChevronRight class="chevrot h-4 w-4 mb-0.5 ml-4 inline-block transition-transform" />
|
||||||
|
{{ profileTag }} <span class="text-xs text-zinc-600">(TAG)</span>
|
||||||
|
</CollapsibleTrigger>
|
||||||
|
<CollapsibleContent>
|
||||||
|
<button v-for="profile in tagProfiles" :key="profile.id" class="w-full h-10 text-left hover:bg-zinc-900">
|
||||||
|
<FileDigit class="h-4 w-4 mb-1 ml-10 mr-2 inline-block text-muted-foreground" />
|
||||||
|
<span>{{ profile.name }}</span> <span class="text-xs text-zinc-600">uID:{{ profile.id }}</span>
|
||||||
|
</button>
|
||||||
|
</CollapsibleContent>
|
||||||
|
</Collapsible>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<SchemaTest />
|
<SchemaTest />
|
||||||
</div>
|
</div>
|
||||||
@@ -44,30 +56,24 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import SchemaTest from '@/components/SchemaTest.vue'
|
import SchemaTest from '@/components/SchemaTest.vue'
|
||||||
import { Separator } from '@/components/ui/separator/index.js'
|
import { Separator } from '@/components/ui/separator/index.js'
|
||||||
import { Input } from '@/components/ui/input'
|
import { FileDigit, ChevronRight } from 'lucide-vue-next'
|
||||||
import { FileDigit } from 'lucide-vue-next'
|
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { computed, onMounted, ref } from 'vue'
|
import { computed, onMounted, ref } from 'vue'
|
||||||
import { MagnifyingGlassIcon } from '@radix-icons/vue'
|
import { MagnifyingGlassIcon } from '@radix-icons/vue'
|
||||||
import { cn } from '@/lib/utils.js'
|
import {
|
||||||
|
Collapsible,
|
||||||
|
CollapsibleContent,
|
||||||
|
CollapsibleTrigger,
|
||||||
|
} from '@/components/ui/collapsible'
|
||||||
|
|
||||||
const profiles = ref([])
|
const profiles = ref([])
|
||||||
|
|
||||||
const filter = ref('')
|
const filter = ref('')
|
||||||
|
const collapse = ref({})
|
||||||
const profilesByTag = computed(() => {
|
|
||||||
const map = new Map()
|
|
||||||
profiles.value.forEach(profile => {
|
|
||||||
const tag = profile.profileTag || 'Uncategorized'
|
|
||||||
if (!map.has(tag)) {
|
|
||||||
map.set(tag, [])
|
|
||||||
}
|
|
||||||
map.get(tag).push(profile)
|
|
||||||
})
|
|
||||||
return map
|
|
||||||
})
|
|
||||||
|
|
||||||
const filteredProfiles = computed(() => {
|
const filteredProfiles = computed(() => {
|
||||||
|
if (!filter.value) {
|
||||||
|
return profiles.value
|
||||||
|
}
|
||||||
const filterLower = filter.value.toLowerCase()
|
const filterLower = filter.value.toLowerCase()
|
||||||
return profiles.value.filter(profile => {
|
return profiles.value.filter(profile => {
|
||||||
const nameLower = profile.name.toLowerCase()
|
const nameLower = profile.name.toLowerCase()
|
||||||
@@ -77,6 +83,18 @@ const filteredProfiles = computed(() => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const filteredProfilesByTag = computed(() => {
|
||||||
|
const map = new Map()
|
||||||
|
filteredProfiles.value.forEach(profile => {
|
||||||
|
const tag = profile.profileTag || 'Uncategorized'
|
||||||
|
if (!map.has(tag)) {
|
||||||
|
map.set(tag, [])
|
||||||
|
}
|
||||||
|
map.get(tag).push(profile)
|
||||||
|
})
|
||||||
|
return map
|
||||||
|
})
|
||||||
|
|
||||||
function fetchProfiles() {
|
function fetchProfiles() {
|
||||||
axios.get('http://localhost:3001/profiles').then(res => {
|
axios.get('http://localhost:3001/profiles').then(res => {
|
||||||
profiles.value = res.data
|
profiles.value = res.data
|
||||||
@@ -88,4 +106,9 @@ function fetchProfiles() {
|
|||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
fetchProfiles()
|
fetchProfiles()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
<style>
|
||||||
|
[data-state=open] > .chevrot {
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user