Skip to content

Instantly share code, notes, and snippets.

@DanielRamosAcosta
Last active December 6, 2018 20:23
Show Gist options
  • Save DanielRamosAcosta/0708d6380c673d7b244c131f77e6072a to your computer and use it in GitHub Desktop.
Save DanielRamosAcosta/0708d6380c673d7b244c131f77e6072a to your computer and use it in GitHub Desktop.
function mapStateToProps (state) {
const repository = userRepository(state)
const userPreferences = repository.getUserPreferences() // Toggler instance
return {
heading: 'User Profile',
availableElements: typesToElements(userPreferences.getAvailableTypes()),
selectedElements: typesToElements(userPreferences.getSelectedTypes()),
totalCount: userPreferences.count(),
allSelected: userPreferences.hasNothingSelected()
}
}
import flow from 'lodash/flow'
function Toggler(toggler) {
// PRIVATE ====================================================================
function updateSelectedTypes (types) {
return {
...toggler,
types
}
}
function availableTypeFor (availableTypes, typeId) {
const availableType = availableTypes.find(availableType => availableType.id === typeId)
if (!availableType) {
throw new Error(`Couldn't find type with id: ${typeId}`)
}
return availableType
}
function typeHasSubtypes (type) {
return !!type.subtypes
}
function findType (types, typeId) {
return types.find(type => type.id === typeId)
}
function newType (typeId) {
return {id: typeId}
}
function newTypeWithSubtypes (typeId, subtypes = []) {
return {id: typeId, subtypes}
}
function hasSubtypesSelected (typeWithSubtypes) {
return !!typeWithSubtypes.subtypes.length
}
function toggleTypeSubtypes (availableType, typeWithSubtypes = newTypeWithSubtypes(availableType.id)) {
return typeWithSubtypes.subtypes.length === availableType.subtypes.length
? newTypeWithSubtypes(typeWithSubtypes.id)
: newTypeWithSubtypes(typeWithSubtypes.id, availableType.subtypes)
}
function removeType (types, typeId) {
return types.filter(type => type.id !== typeId)
}
function addType (types, type) {
return types.concat(type)
}
function cleanTypes (types) {
// Remove TypesWithSubtypes if they have an empty array as subtypes
return types.filter(type => !typeHasSubtypes(type) || hasSubtypesSelected(type))
}
function updateTypes (types, newUpdatedType) {
return flow(
types => removeType(types, newUpdatedType.id),
types => addType(types, newUpdatedType),
cleanTypes
)(types)
}
function toggleTypeFromList (typeId) {
const availableTypes = getAvailableTypes(toggler)
const types = getSelectedTypes(toggler)
const availableType = availableTypeFor(availableTypes, typeId)
const type = findType(types, typeId)
if (typeHasSubtypes(availableType)) {
return updateTypes(types, toggleTypeSubtypes(availableType, type))
}
if (type) {
return removeType(types, type.id)
}
return addType(types, newType(typeId))
}
function toggleSubtypeFromList (typeId, subtypeId) {
const availableTypes = getAvailableTypes(toggler)
const types = getSelectedTypes(toggler)
const availableType = availableTypeFor(availableTypes, typeId)
const typeWithSubtypes = findType(types, typeId)
const subtypes = typeWithSubtypes ? typeWithSubtypes.subtypes : []
const subToggler = create(availableType.subtypes, subtypes)
const typeWithSubtypesToggled = newTypeWithSubtypes(
typeId,
toggleTypeFromList(subToggler, subtypeId)
)
return updateTypes(types, typeWithSubtypesToggled)
}
// PUBLIC ====================================================================
function toggleType (typeId) {
return updateSelectedTypes(
toggler,
toggleTypeFromList(typeId)
)
}
function toggleSubtype (typeId, subtypeId) {
return updateSelectedTypes(
toggler,
toggleSubtypeFromList(typeId, subtypeId)
)
}
function countSelectedTypes () {
return getSelectedTypes(toggler).reduce((accumulator, type) =>
type.subtypes
? accumulator + type.subtypes.length
: accumulator + 1
, 0)
}
function hasSelection () {
return getSelectedTypes(toggler).length !== 0
}
function getAvailableTypes () {
return toggler.availableTypes
}
function getSelectedTypes () {
return toggler.types
}
return {
toggleType,
toggleSubtype,
countSelectedTypes,
hasSelection,
getAvailableTypes,
getSelectedTypes
}
}
Toggler.createAttributes = (availableTypes, types = []) => {
return {
types,
availableTypes
}
}
export default Toggler
import { Toggler } from '../../domain/Toggler'
export function userRepository (state) {
return {
// ...
getUserPreferences: () => Toggler(state.user.userPreferences),
// ...
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment