github.com/resonatecoop/id@v1.1.0-43/frontend/src/components/forms/profileSwitcher.js (about)

     1  const Component = require('choo/component')
     2  const compare = require('nanocomponent/compare')
     3  const html = require('choo/html')
     4  const icon = require('@resonate/icon-element')
     5  const morph = require('nanomorph')
     6  const imagePlaceholder = require('@resonate/svg-image-placeholder')
     7  const NIL_UUID = require('../../lib/nil')
     8  
     9  // ProfileSwitcher component class
    10  // [Profile switcher for Artists and Labels only...  multiple tabs, initially one only, scrolling if necessary...  If Label, label tab shown first in different colour, followed by artists on label ]
    11  class ProfileSwitcher extends Component {
    12    /***
    13     * Create profile switcher component
    14     * @param {String} id - The profile switcher component id (unique)
    15     * @param {Number} state - The choo app state
    16     * @param {Function} emit - Emit event on choo app
    17     */
    18    constructor (id, state, emit) {
    19      super(id)
    20  
    21      this.emit = emit
    22      this.state = state
    23  
    24      this.local = state.components[id] = {}
    25  
    26      this.handleKeyPress = this.handleKeyPress.bind(this)
    27      this.updateSelection = this.updateSelection.bind(this)
    28    }
    29  
    30    /***
    31     * Create profile switcher component element
    32     * @param {Object} props - The profile switcher component props
    33     * @param {String} props.value - Selected value
    34     * @returns {HTMLElement}
    35     */
    36    createElement (props = {}) {
    37      this.local.value = props.value
    38      this.local.usergroups = props.usergroups || []
    39      this.onChangeCallback = typeof props.onChangeCallback === 'function'
    40        ? props.onChangeCallback
    41        : this.onChangeCallback
    42      this.local.items = this.local.usergroups.map((item) => {
    43        return {
    44          value: item.id,
    45          name: item.displayName,
    46          banner: item.banner,
    47          avatar: item.avatar
    48        }
    49      })
    50  
    51      return html`
    52        <div class="mb5">
    53          ${this.renderItems()}
    54        </div>
    55      `
    56    }
    57  
    58    renderItems () {
    59      const length = this.local.items.length
    60  
    61      const attrs = {
    62        method: 'POST',
    63        onsubmit: (e) => {
    64          e.preventDefault()
    65  
    66          this.onChangeCallback()
    67        },
    68        novalidate: 'novalidate',
    69        action: '/'
    70      }
    71  
    72      return html`
    73        <form ${attrs}>
    74          <div class="items overflow-x-auto overflow-y-hidden bg-light-gray bw bb b--mid-gray">
    75            <div class="cf flex${length <= 3 ? ' justify-center' : ''}">
    76              ${this.local.items.map((item, index) => {
    77                const { value, name, avatar } = item
    78  
    79                const id = 'usergroup-item-' + index
    80                const checked = value === this.local.value
    81  
    82                // input attrs
    83                const attrs = {
    84                  onchange: this.updateSelection,
    85                  id: id,
    86                  tabindex: -1,
    87                  name: 'usergroup',
    88                  type: 'radio',
    89                  checked: checked,
    90                  value: value
    91                }
    92  
    93                // label attrs
    94                const attrs2 = {
    95                  class: 'flex flex-column fw4',
    96                  style: 'outline:solid 1px var(--near-black);outline-offset:0px',
    97                  tabindex: '0',
    98                  title: 'Select profile',
    99                  onkeypress: this.handleKeyPress,
   100                  for: id
   101                }
   102  
   103                const src = avatar !== NIL_UUID
   104                  ? `https://${process.env.STATIC_HOSTNAME}/images/${avatar}-x300.jpg`
   105                  : imagePlaceholder(400, 400)
   106  
   107                // item background attrs
   108                const attrs3 = {
   109                  class: 'flex items-end pb2 aspect-ratio--object z-1',
   110                  style: `background: url(${src}) center center / cover no-repeat;`
   111                }
   112  
   113                return html`
   114                  <div class="fl flex flex-column justify-center flex-shrink-0 w4 pt2 pb4 ph3">
   115                    <input ${attrs}>
   116                    <label ${attrs2}>
   117                      <div class="aspect-ratio aspect-ratio--1x1">
   118                        <div ${attrs3}>
   119                          <div class="flex flex-shrink-0 justify-center items-center ml2">
   120                            ${icon('circle', { size: 'sm', class: 'fill-transparent' })}
   121                          </div>
   122                          <span class="absolute truncate w-100 f5 bottom-0${checked ? ' b' : ''}" style="transform:translateY(100%)">${name}</span>
   123                        </div>
   124                      </div>
   125                    </label>
   126                  </div>
   127                `
   128              })}
   129              <div class="fl flex justify-center items-center flex-shrink-0 w4">
   130                <button type="submit" title="Create new profile" class="bg-white ba b--mid-gray br-pill w3 h3 mb3 grow">
   131                  <div class="flex items-center justify-center">
   132                    ${icon('add', { size: 'sm' })}
   133                  </div>
   134                </button>
   135              </div>
   136            </div>
   137          </div>
   138        </form>
   139      `
   140    }
   141  
   142    updateSelection (e) {
   143      const val = e.target.value
   144      this.local.value = val
   145      morph(this.element.querySelector('.items'), this.renderItems())
   146      this.onChangeCallback(this.local.value)
   147    }
   148  
   149    handleKeyPress (e) {
   150      if (e.keyCode === 13) {
   151        e.preventDefault()
   152        e.target.control.checked = !e.target.control.checked
   153        const val = e.target.control.value
   154        this.local.value = val
   155        morph(this.element.querySelector('.items'), this.renderItems())
   156        this.onChangeCallback(this.local.value)
   157      }
   158    }
   159  
   160    handleSubmit (e) {
   161      e.preventDefault()
   162  
   163      this.onChangeCallback(this.local.value)
   164    }
   165  
   166    onSubmit () {}
   167  
   168    update (props) {
   169      return compare(this.local.usergroups, props.usergroups) ||
   170        this.local.value !== props.value
   171    }
   172  }
   173  
   174  module.exports = ProfileSwitcher