flashcards in the frontend!!!

This commit is contained in:
2026-06-26 01:25:25 -07:00
parent f83d4d579c
commit cb60ec8480
14 changed files with 1134 additions and 3 deletions
@@ -0,0 +1,126 @@
<template>
<div>
<div
class="deck-node d-flex align-center px-3 py-2 rounded"
:class="{ selected: isSelected }"
@click="$emit('select', deck)"
>
<v-btn
icon
variant="text"
density="comfortable"
size="default"
class="mr-1"
@click.stop="expanded = !expanded"
>
<v-icon size="default">
{{
hasChildren ? (expanded ? "mdi-chevron-down" : "mdi-chevron-right") : "mdi-circle-small"
}}
</v-icon>
</v-btn>
<v-icon
size="default"
class="mr-2 text-medium-emphasis"
:icon="expanded && hasChildren ? 'mdi-folder-open-outline' : 'mdi-folder-outline'"
/>
<span
class="flex-grow-1 text-body-1"
:class="{ 'font-weight-medium': isSelected }"
>
{{ deck.name }}
</span>
<v-btn
icon
variant="text"
density="comfortable"
size="default"
title="Add sub-deck"
class="add-btn"
@click.stop="$emit('add-child', deck.id)"
>
<v-icon
size="default"
icon="mdi-plus"
/>
</v-btn>
</div>
<div
v-show="expanded"
class="pl-5"
>
<draggable
v-model="children"
:group="{ name: 'decks' }"
item-key="id"
@change="onChange"
>
<template #item="{ element }">
<FlashcardDeckTreeNode
v-model:children="element.children"
:deck="element"
:selected-id="selectedId"
@select="$emit('select', $event)"
@move="$emit('move', $event)"
@add-child="$emit('add-child', $event)"
/>
</template>
</draggable>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, computed } from "vue"
import draggable from "vuedraggable"
import type { DeckNode } from "@/components/flashcard-decks/FlashcardDeckTree.vue"
const props = defineProps<{
deck: DeckNode
selectedId?: number | null
}>()
const children = defineModel<DeckNode[]>("children", { required: true })
const emit = defineEmits<{
select: [deck: DeckNode]
move: [payload: { deckId: number; newParentId: number | null }]
"add-child": [parentId: number]
}>()
const expanded = ref(true)
const isSelected = computed(() => props.selectedId === props.deck.id)
const hasChildren = computed(() => children.value.length > 0)
function onChange(event: { added?: { element: DeckNode } }) {
if (event.added) {
emit("move", { deckId: event.added.element.id, newParentId: props.deck.id })
}
}
</script>
<style scoped>
.deck-node {
cursor: grab;
user-select: none;
}
.deck-node:hover {
background: rgb(var(--v-theme-hoverColor));
}
.deck-node.selected {
background: rgb(var(--v-theme-lightprimary));
}
.add-btn {
opacity: 0;
transition: opacity 0.15s;
}
.deck-node:hover .add-btn {
opacity: 1;
}
</style>