---
# System prepended metadata

title: File Structure

---

# File Structure
## How it used before (chat-area example)
:::spoiler Old file structure
```
├── chat-parts.component.jsx
├── chat.component.jsx
├── chat.styles.jsx
├── editor
│   ├── editor.component.jsx
│   ├── editor.styles.js
│   ├── index.js
│   ├── plugins.jsx
│   └── utils.js
├── file-uploading
│   ├── dropzone.component.jsx
│   └── modal
│       ├── file-modal.component.jsx
│       ├── index.js
│       ├── styles.js
│       └── thumb.component.jsx
├── index.js
├── session-tags
│   ├── index.js
│   ├── session-tags.component.jsx
│   └── session-tags.styles.js
├── start-meeting
│   ├── google-modal
│   │   ├── google-modal.component.jsx
│   │   ├── google-modal.styles.js
│   │   └── index.js
│   ├── index.js
│   ├── start-meeting.component.jsx
│   ├── start-meeting.styles.js
│   └── zoom-modal
│       ├── index.js
│       ├── zoom-modal.component.jsx
│       └── zoom-modal.styles.js
├── styles.css
├── task-button
│   ├── index.js
│   └── task-button.jsx
├── utils.js
```
:::
## Rules: components folder & separation
- every component should be separated in own directory and exported via index.ts file
- every component which require additional components should have **components** folder on the same directory level.
- extra files that isn't a components should be separated in **utils** folder on the same directory level. (?)
- index.ts file should only export component without any connection wrappers like redux-form, withStyles, etc: 
### index.ts in component folder
```
export * from './recorder.component.tsx';
```
### index.ts in components folder
```
export * from './recorder';
export * from './attachments';
```
### Directory structure
```
├── index.ts
├── voice-clip.component.tsx
├── voice-clip.props.ts
├── voice-clip.styles.ts
├── components
│   ├── index.ts
│   ├── attachments
│   │   ├── attachments.component.tsx
│   │   ├── attachments.props.ts
│   │   ├── attachments.styles.ts
│   │   └── index.ts
│   └── recorder
│       ├── index.ts
│       ├── recorder.component.tsx
│       ├── recorder.props.ts
│       ├── recorder.styles.ts
│       └── utils
│           └── somefile.ts
```

## How component should look like
### component-name.component.ts
```
import React from 'react';
import { useTranslation } from 'react-i18next';
import { localizationIdsLibrary } from '@localization';
import { withStyles } from '@material-ui/core';
import { Preloader } from '@shared/containers/Preloader';
import { PreloaderNames } from '@shared/utils/enums';
import { GeneratingLinkProps } from './generating-link.props'
import { styles } from './generating-link.styles';

const GeneratingLink = withStyles(styles)(
  ({ classes }: GeneratingLinkProps) => {
    const { t } = useTranslation();

    return (
      <div className={classes.beforeCreate}>
        <h3>{t(localizationIdsLibrary.modules.conversations.generatingLinkPleaseWait)}</h3>
        <Preloader name={PreloaderNames.meetLink} />
      </div>
    )
  }
);

export { GeneratingLink };

```
## component-name.props.ts
```
import { WithStyles } from '@material-ui/core';
import { styles } from './ready-link.styles';

type ReadyLinkProps = WithStyles<ReturnType<typeof styles>> & {
  link: string,
};

export { ReadyLinkProps };

```

## component-name.styles.ts
```
import { StyleRulesCallback } from '@modules/App/components/AppTheme';

const styles: StyleRulesCallback = (theme) => ({
  copyZone: {
    display: 'flex',
    alignItems: 'center',
  },
  copyMeetLink: {
    marginLeft: 5,
  },
  meetLinkPlaceholder: {
    margin: '10px 5px 10px auto',
    background: theme.colors.secondary.main,
  },
});

export { styles };

```

---

# Eslint & Prettier configs
:::spoiler Old .eslintrc.json
```
{
  "extends": [
    "airbnb",
    "plugin:jest/recommended"
  ],
  "plugins": [
    "react",
    "import",
    "jest",
    "react-hooks"
  ],
  "parser": "babel-eslint",
  "parserOptions": {
    "ecmaVersion": 6,
    "sourceType": "module",
    "ecmaFeatures": {
      "experimentalObjectRestSpread": true,
      "jsx": true,
      "legacyDecorators": true
    }
  },
  "globals": {
    "window": true
  },
  "settings": {
    "import/resolver": "webpack",
    "import/ignore": [
      "node_modules",
      "\\.(css|less|svg)$"
    ]
  },
  "rules": {
    "no-return-assign": "off",
    "no-param-reassign": "off",
    "import/prefer-default-export": "off",
    "import/no-unresolved": "off",
    "import/no-extraneous-dependencies": "off",
    "func-names": "off",
    "no-underscore-dangle": "off",
    "react/prop-types": "off",
    "react/no-unescaped-entities": "off",
    "jsx-a11y/anchor-is-valid": "off",
    "no-extra-boolean-cast": "off",
    "no-shadow": "off",
    "no-case-declarations": "off",
    "react/no-array-index-key": "off",
    "react-hooks/rules-of-hooks": "error",
    "react-hooks/exhaustive-deps": "warn",
    "no-restricted-syntax": "off"
  },
  "env": {
    "browser": true,
    "mocha": true
  }
}

```
:::
:::spoiler New .eslintrc.json
```
{
  "env": {
    "browser": true,
    "es6": true
  },
  "extends": [
    "plugin:@typescript-eslint/eslint-recommended",
    "plugin:react-hooks/recommended",
    "plugin:react/recommended",
    "plugin:import/errors",
    "plugin:import/warnings",
    "plugin:import/typescript",
    "airbnb",
    "prettier"
  ],
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "ecmaFeatures": {
      "jsx": true,
      "experimentalObjectRestSpread": true,
      "legacyDecorators": true
    },
    "ecmaVersion": "latest",
    "sourceType": "module"
  },
  "plugins": [
    "react",
    "@typescript-eslint",
    "prettier"
  ],
  "rules": {
    "@typescript-eslint/ban-ts-comment": "off",
    "react/jsx-filename-extension": [
      2,
      {
        "extensions": [
          ".js",
          ".jsx",
          ".ts",
          ".tsx"
        ]
      }
    ],
    "no-use-before-define": "off",
    "@typescript-eslint/no-use-before-define": [
      "error"
    ],
    "no-return-assign": "off",
    "no-param-reassign": "off",
    "react-hooks/rules-of-hooks": "error",
    "import/prefer-default-export": "off",
    "import/no-unresolved": "off",
    "import/no-extraneous-dependencies": "off",
    "func-names": "off",
    "comma-dangle": [
      "error",
      {
        "arrays": "never",
        "objects": "always",
        "imports": "never",
        "exports": "never",
        "functions": "never"
      }
    ],
    "no-underscore-dangle": "off",
    "react/prop-types": "off",
    "react/no-unescaped-entities": "off",
    "jsx-a11y/anchor-is-valid": "off",
    "no-extra-boolean-cast": "off",
    "no-shadow": "off",
    "no-case-declarations": "off",
    "react/no-array-index-key": "off",
    "react-hooks/exhaustive-deps": "warn",
    "no-restricted-syntax": "off",
    "arrow-parens": "off",
    "no-unused-vars": "warn",
    "react/jsx-props-no-multi-spaces": "off"
  },
  "overrides": [
    {
      "files": [
        "*.ts"
      ],
      "parserOptions": {
        "project": [
          "src/tsconfig.json"
        ]
      }
    }
  ]
}
```
:::
---
:::spoiler .prettierrc.json
```
{
  "singleQuote": true,
  "useTabs": false,
  "tabWidth": 2,
  "semi": true,
  "jsxSingleQuote": false,
  "arrowParens": "avoid",
  "trailingComma": "all",
  "printWidth": 100
}
```
:::

TODO:
- Material UI 3 -> 4 -> 5
- wrapper / container / hoc for react extra logic
- Types for API services & reducers
- Theme file refactor