refactor(private-zone): use canonical product name
This commit is contained in:
@@ -0,0 +1,188 @@
|
||||
import type { DoneActorEvent, ErrorActorEvent } from "xstate";
|
||||
|
||||
import type { PrivateAlbumUnlockResponse } from "@/data/schemas/private-zone";
|
||||
|
||||
import {
|
||||
getPendingAlbum,
|
||||
patchAlbumInList,
|
||||
removeAlbum,
|
||||
} from "../helper/albums";
|
||||
import {
|
||||
toPaywallRequest,
|
||||
toPrivateZoneErrorMessage,
|
||||
toUnlockErrorMessage,
|
||||
} from "../helper/unlock";
|
||||
import {
|
||||
albumMachineSetup,
|
||||
failedState,
|
||||
idleState,
|
||||
loadingState,
|
||||
} from "./album-flow";
|
||||
import { createPrivateZoneActorActionSetup } from "./setup";
|
||||
|
||||
const requestUnlockAction = albumMachineSetup.assign(({ event }) =>
|
||||
event.type === "PrivateZoneUnlockRequested"
|
||||
? {
|
||||
pendingConfirmAlbumId: event.albumId,
|
||||
unlockErrorMessage: null,
|
||||
unlockPaywallRequest: null,
|
||||
}
|
||||
: {},
|
||||
);
|
||||
|
||||
const cancelUnlockAction = albumMachineSetup.assign({
|
||||
pendingConfirmAlbumId: null,
|
||||
});
|
||||
|
||||
const clearUnlockPaywallAction = albumMachineSetup.assign({
|
||||
unlockPaywallRequest: null,
|
||||
});
|
||||
|
||||
const beginUnlockAction = albumMachineSetup.assign(({ context }) => ({
|
||||
unlockingAlbumId: context.pendingConfirmAlbumId,
|
||||
unlockErrorMessage: null,
|
||||
unlockPaywallRequest: null,
|
||||
}));
|
||||
|
||||
export const privateZoneMachineSetup = albumMachineSetup.extend({
|
||||
actions: {
|
||||
requestUnlock: requestUnlockAction,
|
||||
cancelUnlock: cancelUnlockAction,
|
||||
clearUnlockPaywall: clearUnlockPaywallAction,
|
||||
beginUnlock: beginUnlockAction,
|
||||
},
|
||||
});
|
||||
|
||||
const unlockDoneSetup =
|
||||
createPrivateZoneActorActionSetup<
|
||||
DoneActorEvent<PrivateAlbumUnlockResponse>
|
||||
>();
|
||||
const unlockErrorSetup =
|
||||
createPrivateZoneActorActionSetup<ErrorActorEvent>();
|
||||
|
||||
const applyUnlockSuccessAction = unlockDoneSetup.assign(
|
||||
({ context, event }) => ({
|
||||
items: patchAlbumInList(context.items, event.output),
|
||||
creditBalance: event.output.creditBalance,
|
||||
pendingConfirmAlbumId: null,
|
||||
unlockingAlbumId: null,
|
||||
unlockErrorMessage: null,
|
||||
unlockSuccessNonce: context.unlockSuccessNonce + 1,
|
||||
}),
|
||||
);
|
||||
|
||||
const applyUnlockPaywallAction = unlockDoneSetup.assign(
|
||||
({ context, event }) => ({
|
||||
items: patchAlbumInList(context.items, event.output),
|
||||
creditBalance: event.output.creditBalance,
|
||||
pendingConfirmAlbumId: null,
|
||||
unlockingAlbumId: null,
|
||||
unlockErrorMessage: null,
|
||||
unlockPaywallRequest: toPaywallRequest(event.output),
|
||||
}),
|
||||
);
|
||||
|
||||
const applyCostChangedAction = unlockDoneSetup.assign(({ event }) => ({
|
||||
pendingConfirmAlbumId: null,
|
||||
unlockingAlbumId: null,
|
||||
unlockErrorMessage: toUnlockErrorMessage(event.output),
|
||||
}));
|
||||
|
||||
const applyAlbumNotFoundAction = unlockDoneSetup.assign(
|
||||
({ context, event }) => ({
|
||||
items: removeAlbum(context.items, event.output.albumId),
|
||||
creditBalance: event.output.creditBalance,
|
||||
pendingConfirmAlbumId: null,
|
||||
unlockingAlbumId: null,
|
||||
unlockErrorMessage: toUnlockErrorMessage(event.output),
|
||||
}),
|
||||
);
|
||||
|
||||
const applyUnlockFailureAction = unlockDoneSetup.assign(
|
||||
({ context, event }) => ({
|
||||
items: patchAlbumInList(context.items, event.output),
|
||||
creditBalance: event.output.creditBalance,
|
||||
pendingConfirmAlbumId: null,
|
||||
unlockingAlbumId: null,
|
||||
unlockErrorMessage: toUnlockErrorMessage(event.output),
|
||||
}),
|
||||
);
|
||||
|
||||
const applyUnlockActorErrorAction = unlockErrorSetup.assign(({ event }) => ({
|
||||
pendingConfirmAlbumId: null,
|
||||
unlockingAlbumId: null,
|
||||
unlockErrorMessage: toPrivateZoneErrorMessage(event.error),
|
||||
}));
|
||||
|
||||
const readyState = privateZoneMachineSetup.createStateConfig({
|
||||
on: {
|
||||
PrivateZoneInit: "loading",
|
||||
PrivateZoneRefresh: "loading",
|
||||
PrivateZoneUnlockRequested: { actions: "requestUnlock" },
|
||||
PrivateZoneUnlockCancelled: { actions: "cancelUnlock" },
|
||||
PrivateZoneUnlockConfirmed: [
|
||||
{
|
||||
guard: "hasPendingAlbum",
|
||||
target: "unlocking",
|
||||
},
|
||||
],
|
||||
PrivateZoneUnlockPaywallConsumed: { actions: "clearUnlockPaywall" },
|
||||
},
|
||||
});
|
||||
|
||||
const unlockingState = privateZoneMachineSetup.createStateConfig({
|
||||
entry: "beginUnlock",
|
||||
invoke: {
|
||||
src: "unlockAlbum",
|
||||
input: ({ context }) => {
|
||||
const pendingAlbum = getPendingAlbum(context);
|
||||
return {
|
||||
albumId: pendingAlbum?.albumId ?? "",
|
||||
expectedCost: pendingAlbum?.unlockCost ?? 0,
|
||||
};
|
||||
},
|
||||
onDone: [
|
||||
{
|
||||
guard: ({ event }) => event.output.unlocked && !event.output.locked,
|
||||
target: "ready",
|
||||
actions: applyUnlockSuccessAction,
|
||||
},
|
||||
{
|
||||
guard: ({ event }) =>
|
||||
event.output.reason === "insufficient_credits",
|
||||
target: "ready",
|
||||
actions: applyUnlockPaywallAction,
|
||||
},
|
||||
{
|
||||
guard: ({ event }) => event.output.reason === "cost_changed",
|
||||
target: "loading",
|
||||
actions: applyCostChangedAction,
|
||||
},
|
||||
{
|
||||
guard: ({ event }) => event.output.reason === "not_found",
|
||||
target: "ready",
|
||||
actions: applyAlbumNotFoundAction,
|
||||
},
|
||||
{
|
||||
target: "ready",
|
||||
actions: applyUnlockFailureAction,
|
||||
},
|
||||
],
|
||||
onError: {
|
||||
target: "ready",
|
||||
actions: applyUnlockActorErrorAction,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const privateZoneRootStateConfig =
|
||||
privateZoneMachineSetup.createStateConfig({
|
||||
initial: "idle",
|
||||
states: {
|
||||
idle: idleState,
|
||||
loading: loadingState,
|
||||
failed: failedState,
|
||||
ready: readyState,
|
||||
unlocking: unlockingState,
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user