From 861fd8d9e3e66d84108218accb0071b73b670aea Mon Sep 17 00:00:00 2001
From: Fedor Katurov <gotham48@gmail.com>
Date: Wed, 15 Apr 2020 10:35:35 +0700
Subject: [PATCH] colors for cards

---
 src/components/node/NodeRelatedItem/index.tsx | 23 ++++++++--
 .../node/NodeRelatedItem/styles.scss          |  9 +++-
 src/utils/dom.ts                              | 45 +++++++++++++++++++
 3 files changed, 71 insertions(+), 6 deletions(-)

diff --git a/src/components/node/NodeRelatedItem/index.tsx b/src/components/node/NodeRelatedItem/index.tsx
index ebdfbdf8..982f62e9 100644
--- a/src/components/node/NodeRelatedItem/index.tsx
+++ b/src/components/node/NodeRelatedItem/index.tsx
@@ -1,10 +1,10 @@
-import React, { FC, memo, useCallback, useState } from 'react';
+import React, { FC, memo, useCallback, useState, useMemo } from 'react';
 import * as styles from './styles.scss';
 import classNames from 'classnames';
 import { INode } from '~/redux/types';
 import { URLS, PRESETS } from '~/constants/urls';
 import { RouteComponentProps, withRouter } from 'react-router';
-import { getURL } from '~/utils/dom';
+import { getURL, stringToColour } from '~/utils/dom';
 
 type IProps = RouteComponentProps & {
   item: Partial<INode>;
@@ -28,6 +28,15 @@ const NodeRelatedItemUnconnected: FC<IProps> = memo(({ item, history }) => {
   const [is_loaded, setIsLoaded] = useState(false);
   const onClick = useCallback(() => history.push(URLS.NODE_URL(item.id)), [item, history]);
 
+  const thumb = useMemo(
+    () => (item.thumbnail ? getURL({ url: item.thumbnail }, PRESETS.avatar) : ''),
+    [item]
+  );
+  const backgroundColor = useMemo(
+    () => (!thumb && item.title && stringToColour(item.title)) || '',
+    []
+  );
+
   return (
     <div
       className={classNames(styles.item, { [styles.is_loaded]: is_loaded })}
@@ -36,10 +45,16 @@ const NodeRelatedItemUnconnected: FC<IProps> = memo(({ item, history }) => {
     >
       <div
         className={styles.thumb}
-        style={{ backgroundImage: `url("${getURL({ url: item.thumbnail }, PRESETS.avatar)}")` }}
+        style={{
+          backgroundImage: `url("${thumb}")`,
+        }}
       />
 
-      {!item.thumbnail && <div className={styles.letters}>{getTitleLetters(item.title)}</div>}
+      {!item.thumbnail && (
+        <div className={styles.letters} style={{ backgroundColor }}>
+          {getTitleLetters(item.title)}
+        </div>
+      )}
 
       <img
         src={getURL({ url: item.thumbnail }, PRESETS.avatar)}
diff --git a/src/components/node/NodeRelatedItem/styles.scss b/src/components/node/NodeRelatedItem/styles.scss
index eccc8b81..39ce0041 100644
--- a/src/components/node/NodeRelatedItem/styles.scss
+++ b/src/components/node/NodeRelatedItem/styles.scss
@@ -40,6 +40,11 @@
   width: 100%;
   height: 100%;
   font: $font_24_semibold;
-  // opacity: 0.2;
-  color: #444444;
+  color: white;
+  border-radius: $cell_radius;
+  background-image: linear-gradient(
+    180deg,
+    transparentize($content_bg, 0.4),
+    transparentize($content_bg, 0.4)
+  );
 }
diff --git a/src/utils/dom.ts b/src/utils/dom.ts
index d0624e25..7ef404a9 100644
--- a/src/utils/dom.ts
+++ b/src/utils/dom.ts
@@ -170,3 +170,48 @@ export function plural(n: number, one: string, two: string, five: string) {
     return `${n} ${five}`;
   }
 }
+
+export const stringToColour = (str: string) => {
+  let hash = 0;
+
+  for (let i = 0; i < str.length; i++) {
+    hash = str.charCodeAt(i) + ((hash << 5) - hash);
+  }
+
+  let colour = '#';
+
+  for (let i = 0; i < 3; i++) {
+    let value = (hash >> (i * 8)) & 0xff;
+    colour += ('00' + value.toString(16)).substr(-2);
+  }
+
+  return colour;
+};
+
+export const darken = (col: string, amt: number) => {
+  var usePound = false;
+
+  if (col[0] == '#') {
+    col = col.slice(1);
+    usePound = true;
+  }
+
+  var num = parseInt(col, 16);
+
+  var r = (num >> 16) + amt;
+
+  if (r > 255) r = 255;
+  else if (r < 0) r = 0;
+
+  var b = ((num >> 8) & 0x00ff) + amt;
+
+  if (b > 255) b = 255;
+  else if (b < 0) b = 0;
+
+  var g = (num & 0x0000ff) + amt;
+
+  if (g > 255) g = 255;
+  else if (g < 0) g = 0;
+
+  return (usePound ? '#' : '') + (g | (b << 8) | (r << 16)).toString(16);
+};