<repo_name>sdaudishvili/nextjs-project<file_sep>/DUMMY_DATA.js
export const aboutUs = {
  title: 'About Us',
  image: 'https://colorlib.com/preview/theme/samira/images/about_intro.jpg',
  description:
    'Praesent fermentum ligula in dui imperdiet, vel tempus nulla ultricies. Phasellus at commodo ligula. Nullam molestie volutpat sapien, a dignissim tortor laoreet quis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos'
};

export const sliderItems = [
  'https://colorlib.com/preview/theme/samira/images/gallery_1.jpg',
  'https://colorlib.com/preview/theme/samira/images/gallery_2.jpg',
  'https://colorlib.com/preview/theme/samira/images/gallery_3.jpg',
  'https://colorlib.com/preview/theme/samira/images/gallery_4.jpg',
  'https://colorlib.com/preview/theme/samira/images/gallery_5.jpg'
];

export const blogs = [
  {
    id: 1,
    image: '/images/pinnedBlog.jpg',
    title: 'Rooms with private swimming pool',
    description:
      'Praesent fermentum ligula in dui imperdiet, vel tempus nulla ultricies. Phasellus at commodo ligula. Nullam molestie volutpat sapien, a dignissim tortor laoreet quis. Class aptent taciti sociosqu ad litora torquent per conubia nostra. Phasellus at commodo ligula. Nullam molestie volutpat sapien, a dignissim tortor per inceptos himenaeos laoreet quis. Class aptent taciti soci osqu ad litora torquent per conubia nostra, per inceptos himenaeos.'
  },
  {
    id: 2,
    image: '/images/pinnedBlog.jpg',
    title: 'Rooms with private swimming pool',
    description:
      'Praesent fermentum ligula in dui imperdiet, vel tempus nulla ultricies. Phasellus at commodo ligula. Nullam molestie volutpat sapien, a dignissim tortor laoreet quis. Class aptent taciti sociosqu ad litora torquent per conubia nostra. Phasellus at commodo ligula. Nullam molestie volutpat sapien, a dignissim tortor per inceptos himenaeos laoreet quis. Class aptent taciti soci osqu ad litora torquent per conubia nostra, per inceptos himenaeos.'
  },
  {
    id: 3,
    image: '/images/pinnedBlog.jpg',
    title: 'Rooms with private swimming pool',
    description:
      'Praesent fermentum ligula in dui imperdiet, vel tempus nulla ultricies. Phasellus at commodo ligula. Nullam molestie volutpat sapien, a dignissim tortor laoreet quis. Class aptent taciti sociosqu ad litora torquent per conubia nostra. Phasellus at commodo ligula. Nullam molestie volutpat sapien, a dignissim tortor per inceptos himenaeos laoreet quis. Class aptent taciti soci osqu ad litora torquent per conubia nostra, per inceptos himenaeos.'
  },
  {
    id: 4,
    image: '/images/pinnedBlog.jpg',
    title: 'Rooms with private swimming pool',
    description:
      'Praesent fermentum ligula in dui imperdiet, vel tempus nulla ultricies. Phasellus at commodo ligula. Nullam molestie volutpat sapien, a dignissim tortor laoreet quis. Class aptent taciti sociosqu ad litora torquent per conubia nostra. Phasellus at commodo ligula. Nullam molestie volutpat sapien, a dignissim tortor per inceptos himenaeos laoreet quis. Class aptent taciti soci osqu ad litora torquent per conubia nostra, per inceptos himenaeos.'
  },
  {
    id: 5,
    image: '/images/pinnedBlog.jpg',
    title: 'Rooms with private swimming pool',
    description:
      'Praesent fermentum ligula in dui imperdiet, vel tempus nulla ultricies. Phasellus at commodo ligula. Nullam molestie volutpat sapien, a dignissim tortor laoreet quis. Class aptent taciti sociosqu ad litora torquent per conubia nostra. Phasellus at commodo ligula. Nullam molestie volutpat sapien, a dignissim tortor per inceptos himenaeos laoreet quis. Class aptent taciti soci osqu ad litora torquent per conubia nostra, per inceptos himenaeos.'
  }
];

export const projects = [
  {
    slug: 'deluxe-suite',
    image: 'https://colorlib.com/preview/theme/samira/images/room_1.jpg',
    title: 'Deluxe Suite',
    description:
      'Praesent fermentum ligula in dui imper diet, vel tempus nulla ultricies. Phasellus at commodo ligula.',
    dates: '10/03/2020 - 21/03/2020'
  },
  {
    slug: 'luxury-suite',
    image: 'https://colorlib.com/preview/theme/samira/images/room_2.jpg',
    title: 'Luxury Suite',
    description:
      'Praesent fermentum ligula in dui imper diet, vel tempus nulla ultricies. Phasellus at commodo ligula.',
    dates: '10/03/2020 - 21/03/2020'
  },
  {
    slug: 'd-suite',
    image: 'https://colorlib.com/preview/theme/samira/images/room_3.jpg',
    title: 'Deluxe Suite',
    description:
      'Praesent fermentum ligula in dui imper diet, vel tempus nulla ultricies. Phasellus at commodo ligula.',
    dates: '10/03/2020 - 21/03/2020'
  },
  {
    slug: 'dv-suite',
    image: 'https://colorlib.com/preview/theme/samira/images/room_3.jpg',
    title: 'Deluxe Suddite',
    description:
      'Praesent fermentum ligula in dui imper diet, vel tempus nulla ultricies. Phasellus at commodo ligula.',
    dates: '10/03/2020 - 21/03/2020'
  },
  {
    slug: 'd3-suite',
    image: 'https://colorlib.com/preview/theme/samira/images/room_1.jpg',
    title: 'Deluxete',
    description:
      'Praesent fermentum ligula in dui imper diet, vel tempus nulla ultricies. Phasellus at commodo ligula.',
    dates: '10/03/2020 - 21/03/2020'
  }
];
<file_sep>/components/organisms/Article.js
import PropTypes from 'prop-types';
import clsx from 'clsx';
import { ReadMore, Button } from '@/components/atoms';
import { Typography } from '@/components/molecules';

const Article = (props) => {
  const { article, className } = props;
  return (
    <article className={clsx(className, 'container [ flex ]')}>
      <div className="[ flex-1 pr-4-0 ]">
        <Typography variant="h2">{article.title}</Typography>
        <Typography className="[ mt-2-7 text-secondary-text ]">{article.description}</Typography>
        <ReadMore className="[ mt-3-8 ]" />
        <Button className="[ mt-3-0 ]">Contact Us</Button>
      </div>
      <div className="[ w-60-percent pl-4-0 ]">
        <img className="[ w-full ]" src={article.image} alt={article.title} />
      </div>
    </article>
  );
};

Article.propTypes = {
  article: PropTypes.object,
  className: PropTypes.string
};

Article.defaultProps = {
  article: () => ({}),
  className: ''
};

export default Article;
<file_sep>/components/layout/DefaultLayout/Footer/components/BottomFooter.js
import PropTypes from 'prop-types';
import clsx from 'clsx';
import { ContactNote, Typography } from '@/components/molecules';
import BottomNavbar from './BottomNavbar';

const Subscribe = (props) => {
  const { className, contactItems } = props;
  return (
    <div className={clsx(className, '[ grid grid-cols-12 gap-4-2 ]')}>
      <div className="[ col-span-3 ]">
        <div className="[ h-7-0 flex items-center ]">
          <img className="[ h-full ]" src="/images/logo.png" alt="" />
          <Typography variant="h2" className="[ ml-1-0 ]">
            IGI
          </Typography>
        </div>
        <div className="[ text-secondary-text ]">
          <Typography variant="body2" className="[ mt-1-0 ]">
            Copyright ©2020 All rights reserved!
          </Typography>
          <Typography variant="body2" className="[ mt-1-0 ]">
            Independent Group of Initiators!
          </Typography>
        </div>
      </div>
      <div className="[ col-span-5 ]">
        <BottomNavbar />
      </div>
      <ContactNote isFooter className="[ col-span-4 text-1-4 ]" contactItems={contactItems} />
    </div>
  );
};

Subscribe.propTypes = {
  className: PropTypes.string,
  contactItems: PropTypes.object
};

Subscribe.defaultProps = {
  className: '',
  contactItems: () => ({})
};

export default Subscribe;
<file_sep>/components/atoms/IconCircle.js
import PropTypes from 'prop-types';
import clsx from 'clsx';

const IconCircle = (props) => {
  const { children, className, ...rest } = props;

  return (
    <div
      className={clsx(className, 'flex items-center justify-center border-solid border rounded-full')}
      {...rest}
    >
      {children}
    </div>
  );
};

IconCircle.propTypes = {
  children: PropTypes.node,
  className: PropTypes.string
};

IconCircle.defaultProps = {
  children: null,
  className: ''
};

export default IconCircle;
<file_sep>/components/layout/DefaultLayout/Footer/components/index.js
export { default as Subscribe } from './Subscribe';
export { default as BottomFooter } from './BottomFooter';
<file_sep>/components/layout/AdminLayout/index.js
import React from 'react';
import PropTypes from 'prop-types';
import Body from './Body';
import SideBar from './SideBar';
import Header from './Header';

function AdminLayout(props) {
  const { children } = props;
  return (
    <>
      <Header />
      <div className="[ flex min-h-full ]">
        <SideBar />
        <Body>{children}</Body>
      </div>
    </>
  );
}

AdminLayout.propTypes = {
  children: PropTypes.any
};

AdminLayout.defaultProps = {
  children: null
};

export default AdminLayout;
<file_sep>/components/organisms/Login/index.js
import Container from '@material-ui/core/Container';
import { useDispatch, useSelector } from 'react-redux';
import { useRouter } from 'next/router';
import { authenticateUser } from '@/redux/actions/userActions';
import { NoSSR } from '@/components/atoms';
import { Copyright, SignInForm, SignInAvatar } from './components';

const Login = () => {
  const router = useRouter();
  const user = useSelector((state) => state.userState);
  const dispatch = useDispatch();
  React.useEffect(() => {
    if (user.user !== '') router.push('/admin');
  }, [user]);

  async function Submit(e) {
    e.preventDefault();
    const arr = [...e.target.elements];
    const data = { email: '', password: '' };
    arr.map((elem) => {
      if (elem.name === 'email' || elem.name === 'password') {
        data[elem.name] = elem.value;
      }
      return '';
    });
    await dispatch(authenticateUser(data));
  }
  return (
    <Container className="[ pt-8-0 flex flex-col items-center ]" component="main" maxWidth="xs">
      <SignInAvatar />
      <NoSSR>
        <SignInForm onSubmit={Submit} error={user.error !== ''} />
      </NoSSR>
      <Copyright />
    </Container>
  );
};
export default Login;
<file_sep>/redux/actions/notificationActions.js
import { SET_ERROR, SET_SUCCESS, SET_LOADING } from '../actionTypes';

export const setError = (payload) => {
  return {
    type: SET_ERROR,
    payload
  };
};
export const setSuccess = (payload) => {
  return {
    type: SET_SUCCESS,
    payload
  };
};
export const setLoading = (payload) => {
  return {
    type: SET_LOADING,
    payload
  };
};
<file_sep>/redux/actions/userActions.js
import { SET_USER, SET_AUTH_ERR, AUTHENTICATE_USER, SIGN_OUT } from '../actionTypes';

export const setUser = (payload) => {
  return {
    type: SET_USER,
    payload
  };
};

export const setAuthError = (payload) => {
  return {
    type: SET_AUTH_ERR,
    payload
  };
};

export const authenticateUser = (payload) => {
  return {
    type: AUTHENTICATE_USER,
    payload
  };
};

export const signOut = (payload) => {
  return {
    type: SIGN_OUT,
    payload
  };
};
<file_sep>/components/molecules/TwoButtons.js
import { Button, ButtonGroup } from '@material-ui/core';
import PropTypes from 'prop-types';

const TwoButtons = (props) => {
  const { onSubmit, onCancel } = props;
  return (
    <ButtonGroup aria-label="text primary button group">
      <Button fontSize={16} className="[ text-2-0 ]" variant="contained" color="primary" onClick={onSubmit}>
        <span className="[ text-1-3 ]">Save</span>
      </Button>
      <Button variant="contained" color="secondary" onClick={onCancel}>
        <span className="[ text-1-3 ]">Cancel</span>
      </Button>
    </ButtonGroup>
  );
};

TwoButtons.propTypes = {
  onSubmit: PropTypes.func,
  onCancel: PropTypes.func
};

TwoButtons.defaultProps = {
  onSubmit: () => {},
  onCancel: () => {}
};

export default TwoButtons;
<file_sep>/components/molecules/Typography.js
import PropTypes from 'prop-types';
import clsx from 'clsx';

const variantsSet = {
  h1: 'text-10-0 font-p-md',
  h2: 'text-4-8 font-p-bd',
  h3: 'text-2-4 font-p-bd',
  h4: 'text-4-0 font-p-bd',
  h5: 'text-3-0 font-p-bd',
  h6: 'text-2-3 font-p-bd',
  subtitle1: 'text-1-4 font-m-sbd tracking-subtitle',
  subtitle2: 'text-1-2 font-m-sbd tracking-subtitle',
  body1: 'text-1-4 font-m-md',
  body2: 'text-1-2 font-m-md'
};

const leadingsSet = {
  h1: 'leading-h1',
  h2: 'leading-h2',
  h3: 'leading-h3',
  h4: 'leading-h4',
  h5: 'leading-h5',
  h6: 'leading-h6',
  subtitle1: 'leading-subtitle1',
  subtitle2: 'leading-subtitle2',
  body1: 'leading-2-0',
  body2: 'leading-1-2'
};

const Typography = (props) => {
  const { span, variant, leading, className, upper, lineClamp, children, ...rest } = props;

  // eslint-disable-next-line no-nested-ternary
  const Component = span
    ? 'span'
    : variant === 'body1' || variant === 'body2' || variant === 'subtitle1' || variant === 'subtitle2'
    ? 'p'
    : variant;
  const calculatedLeading = leading ? `leading-${leading}` : leadingsSet[variant];

  return (
    <Component
      className={clsx(
        { [variantsSet[variant]]: variant, uppercase: upper, 'l-c': lineClamp },
        calculatedLeading,
        className
      )}
      {...rest}
    >
      {children}
      <style jsx>{`
        @mixin line-clamp($count) {
          display: -webkit-box;
          -webkit-line-clamp: $count;
          -webkit-box-orient: vertical;
          overflow: hidden;
        }

        .l-c {
          @include line-clamp(${lineClamp});
        }
      `}</style>
    </Component>
  );
};

Typography.propTypes = {
  className: PropTypes.string,
  span: PropTypes.bool,
  variant: PropTypes.oneOf(Object.keys(variantsSet)),
  leading: PropTypes.string,
  upper: PropTypes.bool,
  lineClamp: PropTypes.number,
  children: PropTypes.node
};

Typography.defaultProps = {
  className: '',
  span: false,
  variant: 'body1',
  leading: null,
  upper: false,
  lineClamp: null,
  children: null
};

export default Typography;
<file_sep>/components/organisms/Login/components/SignInAvatar.js
import React from 'react';
import LockOutlinedIcon from '@material-ui/icons/LockOutlined';

export default function SignInAvatar() {
  return (
    <>
      <div className="[ text-white w-5-0 h-5-0 m-1-0 bg-sign-in-avatar rounded-full flex items-center justify-center ]">
        <LockOutlinedIcon />
      </div>
      <h1 className="[ text-2-2 ]">Sign in</h1>
    </>
  );
}
<file_sep>/commons/ui/theme/boxShadow.js
const boxShadow = {
  primary: '0px 23px 35px rgba(4, 4, 4, 0.18)'
};

module.exports = boxShadow;
<file_sep>/components/organisms/Page/Page.js
import React from 'react';
import PropTypes from 'prop-types';

const generateElement = (e, i) => (
  <div className="[ p-2-0 border-solid border-b border-border-secondary ] col-md-10" key={i.toString()}>
    {e}
  </div>
);

const Page = (props) => {
  const { pageTitle, bodyElems } = props;
  return (
    <main id="main" role="main">
      <h1 className="[ px-3-0 mt-2-0 text-3-0 ]">{pageTitle}</h1>
      <section className="box-shadow [ bg-white text-1-5 ]">
        <div className="[ py-2-0 px-3-0 border-solid border-b border-border-secondary ]">Information</div>
        <div className="[ px-3-0 ]">{bodyElems.map(generateElement)}</div>
      </section>
    </main>
  );
};

Page.propTypes = {
  pageTitle: PropTypes.string,
  bodyElems: PropTypes.instanceOf(Array)
};

Page.defaultProps = {
  pageTitle: '',
  bodyElems: []
};

export default Page;
<file_sep>/redux/sagas/contactSaga.js
import { takeLatest, put, call } from 'redux-saga/effects';

import { FETCH_CONTACTS, UPDATE_CONTACTS } from '../actionTypes';
import { setContacts } from '../actions/contactsActions';
import { setError, setSuccess, setLoading } from '../actions/notificationActions';

function* fetchData() {
  try {
    yield put(setLoading(true));
    const response = yield call(axios.get, 'contacts');
    yield put(setLoading(false));
    yield put(setContacts(response.data));
  } catch (error) {
    yield put(setLoading(false));
    console.log(error);
  }
}

function* updateData({ payload }) {
  try {
    yield put(setLoading(true));
    yield call(axios.post, 'contacts', payload);
    yield put(setLoading(false));
    yield put(setSuccess(true));
  } catch (error) {
    yield put(setLoading(false));
    yield put(setError(true));
  }
  yield put(setError(false));
  yield put(setSuccess(false));
}

export default function* watchContacts() {
  yield takeLatest(FETCH_CONTACTS, fetchData);
  yield takeLatest(UPDATE_CONTACTS, updateData);
}
<file_sep>/components/molecules/ImageUploader.js
import PropTypes from 'prop-types';

const ImageUploader = (props) => {
  const { label, handleInput, name, image } = props;
  return (
    <>
      <div className="[ grid grid-cols-12 ]">
        <div className="[ col-span-2 text-right self-center mr-3-0 ]">{label}</div>
        <div className="[ col-span-7 ]">
          <input type="file" onChange={handleInput} name={name} />
        </div>
      </div>
      {image && (
        <img className="[ mt-2-0 w-30-percent ml-30-percent ]" src={process.env.staticUrl + image} alt="" />
      )}
    </>
  );
};

ImageUploader.propTypes = {
  label: PropTypes.string,
  handleInput: PropTypes.func,
  name: PropTypes.string,
  image: PropTypes.node
};

ImageUploader.defaultProps = {
  label: '',
  handleInput: () => {},
  name: '',
  image: null
};

export default ImageUploader;
<file_sep>/pages/blogs.js
import { PageHeader } from '@/components/atoms';
import { PinnedBlogs } from '@/components/organisms';
import { blogs } from '@/DUMMY_DATA';
import { SingleBlog } from '@/components/molecules';

const Blogs = () => {
  return (
    <section>
      <PageHeader title="Blogs" />
      {blogs && <PinnedBlogs blogs={blogs.slice(0, 3)} />}
      {blogs && (
        <div className="container [ grid grid-cols-3 gap-5-0 py-12-5 ]">
          {blogs && blogs.map((x) => <SingleBlog item={x} key={x.id} />)}
        </div>
      )}
    </section>
  );
};

export default Blogs;
<file_sep>/components/organisms/Login/components/index.js
export { default as Copyright } from './Copyright';
export { default as SignInAvatar } from './SignInAvatar';
export { default as SignInForm } from './SignInForm';
<file_sep>/components/layout/DefaultLayout/index.js
import PropTypes from 'prop-types';
import Header from './Header';
import Footer from './Footer';

function DefaultLayout(props) {
  const { children } = props;
  return (
    <>
      <Header />
      <main role="main" className="[ flex-1 ]">
        {children}
      </main>
      <Footer />
    </>
  );
}

DefaultLayout.propTypes = {
  children: PropTypes.any
};

DefaultLayout.defaultProps = {
  children: null
};

export default DefaultLayout;
<file_sep>/components/molecules/SocialIcons.js
import PropTypes from 'prop-types';
import { SVG, IconButton, IconCircle } from '@/components/atoms';
import { FacebookIcon, InstagramIcon, TwitterIcon } from '@/components/icons';

import clsx from 'clsx';

const iconButtonClassSet = 'w-4-2 h-4-2 hover:text-primary-hover duration-300';

const SocialIcons = (props) => {
  const { className } = props;
  return (
    <div className={clsx(className, 'grid grid-cols-3 gap-3-2 w-mc')}>
      <IconButton className={iconButtonClassSet} Component={IconCircle}>
        <SVG className="w-0-7" src={FacebookIcon} />
      </IconButton>
      <IconButton className={iconButtonClassSet} Component={IconCircle}>
        <SVG className="w-1-5" src={InstagramIcon} />
      </IconButton>
      <IconButton className={iconButtonClassSet} Component={IconCircle}>
        <SVG className="w-1-8" src={TwitterIcon} />
      </IconButton>
    </div>
  );
};

SocialIcons.propTypes = {
  className: PropTypes.string
};

SocialIcons.defaultProps = {
  className: ''
};

export default SocialIcons;
<file_sep>/components/atoms/RouterLink.js
import Link from 'next/link';
import PropTypes from 'prop-types';

const RouterLink = (props) => {
  const { className, children, ...rest } = props;
  return (
    <Link {...rest}>
      <a className={className}>{children}</a>
    </Link>
  );
};

RouterLink.propTypes = {
  className: PropTypes.string,
  children: PropTypes.node
};

RouterLink.defaultProps = {
  className: '',
  children: null
};
export default RouterLink;
<file_sep>/components/organisms/PinnedBlogs/PinnedBlogs.js
import PropTypes from 'prop-types';
import clsx from 'clsx';
import { SocialIcons, Typography } from '@/components/molecules';
import { Share } from '@/components/atoms';

const PinnedBlogs = (props) => {
  const { blogs, className } = props;
  const blog = blogs[0];
  return (
    <div className={clsx(className, '[ flex ]')}>
      <div className="[ w-50-percent ]">
        <img className="[ w-full ]" src={blog.image} alt={blog.title} />
      </div>
      <div className="[ w-50-percent bg-pinned-blogs text-white px-10-0 pt-11-2 pb-10-0 flex flex-col justify-between ]">
        <div>
          <Typography variant="subtitle2" className="[ text-secondary-text ]">
            BLOG
          </Typography>
          <Typography variant="h2" className="[ mt-1-0 w-80-percent ]">
            {blog.title}
          </Typography>
          <Typography className="two-columns [ mt-3-7 text-secondary-text ]">{blog.description}</Typography>
        </div>
        <div className="[ flex items-center justify-between text-1-6 font-p-md-it ]">
          <div className="[ text-primary-hover ]">29/08/2020</div>
          <div className="[ flex items-center ]">
            <Share />
            <SocialIcons className="ml-3-0" />
          </div>
        </div>
      </div>
      <style jsx global>{`
        .two-columns {
          column-count: 2;
          column-gap: 7rem;
        }
      `}</style>
    </div>
  );
};

PinnedBlogs.propTypes = {
  blogs: PropTypes.array.isRequired,
  className: PropTypes.string
};

PinnedBlogs.defaultProps = {
  className: PropTypes.string
};

export default PinnedBlogs;
<file_sep>/components/layout/AdminLayout/Header.js
import React from 'react';
import Toolbar from '@material-ui/core/Toolbar';
import IconButton from '@material-ui/core/IconButton';
import MenuIcon from '@material-ui/icons/Menu';
import ExitToAppIcon from '@material-ui/icons/ExitToApp';
import { useDispatch } from 'react-redux';
import { useRouter } from 'next/router';
import { signOut } from '../../../redux/actions/userActions';

const AdminLayoutHeader = () => {
  const router = useRouter();
  const dispatch = useDispatch();

  function handleSignOutButton() {
    dispatch(signOut());
    router.push('/admin/auth/login');
  }
  return (
    <div className="[ fixed top-0 left-0 right-0 text-white bg-admin-header h-7-0 z-2 ]">
      <Toolbar>
        <IconButton edge="start" color="inherit" aria-label="open drawer">
          <MenuIcon />
        </IconButton>
        <div className="[ flex-grow ]" />
        <IconButton edge="end" aria-label="email of current user" color="inherit" />
        <IconButton onClick={handleSignOutButton} edge="end" aria-label="logout" color="inherit">
          <ExitToAppIcon />
        </IconButton>
      </Toolbar>
    </div>
  );
};

export default AdminLayoutHeader;
<file_sep>/components/molecules/TinyMCE.js
import { Editor } from '@tinymce/tinymce-react';
import { useDispatch } from 'react-redux';
import PropTypes from 'prop-types';
import { NoSSR } from '@/components/atoms';
import { uploadImage } from '@/redux/actions/imageActions';

const apiKey = '<KEY>';
const plugins = ['advlist autolink lists link image media', 'table paste code wordcount'];
const toolbar = `code | undo redo | formatselect | bold italic backcolor blockquote | bullist numlist | image | media | link | myCustomToolbarButton`;

function TinyMCE(props) {
  const { handleInput, name, label, initialValue } = props;
  const dispatch = useDispatch();

  const imagesUploadHandler = (blobInfo, success) => {
    const formData = new FormData();
    formData.append('image', blobInfo.blob());
    dispatch(
      uploadImage({
        file: formData,
        getResponse: (response) => {
          success(process.env.staticUrl + response.data.filename);
        }
      })
    );
  };
  const TinyInit = {
    height: 500,
    menubar: true,
    plugins,
    toolbar,
    branding: false,
    images_upload_handler: imagesUploadHandler,
    image_dimensions: false,
    image_description: false,
    media_dimensions: false,
    media_alt_source: false,
    media_poster: false,
    media_url_resolver: (data, resolve, reject) => {
      const splittedUrl = data.url.split('watch?v=');
      console.log(splittedUrl);
      if (splittedUrl.length > 1) {
        const embedHtml = `<figure class="media"><iframe src="https://www.youtube.com/embed/${splittedUrl.pop()}"></iframe></figure>`;
        resolve({ html: embedHtml });
      } else {
        reject({ msg: 'WRONG URL' });
      }
    },
    setup: (editor) => {
      editor.ui.registry.addButton('myCustomToolbarButton', {
        text: 'My Custom Button',
        onAction: () => console.log('Button clicked!')
      });
    }
  };

  const onChange = (e) => {
    handleInput({ name, value: e.target.getContent() });
  };

  return (
    <div className="[ grid grid-cols-12 ]">
      <div className="[ col-span-2 text-right mr-3-0 ]">{label}</div>
      <div className="[ col-span-7 ]">
        <NoSSR>
          <Editor apiKey={apiKey} initialValue={initialValue} init={TinyInit} onChange={onChange} />
        </NoSSR>
      </div>
    </div>
  );
}

TinyMCE.propTypes = {
  handleInput: PropTypes.func,
  name: PropTypes.string,
  label: PropTypes.string,
  initialValue: PropTypes.string
};

TinyMCE.defaultProps = {
  handleInput: () => {},
  name: '',
  label: '',
  initialValue: ''
};

export default TinyMCE;
<file_sep>/components/molecules/Navigation.js
import Link from 'next/link';
import routes from '@/components/routerConfig';
import { useRouter } from 'next/router';
import clsx from 'clsx';

const Navigation = () => {
  const router = useRouter();
  return (
    <nav className="[ h-full ]">
      <ul className="[ flex h-full text-1-4 text-white uppercase font-ms-bd ]">
        {routes.map((e) => (
          <li key={e.id}>
            <Link href={e.path}>
              <div
                className={clsx(
                  { 'nav-item--active': router.pathname === e.path },
                  'nav-item [ px-3-2 duration-200 h-full cursor-pointer ]'
                )}
              >
                <div className="nav-item__action [ w-full h-full flex items-center relative ]">{e.title}</div>
              </div>
            </Link>
          </li>
        ))}
      </ul>
      <style jsx>{`
        .nav-item {
          $self: &;
          &__action {
            &:after {
              content: '';
              @apply absolute h-0 bottom-0 left-0 right-0 duration-200 bg-primary-hover;
            }
          }
          &--active,
          &:hover {
            @apply bg-primary;
            #{$self}__action {
              &:after {
                height: 3px;
              }
            }
          }
        }
      `}</style>
    </nav>
  );
};
export default Navigation;
<file_sep>/components/organisms/Gallery.js
import PropTypes from 'prop-types';
import { Swiper, SwiperSlide } from 'swiper/react';
import clsx from 'clsx';

const swiperOptions = {
  spaceBetween: 24,
  slidesPerView: 3,
  loop: true
};

const Gallery = (props) => {
  const { items, className } = props;
  return (
    <div className={clsx(className, 'overflow--visible [ py-13-2 bg-slider px-27-5 ]')}>
      <Swiper style={{ overflow: 'visible' }} {...swiperOptions}>
        {items.map((x) => (
          <SwiperSlide key={x}>
            <div className="hover-item [ relative cursor-pointer ]">
              <img src={x} alt="" className="[ w-full ]" />
              <div className="hover-item__bg [ absolute inset-0 border-primary-hover border-solid border-2 duration-500 opacity-0 pointer-events-none flex items-center justify-center ]">
                <div className="[ w-5-0 h-5-0 flex items-center justify-center bg-primary text-primary-hover text-3-0 ]">
                  +
                </div>
              </div>
            </div>
          </SwiperSlide>
        ))}
      </Swiper>

      <style jsx>{`
        .hover-item {
          $self: &;
          &__bg {
            background: rgba(0, 0, 0, 0.62);
          }
          &:hover {
            #{$self}__bg {
              @apply opacity-100 pointer-events-auto;
            }
          }
        }
      `}</style>
    </div>
  );
};

Gallery.propTypes = {
  items: PropTypes.instanceOf(Array).isRequired,
  className: PropTypes.string
};

Gallery.defaultProps = {
  className: ''
};

export default Gallery;
<file_sep>/components/atoms/IconButton.js
import PropTypes from 'prop-types';
import clsx from 'clsx';
import { motion } from 'framer-motion';

const IconButton = (props) => {
  const { Component, children, className, ...rest } = props;
  return (
    <motion.div className="w-mc" whileHover={{ scale: 1.05 }} whileTap={{ scale: 0.95 }}>
      <Component className={clsx(className, 'cursor-pointer')} {...rest}>
        {children}
      </Component>
    </motion.div>
  );
};

IconButton.propTypes = {
  Component: PropTypes.any,
  children: PropTypes.node,
  className: PropTypes.string
};

IconButton.defaultProps = {
  Component: 'div',
  children: null,
  className: ''
};

export default IconButton;
<file_sep>/components/atoms/TextField.js
import PropTypes from 'prop-types';
import clsx from 'clsx';

const TextField = (props) => {
  const { className, variant, type, multiline, ...rest } = props;
  const propsObject = {
    ...rest,
    type,
    className: clsx(
      {
        '[ border-2 border-border-secondary border-solid ]': variant === 'outlined',
        '[ border-b-2 border-primary-hover border-solid bg-primary-input-bg ]': variant === 'primary',
        '[ h-5-0 ]': !multiline
      },
      className,
      '[ font-m-rg px-2-8 italic placeholder-secondary-text py-1-0 ]'
    )
  };
  return multiline ? <textarea {...propsObject} /> : <input {...propsObject} />;
};

TextField.propTypes = {
  className: PropTypes.string,
  type: PropTypes.string,
  variant: PropTypes.oneOf(['outlined', 'primary']),
  multiline: PropTypes.bool
};

TextField.defaultProps = {
  className: '',
  type: 'text',
  variant: 'primary',
  multiline: false
};

export default TextField;
<file_sep>/components/layout/DefaultLayout/Footer/components/Subscribe.js
import PropTypes from 'prop-types';
import { TextField, Button } from '@/components/atoms';
import clsx from 'clsx';
import { Typography } from '@/components/molecules';

const Subscribe = (props) => {
  const { className } = props;
  return (
    <div className={clsx(className, '[ [ pt-7-0 pb-7-0 ] flex border-t-2 border-border border-solid ]')}>
      <div className="[ flex-1 pr-2-0 ]">
        <Typography variant="subtitle2" className="[ text-secondary-text ]">
          SUBSCRIBE
        </Typography>
        <Typography variant="h2">Our Newsletter</Typography>
        <Typography className="[ mt-2-8 text-secondary-text ]">
          Praesent fermentum ligula in dui imperdiet, vel tempus nulla ultricies. Phasellus at commodo ligula.
          Nullam molestie volutp at sapien.
        </Typography>
      </div>
      <div className="[ w-60-percent pl-2-0 mt-9-0 ]">
        <div className="[ flex text-1-4 ]">
          <TextField placeholder="Your e-mail" variant="outlined" className="[ flex-1 border-r-0 ]" />
          <Button>Subscribe</Button>
        </div>
      </div>
    </div>
  );
};

Subscribe.propTypes = {
  className: PropTypes.string
};

Subscribe.defaultProps = {
  className: ''
};

export default Subscribe;
<file_sep>/components/molecules/HtmlText.js
const HtmlText = (props) => {
  return (
    <div {...props}>
      <div className="container [ px-20-5 leading-2-0 text-1-4 font-m-md ]">
        Praesent fermentum ligula in dui imperdiet, vel tempus nulla ultricies. Phasellus at commodo ligula.
        Nullam molestie volutpat sapien, a dignissim tortor laoreet quis. Class aptent taciti sociosqu ad
        litora torquent per conubia nostra, per inceptos himenaeos Praesent fermentum ligula in dui imperdiet,
        vel tempus nulla ultricies. Phasellus at commodo ligula. Nullam molestie volutpat sapien, a dignissim
        tortor laoreet quis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos
        himenaeos Praesent fermentum ligula in dui imperdiet, vel tempus nulla ultricies. Phasellus at commodo
        ligula. Nullam molestie volutpat sapien, a dignissim tortor laoreet quis. Class aptent taciti sociosqu
        ad litora torquent per conubia nostra, per inceptos himenaeos
      </div>
    </div>
  );
};

export default HtmlText;
<file_sep>/commons/ui/theme/letterSpacing.js
const letterSpacing = {
  subtitle: '0.2em'
};

module.exports = letterSpacing;
<file_sep>/redux/actionTypes.js
export const SET_CONTACTS = 'SET_CONTACTS';
export const FETCH_CONTACTS = 'FETCH_CONTACTS';
export const UPDATE_CONTACTS = 'UPDATE_CONTACTS';

export const SET_ABOUT = 'SET_ABOUT';
export const FETCH_ABOUT = 'FETCH_ABOUT';
export const UPDATE_ABOUT = 'UPDATE_ABOUT';

export const SET_UPLOADED_IMAGE_FILENAME = 'SET_UPLOADED_IMAGE_FILENAME';
export const SET_UPLOADED_IMAGE_ERROR = 'SET_UPLOADED_IMAGE_ERROR';
export const UPLOAD_IMAGE = 'UPLOAD_IMAGE';
export const CROP_IMAGE = 'CROP_IMAGE';

export const SET_ERROR = 'SET_ERROR';
export const SET_SUCCESS = 'SET_SUCCESS';
export const SET_LOADING = 'SET_LOADING';

export const SET_USER = 'SET_USER';
export const AUTHENTICATE_USER = 'AUTHENTICATE_USER';
export const SET_AUTH_ERR = 'SET_AUTH_ERR';
export const SIGN_OUT = 'SIGN_OUT';
<file_sep>/redux/sagas/uploadSaga.js
import { takeLatest, put, call } from 'redux-saga/effects';

import { UPLOAD_IMAGE } from '../actionTypes';
import { setError, setSuccess, setLoading } from '../actions/notificationActions';

function* uploadImage(data) {
  try {
    yield put(setLoading(true));
    const response = yield call(axios.post, 'upload', data.payload.file);
    data.payload.getResponse(response);
    yield put(setSuccess(true));
  } catch (error) {
    yield put(setError(true));
    throw error;
  }
  yield put(setLoading(false));
  yield put(setError(false));
  yield put(setSuccess(false));
}

export default function* watchContacts() {
  yield takeLatest(UPLOAD_IMAGE, uploadImage);
}
<file_sep>/components/organisms/MainContainer.js
import { Typography } from '@/components/molecules';

const MainContainer = () => {
  return (
    <div className="[ relative ]">
      <img src="/images/main-container.jpg" alt="" />
      <div className="[ absolute inset-0 text-white flex items-center justify-center flex-col ]">
        <Typography variant="subtitle1">IGI</Typography>
        <Typography variant="h1" className="[ text-center ]">
          Independent Group <br /> of Initiators
        </Typography>
      </div>
    </div>
  );
};

export default MainContainer;
<file_sep>/pages/admin/auth/login.js
import { Login } from '@/components/organisms';

export default function LoginPage() {
  return <Login />;
}
<file_sep>/components/atoms/Burger.js
import PropTypes from 'prop-types';

const Burger = (props) => {
  const { onClick, isOpened } = props;
  return (
    <button
      type="button"
      onClick={onClick}
      className={`[ relative w-3-2 h-1-8 pointer-events-auto cursor-pointer ] burger-menu-icon ${
        isOpened ? 'burger-menu-icon--is-opened' : ''
      }`}
    >
      <span className="burger-menu-icon__line [ block absolute left-0 h-0-2 bg-white ]" />
      <span className="burger-menu-icon__line [ block absolute left-0 h-0-2 bg-white ]" />
      <span className="burger-menu-icon__line [ block absolute left-0 h-0-2 bg-white ]" />
      <span className="burger-menu-icon__line [ block absolute left-0 h-0-2 bg-white ]" />
      <style jsx>{`
        .burger-menu-icon {
          $self: &;
          &__line {
            transform: rotate(0deg);
            width: 100%;

            &:nth-child(1) {
              top: 0px;
              transform: scaleX(1);
              transform-origin: right;
              transition: all 0.25s ease 0.25s;
            }

            &:nth-child(2),
            &:nth-child(3) {
              top: 50%;
              transform: translateY(-50%);
              transition: all 0.25s ease;
            }

            &:nth-child(4) {
              top: 100%;
              transform: scaleX(1) translateY(-100%);
              transform-origin: left;
              transition: all 0.25s ease 0.25s;
            }
          }
          &--is-opened {
            #{$self}__line {
              &:nth-child(1) {
                transition: all 0.25s ease;
                transform: scaleX(0);
                transform-origin: right;
              }

              &:nth-child(2) {
                transform: rotate(45deg);
                transition: all 0.25s ease 0.15s;
              }

              &:nth-child(3) {
                transform: rotate(135deg);
                transition: all 0.25s ease 0.15s;
              }
              &:nth-child(4) {
                transition: all 0.25s ease;
                transform: scaleX(0) translateY(-100%);
                transform-origin: left;
              }
            }
          }
        }
      `}</style>
    </button>
  );
};

Burger.propTypes = {
  onClick: PropTypes.func,
  isOpened: PropTypes.bool
};

Burger.defaultProps = {
  onClick: () => {},
  isOpened: false
};

export default Burger;
<file_sep>/components/atoms/Button.js
/* eslint-disable react/button-has-type */
import PropTypes from 'prop-types';
import clsx from 'clsx';

const Button = (props) => {
  const { className, children, type, ...rest } = props;
  return (
    <button
      {...rest}
      type={type}
      className={clsx(
        className,
        'btn [ h-5-0 flex items-center justify-center bg-primary px-3-0 text-1-6 relative hover:bg-primary-hover duration-200 text-white ]'
      )}
    >
      {children}
      <style jsx>{`
        .btn {
          min-width: 16rem;
          &:after {
            content: '';
            @apply absolute h-0-3 bg-primary-hover bottom-0;
            width: calc(100% - 6rem);
          }
        }
      `}</style>
    </button>
  );
};

Button.propTypes = {
  className: PropTypes.string,
  children: PropTypes.node.isRequired,
  type: PropTypes.string
};

Button.defaultProps = {
  className: '',
  type: 'button'
};

export default Button;
<file_sep>/redux/sagas/userSaga.js
import { takeLatest, call, put } from 'redux-saga/effects';
import Cookies from 'universal-cookie';
import jwtDecode from 'jwt-decode';

import { setUser, setAuthError } from '../actions/userActions';
import { AUTHENTICATE_USER, SIGN_OUT } from '../actionTypes';

const cookies = new Cookies();

function* authenticateUser({ payload }) {
  try {
    const response = yield call(axios.post, 'auth/adminAuthenticate', payload);
    const { token } = response.data;
    cookies.set('testUser', token, { path: '/' });
    yield put(setUser(jwtDecode(token).email));
  } catch (error) {
    yield put(setAuthError(error.err));
  }
}

function* signOut() {
  cookies.remove('testUser', { path: '/' });
  yield put(setUser(''));
}
export default function* watchAuthUser() {
  yield takeLatest(AUTHENTICATE_USER, authenticateUser);
  yield takeLatest(SIGN_OUT, signOut);
}
<file_sep>/components/layout/DefaultLayout/Footer/components/BottomNavbar.js
import Link from 'next/link';
import routes from '@/components/routerConfig';

function Navigation() {
  return (
    <nav className="[ text-1-4 font-m-md ]">
      <ul className="[ flex justify-between ]">
        {routes.map((e) => (
          <li key={e.id}>
            <Link href={e.path}>
              <div className="[ w-full h-full flex items-center mx-1-0 cursor-pointer hover:text-primary-hover duration-200 ]">
                {e.title}
              </div>
            </Link>
          </li>
        ))}
      </ul>
    </nav>
  );
}
export default Navigation;
<file_sep>/components/atoms/Logo.js
export default function Logo() {
  return (
    <div className="[ flex items-center bg-primary h-full w-27-5 justify-center ]">
      <div className="[ h-8-0 flex items-center ]">
        <img className="[ h-full ]" src="/images/logo.png" alt="" />
      </div>
    </div>
  );
}
<file_sep>/components/atoms/Share.js
import { ShareIcon } from '@/components/icons';
import SVG from './SVG';

const Share = () => {
  return (
    <div className="[ text-1-6 font-p-md-it flex items-center duration-200 ]">
      <div>Share</div>
      <SVG src={ShareIcon} className="w-1-5 ml-2-0" />
    </div>
  );
};

export default Share;
<file_sep>/components/molecules/ContactForm.js
import { TextField, Button } from '@/components/atoms';

const ContactNote = () => {
  const handleSubmit = (e) => {
    e.preventDefault();
    console.log(e);
  };

  return (
    <form onSubmit={handleSubmit} className="[ text-1-4 grid grid-cols-2 gap-y-2-0 gap-x-3-0 ]">
      <TextField placeholder="<NAME>" />
      <TextField placeholder="Your Email" />
      <TextField className="col-span-2" placeholder="Your Email" multiline rows={8} />
      <Button type="submit" className="w-mc">
        Send
      </Button>
    </form>
  );
};

export default ContactNote;
<file_sep>/redux/rootSaga.js
import { all } from 'redux-saga/effects';

import watchAuthUser from './sagas/userSaga';
import watchContacts from './sagas/contactSaga';
import watchAbout from './sagas/aboutSaga';
import watchUpload from './sagas/uploadSaga';

export default function* rootSaga(payload) {
  yield all([watchContacts(payload), watchAuthUser(payload), watchAbout(payload), watchUpload(payload)]);
}
<file_sep>/plugins/axios.js
import axios from 'axios';
import Cookies from 'universal-cookie';

const cookies = new Cookies();

const restApi = axios.create({
  baseURL: `http://localhost:3001/api/`
});

restApi.interceptors.request.use((config) => {
  const token = cookies.get('testUser');
  if (token !== undefined) {
    // eslint-disable-next-line no-param-reassign
    config.headers.common.Authorization = token;
  }
  return config;
});

export default restApi;
<file_sep>/redux/rootReducer.js
import { combineReducers } from 'redux';
import contactsReducer from './reducers/contactsReducer';
import userReducer from './reducers/userReducer';
import aboutReducer from './reducers/aboutReducer';
import notificationReducer from './reducers/notificationReducer';

export const exampleInitialState = {};

const rootReducer = combineReducers({
  contacts: contactsReducer,
  notifs: notificationReducer,
  userState: userReducer,
  about: aboutReducer
});

export default rootReducer;
<file_sep>/pages/admin/projects/newproject.js
import { useRouter } from 'next/router';
import { Input, TwoButtons, Cropper, TinyMCE } from '@/components/molecules';

import Page from '../../../components/organisms/Page/Page';

function NewProject() {
  const router = useRouter();
  const [data, setData] = React.useState({});

  function handleInput(event) {
    setData({ ...data, [event.target.name]: event.target.value });
  }

  function onSubmit() {
    router.push('/admin');
  }

  function onCancel() {
    router.push('/admin');
  }
  function getFilename(filename) {
    console.log(filename);
  }
  const elems = [
    <Input type="text" label="Title" value={data.title || ''} handleInput={handleInput} name="title" />,
    <Cropper name="mainImage" width={100} height={100} label="Main Image" getFilename={getFilename} />,
    <Cropper name="shareImage" width={600} height={315} label="Share Image" getFilename={getFilename} />,
    <Input
      type="text"
      label="Short Description"
      value={data.shortDescription || ''}
      handleInput={handleInput}
      name="shortDescription"
    />,
    <TinyMCE
      initialValue={data.description || ''}
      label="Description"
      handleInput={handleInput}
      name="description"
    />,
    <TwoButtons onSubmit={onSubmit} onCancel={onCancel} />
  ];
  return <Page pageTitle="New Project" bodyElems={elems} />;
}

export default NewProject;
<file_sep>/components/layout/AdminLayout/SideBar.js
import React from 'react';
import Navigation from './Navigation';

function DefaultLayoutSideBar() {
  return (
    <div className="[ fixed top-7-0 bottom-0 left-0 w-27-5 py-3-0 bg-sidebar-bg ]">
      <Navigation />
    </div>
  );
}

export default DefaultLayoutSideBar;
<file_sep>/components/layout/AdminLayout/Navigation/components/NavItem.js
import ListItem from '@material-ui/core/ListItem';
import { makeStyles } from '@material-ui/core/styles';
import Link from 'next/link';
import { useRouter } from 'next/router';
import PropTypes from 'prop-types';

const useStyles = makeStyles({
  root: {
    padding: '0 0'
  }
});
const NavItem = (props) => {
  const { path, title } = props;
  const router = useRouter();
  const classes = useStyles();
  return (
    <ListItem className={classes.root} selected={router.pathname === path} button>
      <Link href={path}>
        <div className="[ py-1-0 px-1-5 h-full w-full text-1-6 text-white ] ">{title}</div>
      </Link>
    </ListItem>
  );
};
NavItem.propTypes = {
  path: PropTypes.string,
  title: PropTypes.string
};

NavItem.defaultProps = {
  path: '',
  title: ''
};

export default NavItem;
<file_sep>/components/atoms/SVG.js
import PropTypes from 'prop-types';
import InlineSVG from 'react-inlinesvg';

const SVG = (props) => {
  const { className, src, original, withoutStrokes, ...rest } = props;

  const preProcessorHandler = (code) => {
    let svgData = code.replace(/(width=".*?"|height=".*?")/g, '');
    if (!original) svgData = svgData.replace(/fill=".*?"/g, 'fill="currentColor"');
    if (withoutStrokes) svgData = svgData.replace(/stroke=".*?"/g, 'stroke="currentColor"');
    return svgData;
  };

  return <InlineSVG {...rest} className={className} src={src} preProcessor={preProcessorHandler} />;
};

SVG.propTypes = {
  className: PropTypes.string,
  src: PropTypes.string,
  original: PropTypes.bool,
  withoutStrokes: PropTypes.bool
};

SVG.defaultProps = {
  className: '',
  src: '',
  original: false,
  withoutStrokes: false
};

export default SVG;
<file_sep>/commons/ui/plugins/plugins.js
const plugins = [
  ({ addComponents }) => {
    addComponents({
      '.container': {
        maxWidth: '1140px',
        margin: '0 auto',
        width: '100%',
        paddingRight: '15px',
        paddingLeft: '15px'
      }
    });
  }
];

module.exports = plugins;
<file_sep>/commons/ui/theme/minHeight.js
const minHeight = {
  '4-5': '4.5rem'
};

module.exports = minHeight;
<file_sep>/pages/admin/about.js
import { useSelector, useDispatch } from 'react-redux';
import { useRouter } from 'next/router';
import { Input, TwoButtons, TinyMCE } from '@/components/molecules';
import { Page } from '@/components/organisms';
import { fetchAbout, updateAbout } from '@/redux/actions/aboutActions';

function About() {
  const router = useRouter();
  const about = useSelector((state) => state.about);
  const dispatch = useDispatch();
  const [data, setData] = React.useState({ ...about.data });

  React.useEffect(() => {
    setData({ ...data, ...about.data });
  }, [about]);

  function handleInput(e) {
    setData({ ...data, [e.name]: e.value });
  }

  function onSubmit() {
    dispatch(updateAbout(data));
    router.push('/admin');
  }

  function onCancel() {
    router.push('/admin');
  }

  const elems = [
    <Input type="text" label="Title" value={data.title || ''} handleInput={handleInput} name="title" />,
    <TinyMCE initialValue={data.content || ''} label="Content" handleInput={handleInput} name="content" />,
    <TwoButtons onSubmit={onSubmit} onCancel={onCancel} />
  ];

  return <Page pageTitle="About" bodyElems={elems} />;
}

About.getInitialProps = async ({ ctx }) => {
  await ctx.store.dispatch(fetchAbout());
};

export default About;
<file_sep>/pages/contact.js
import { PageHeader } from '@/components/atoms';
import { ContactNote, Typography, ContactForm } from '@/components/molecules';

const contactItems = {
  address: '481 Creekside Lane Avila CA 93424',
  phone: '+53 345 7953 32453',
  email: '<EMAIL>'
};

const Contact = () => {
  return (
    <section>
      <PageHeader title="Contact" />
      <div className="container [ py-12-7 flex ]">
        <div className="[ w-1/3 px-1-5 ]">
          <Typography variant="h2">Contact Us</Typography>
          <Typography className="[ text-secondary-text ]">
            Send us message. We are always ready to answer your questions
          </Typography>
          <ContactNote contactItems={contactItems} className="[ text-1-6 mt-5-8 ]" />
        </div>
        <div className="[ w-2/3 px-1-5 ]">
          <ContactForm />
        </div>
      </div>
    </section>
  );
};

export default Contact;
<file_sep>/components/molecules/SingleBlog.js
import PropTypes from 'prop-types';
import { Typography } from '@/components/molecules';

const SingleProject = (props) => {
  const { item } = props;
  return (
    <div className="[ shadow-primary relative ]">
      <img className="[ w-full ]" src={item.image} alt={item.title} />
      <div className="[ px-3-0 pt-3-8 pb-3-2 ]">
        <div className="[ text-center ]">
          <Typography lineClamp={2} variant="h3">
            {item.title}
          </Typography>
          <Typography lineClamp={3} className="[ text-secondary-text mt-2-7 ]">
            {item.description}
          </Typography>
        </div>
        <div className="[ flex items-center justify-between text-1-6 font-p-md-it mt-2-0 ]">
          <div className="[ text-primary-hover ]">29/08/2020</div>
          <div className="[ text-primary-hover border-b border-solid hover:text-primary duration-200 cursor-pointer ]">
            Read More...
          </div>
        </div>
      </div>
    </div>
  );
};

SingleProject.propTypes = {
  item: PropTypes.object.isRequired
};

export default SingleProject;
<file_sep>/components/molecules/index.js
export { default as Cropper } from './Cropper';
export { default as ImageUploader } from './ImageUploader';
export { default as Input } from './Input';
export { default as Loader } from './Loader';
export { default as Navigation } from './Navigation';
export { default as Switcher } from './Switcher';
export { default as TextBox } from './TextBox';
export { default as TinyMCE } from './TinyMCE';
export { default as TwoButtons } from './TwoButtons';
export { default as ContactNote } from './ContactNote';
export { default as SocialIcons } from './SocialIcons';
export { default as SingleProject } from './SingleProject';
export { default as Typography } from './Typography';
export { default as HtmlText } from './HtmlText';
export { default as SingleBlog } from './SingleBlog';
export { default as ContactForm } from './ContactForm';
<file_sep>/components/layout/AdminLayout/Body.js
import PropTypes from 'prop-types';

const AdminLayoutBody = (props) => {
  const { children } = props;
  return <div className="[ mb-7-0 flex-1 ml-27-5 mt-7-0 ]">{children}</div>;
};

AdminLayoutBody.propTypes = {
  children: PropTypes.any
};

AdminLayoutBody.defaultProps = {
  children: null
};
export default AdminLayoutBody;
<file_sep>/pages/admin/contact.js
import { useSelector, useDispatch } from 'react-redux';
import { useRouter } from 'next/router';
import { Input, TwoButtons } from '@/components/molecules';
import { Page } from '@/components/organisms';

import { fetchContacts, updateContacts } from '@/redux/actions/contactsActions';

function Contacts() {
  const router = useRouter();
  const contacts = useSelector((state) => state.contacts);
  const [data, setData] = React.useState({ ...contacts.data });
  const dispatch = useDispatch();

  React.useEffect(() => {
    setData({ ...data, ...contacts.data });
  }, [contacts]);

  function handleInput(e) {
    setData({ ...data, [e.name]: e.value });
  }

  function onSubmit() {
    dispatch(updateContacts(data));
    router.push('/admin');
  }

  function onCancel() {
    router.push('/admin');
  }

  const elems = [
    <Input type="text" label="Mobile" value={data.phone || ''} handleInput={handleInput} name="phone" />,
    <Input type="text" label="Email" value={data.email || ''} handleInput={handleInput} name="email" />,
    <Input type="text" label="Address" value={data.address || ''} handleInput={handleInput} name="address" />,
    <TwoButtons onSubmit={onSubmit} onCancel={onCancel} />
  ];

  return <Page pageTitle="Contacts" bodyElems={elems} />;
}

Contacts.getInitialProps = async ({ ctx }) => {
  await ctx.store.dispatch(fetchContacts());
};
export default Contacts;
<file_sep>/components/layout/AdminLayout/Navigation/index.js
import React from 'react';
import List from '@material-ui/core/List';
import NoSSR from '@/components/atoms/NoSSR';
import { NavItem } from './components';

const routes = [
  { id: 0, path: '/admin', title: 'Home' },
  { id: 1, path: '/admin/contact', title: 'Contact' },
  { id: 2, path: '/admin/about', title: 'About' }
];

function Navigation() {
  return (
    <NoSSR>
      <List component="nav" aria-label="main">
        {routes.map((e) => (
          <NavItem path={e.path} title={e.title} key={e.id} />
        ))}
      </List>
    </NoSSR>
  );
}
export default Navigation;
<file_sep>/pages/admin/index.js
export default function AdminIndex() {
  return (
    <div className="flex">
      <h1>AdminIndex</h1>
    </div>
  );
}
<file_sep>/tailwind.config.js
/* eslint-disable global-require */
module.exports = {
  theme: {
    screens: require('./commons/ui/theme/screens'),
    spacing: require('./commons/ui/theme/spacing'),
    inset: require('./commons/ui/theme/inset'),
    colors: require('./commons/ui/theme/colors'),
    fontSize: require('./commons/ui/theme/fontSize'),
    borderRadius: require('./commons/ui/theme/borderRadius'),
    fontFamily: require('./commons/ui/theme/fontFamily'),
    lineHeight: require('./commons/ui/theme/lineHeight'),
    zIndex: require('./commons/ui/theme/zIndex'),
    opacity: require('./commons/ui/theme/opacity'),
    maxWidth: require('./commons/ui/theme/maxWidth'),
    boxShadow: require('./commons/ui/theme/boxShadow'),
    letterSpacing: require('./commons/ui/theme/letterSpacing')
  },
  corePlugins: require('./commons/ui/plugins/corePlugins'),
  plugins: require('./commons/ui/plugins/plugins')
};
<file_sep>/components/atoms/ReadMore.js
import clsx from 'clsx';
import PropTypes from 'prop-types';
import RouterLink from './RouterLink';

const ReadMore = (props) => {
  const { path, className } = props;

  return (
    <RouterLink
      className={clsx(className, '[ font-m-md text-1-6 text-primary hover:underline block ]')}
      href={path}
    >
      Read More
    </RouterLink>
  );
};
ReadMore.propTypes = {
  path: PropTypes.string,
  className: PropTypes.string
};
ReadMore.defaultProps = {
  path: '/',
  className: ''
};

export default ReadMore;
<file_sep>/pages/admin/projects/updateproject/[id].js
import { useRouter } from 'next/router';

export default function UpdateProjectById() {
  const router = useRouter();
  return (
    <div className="flex">
      <h1>update project id: {router.query.id}</h1>
    </div>
  );
}
<file_sep>/components/layout/DefaultLayout/Header.js
import { Navigation } from '@/components/molecules';
import { Logo, Button } from '@/components/atoms';

function DefaultLayoutHeader() {
  return (
    <header className="[ bg-primary-bg h-12-5 text-white z-2 justify-between flex items-center pr-base-x ]">
      <Logo />
      <Navigation />
      <Button>Button</Button>
    </header>
  );
}

export default DefaultLayoutHeader;
<file_sep>/commons/ui/plugins/corePlugins.js
const corePlugins = {
  container: false
};

module.exports = corePlugins;
<file_sep>/commons/ui/theme/lineHeight.js
const lineHeight = {
  '1-1': 1.1,
  '1-2': 1.2,
  '1-3': 1.3,
  '1-4': 1.4,
  '1-5': 1.5,
  '1-63': 1.63,
  '1-68': 1.68,
  '2-0': 2,
  '3-0': 3,

  h1: 'calc(var(--ratio) * 10rem)',
  h2: 'calc(var(--ratio) * 4.8rem)',
  h3: 'calc(var(--ratio) * 2.4rem)',
  h4: 'calc(var(--ratio) * 4rem)',
  h5: 'calc(var(--ratio) * 3rem)',
  h6: 'calc(var(--ratio) * 2.3rem)',
  subtitle1: 'calc(var(--ratio) * 1.4rem)',
  subtitle2: 'calc(var(--ratio) * 1.2rem)',
  body1: 'calc(var(--ratio) * 1.4rem)'
};

module.exports = lineHeight;
<file_sep>/components/molecules/Input.js
import PropTypes from 'prop-types';

function Input(props) {
  const { label, type, name, value, handleInput } = props;
  const onChange = (e) => {
    handleInput({ name: e.target.name, value: e.target.value });
  };
  return (
    <div className="[ grid grid-cols-12 ]">
      <div className="[ col-span-2 text-right self-center mr-3-0 ]">{label}</div>
      <div className="[ col-span-7 ]">
        <input type={type} onChange={onChange} name={name} value={value} />
      </div>
      <style jsx>{`
        input {
          width: 100%;
          border: 1px solid #ebedf2;
          padding: 0.5rem 1rem;
          transition: 0.15s;
        }

        input:focus {
          border-color: #716aca;
          transition: 0.15s;
        }
      `}</style>
    </div>
  );
}

Input.propTypes = {
  label: PropTypes.string,
  handleInput: PropTypes.func,
  name: PropTypes.string,
  value: PropTypes.string,
  type: PropTypes.string
};

Input.defaultProps = {
  label: '',
  handleInput: () => {},
  name: '',
  value: '',
  type: 'text'
};

export default Input;
<file_sep>/components/icons/index.js
export { default as EmailIcon } from './email.svg';
export { default as FacebookIcon } from './facebook.svg';
export { default as InstagramIcon } from './instagram.svg';
export { default as ShareIcon } from './share.svg';
export { default as TwitterIcon } from './twitter.svg';
export { default as YoutubeIcon } from './youtube.svg';
