Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import "../common/sw-init"
- import { createStore, applyMiddleware, compose } from "redux"
- import { createRedutser } from "redutser"
- import thunkMw from "redux-thunk"
- import { ajaxRequest, url } from "../common/site"
- import { createEffects } from "@proerd/nextpress-client/built/connext"
- import { asyncThunkErrorMw } from "@proerd/nextpress-client/built/error"
- import { groupBy, toPairs } from "lodash"
- import { serviceWorker } from "../common/sw-init"
- const initialState = {
- newRule: undefined as undefined | Rule_Client,
- ruleList: [] as Rule_Client[],
- showUserDropdown: false,
- error: undefined as string | undefined,
- selectedTab: "rules" as "rules" | "realms" | "scan" | "options",
- newRealm: undefined as undefined | NewRealm,
- realmList: [] as NewRealm[],
- scanTab: undefined as
- | undefined
- | {
- results: [string, ScanResult[]][]
- },
- settings: undefined as
- | undefined
- | {
- form: { optEmailNotifications: boolean; optBrowserNotifications: boolean }
- isSaving?: 1 | 2
- },
- }
- type NewRealm = { name: string; slug: string; alliance: boolean; horde: boolean }
- type Rule_Client = {
- id?: number
- itemId?: number
- _itemName?: string
- type?: string
- value?: string
- }
- export type ScanResult = {
- type: string
- slug: string
- realmName: string
- faction: 0 | 1
- itemId: number
- value: number
- _itemName: string
- stockFound?: number
- minimumFound?: number
- }
- type ScanApiResponse = {
- results: ScanResult[]
- }
- type SettingsApiResponse = {
- settings: { optEmailNotifications: boolean; optBrowserNotifications: boolean }
- }
- export const root = createRedutser(initialState, {
- newRule_init: state => ({
- ...state,
- newRule: { itemId: undefined, rule: undefined },
- }),
- newRule_setField: (
- state,
- action: {
- field: keyof NonNullable<typeof initialState["newRule"]>
- val: string
- },
- ) => {
- return {
- ...state,
- newRule: state.newRule && { ...state.newRule, [action.field]: action.val },
- }
- },
- newRule_hide: state => ({
- ...state,
- newRule: undefined,
- }),
- toggleUserDropdown: state => ({
- ...state,
- showUserDropdown: !state.showUserDropdown,
- }),
- ruleList_replace: (state, act: { rules: Rule_Client[] }) => {
- return {
- ...state,
- ruleList: act.rules || [],
- }
- },
- removeRule: (state, act: { id: number }) => ({
- ...state,
- ruleList: state.ruleList.filter(r => r.id !== act.id),
- }),
- setTab: (state, tab: typeof initialState["selectedTab"]) => ({
- ...state,
- selectedTab: tab,
- }),
- error: (state, action: { error: any }) => {
- console.log(action.error)
- return {
- ...state,
- error: action.error,
- }
- },
- newRealm_init: state => ({
- ...state,
- newRealm: {
- name: "",
- slug: "",
- alliance: false,
- horde: false,
- },
- }),
- newRealm_set: (state, act: Partial<NewRealm>) => ({
- ...state,
- newRealm: state.newRealm && { ...state.newRealm, ...act },
- }),
- newRealm_hide: state => ({
- ...state,
- newRealm: undefined,
- }),
- realmList_replace: (state, act: { realms: NewRealm[] }) => ({
- ...state,
- realmList: act.realms || [],
- }),
- realmList_remove: (state, act: { slug: string }) => ({
- ...state,
- realmList: state.realmList.filter(r => r.slug !== act.slug),
- }),
- scanTab_empty: state => ({
- ...state,
- scanTab: undefined,
- }),
- scanTab_replace: (state, act: { results: Record<string, ScanResult[]> }) => ({
- ...state,
- scanTab: {
- results: toPairs(act.results),
- },
- }),
- settings_set: (state, act: { settings: SettingsApiResponse["settings"] }) => ({
- ...state,
- settings: {
- form: act.settings,
- isSaving: state.settings && state.settings.isSaving,
- },
- }),
- settings_isSaving: (state, act: undefined | 1 | 2) => {
- return {
- ...state,
- settings: state.settings && { ...state.settings, isSaving: act },
- }
- },
- })
- export const effects = createEffects(root)({
- // - rules -
- reloadRules: () => async dispatch => {
- let res = await ajaxRequest<{ rules: any }>({
- url: url("/api/rule/list"),
- method: "POST",
- body: {},
- })
- let rules = res.rules || []
- dispatch(root.creators.ruleList_replace({ rules }))
- },
- createRule: () => async (dispatch, getState) => {
- let state = getState().newRule!
- let rule = {
- type: state.type,
- itemId: state.itemId,
- value: state.value,
- }
- await ajaxRequest({
- url: url("/api/rule/create"),
- method: "POST",
- body: rule,
- })
- dispatch(root.creators.newRule_hide({}))
- await effects.reloadRules()(dispatch)
- },
- removeRule: (id: number) => async dispatch => {
- await ajaxRequest({
- url: url("/api/rule/remove"),
- method: "POST",
- body: { id },
- })
- dispatch(root.creators.removeRule({ id }))
- },
- // - realms -
- reloadRealms: () => async dispatch => {
- let resp = await ajaxRequest<{ realms: NewRealm[] }>({
- url: url("/api/realm/list"),
- method: "POST",
- body: {},
- })
- dispatch(root.creators.realmList_replace({ realms: resp.realms }))
- },
- addRealm: () => async (dispatch, getState) => {
- let state = getState().newRealm!
- await ajaxRequest({
- url: url("/api/realm/create"),
- method: "POST",
- body: state,
- })
- dispatch(root.creators.newRealm_hide({}))
- await effects.reloadRealms()(dispatch)
- },
- removeRealm: (slug: string) => async dispatch => {
- await ajaxRequest({
- url: url("/api/realm/remove"),
- method: "POST",
- body: { slug },
- })
- dispatch(root.creators.realmList_remove({ slug }))
- },
- loadTab: (tab: typeof initialState["selectedTab"]) => async (dispatch, getState) => {
- dispatch(root.creators.setTab(tab))
- if (tab === "scan") {
- await effects.refreshScanTab()(dispatch)
- }
- if (typeof window !== "undefined") {
- window.history.pushState({}, "", url("/dashboard", { tab }))
- }
- },
- refreshScanTab: () => async dispatch => {
- dispatch(root.creators.scanTab_empty({}))
- let { results } = await ajaxRequest<ScanApiResponse>({
- url: url("/api/scan"),
- method: "POST",
- body: {},
- })
- let grouped = groupBy(results, (item: ScanResult) => item.realmName + ":" + item.faction)
- dispatch(root.creators.scanTab_replace({ results: grouped }))
- },
- loadUserSettings: () => async (dispatch, getState) => {
- console.log("loadusersettings")
- if (getState().settings) return
- let { settings } = await ajaxRequest<SettingsApiResponse>({
- url: url("/api/settings/view"),
- method: "POST",
- body: {},
- })
- dispatch(root.creators.settings_set({ settings }))
- if (settings.optBrowserNotifications) {
- let sw = await serviceWorker().init()
- if (!sw) {
- console.log("Unable to initialize service worker")
- return
- }
- let subscription = await sw.getSubscription()
- if (!subscription) {
- console.log("unable to get subscription")
- return
- }
- let _subscription = subscription.toJSON()
- await ajaxRequest({
- url: url("/api/insert-push-subscription"),
- method: "POST",
- body: {
- endpoint: _subscription.endpoint,
- auth: _subscription.keys.auth,
- p256dh: _subscription.keys.p256dh,
- },
- })
- console.log("updated push subscription for this session")
- }
- },
- setUserSettings: (opts: SettingsApiResponse["settings"]) => async (dispatch, getState) => {
- let prev = getState().settings!.form
- if (!prev) {
- await effects.loadUserSettings()(dispatch, getState)
- prev = getState().settings!.form
- }
- dispatch(root.creators.settings_isSaving(1))
- await Promise.all([
- ajaxRequest({
- url: url("/api/settings/update"),
- method: "POST",
- body: { settings: opts },
- }),
- new Promise(res => setTimeout(res, 1000)),
- ])
- dispatch(root.creators.settings_isSaving(2))
- setTimeout(() => {
- dispatch(root.creators.settings_isSaving(undefined))
- }, 3000)
- if (prev!.optBrowserNotifications && opts.optBrowserNotifications) {
- if (typeof Notification !== "undefined" && (Notification as any).permission !== "granted") {
- await Notification.requestPermission()
- }
- }
- dispatch(root.creators.settings_set({ settings: opts }))
- },
- unsubscribePush: () => async () => {
- let sw = await serviceWorker().init()
- if (!sw) return
- await sw.unsubscribe()
- },
- })
- const composeEnhancers =
- (typeof window !== "undefined" && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) || compose
- export const store = createStore(
- root.reducer,
- composeEnhancers(applyMiddleware(asyncThunkErrorMw(), thunkMw)),
- )
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement