popup component, decks and cards get string ids, remove decks

This commit is contained in:
koehr 2020-07-05 20:42:22 +02:00
parent 2062beaefb
commit 08025ba9c6
9 changed files with 65 additions and 36 deletions

View file

@ -15,7 +15,7 @@
</select>
<button type="submit">Save deck</button>
<button class="cancel" @click.prevent="$emit('close')">cancel</button>
<button class="cancel" @click.prevent="$emit('cancel')">cancel</button>
</div>
<DeckCard :deck="{ icon, name, description, color, cardSize, cards: [] }" />
@ -47,7 +47,8 @@ export default defineComponent({
}
},
watch: {
deck (deck, oldDeck) {
deck (deck) {
if (deck === undefined) return
this.icon = deck.icon
this.name = deck.name
this.description = deck.description

5
src/components/Popup.vue Normal file
View file

@ -0,0 +1,5 @@
<template>
<Teleport to="#popup > .popup-content">
<slot></slot>
</Teleport>
</template>

View file

@ -1,9 +1,10 @@
import { CardSize } from '../consts'
import { ICard } from '../types'
import randomId from './randomId'
export function defaultCard (): ICard {
return {
id: 0,
id: randomId(),
name: 'no title yet',
tags: [],
icon: 'robe',

View file

@ -1,8 +1,9 @@
import { CardSize, PageSize, Arrangement } from '../consts'
import { IDeck } from '../types'
import randomId from './randomId'
export const defaultDeckValues: IDeck = {
id: 0,
id: '',
icon: 'robe',
name: 'the nameless',
description: '',
@ -15,7 +16,9 @@ export const defaultDeckValues: IDeck = {
}
export function defaultDeck (): IDeck {
return { ...defaultDeckValues }
const newDeck = { ...defaultDeckValues }
newDeck.id = randomId()
return newDeck
}
export function isValidDeck (deck: any): boolean {

View file

@ -1,6 +1,8 @@
import { Ref } from 'vue'
import { Notification, IDeck, KV } from '../types'
import { defaultDeck, defaultDeckValues } from '../lib/deck'
import { Notification, State, IDeck, KV } from '../types'
import { defaultDeck } from '../lib/deck'
type Decks = State['decks']
/// actions are called like action['sub/foo'](state.sub, payload)
export default {
@ -23,15 +25,14 @@ export default {
// DECK ACTIONS
// returns index of newly created deck
'decks/new' (decks: Ref<IDeck[]>): number {
'decks/new' (decks: Ref<Decks>): string {
const newDeck = defaultDeck()
const id = decks.value.push(newDeck) - 1
newDeck.id = id
return id
const id = newDeck.id
decks.value[id] = newDeck
return newDeck.id
},
// updates decks[updatedDeck.id]
'decks/update' (decks: Ref<IDeck[]>, updatedDeck: IDeck): boolean {
'decks/update' (decks: Ref<Decks>, updatedDeck: IDeck): boolean {
const id = updatedDeck.id
if (!id || !decks.value[id]) return false // can't update non-existing deck
@ -41,6 +42,9 @@ export default {
}
return true
},
'decks/remove' (decks: Ref<Decks>, deckId: string) {
delete decks.value[deckId]
},
// POPUP ACTIONS
'popup/show' (popup: Ref<boolean>): boolean {

View file

@ -7,7 +7,7 @@ import stateActions from './actions'
const state: State = {
settings: ref({}),
decks: ref([]),
decks: ref({}),
notifications: ref([]),
icons: ref(['mouth-watering', 'robe', 'thorny-triskelion']),
popup: ref(false)

View file

@ -3,12 +3,12 @@ import { CardSize, Arrangement, PageSize } from './consts'
import { IDeck, ICard } from './types'
interface IDeckTable {
id: number;
id: string;
name: string;
description: string;
color: string;
icon: string;
cards: number[]; // array of card IDs
cards: string[]; // array of card IDs
cardSize: CardSize;
arrangement: Arrangement;
pageSize: PageSize;
@ -16,8 +16,8 @@ interface IDeckTable {
}
export class DeckDB extends Dexie {
public decks: Dexie.Table<IDeckTable, number>
public cards: Dexie.Table<ICard, number>
public decks: Dexie.Table<IDeckTable, string>
public cards: Dexie.Table<ICard, string>
public tags: Dexie.Table<string>
public constructor () {
@ -25,8 +25,8 @@ export class DeckDB extends Dexie {
console.log('initializing deck db')
this.version(1).stores({
decks: '++id,name',
cards: '++id,name,*tags',
decks: '&id,name',
cards: '&id,name,*tags',
tags: '&tag'
})
@ -53,7 +53,7 @@ export class DeckDB extends Dexie {
}
// add or update card
public async putCard (card: ICard, deckId: number) {
public async putCard (card: ICard, deckId: string) {
const cardId = await this.cards.put(card)
const deck = await this.decks.get(deckId)
@ -64,9 +64,9 @@ export class DeckDB extends Dexie {
}
public async getDecks () {
const decks = await this.decks.toArray()
const deckEntries = await this.decks.toArray()
return Promise.all(decks.map(async deckTable => {
const decks = await Promise.all(deckEntries.map(async deckTable => {
const cardIds = deckTable.cards
const deck: IDeck = {
...deckTable,
@ -74,5 +74,13 @@ export class DeckDB extends Dexie {
}
return deck
}))
// returns object with deck ids as keys
const decksById = decks.reduce((acc, deck) => {
acc[deck.id] = deck
return acc
}, {})
return decksById
}
}

View file

@ -17,7 +17,7 @@ export interface ICardContent {
}
export interface ICard {
id: number;
id: string;
name: string;
tags: string[];
icon: string;
@ -27,7 +27,7 @@ export interface ICard {
}
export interface IDeck {
id: number;
id: string;
name: string;
description: string;
color: string;
@ -57,7 +57,7 @@ export interface Notification {
export interface State {
settings: Ref<Settings>;
decks: Ref<IDeck[]>;
decks: Ref<{ [key: string]: IDeck }>;
notifications: Ref<Notification[]>;
icons: Ref<string[]>;
popup: Ref<boolean>;

View file

@ -8,17 +8,17 @@
<Card id="_add_deck" @click="addDeck" />
</section>
<teleport to="#popup > .popup-content">
<Popup>
<div class="deck new-deck-form-wrapper">
<header>Create a new deck of cards</header>
<DeckForm :deck="newDeck" @save="saveDeck" @close="hidePopup" />
<DeckForm :deck="newDeck" @save="saveDeck" @cancel="cancelDeck" />
<footer class="centered">
You can also
<button @click="importDeck">import</button>
an existing deck.
</footer>
</div>
</teleport>
</Popup>
</template>
@ -26,38 +26,45 @@
import { defineComponent, ref, computed } from 'vue'
import { useState } from '@/state'
import Popup from '@/components/Popup.vue'
import Card from '@/components/Card.vue'
import DeckCard from '@/components/DeckCard.vue'
import DeckForm from '@/components/DeckForm.vue'
export default defineComponent({
name: 'Home',
components: { Card, DeckCard, DeckForm },
components: { Popup, Card, DeckCard, DeckForm },
setup () {
const { actions: popupActions } = useState('popup')
const { collection: decks, actions: deckActions } = useState('decks')
const newDeckIndex = ref(0)
const newDeck = computed(() => decks.value[newDeckIndex.value])
const newDeckId = ref('')
const newDeck = computed(() => decks.value[newDeckId.value])
const addDeck = () => {
const idx = deckActions.new()
newDeckIndex.value = idx
const id = deckActions.new()
newDeckId.value = id
popupActions.show()
}
const saveDeck = (updatedDeck) => {
console.log('saving deck', updatedDeck)
updatedDeck.id = newDeckIndex.value
updatedDeck.id = newDeckId.value
deckActions.update(updatedDeck)
popupActions.hide()
}
const cancelDeck = () => {
popupActions.hide()
deckActions.remove(newDeckId.value)
newDeckId.value = ''
}
return {
decks,
addDeck,
newDeck,
saveDeck,
cancelDeck,
hidePopup: popupActions.hide
// importDeck: deckActions.import,
}