popup component, decks and cards get string ids, remove decks
This commit is contained in:
parent
2062beaefb
commit
08025ba9c6
9 changed files with 65 additions and 36 deletions
|
@ -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
5
src/components/Popup.vue
Normal file
|
@ -0,0 +1,5 @@
|
|||
<template>
|
||||
<Teleport to="#popup > .popup-content">
|
||||
<slot></slot>
|
||||
</Teleport>
|
||||
</template>
|
|
@ -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',
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>;
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue