rusty1s/dotfiles

View on GitHub
widgets/calendar/index.jsx

Summary

Maintainability
A
0 mins
Test Coverage
import { styled, css } from 'uebersicht'

export const command = 'cat ~/ical.txt';
export const refreshFrequency = 1000 * 60 * 10; // 10 minutes.

export const className = css`
  -webkit-backdrop-filter: blur(100px);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-family: SFUIText Nerd Font;
  font-size: 13px;

  background: rgba(255,255,255,0.1);
  border: 1px solid rgba(0,0,0,0.1);
  border-radius: 15px;
  overflow: hidden;
  min-width: 250px;

  position: absolute;
  left: 330px;
  top: 30px;
`

const Text = styled('div')`
  text-align: center;
  font-weight: 500;
  font-style: italic;
  padding: 10px 20px;
`

const header = css`
  background: rgba(255,255,255,0.3);
  font-size: 16px;
  font-weight: 500;
  padding: 15px 20px 15px 70px;
  position: relative;

  &::before {
    height: 36px;
    width: 36px;
    left: 20px;
    top: 6px;
    background: rgba(255,255,255,0.8);
    padding-top: 10px;
    border-radius: 7px;
    font-weight: 300;
    text-align: center;
    box-sizing: border-box;
    font-size: 22px;
    content: attr(data-day);
    position: absolute;
  }

  &::after {
    width: 36px;
    content: attr(data-month);
    position: absolute;
    left:20px;
    top: 6px;
    text-align: center;
    color: red;
    font-weight: 300;
    font-size: 10px;
  }
`

const borderColor = {
  'Arbeit': 'rgb(90,214,67)',
  'Matthias': 'rgb(90,214,67)',
  'Sarah Arbeit': 'rgb(190,88,214)',
  'Termine': 'rgb(32,173,244)',
  'Privat': 'rgb(32,173,244)',
};

const Entry = styled('div')(props => ({
  padding: '7px 20px',
  borderLeft: `3px solid ${borderColor[props.type]}`,
  ':nth-child(odd)': {
    background: 'rgba(255,255,255,0.1)',
  },
}))

const Desc = styled('span')`
  font-size: 14px;
  font-weight: 500;
  padding-bottom: 2px;
`

const parse = output => {
  return output.split('\n\n').map(dayEvents => {
    const [ week_name, day, month ] = dayEvents.split('\n')[0].slice(0, -1).split(' ');
    const events = dayEvents.split('* ').slice(1).map(e => {
      const lines = e.split('\n').filter(str => str.length > 0);
      e = [lines.slice(0, 1), lines.slice(-1)].join('\n')
      if (e.includes(" - ")) {
        const [ desc, type, start, end ] = /(.*) \((.*)\)\s+(.*) - (.*)/.exec(e).slice(1);
        return { desc, type, start, end };
      } else {
        const [desc, type ] = /(.*) \((.*)\)/.exec(e).slice(1);
        return { desc, type };
      }
      return e;
    });
    return { week_name, day, month, events };
  });
}

export const render = ({ output, error }) => {
  if (error) return <Text>An error occurred.</Text>;
  if (output.length == 0) return <Text>No calendar entries found.</Text>;

  const days = parse(output);

  return (
    <div>
      {days.map(day => (
        <div key={day['day']}>
          <div className={header} data-day={day['day']} data-month={day['month']}>{day['week_name']}</div>
          {day['events'].map(e => (
            <Entry key={e['desc']} type={e['type']}>
              <Desc>{e['desc']}</Desc>
              {e['start'] && <div>{e['start']} - {e['end']}</div>}
            </Entry>
          ))}
        </div>
      ))}
    </div>
  );
}