Implementing the List View of the Skill Cards

In this blog post, we are going to understand the implementation of the UI for the SUSI.AI skill card that is displayed on various routes of the SUSI Skill CMS Web-App. Now, there are two types of views of the views for the skill cards – List view and Grid view. We will learn to implement the List View in this blog.

Final UI of the Skill Card

Going through the implementation

The UI has multiple components –

  • The image thumbnail.
  • The title and author section,
  • Below that we have examples, ratings and the description section.

Fetching the data

  • The Skill Metadata for each skill is passed as props from the parent of the component, where this UI is implemented. This data object contains the various data points that are needed to display the UI. The key values used are –
    • skill_name – Used in the Title of the Skill Card
    • image – Used to display the thumbnail image of the skill
    • model – used to create the link to the Skill Details page
    • group – used to create the link to the Skill Details page
    • language – used to create the link to the Skill Details page
    • skill_tag – used to create the link to the Skill Details page
    • examples – used to display the examples card.
    • author – used to display the Author name
    • skill_rating – Used to display the stars and the total number of ratings of the skill
  • The following image shows the various areas, where the data is being used.

Parsing the data and creating JSX

  • Below is the code used to parse the data and achieving the UI, followed by the explanation.

…..
loadSkillCards = () => {
  let cards = [];
  Object.keys(this.state.skills).forEach(el => {
    let skill = this.state.skills[el];
    let skill_name = 'Name not available', examples = [], image = '', description =      
    'No description available', author_name = 'Author', average_rating = 0, 
    total_rating = 0;
    if (skill.skill_name) 
      skill_name = skill.skill_name.charAt(0).toUpperCase() + skill_name.slice(1);
    ….
    // Similarly parse, image, descriptions, author 
    ….
    if (skill.examples)
      examples = skill.examples.slice(0, 2); // Select max 2 examples
    if (skill.skill_rating) {
      average_rating = parseFloat(skill.skill_rating.stars.avg_star);
      total_rating = parseInt(skill.skill_rating.stars.total_star, 10);
    }
    cards.push(
      <div style={styles.skillCard} key={el}>
        <div style={styles.imageContainer}>
          // Display the image, else default avatar compoennt CircleImage
        </div>
        <div style={styles.content}>
          <div style={styles.header}>
            // Add Link to the skill title
              <div style={styles.title}><span>{skill_name}</span></div>
            <div style={styles.authorName}><span>{author_name}</span></div>
          </div>
          <div style={styles.details}>
            <div style={styles.exampleSection}>
              {examples.map((eg, index) => { return (
                <div key={index} style={styles.example}>&quot;{eg}&quot;</div>);
              })}
            </div>
            <div style={styles.textData}>
              <div style={styles.row}>
                <div style={styles.rating}>
                  // Show the 5-star rating section
                </div>
              </div>
              <div style={styles.row}>
                // Insert the skill description
              </div>
        //Close the div tags
    );
  });
  this.setState({cards});
};

render() {
.
.
  return (<div style={styles.gridList}>{skillDisplay}</div>);
}
.
.

 

  • An array of skills is passed as props and set in the state of the component in the constructor lifecycle method. The loadSkillCards() function is called in the didComponentMount lifecycle method, which is responsible for creating the JSX for all the Skill Cards.
  • In this function, the map property of array is used, to iterate over each skill and the corresponding Skill Card is pushed to the cards array, after successfully parsing the data.
  • At the end of the function definition, the state is updated, which in turn triggers the render function. In the render function, the cards are returned enclosed in a <div> tag. This helps us to create the above UI.

Styling the UI

Some important styling used is shown below. For the full styles object, please follow this link.

const styles = {
  skillCard: {
    width: '100%',
    overflow: 'hidden',
    display: 'flex',
    flexDirection: 'row',
    borderTop: '1px solid #eaeded',
    padding: 7,
  },
  imageContainer: {
    display: 'inline-block',
    alignItems: 'center',
    padding: '10px',
    background: '#fff',
    height: '218px',
    marginBottom: '6px',
  },
  image: {
    position: 'relative',
    height: '180px',
    width: '180px',
    verticalAlign: 'top',
    borderRadius: '50%',
  },
….
  gridlist: {
    marginTop: '20px',
    marginBottom: '40px',
    padding: '0px 10px',
    width: '100%',
….
  example: {
    fontStyle: 'italic',
    fontSize: '14px',
    padding: '14px 18px',
    borderRadius: '4px',
    border: '1px #ddd solid',
    float: 'left',
    display: 'flex row',
    justifyContent: 'center',
    alignItems: 'center',
    width: 192,
  },
….
};

export default styles;

 

I hope the implementation of the UI is clear and proved to be helpful for your understanding.

Resources

Showcase of the Material-UI icons (used for View type icons) – https://material.io/icons/