-
Notifications
You must be signed in to change notification settings - Fork 6
/
books.state.ts
110 lines (93 loc) · 2.74 KB
/
books.state.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import { Action, Selector, State, StateContext } from '@ngxs/store';
import { Book } from '../../models/book';
import { SearchState, SearchStateModel } from './search.state';
import { CollectionState, CollectionStateModel } from './collection.state';
import { Load, Select } from '../actions/book.actions';
import { SearchComplete } from '../actions/search.actions';
export const arrayToObject = entities => {
return entities.reduce((obj, book: Book) => {
return { ...obj, [book.id]: book };
}, {});
};
export interface BooksStateModel {
ids: string[];
entities: {
[id: string]: Book;
};
selectedBookId: string | null;
}
export const booksStateDefaults: BooksStateModel = {
ids: [],
entities: {},
selectedBookId: null,
};
@State<BooksStateModel>({
name: 'books',
defaults: booksStateDefaults,
children: [SearchState, CollectionState],
})
export class BooksState {
@Selector()
static getEntities(state: BooksStateModel) {
return state.entities;
}
@Selector()
static getSelectedId(state: BooksStateModel) {
return state.selectedBookId;
}
@Selector()
static getSelectedBook(state: BooksStateModel) {
return state.selectedBookId && state.entities[state.selectedBookId];
}
@Selector([CollectionState])
static isSelectedBookInCollection(
state: BooksStateModel,
collectionState: CollectionStateModel
) {
return collectionState.ids.indexOf(state.selectedBookId) > -1;
}
@Selector([CollectionState])
static getBookCollection(
state: BooksStateModel,
collectionState: CollectionStateModel
): Book[] {
const entities = state.entities;
const ids = [...collectionState.ids];
return ids.map(id => entities[id]);
}
@Selector([SearchState])
static getSearchResults(
state: BooksStateModel,
searchState: SearchStateModel
) {
const searchIds = [...searchState.ids];
const books = state.entities;
return searchIds.map(id => books[id]);
}
@Action(Load)
load({ getState, patchState }: StateContext<BooksStateModel>, action: Load) {
const state = getState();
const book = action.payload;
patchState({
ids: [...state.ids, book.id],
entities: { ...state.entities, [book.id]: book },
});
}
@Action(Select)
select({ patchState }: StateContext<BooksStateModel>, action: Select) {
patchState({ selectedBookId: action.payload });
}
@Action(SearchComplete)
searchComplete(
{ getState, patchState }: StateContext<BooksStateModel>,
action: SearchComplete
) {
const state = getState();
const ids = action.payload.map<string>(book => book.id);
const entities = arrayToObject(action.payload);
patchState({
ids: [...state.ids, ...ids],
entities: { ...state.entities, ...entities },
});
}
}