diff --git a/src/components/DeckForm.vue b/src/components/DeckForm.vue index 6ec76b4..c06577a 100644 --- a/src/components/DeckForm.vue +++ b/src/components/DeckForm.vue @@ -15,7 +15,7 @@ Save deck - cancel + cancel @@ -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 diff --git a/src/components/Popup.vue b/src/components/Popup.vue new file mode 100644 index 0000000..0fae9df --- /dev/null +++ b/src/components/Popup.vue @@ -0,0 +1,5 @@ + + + + + diff --git a/src/lib/card.ts b/src/lib/card.ts index 2c780d0..7cb421f 100644 --- a/src/lib/card.ts +++ b/src/lib/card.ts @@ -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', diff --git a/src/lib/deck.ts b/src/lib/deck.ts index 418b470..fce5fd5 100644 --- a/src/lib/deck.ts +++ b/src/lib/deck.ts @@ -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 { diff --git a/src/state/actions.ts b/src/state/actions.ts index 8f20d8c..8f7587d 100644 --- a/src/state/actions.ts +++ b/src/state/actions.ts @@ -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): number { + 'decks/new' (decks: Ref): 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, updatedDeck: IDeck): boolean { + 'decks/update' (decks: Ref, 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, deckId: string) { + delete decks.value[deckId] + }, // POPUP ACTIONS 'popup/show' (popup: Ref): boolean { diff --git a/src/state/index.ts b/src/state/index.ts index 4223490..46c9e6b 100644 --- a/src/state/index.ts +++ b/src/state/index.ts @@ -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) diff --git a/src/storage.ts b/src/storage.ts index 86436f5..f6503d9 100644 --- a/src/storage.ts +++ b/src/storage.ts @@ -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 - public cards: Dexie.Table + public decks: Dexie.Table + public cards: Dexie.Table public tags: Dexie.Table 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 } } diff --git a/src/types.ts b/src/types.ts index 8f4b25c..5d44043 100644 --- a/src/types.ts +++ b/src/types.ts @@ -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; - decks: Ref; + decks: Ref<{ [key: string]: IDeck }>; notifications: Ref; icons: Ref; popup: Ref; diff --git a/src/views/Home.vue b/src/views/Home.vue index 344e4d1..6d33bd4 100644 --- a/src/views/Home.vue +++ b/src/views/Home.vue @@ -8,17 +8,17 @@ - + Create a new deck of cards - + - + @@ -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, }