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>
|
</select>
|
||||||
|
|
||||||
<button type="submit">Save deck</button>
|
<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>
|
</div>
|
||||||
|
|
||||||
<DeckCard :deck="{ icon, name, description, color, cardSize, cards: [] }" />
|
<DeckCard :deck="{ icon, name, description, color, cardSize, cards: [] }" />
|
||||||
|
@ -47,7 +47,8 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
deck (deck, oldDeck) {
|
deck (deck) {
|
||||||
|
if (deck === undefined) return
|
||||||
this.icon = deck.icon
|
this.icon = deck.icon
|
||||||
this.name = deck.name
|
this.name = deck.name
|
||||||
this.description = deck.description
|
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 { CardSize } from '../consts'
|
||||||
import { ICard } from '../types'
|
import { ICard } from '../types'
|
||||||
|
import randomId from './randomId'
|
||||||
|
|
||||||
export function defaultCard (): ICard {
|
export function defaultCard (): ICard {
|
||||||
return {
|
return {
|
||||||
id: 0,
|
id: randomId(),
|
||||||
name: 'no title yet',
|
name: 'no title yet',
|
||||||
tags: [],
|
tags: [],
|
||||||
icon: 'robe',
|
icon: 'robe',
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import { CardSize, PageSize, Arrangement } from '../consts'
|
import { CardSize, PageSize, Arrangement } from '../consts'
|
||||||
import { IDeck } from '../types'
|
import { IDeck } from '../types'
|
||||||
|
import randomId from './randomId'
|
||||||
|
|
||||||
export const defaultDeckValues: IDeck = {
|
export const defaultDeckValues: IDeck = {
|
||||||
id: 0,
|
id: '',
|
||||||
icon: 'robe',
|
icon: 'robe',
|
||||||
name: 'the nameless',
|
name: 'the nameless',
|
||||||
description: '',
|
description: '',
|
||||||
|
@ -15,7 +16,9 @@ export const defaultDeckValues: IDeck = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function defaultDeck (): IDeck {
|
export function defaultDeck (): IDeck {
|
||||||
return { ...defaultDeckValues }
|
const newDeck = { ...defaultDeckValues }
|
||||||
|
newDeck.id = randomId()
|
||||||
|
return newDeck
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isValidDeck (deck: any): boolean {
|
export function isValidDeck (deck: any): boolean {
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import { Ref } from 'vue'
|
import { Ref } from 'vue'
|
||||||
import { Notification, IDeck, KV } from '../types'
|
import { Notification, State, IDeck, KV } from '../types'
|
||||||
import { defaultDeck, defaultDeckValues } from '../lib/deck'
|
import { defaultDeck } from '../lib/deck'
|
||||||
|
|
||||||
|
type Decks = State['decks']
|
||||||
|
|
||||||
/// actions are called like action['sub/foo'](state.sub, payload)
|
/// actions are called like action['sub/foo'](state.sub, payload)
|
||||||
export default {
|
export default {
|
||||||
|
@ -23,15 +25,14 @@ export default {
|
||||||
|
|
||||||
// DECK ACTIONS
|
// DECK ACTIONS
|
||||||
// returns index of newly created deck
|
// returns index of newly created deck
|
||||||
'decks/new' (decks: Ref<IDeck[]>): number {
|
'decks/new' (decks: Ref<Decks>): string {
|
||||||
const newDeck = defaultDeck()
|
const newDeck = defaultDeck()
|
||||||
const id = decks.value.push(newDeck) - 1
|
const id = newDeck.id
|
||||||
newDeck.id = id
|
decks.value[id] = newDeck
|
||||||
|
return newDeck.id
|
||||||
return id
|
|
||||||
},
|
},
|
||||||
// updates decks[updatedDeck.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
|
const id = updatedDeck.id
|
||||||
if (!id || !decks.value[id]) return false // can't update non-existing deck
|
if (!id || !decks.value[id]) return false // can't update non-existing deck
|
||||||
|
|
||||||
|
@ -41,6 +42,9 @@ export default {
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
|
'decks/remove' (decks: Ref<Decks>, deckId: string) {
|
||||||
|
delete decks.value[deckId]
|
||||||
|
},
|
||||||
|
|
||||||
// POPUP ACTIONS
|
// POPUP ACTIONS
|
||||||
'popup/show' (popup: Ref<boolean>): boolean {
|
'popup/show' (popup: Ref<boolean>): boolean {
|
||||||
|
|
|
@ -7,7 +7,7 @@ import stateActions from './actions'
|
||||||
|
|
||||||
const state: State = {
|
const state: State = {
|
||||||
settings: ref({}),
|
settings: ref({}),
|
||||||
decks: ref([]),
|
decks: ref({}),
|
||||||
notifications: ref([]),
|
notifications: ref([]),
|
||||||
icons: ref(['mouth-watering', 'robe', 'thorny-triskelion']),
|
icons: ref(['mouth-watering', 'robe', 'thorny-triskelion']),
|
||||||
popup: ref(false)
|
popup: ref(false)
|
||||||
|
|
|
@ -3,12 +3,12 @@ import { CardSize, Arrangement, PageSize } from './consts'
|
||||||
import { IDeck, ICard } from './types'
|
import { IDeck, ICard } from './types'
|
||||||
|
|
||||||
interface IDeckTable {
|
interface IDeckTable {
|
||||||
id: number;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
description: string;
|
description: string;
|
||||||
color: string;
|
color: string;
|
||||||
icon: string;
|
icon: string;
|
||||||
cards: number[]; // array of card IDs
|
cards: string[]; // array of card IDs
|
||||||
cardSize: CardSize;
|
cardSize: CardSize;
|
||||||
arrangement: Arrangement;
|
arrangement: Arrangement;
|
||||||
pageSize: PageSize;
|
pageSize: PageSize;
|
||||||
|
@ -16,8 +16,8 @@ interface IDeckTable {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DeckDB extends Dexie {
|
export class DeckDB extends Dexie {
|
||||||
public decks: Dexie.Table<IDeckTable, number>
|
public decks: Dexie.Table<IDeckTable, string>
|
||||||
public cards: Dexie.Table<ICard, number>
|
public cards: Dexie.Table<ICard, string>
|
||||||
public tags: Dexie.Table<string>
|
public tags: Dexie.Table<string>
|
||||||
|
|
||||||
public constructor () {
|
public constructor () {
|
||||||
|
@ -25,8 +25,8 @@ export class DeckDB extends Dexie {
|
||||||
console.log('initializing deck db')
|
console.log('initializing deck db')
|
||||||
|
|
||||||
this.version(1).stores({
|
this.version(1).stores({
|
||||||
decks: '++id,name',
|
decks: '&id,name',
|
||||||
cards: '++id,name,*tags',
|
cards: '&id,name,*tags',
|
||||||
tags: '&tag'
|
tags: '&tag'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ export class DeckDB extends Dexie {
|
||||||
}
|
}
|
||||||
|
|
||||||
// add or update card
|
// 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 cardId = await this.cards.put(card)
|
||||||
const deck = await this.decks.get(deckId)
|
const deck = await this.decks.get(deckId)
|
||||||
|
|
||||||
|
@ -64,9 +64,9 @@ export class DeckDB extends Dexie {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getDecks () {
|
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 cardIds = deckTable.cards
|
||||||
const deck: IDeck = {
|
const deck: IDeck = {
|
||||||
...deckTable,
|
...deckTable,
|
||||||
|
@ -74,5 +74,13 @@ export class DeckDB extends Dexie {
|
||||||
}
|
}
|
||||||
return deck
|
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 {
|
export interface ICard {
|
||||||
id: number;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
tags: string[];
|
tags: string[];
|
||||||
icon: string;
|
icon: string;
|
||||||
|
@ -27,7 +27,7 @@ export interface ICard {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IDeck {
|
export interface IDeck {
|
||||||
id: number;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
description: string;
|
description: string;
|
||||||
color: string;
|
color: string;
|
||||||
|
@ -57,7 +57,7 @@ export interface Notification {
|
||||||
|
|
||||||
export interface State {
|
export interface State {
|
||||||
settings: Ref<Settings>;
|
settings: Ref<Settings>;
|
||||||
decks: Ref<IDeck[]>;
|
decks: Ref<{ [key: string]: IDeck }>;
|
||||||
notifications: Ref<Notification[]>;
|
notifications: Ref<Notification[]>;
|
||||||
icons: Ref<string[]>;
|
icons: Ref<string[]>;
|
||||||
popup: Ref<boolean>;
|
popup: Ref<boolean>;
|
||||||
|
|
|
@ -8,17 +8,17 @@
|
||||||
<Card id="_add_deck" @click="addDeck" />
|
<Card id="_add_deck" @click="addDeck" />
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<teleport to="#popup > .popup-content">
|
<Popup>
|
||||||
<div class="deck new-deck-form-wrapper">
|
<div class="deck new-deck-form-wrapper">
|
||||||
<header>Create a new deck of cards</header>
|
<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">
|
<footer class="centered">
|
||||||
You can also
|
You can also
|
||||||
<button @click="importDeck">import</button>
|
<button @click="importDeck">import</button>
|
||||||
an existing deck.
|
an existing deck.
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
</teleport>
|
</Popup>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -26,38 +26,45 @@
|
||||||
import { defineComponent, ref, computed } from 'vue'
|
import { defineComponent, ref, computed } from 'vue'
|
||||||
import { useState } from '@/state'
|
import { useState } from '@/state'
|
||||||
|
|
||||||
|
import Popup from '@/components/Popup.vue'
|
||||||
import Card from '@/components/Card.vue'
|
import Card from '@/components/Card.vue'
|
||||||
import DeckCard from '@/components/DeckCard.vue'
|
import DeckCard from '@/components/DeckCard.vue'
|
||||||
import DeckForm from '@/components/DeckForm.vue'
|
import DeckForm from '@/components/DeckForm.vue'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'Home',
|
name: 'Home',
|
||||||
components: { Card, DeckCard, DeckForm },
|
components: { Popup, Card, DeckCard, DeckForm },
|
||||||
setup () {
|
setup () {
|
||||||
const { actions: popupActions } = useState('popup')
|
const { actions: popupActions } = useState('popup')
|
||||||
const { collection: decks, actions: deckActions } = useState('decks')
|
const { collection: decks, actions: deckActions } = useState('decks')
|
||||||
|
|
||||||
const newDeckIndex = ref(0)
|
const newDeckId = ref('')
|
||||||
const newDeck = computed(() => decks.value[newDeckIndex.value])
|
const newDeck = computed(() => decks.value[newDeckId.value])
|
||||||
|
|
||||||
const addDeck = () => {
|
const addDeck = () => {
|
||||||
const idx = deckActions.new()
|
const id = deckActions.new()
|
||||||
newDeckIndex.value = idx
|
newDeckId.value = id
|
||||||
popupActions.show()
|
popupActions.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
const saveDeck = (updatedDeck) => {
|
const saveDeck = (updatedDeck) => {
|
||||||
console.log('saving deck', updatedDeck)
|
updatedDeck.id = newDeckId.value
|
||||||
updatedDeck.id = newDeckIndex.value
|
|
||||||
deckActions.update(updatedDeck)
|
deckActions.update(updatedDeck)
|
||||||
popupActions.hide()
|
popupActions.hide()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const cancelDeck = () => {
|
||||||
|
popupActions.hide()
|
||||||
|
deckActions.remove(newDeckId.value)
|
||||||
|
newDeckId.value = ''
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
decks,
|
decks,
|
||||||
addDeck,
|
addDeck,
|
||||||
newDeck,
|
newDeck,
|
||||||
saveDeck,
|
saveDeck,
|
||||||
|
cancelDeck,
|
||||||
hidePopup: popupActions.hide
|
hidePopup: popupActions.hide
|
||||||
// importDeck: deckActions.import,
|
// importDeck: deckActions.import,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue