Skip to content

Instantly share code, notes, and snippets.

@jacobwgillespie jacobwgillespie/redux.js Secret
Created Feb 29, 2016

Embed
What would you like to do?
import { bind } from 'redux-effects';
import { createAction } from 'redux-actions';
import { fetch } from 'redux-effects-fetch';
export const CART_DID_LOAD = 'CART_DID_LOAD';
export const OPTIMISTIC_CART_ADD = 'OPTIMISTIC_CART_ADD';
export const OPTIMISTIC_QUANTITY_UPDATE = 'OPTIMISTIC_QUANTITY_UPDATE';
export const BASE_URI = 'https://api.basicman.co';
export const cartDidLoad = createAction(CART_DID_LOAD);
export const optimisticCartAdd = createAction(OPTIMISTIC_CART_ADD);
export const optimisticQuantityUpdate = createAction(OPTIMISTIC_QUANTITY_UPDATE);
export const loadCart = () => (
bind(
fetch(
`${BASE_URI}/cart`, {
credentials: 'include',
}
),
({ value }) => cartDidLoad(value),
err => console.error(err), // eslint-disable-line no-console
)
);
export const addToCart = (slug) => (
[
optimisticCartAdd({ slug }),
bind(
fetch(
`${BASE_URI}/add/${slug}`, {
credentials: 'include',
}
),
({ value }) => cartDidLoad(value),
err => console.error(err), // eslint-disable-line no-console
),
]
);
let latestUpdateID = 0;
export const changeCartQuantity = (slug, quantity) => {
const updateID = (latestUpdateID += 1);
return [
optimisticQuantityUpdate({ slug, quantity }),
bind(
fetch(
`${BASE_URI}/change/${slug}/${quantity}`, {
credentials: 'include',
}
),
({ value }) => updateID === latestUpdateID ? cartDidLoad(value) : true,
err => console.error(err), // eslint-disable-line no-console
),
];
};
export const removeFromCart = (slug) => (
bind(
fetch(
`${BASE_URI}/remove/${slug}`, {
credentials: 'include',
}
),
({ value }) => cartDidLoad(value),
err => console.error(err), // eslint-disable-line no-console
)
);
export const clearCart = () => (
bind(
fetch(
`${BASE_URI}/clear`, {
credentials: 'include',
}
),
({ value }) => cartDidLoad(value),
err => console.error(err), // eslint-disable-line no-console
)
);
export const actions = {
addToCart,
cartDidLoad,
changeCartQuantity,
clearCart,
loadCart,
removeFromCart,
};
const ACTION_HANDLERS = {
[CART_DID_LOAD]: (state, { payload }) => payload,
[OPTIMISTIC_CART_ADD]: (state, action) => {
const { slug } = action.payload;
const { items, quantity } = state;
if (items[slug]) {
return {
...state,
items: {
...items,
[slug]: {
...items[slug],
quantity: items[slug].quantity + 1,
},
},
quantity: quantity + 1,
};
}
return {
...state,
items: {
...items,
[slug]: {
quantity: 1,
loading: true,
product: {
slug,
},
},
},
quantity: quantity + 1,
};
},
[OPTIMISTIC_QUANTITY_UPDATE]: (state, action) => {
const { slug, quantity } = action.payload;
const newCount = state.count - state.items[slug].quantity + quantity;
if (quantity === 0) {
const newItems = {};
Object.keys(state.items).forEach(key => {
if (key !== slug) newItems[key] = state.items[key];
});
return {
...state,
items: newItems,
count: newCount,
};
}
return {
...state,
items: {
...state.items,
[slug]: {
...state.items[slug],
quantity,
},
},
count: newCount,
};
},
};
const initialState = {
loading: true,
items: [],
count: 0,
};
export default function cartReducer(state = initialState, action) {
const handler = ACTION_HANDLERS[action.type];
return handler ? handler(state, action) : state;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.