import { Injectable } from "@angular/core";
import { Actions, concatLatestFrom, createEffect, ofType } from "@ngrx/effects";
import { Store } from "@ngrx/store";
import { catchError, filter, map, of, tap } from "rxjs";
import { z } from "zod";
import { selectCountData } from "..";
import { CounterCommands, CounterDocuments } from "../actions/count-actions";
import { CountState } from "../reducers/count-reducer";
@Injectable()
export class CounterDataEffects {
private readonly COUNT_DATA_KEY = "count-data";
private readonly CountDataSchema = z.object({
current: z.number(),
by: z.union([z.literal(1), z.literal(3), z.literal(5)]),
});
loadCountData$ = createEffect(
() => {
return this.actions$.pipe(
ofType(CounterCommands.load),
map(() => localStorage.getItem(this.COUNT_DATA_KEY)),
filter((x) => !!x),
map((stringy) => JSON.parse(stringy || "{}") as CountState),
map((obj) => this.CountDataSchema.parse(obj) as CountState),
map((data) => CounterDocuments.counter({ payload: data })),
catchError((err) =>
of({
type: "error",
source: "counter-prefs",
message: "we have ourselves a hacker here!",
payload: err,
})
)
);
},
{ dispatch: true }
);
saveCountData$ = createEffect(
() => {
return this.actions$.pipe(
ofType(
CounterCommands.countby,
CounterCommands.decremented,
CounterCommands.incremented,
CounterCommands.reset
),
concatLatestFrom(() => this.store.select(selectCountData)),
map(([, data]) => JSON.stringify(data)),
tap((data) => localStorage.setItem(this.COUNT_DATA_KEY, data))
);
},
{ dispatch: false }
);
constructor(private actions$: Actions, private store: Store) {}
}